summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/obsolete/sysfs-gpio2
-rw-r--r--Documentation/ABI/testing/sysfs-bus-rpmsg20
-rw-r--r--Documentation/ABI/testing/sysfs-devices-system-cpu3
-rw-r--r--Documentation/ABI/testing/sysfs-fs-f2fs3
-rw-r--r--Documentation/ABI/testing/sysfs-platform-ideapad-laptop13
-rw-r--r--Documentation/acpi/method-customizing.txt10
-rw-r--r--Documentation/admin-guide/LSM/apparmor.rst6
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt9
-rw-r--r--Documentation/admin-guide/pm/intel_pstate.rst2
-rw-r--r--Documentation/arm/OMAP/README4
-rw-r--r--Documentation/block/biodoc.txt15
-rw-r--r--Documentation/core-api/kernel-api.rst2
-rw-r--r--Documentation/crypto/crypto_engine.rst8
-rw-r--r--Documentation/device-mapper/writecache.txt68
-rw-r--r--Documentation/devicetree/bindings/arm/amlogic.txt6
-rw-r--r--Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt4
-rw-r--r--Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt2
-rw-r--r--Documentation/devicetree/bindings/arm/shmobile.txt12
-rw-r--r--Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt18
-rw-r--r--Documentation/devicetree/bindings/bus/ti-sysc.txt6
-rw-r--r--Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt16
-rw-r--r--Documentation/devicetree/bindings/clock/st/st,clkgen.txt8
-rw-r--r--Documentation/devicetree/bindings/clock/ti/gate.txt2
-rw-r--r--Documentation/devicetree/bindings/clock/ti/interface.txt2
-rw-r--r--Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt2
-rw-r--r--Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt2
-rw-r--r--Documentation/devicetree/bindings/display/bridge/tda998x.txt2
-rw-r--r--Documentation/devicetree/bindings/firmware/qcom,scm.txt3
-rw-r--r--Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt2
-rw-r--r--Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt2
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-davinci.txt2
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-rcar.txt1
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt4
-rw-r--r--Documentation/devicetree/bindings/input/mtk-pmic-keys.txt43
-rw-r--r--Documentation/devicetree/bindings/input/rmi4/rmi_2d_sensor.txt2
-rw-r--r--Documentation/devicetree/bindings/input/rotary-encoder.txt2
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt6
-rw-r--r--Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.txt23
-rw-r--r--Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt2
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt12
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt5
-rw-r--r--Documentation/devicetree/bindings/mfd/arizona.txt6
-rw-r--r--Documentation/devicetree/bindings/mfd/as3722.txt2
-rw-r--r--Documentation/devicetree/bindings/mfd/da9063.txt32
-rw-r--r--Documentation/devicetree/bindings/mfd/motorola-cpcap.txt42
-rw-r--r--Documentation/devicetree/bindings/mfd/mt6397.txt8
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt3
-rw-r--r--Documentation/devicetree/bindings/mfd/stm32-timers.txt20
-rw-r--r--Documentation/devicetree/bindings/mfd/sun6i-prcm.txt4
-rw-r--r--Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt2
-rw-r--r--Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt2
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-st.txt2
-rw-r--r--Documentation/devicetree/bindings/net/dsa/ksz.txt2
-rw-r--r--Documentation/devicetree/bindings/net/dsa/mt7530.txt2
-rw-r--r--Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt1
-rw-r--r--Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt2
-rw-r--r--Documentation/devicetree/bindings/pci/hisilicon-pcie.txt2
-rw-r--r--Documentation/devicetree/bindings/pci/kirin-pcie.txt2
-rw-r--r--Documentation/devicetree/bindings/pci/pci-keystone.txt4
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-max77620.txt4
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt4
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-rk805.txt4
-rw-r--r--Documentation/devicetree/bindings/power/fsl,imx-gpc.txt2
-rw-r--r--Documentation/devicetree/bindings/power/pd-samsung.txt20
-rw-r--r--Documentation/devicetree/bindings/power/power_domain.txt19
-rw-r--r--Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt2
-rw-r--r--Documentation/devicetree/bindings/power/supply/ab8500/btemp.txt2
-rw-r--r--Documentation/devicetree/bindings/power/supply/ab8500/chargalg.txt2
-rw-r--r--Documentation/devicetree/bindings/power/supply/ab8500/charger.txt2
-rw-r--r--Documentation/devicetree/bindings/power/wakeup-source.txt2
-rw-r--r--Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt1
-rw-r--r--Documentation/devicetree/bindings/reserved-memory/qcom,cmd-db.txt37
-rw-r--r--Documentation/devicetree/bindings/reset/renesas,rst.txt2
-rw-r--r--Documentation/devicetree/bindings/rng/brcm,bcm2835.txt9
-rw-r--r--Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt2
-rw-r--r--Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt37
-rw-r--r--Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt2
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.txt119
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt1
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt8
-rw-r--r--Documentation/devicetree/bindings/soc/rockchip/power_domain.txt12
-rw-r--r--Documentation/devicetree/bindings/sound/st,stm32-i2s.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/st,stm32-sai.txt2
-rw-r--r--Documentation/devicetree/bindings/spi/spi-st-ssc.txt2
-rw-r--r--Documentation/devicetree/bindings/thermal/exynos-thermal.txt14
-rw-r--r--Documentation/devicetree/bindings/thermal/imx-thermal.txt9
-rw-r--r--Documentation/devicetree/bindings/thermal/mediatek-thermal.txt1
-rw-r--r--Documentation/devicetree/bindings/thermal/qcom-tsens.txt1
-rw-r--r--Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt3
-rw-r--r--Documentation/devicetree/bindings/thermal/rcar-thermal.txt7
-rw-r--r--Documentation/devicetree/bindings/thermal/uniphier-thermal.txt1
-rw-r--r--Documentation/devicetree/bindings/timer/renesas,cmt.txt14
-rw-r--r--Documentation/devicetree/bindings/usb/rockchip,dwc3.txt2
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.txt2
-rw-r--r--Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt7
-rw-r--r--Documentation/devicetree/bindings/watchdog/renesas-wdt.txt23
-rw-r--r--Documentation/driver-api/gpio/consumer.rst2
-rw-r--r--Documentation/driver-api/index.rst1
-rw-r--r--Documentation/driver-api/infrastructure.rst4
-rw-r--r--Documentation/driver-api/scsi.rst2
-rw-r--r--Documentation/driver-api/target.rst64
-rw-r--r--Documentation/features/debug/stackprotector/arch-support.txt2
-rw-r--r--Documentation/filesystems/ceph.txt8
-rw-r--r--Documentation/filesystems/cifs/AUTHORS7
-rw-r--r--Documentation/filesystems/cifs/CHANGES3
-rw-r--r--Documentation/filesystems/cifs/TODO17
-rw-r--r--Documentation/filesystems/f2fs.txt16
-rw-r--r--Documentation/hwmon/ina2xx2
-rw-r--r--Documentation/i2c/busses/i2c-mlxcpld4
-rw-r--r--Documentation/i2c/busses/i2c-ocores2
-rw-r--r--Documentation/i2c/muxes/i2c-mux-gpio4
-rw-r--r--Documentation/ioctl/ioctl-number.txt2
-rw-r--r--Documentation/kbuild/kconfig-language.txt18
-rw-r--r--Documentation/kprobes.txt4
-rw-r--r--Documentation/laptops/thinkpad-acpi.txt2
-rw-r--r--Documentation/maintainer/pull-requests.rst2
-rw-r--r--Documentation/networking/can.rst4
-rw-r--r--Documentation/riscv/pmu.txt249
-rw-r--r--Documentation/security/self-protection.rst2
-rwxr-xr-xDocumentation/sphinx/rstFlatTable.py2
-rw-r--r--Documentation/trace/coresight.txt2
-rw-r--r--Documentation/trace/events.rst2
-rw-r--r--Documentation/trace/ftrace-uses.rst2
-rw-r--r--Documentation/trace/histogram.txt25
-rw-r--r--Documentation/trace/intel_th.rst2
-rw-r--r--Documentation/trace/tracepoint-analysis.rst8
-rw-r--r--Documentation/translations/ja_JP/howto.rst4
-rw-r--r--Documentation/translations/ko_KR/howto.rst2
-rw-r--r--Documentation/translations/zh_CN/SubmittingDrivers2
-rw-r--r--Documentation/translations/zh_CN/gpio.txt4
-rw-r--r--Documentation/translations/zh_CN/io_ordering.txt2
-rw-r--r--Documentation/translations/zh_CN/magic-number.txt4
-rw-r--r--Documentation/translations/zh_CN/video4linux/omap3isp.txt4
-rw-r--r--Documentation/translations/zh_CN/video4linux/v4l2-framework.txt6
-rw-r--r--Documentation/vfio-mediated-device.txt5
-rw-r--r--Documentation/virtual/kvm/api.txt27
-rw-r--r--Documentation/virtual/kvm/devices/arm-vgic-v3.txt30
-rw-r--r--Documentation/virtual/kvm/mmu.txt6
-rw-r--r--Documentation/virtual/kvm/nested-vmx.txt11
-rw-r--r--MAINTAINERS194
-rw-r--r--Makefile151
-rw-r--r--arch/Kconfig58
-rw-r--r--arch/alpha/Kconfig5
-rw-r--r--arch/alpha/lib/Makefile2
-rw-r--r--arch/alpha/lib/dec_and_lock.c44
-rw-r--r--arch/arm/Kconfig9
-rw-r--r--arch/arm/Kconfig.debug13
-rw-r--r--arch/arm/Makefile2
-rw-r--r--arch/arm/boot/compressed/Makefile3
-rw-r--r--arch/arm/boot/dts/Makefile41
-rw-r--r--arch/arm/boot/dts/am335x-baltos-ir3220.dts2
-rw-r--r--arch/arm/boot/dts/am335x-baltos-ir5221.dts2
-rw-r--r--arch/arm/boot/dts/am335x-baltos.dtsi2
-rw-r--r--arch/arm/boot/dts/am335x-bone-common.dtsi9
-rw-r--r--arch/arm/boot/dts/am335x-boneblue.dts2
-rw-r--r--arch/arm/boot/dts/am335x-evm.dts9
-rw-r--r--arch/arm/boot/dts/am335x-evmsk.dts12
-rw-r--r--arch/arm/boot/dts/am335x-osd335x-common.dtsi124
-rw-r--r--arch/arm/boot/dts/am335x-pocketbeagle.dts237
-rw-r--r--arch/arm/boot/dts/am3517-evm.dts233
-rw-r--r--arch/arm/boot/dts/am3517-som.dtsi142
-rw-r--r--arch/arm/boot/dts/am437x-cm-t43.dts2
-rw-r--r--arch/arm/boot/dts/am437x-gp-evm.dts2
-rw-r--r--arch/arm/boot/dts/am437x-sk-evm.dts115
-rw-r--r--arch/arm/boot/dts/am43x-epos-evm.dts2
-rw-r--r--arch/arm/boot/dts/am571x-idk.dts5
-rw-r--r--arch/arm/boot/dts/am572x-idk.dts5
-rw-r--r--arch/arm/boot/dts/am574x-idk.dts20
-rw-r--r--arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi4
-rw-r--r--arch/arm/boot/dts/am57xx-beagle-x15.dts3
-rw-r--r--arch/arm/boot/dts/am57xx-idk-common.dtsi14
-rw-r--r--arch/arm/boot/dts/armada-370-db.dts57
-rw-r--r--arch/arm/boot/dts/armada-370-dlink-dns327l.dts120
-rw-r--r--arch/arm/boot/dts/armada-370-mirabox.dts51
-rw-r--r--arch/arm/boot/dts/armada-370-netgear-rn102.dts90
-rw-r--r--arch/arm/boot/dts/armada-370-netgear-rn104.dts90
-rw-r--r--arch/arm/boot/dts/armada-370-rd.dts52
-rw-r--r--arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi64
-rw-r--r--arch/arm/boot/dts/armada-370-xp.dtsi6
-rw-r--r--arch/arm/boot/dts/armada-375-db.dts50
-rw-r--r--arch/arm/boot/dts/armada-375.dtsi6
-rw-r--r--arch/arm/boot/dts/armada-385-db-ap.dts69
-rw-r--r--arch/arm/boot/dts/armada-385-linksys-caiman.dts129
-rw-r--r--arch/arm/boot/dts/armada-385-linksys-cobra.dts129
-rw-r--r--arch/arm/boot/dts/armada-385-linksys-rango.dts141
-rw-r--r--arch/arm/boot/dts/armada-385-linksys-shelby.dts129
-rw-r--r--arch/arm/boot/dts/armada-385-linksys.dtsi16
-rw-r--r--arch/arm/boot/dts/armada-388-db.dts55
-rw-r--r--arch/arm/boot/dts/armada-38x.dtsi6
-rw-r--r--arch/arm/boot/dts/armada-390-db.dts66
-rw-r--r--arch/arm/boot/dts/armada-395-gp.dts74
-rw-r--r--arch/arm/boot/dts/armada-398-db.dts60
-rw-r--r--arch/arm/boot/dts/armada-39x.dtsi6
-rw-r--r--arch/arm/boot/dts/armada-xp-98dx3236.dtsi13
-rw-r--r--arch/arm/boot/dts/armada-xp-db-dxbc2.dts2
-rw-r--r--arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts2
-rw-r--r--arch/arm/boot/dts/armada-xp-db.dts2
-rw-r--r--arch/arm/boot/dts/armada-xp-gp.dts2
-rw-r--r--arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts2
-rw-r--r--arch/arm/boot/dts/armada-xp-linksys-mamba.dts156
-rw-r--r--arch/arm/boot/dts/armada-xp-netgear-rn2120.dts90
-rw-r--r--arch/arm/boot/dts/aspeed-ast2500-evb.dts18
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts129
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-opp-lanyang.dts325
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts6
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts32
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts6
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-portwell-neptune.dts159
-rw-r--r--arch/arm/boot/dts/aspeed-g4.dtsi35
-rw-r--r--arch/arm/boot/dts/aspeed-g5.dtsi47
-rw-r--r--arch/arm/boot/dts/at91-sama5d2_xplained.dts2
-rw-r--r--arch/arm/boot/dts/at91-sama5d4ek.dts4
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-a-plus.dts6
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-a.dts6
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-b-plus.dts6
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts6
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-b.dts6
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi.dtsi6
-rw-r--r--arch/arm/boot/dts/bcm2836-rpi-2-b.dts6
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts108
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-3-b.dts26
-rw-r--r--arch/arm/boot/dts/bcm283x-rpi-lan7515.dtsi27
-rw-r--r--arch/arm/boot/dts/bcm283x.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts13
-rw-r--r--arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts13
-rw-r--r--arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts3
-rw-r--r--arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts3
-rw-r--r--arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts3
-rw-r--r--arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts15
-rw-r--r--arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts13
-rw-r--r--arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts3
-rw-r--r--arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts13
-rw-r--r--arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts13
-rw-r--r--arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts13
-rw-r--r--arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts3
-rw-r--r--arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts3
-rw-r--r--arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts3
-rw-r--r--arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts13
-rw-r--r--arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts3
-rw-r--r--arch/arm/boot/dts/bcm4709-linksys-ea9200.dts3
-rw-r--r--arch/arm/boot/dts/bcm4709-netgear-r7000.dts13
-rw-r--r--arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts3
-rw-r--r--arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts25
-rw-r--r--arch/arm/boot/dts/bcm47094-linksys-panamera.dts3
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts3
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts57
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts3
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts3
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts77
-rw-r--r--arch/arm/boot/dts/bcm47094-netgear-r8500.dts3
-rw-r--r--arch/arm/boot/dts/bcm5301x-nand-cs0-bch1.dtsi3
-rw-r--r--arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi3
-rw-r--r--arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi3
-rw-r--r--arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi3
-rw-r--r--arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts33
-rw-r--r--arch/arm/boot/dts/berlin2.dtsi35
-rw-r--r--arch/arm/boot/dts/berlin2cd-google-chromecast.dts65
-rw-r--r--arch/arm/boot/dts/berlin2cd-valve-steamlink.dts79
-rw-r--r--arch/arm/boot/dts/berlin2cd.dtsi167
-rw-r--r--arch/arm/boot/dts/berlin2q-marvell-dmp.dts33
-rw-r--r--arch/arm/boot/dts/berlin2q.dtsi65
-rw-r--r--arch/arm/boot/dts/da850-evm.dts298
-rw-r--r--arch/arm/boot/dts/da850-lego-ev3.dts83
-rw-r--r--arch/arm/boot/dts/da850.dtsi154
-rw-r--r--arch/arm/boot/dts/dm8148-t410.dts2
-rw-r--r--arch/arm/boot/dts/dra7-evm-common.dtsi15
-rw-r--r--arch/arm/boot/dts/dra7-evm.dts68
-rw-r--r--arch/arm/boot/dts/dra7-mmc-iodelay.dtsi19
-rw-r--r--arch/arm/boot/dts/dra7.dtsi32
-rw-r--r--arch/arm/boot/dts/dra71-evm.dts17
-rw-r--r--arch/arm/boot/dts/dra72-evm-common.dtsi71
-rw-r--r--arch/arm/boot/dts/dra72x-mmc-iodelay.dtsi11
-rw-r--r--arch/arm/boot/dts/dra76-evm.dts34
-rw-r--r--arch/arm/boot/dts/emev2-kzm9d.dts3
-rw-r--r--arch/arm/boot/dts/emev2.dtsi5
-rw-r--r--arch/arm/boot/dts/exynos-syscon-restart.dtsi28
-rw-r--r--arch/arm/boot/dts/exynos3250-rinato.dts4
-rw-r--r--arch/arm/boot/dts/exynos3250.dtsi2
-rw-r--r--arch/arm/boot/dts/exynos4.dtsi3
-rw-r--r--arch/arm/boot/dts/exynos4210-origen.dts34
-rw-r--r--arch/arm/boot/dts/exynos4210-trats.dts4
-rw-r--r--arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi36
-rw-r--r--arch/arm/boot/dts/exynos4412-midas.dtsi86
-rw-r--r--arch/arm/boot/dts/exynos4412-n710x.dts16
-rw-r--r--arch/arm/boot/dts/exynos4412-odroid-common.dtsi33
-rw-r--r--arch/arm/boot/dts/exynos4412-odroidu3.dts6
-rw-r--r--arch/arm/boot/dts/exynos4412-odroidx.dts6
-rw-r--r--arch/arm/boot/dts/exynos4412-origen.dts2
-rw-r--r--arch/arm/boot/dts/exynos4412.dtsi2
-rw-r--r--arch/arm/boot/dts/exynos5.dtsi3
-rw-r--r--arch/arm/boot/dts/exynos5250.dtsi7
-rw-r--r--arch/arm/boot/dts/exynos5410.dtsi1
-rw-r--r--arch/arm/boot/dts/exynos5420-peach-pit.dts4
-rw-r--r--arch/arm/boot/dts/exynos5420.dtsi87
-rw-r--r--arch/arm/boot/dts/exynos5422-odroid-core.dtsi2
-rw-r--r--arch/arm/boot/dts/exynos5440-sd5v1.dts42
-rw-r--r--arch/arm/boot/dts/exynos5440-ssdk5440.dts81
-rw-r--r--arch/arm/boot/dts/exynos5440-tmu-sensor-conf.dtsi20
-rw-r--r--arch/arm/boot/dts/exynos5440-trip-points.dtsi21
-rw-r--r--arch/arm/boot/dts/exynos5440.dtsi355
-rw-r--r--arch/arm/boot/dts/exynos5800-peach-pi.dts4
-rw-r--r--arch/arm/boot/dts/gemini-dlink-dir-685.dts16
-rw-r--r--arch/arm/boot/dts/gemini-dlink-dns-313.dts19
-rw-r--r--arch/arm/boot/dts/gemini-nas4220b.dts20
-rw-r--r--arch/arm/boot/dts/gemini-rut1xx.dts12
-rw-r--r--arch/arm/boot/dts/gemini-sq201.dts12
-rw-r--r--arch/arm/boot/dts/gemini-wbd111.dts17
-rw-r--r--arch/arm/boot/dts/gemini-wbd222.dts16
-rw-r--r--arch/arm/boot/dts/gemini.dtsi2
-rw-r--r--arch/arm/boot/dts/imx1-ads.dts11
-rw-r--r--arch/arm/boot/dts/imx1.dtsi21
-rw-r--r--arch/arm/boot/dts/imx23-evk.dts13
-rw-r--r--arch/arm/boot/dts/imx23.dtsi13
-rw-r--r--arch/arm/boot/dts/imx25-pdk.dts14
-rw-r--r--arch/arm/boot/dts/imx25.dtsi16
-rw-r--r--arch/arm/boot/dts/imx27-apf27.dts13
-rw-r--r--arch/arm/boot/dts/imx27-pdk.dts13
-rw-r--r--arch/arm/boot/dts/imx27.dtsi18
-rw-r--r--arch/arm/boot/dts/imx28-cfa10049.dts2
-rw-r--r--arch/arm/boot/dts/imx28-duckbill-2-enocean.dts2
-rw-r--r--arch/arm/boot/dts/imx28-evk.dts13
-rw-r--r--arch/arm/boot/dts/imx28-tx28.dts14
-rw-r--r--arch/arm/boot/dts/imx28.dtsi13
-rw-r--r--arch/arm/boot/dts/imx31.dtsi13
-rw-r--r--arch/arm/boot/dts/imx35-pdk.dts15
-rw-r--r--arch/arm/boot/dts/imx35.dtsi14
-rw-r--r--arch/arm/boot/dts/imx50-evk.dts17
-rw-r--r--arch/arm/boot/dts/imx50.dtsi3
-rw-r--r--arch/arm/boot/dts/imx51-babbage.dts15
-rw-r--r--arch/arm/boot/dts/imx51-zii-rdu1.dts6
-rw-r--r--arch/arm/boot/dts/imx51.dtsi18
-rw-r--r--arch/arm/boot/dts/imx53-ard.dts11
-rw-r--r--arch/arm/boot/dts/imx53-m53.dtsi2
-rw-r--r--arch/arm/boot/dts/imx53-ppd.dts12
-rw-r--r--arch/arm/boot/dts/imx53-qsb-common.dtsi15
-rw-r--r--arch/arm/boot/dts/imx53-qsb.dts17
-rw-r--r--arch/arm/boot/dts/imx53-qsrb.dts15
-rw-r--r--arch/arm/boot/dts/imx53-smd.dts20
-rw-r--r--arch/arm/boot/dts/imx53-tx53-x03x.dts1
-rw-r--r--arch/arm/boot/dts/imx53-tx53.dtsi14
-rw-r--r--arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi2
-rw-r--r--arch/arm/boot/dts/imx53.dtsi11
-rw-r--r--arch/arm/boot/dts/imx6dl-aristainetos2_4.dts2
-rw-r--r--arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts15
-rw-r--r--arch/arm/boot/dts/imx6dl-mamoj.dts224
-rw-r--r--arch/arm/boot/dts/imx6dl-sabreauto.dts10
-rw-r--r--arch/arm/boot/dts/imx6dl-sabresd.dts10
-rw-r--r--arch/arm/boot/dts/imx6dl-udoo.dts6
-rw-r--r--arch/arm/boot/dts/imx6dl-wandboard-revb1.dts6
-rw-r--r--arch/arm/boot/dts/imx6dl-wandboard-revd1.dts6
-rw-r--r--arch/arm/boot/dts/imx6dl-wandboard.dts6
-rw-r--r--arch/arm/boot/dts/imx6dl.dtsi12
-rw-r--r--arch/arm/boot/dts/imx6q-b850v3.dts4
-rw-r--r--arch/arm/boot/dts/imx6q-ba16.dtsi7
-rw-r--r--arch/arm/boot/dts/imx6q-bx50v3.dtsi13
-rw-r--r--arch/arm/boot/dts/imx6q-dhcom-pdk2.dts151
-rw-r--r--arch/arm/boot/dts/imx6q-dhcom-som.dtsi476
-rw-r--r--arch/arm/boot/dts/imx6q-gk802.dts3
-rw-r--r--arch/arm/boot/dts/imx6q-icore-mipi.dts25
-rw-r--r--arch/arm/boot/dts/imx6q-icore-ofcap12.dts31
-rw-r--r--arch/arm/boot/dts/imx6q-kp-tpc.dts22
-rw-r--r--arch/arm/boot/dts/imx6q-kp.dtsi432
-rw-r--r--arch/arm/boot/dts/imx6q-novena.dts2
-rw-r--r--arch/arm/boot/dts/imx6q-pistachio.dts2
-rw-r--r--arch/arm/boot/dts/imx6q-sabreauto.dts15
-rw-r--r--arch/arm/boot/dts/imx6q-sabresd.dts15
-rw-r--r--arch/arm/boot/dts/imx6q-udoo.dts6
-rw-r--r--arch/arm/boot/dts/imx6q-utilite-pro.dts2
-rw-r--r--arch/arm/boot/dts/imx6q-var-dt6customboard.dts2
-rw-r--r--arch/arm/boot/dts/imx6q-wandboard-revb1.dts6
-rw-r--r--arch/arm/boot/dts/imx6q-wandboard-revd1.dts6
-rw-r--r--arch/arm/boot/dts/imx6q-wandboard.dts6
-rw-r--r--arch/arm/boot/dts/imx6q.dtsi39
-rw-r--r--arch/arm/boot/dts/imx6qdl-apalis.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6qdl-colibri.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6qdl-gw5904.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6qdl-hummingboard.dtsi52
-rw-r--r--arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi47
-rw-r--r--arch/arm/boot/dts/imx6qdl-icore.dtsi25
-rw-r--r--arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabreauto.dtsi15
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabrelite.dtsi3
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabresd.dtsi18
-rw-r--r--arch/arm/boot/dts/imx6qdl-tx6-lcd.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-tx6-mb7.dtsi3
-rw-r--r--arch/arm/boot/dts/imx6qdl-tx6.dtsi6
-rw-r--r--arch/arm/boot/dts/imx6qdl-udoo.dtsi6
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard-revd1.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard.dtsi14
-rw-r--r--arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi24
-rw-r--r--arch/arm/boot/dts/imx6qdl.dtsi70
-rw-r--r--arch/arm/boot/dts/imx6qp-sabreauto.dts44
-rw-r--r--arch/arm/boot/dts/imx6qp-sabresd.dts44
-rw-r--r--arch/arm/boot/dts/imx6qp-wandboard-revd1.dts6
-rw-r--r--arch/arm/boot/dts/imx6qp-zii-rdu2.dts5
-rw-r--r--arch/arm/boot/dts/imx6qp.dtsi44
-rw-r--r--arch/arm/boot/dts/imx6sl-evk.dts10
-rw-r--r--arch/arm/boot/dts/imx6sl.dtsi34
-rw-r--r--arch/arm/boot/dts/imx6sx-nitrogen6sx.dts4
-rw-r--r--arch/arm/boot/dts/imx6sx-sabreauto.dts427
-rw-r--r--arch/arm/boot/dts/imx6sx.dtsi101
-rw-r--r--arch/arm/boot/dts/imx6ul-14x14-evk.dts10
-rw-r--r--arch/arm/boot/dts/imx6ul-isiot.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts2
-rw-r--r--arch/arm/boot/dts/imx6ul-tx6ul.dtsi6
-rw-r--r--arch/arm/boot/dts/imx6ul.dtsi51
-rw-r--r--arch/arm/boot/dts/imx6ull-pinfunc.h9
-rw-r--r--arch/arm/boot/dts/imx6ull.dtsi2
-rw-r--r--arch/arm/boot/dts/imx7d-cl-som-imx7.dts2
-rw-r--r--arch/arm/boot/dts/imx7d-nitrogen7.dts6
-rw-r--r--arch/arm/boot/dts/imx7d-pinfunc.h6
-rw-r--r--arch/arm/boot/dts/imx7d-sdb-sht11.dts44
-rw-r--r--arch/arm/boot/dts/imx7d-sdb.dts70
-rw-r--r--arch/arm/boot/dts/imx7d.dtsi71
-rw-r--r--arch/arm/boot/dts/imx7s-warp.dts4
-rw-r--r--arch/arm/boot/dts/imx7s.dtsi88
-rw-r--r--arch/arm/boot/dts/keystone-k2g-evm.dts26
-rw-r--r--arch/arm/boot/dts/logicpd-som-lv.dtsi34
-rw-r--r--arch/arm/boot/dts/logicpd-torpedo-som.dtsi10
-rw-r--r--arch/arm/boot/dts/meson8.dtsi33
-rw-r--r--arch/arm/boot/dts/meson8b-odroidc1.dts68
-rw-r--r--arch/arm/boot/dts/meson8b.dtsi24
-rw-r--r--arch/arm/boot/dts/meson8m2-mxiii-plus.dts244
-rw-r--r--arch/arm/boot/dts/meson8m2.dtsi54
-rw-r--r--arch/arm/boot/dts/mt2701-evb.dts9
-rw-r--r--arch/arm/boot/dts/mt2701.dtsi197
-rw-r--r--arch/arm/boot/dts/mt6323.dtsi17
-rw-r--r--arch/arm/boot/dts/mt6580-evbp1.dts9
-rw-r--r--arch/arm/boot/dts/mt6580.dtsi9
-rw-r--r--arch/arm/boot/dts/mt6589-aquaris5.dts10
-rw-r--r--arch/arm/boot/dts/mt6589.dtsi12
-rw-r--r--arch/arm/boot/dts/mt6592-evb.dts9
-rw-r--r--arch/arm/boot/dts/mt6592.dtsi9
-rw-r--r--arch/arm/boot/dts/mt7623.dtsi537
-rw-r--r--arch/arm/boot/dts/mt7623a-rfb-emmc.dts291
-rw-r--r--arch/arm/boot/dts/mt7623a-rfb-nand.dts337
-rw-r--r--arch/arm/boot/dts/mt7623a.dtsi44
-rw-r--r--arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts279
-rw-r--r--arch/arm/boot/dts/mt7623n-rfb-emmc.dts326
-rw-r--r--arch/arm/boot/dts/mt7623n-rfb-nand.dts40
-rw-r--r--arch/arm/boot/dts/mt7623n-rfb.dtsi12
-rw-r--r--arch/arm/boot/dts/mt8127-moose.dts9
-rw-r--r--arch/arm/boot/dts/mt8127.dtsi9
-rw-r--r--arch/arm/boot/dts/mt8135-evbp1.dts9
-rw-r--r--arch/arm/boot/dts/mt8135.dtsi9
-rw-r--r--arch/arm/boot/dts/omap2420-n810.dts63
-rw-r--r--arch/arm/boot/dts/omap3-beagle-xm.dts10
-rw-r--r--arch/arm/boot/dts/omap3-cm-t3x.dtsi2
-rw-r--r--arch/arm/boot/dts/omap3-devkit8000-common.dtsi9
-rw-r--r--arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi5
-rw-r--r--arch/arm/boot/dts/omap3-gta04.dtsi10
-rw-r--r--arch/arm/boot/dts/omap3-pandora-common.dtsi12
-rw-r--r--arch/arm/boot/dts/omap3-sb-t35.dtsi2
-rw-r--r--arch/arm/boot/dts/pxa3xx.dtsi20
-rw-r--r--arch/arm/boot/dts/qcom-apq8064.dtsi58
-rw-r--r--arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts19
-rw-r--r--arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c3.dts9
-rw-r--r--arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi111
-rw-r--r--arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c1.dts64
-rw-r--r--arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c2.dts25
-rw-r--r--arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi75
-rw-r--r--arch/arm/boot/dts/qcom-ipq4019.dtsi178
-rw-r--r--arch/arm/boot/dts/qcom-msm8660.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom-msm8974-sony-xperia-amami.dts436
-rw-r--r--arch/arm/boot/dts/qcom-pm8941.dtsi6
-rw-r--r--arch/arm/boot/dts/r7s72100.dtsi1038
-rw-r--r--arch/arm/boot/dts/r8a73a4-ape6evm.dts4
-rw-r--r--arch/arm/boot/dts/r8a73a4.dtsi10
-rw-r--r--arch/arm/boot/dts/r8a7740.dtsi18
-rw-r--r--arch/arm/boot/dts/r8a7743-iwg20m.dtsi5
-rw-r--r--arch/arm/boot/dts/r8a7743.dtsi19
-rw-r--r--arch/arm/boot/dts/r8a7745-iwg22m.dtsi5
-rw-r--r--arch/arm/boot/dts/r8a7745.dtsi19
-rw-r--r--arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts48
-rw-r--r--arch/arm/boot/dts/r8a77470.dtsi336
-rw-r--r--arch/arm/boot/dts/r8a7790-lager.dts8
-rw-r--r--arch/arm/boot/dts/r8a7790.dtsi67
-rw-r--r--arch/arm/boot/dts/r8a7791-koelsch.dts11
-rw-r--r--arch/arm/boot/dts/r8a7791-porter.dts8
-rw-r--r--arch/arm/boot/dts/r8a7791.dtsi37
-rw-r--r--arch/arm/boot/dts/r8a7792-blanche.dts5
-rw-r--r--arch/arm/boot/dts/r8a7792-wheat.dts16
-rw-r--r--arch/arm/boot/dts/r8a7792.dtsi19
-rw-r--r--arch/arm/boot/dts/r8a7793-gose.dts11
-rw-r--r--arch/arm/boot/dts/r8a7793.dtsi37
-rw-r--r--arch/arm/boot/dts/r8a7794-alt.dts14
-rw-r--r--arch/arm/boot/dts/r8a7794-silk.dts8
-rw-r--r--arch/arm/boot/dts/r8a7794.dtsi28
-rw-r--r--arch/arm/boot/dts/rk3036.dtsi2
-rw-r--r--arch/arm/boot/dts/rk322x.dtsi8
-rw-r--r--arch/arm/boot/dts/rk3288-phycore-som.dtsi1
-rw-r--r--arch/arm/boot/dts/rk3288-tinker.dts4
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi3
-rw-r--r--arch/arm/boot/dts/rk3288-veyron-minnie.dts2
-rw-r--r--arch/arm/boot/dts/rk3288.dtsi20
-rw-r--r--arch/arm/boot/dts/s3c2416-smdk2416.dts5
-rw-r--r--arch/arm/boot/dts/s3c2416.dtsi11
-rw-r--r--arch/arm/boot/dts/s3c24xx.dtsi4
-rw-r--r--arch/arm/boot/dts/s3c6410-mini6410.dts3
-rw-r--r--arch/arm/boot/dts/s3c6410-smdk6410.dts3
-rw-r--r--arch/arm/boot/dts/s3c64xx.dtsi4
-rw-r--r--arch/arm/boot/dts/sh73a0.dtsi9
-rw-r--r--arch/arm/boot/dts/ste-ccu8540-pinctrl.dtsi196
-rw-r--r--arch/arm/boot/dts/ste-ccu8540.dts94
-rw-r--r--arch/arm/boot/dts/ste-ccu9540.dts79
-rw-r--r--arch/arm/boot/dts/ste-snowball.dts10
-rw-r--r--arch/arm/boot/dts/stih407-family.dtsi52
-rw-r--r--arch/arm/boot/dts/stih407-pinctrl.dtsi10
-rw-r--r--arch/arm/boot/dts/stih407.dtsi2
-rw-r--r--arch/arm/boot/dts/stih410.dtsi18
-rw-r--r--arch/arm/boot/dts/stihxxx-b2120.dtsi4
-rw-r--r--arch/arm/boot/dts/stm32f469-disco.dts53
-rw-r--r--arch/arm/boot/dts/stm32f469.dtsi19
-rw-r--r--arch/arm/boot/dts/stm32f746-disco.dts8
-rw-r--r--arch/arm/boot/dts/stm32f746.dtsi36
-rw-r--r--arch/arm/boot/dts/stm32f769-disco.dts8
-rw-r--r--arch/arm/boot/dts/stm32h743-pinctrl.dtsi10
-rw-r--r--arch/arm/boot/dts/stm32h743.dtsi53
-rw-r--r--arch/arm/boot/dts/stm32h743i-eval.dts8
-rw-r--r--arch/arm/boot/dts/stm32mp157-pinctrl.dtsi151
-rw-r--r--arch/arm/boot/dts/stm32mp157c-ed1.dts57
-rw-r--r--arch/arm/boot/dts/stm32mp157c-ev1.dts87
-rw-r--r--arch/arm/boot/dts/stm32mp157c.dtsi720
-rw-r--r--arch/arm/boot/dts/sun7i-a20-olimex-som-evb-emmc.dts37
-rw-r--r--arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts3
-rw-r--r--arch/arm/boot/dts/sun8i-a23-a33.dtsi33
-rw-r--r--arch/arm/boot/dts/sun8i-a33.dtsi44
-rw-r--r--arch/arm/boot/dts/sun8i-a83t.dtsi64
-rw-r--r--arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts13
-rw-r--r--arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts21
-rw-r--r--arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts206
-rw-r--r--arch/arm/boot/dts/sun8i-h3-orangepi-one.dts21
-rw-r--r--arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts28
-rw-r--r--arch/arm/boot/dts/sun8i-h3.dtsi32
-rw-r--r--arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts56
-rw-r--r--arch/arm/boot/dts/sun8i-r16-nintendo-super-nes-classic.dts11
-rw-r--r--arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts99
-rw-r--r--arch/arm/boot/dts/sun8i-r40.dtsi34
-rw-r--r--arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts10
-rw-r--r--arch/arm/boot/dts/sunxi-h3-h5.dtsi18
-rw-r--r--arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi215
-rw-r--r--arch/arm/boot/dts/tegra114.dtsi5
-rw-r--r--arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi6
-rw-r--r--arch/arm/boot/dts/tegra124-apalis.dtsi6
-rw-r--r--arch/arm/boot/dts/tegra30.dtsi14
-rw-r--r--arch/arm/boot/dts/uniphier-pro4.dtsi10
-rw-r--r--arch/arm/boot/dts/uniphier-pxs2.dtsi3
-rw-r--r--arch/arm/boot/dts/vexpress-v2m-rs1.dtsi712
-rw-r--r--arch/arm/boot/dts/vexpress-v2m.dtsi710
-rw-r--r--arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts3
-rw-r--r--arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts9
-rw-r--r--arch/arm/boot/dts/vexpress-v2p-ca5s.dts5
-rw-r--r--arch/arm/boot/dts/vexpress-v2p-ca9.dts5
-rw-r--r--arch/arm/boot/dts/vf-colibri-eval-v3.dtsi2
-rw-r--r--arch/arm/boot/dts/vf610-zii-dev-rev-b.dts6
-rw-r--r--arch/arm/boot/dts/vf610-zii-dev-rev-c.dts4
-rw-r--r--arch/arm/boot/dts/vf610-zii-dev.dtsi4
-rw-r--r--arch/arm/boot/dts/vfxxx.dtsi2
-rw-r--r--arch/arm/common/Makefile1
-rw-r--r--arch/arm/common/secure_cntvoff.S32
-rw-r--r--arch/arm/configs/bcm2835_defconfig2
-rw-r--r--arch/arm/configs/davinci_all_defconfig4
-rw-r--r--arch/arm/configs/exynos_defconfig1
-rw-r--r--arch/arm/configs/imx_v6_v7_defconfig9
-rw-r--r--arch/arm/configs/multi_v7_defconfig12
-rw-r--r--arch/arm/configs/shmobile_defconfig3
-rw-r--r--arch/arm/include/asm/cacheflush.h2
-rw-r--r--arch/arm/include/asm/cputype.h14
-rw-r--r--arch/arm/include/asm/kvm_host.h14
-rw-r--r--arch/arm/include/asm/secure_cntvoff.h8
-rw-r--r--arch/arm/include/debug/brcmstb.S21
-rw-r--r--arch/arm/include/uapi/asm/kvm.h1
-rw-r--r--arch/arm/kernel/asm-offsets.c2
-rw-r--r--arch/arm/kernel/entry-armv.S4
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--arch/arm/kernel/signal.c4
-rw-r--r--arch/arm/kernel/sys_oabi-compat.c4
-rw-r--r--arch/arm/kvm/hyp/Makefile8
-rw-r--r--arch/arm/mach-berlin/Kconfig6
-rw-r--r--arch/arm/mach-berlin/berlin.c5
-rw-r--r--arch/arm/mach-berlin/headsmp.S5
-rw-r--r--arch/arm/mach-berlin/platsmp.c6
-rw-r--r--arch/arm/mach-davinci/aemif.c8
-rw-r--r--arch/arm/mach-davinci/board-da830-evm.c1
-rw-r--r--arch/arm/mach-davinci/board-da850-evm.c1
-rw-r--r--arch/arm/mach-davinci/board-dm355-evm.c1
-rw-r--r--arch/arm/mach-davinci/board-dm355-leopard.c1
-rw-r--r--arch/arm/mach-davinci/board-dm365-evm.c1
-rw-r--r--arch/arm/mach-davinci/board-dm644x-evm.c3
-rw-r--r--arch/arm/mach-davinci/board-dm646x-evm.c1
-rw-r--r--arch/arm/mach-davinci/board-mityomapl138.c1
-rw-r--r--arch/arm/mach-davinci/board-neuros-osd2.c3
-rw-r--r--arch/arm/mach-davinci/board-sffsdr.c2
-rw-r--r--arch/arm/mach-davinci/davinci.h1
-rw-r--r--arch/arm/mach-davinci/dm644x.c13
-rw-r--r--arch/arm/mach-exynos/Kconfig12
-rw-r--r--arch/arm/mach-exynos/common.h17
-rw-r--r--arch/arm/mach-exynos/exynos.c37
-rw-r--r--arch/arm/mach-exynos/include/mach/map.h2
-rw-r--r--arch/arm/mach-exynos/platsmp.c27
-rw-r--r--arch/arm/mach-exynos/pm.c4
-rw-r--r--arch/arm/mach-exynos/suspend.c4
-rw-r--r--arch/arm/mach-footbridge/dc21285.c2
-rw-r--r--arch/arm/mach-imx/Kconfig1
-rw-r--r--arch/arm/mach-imx/mach-mx31_3ds.c18
-rw-r--r--arch/arm/mach-imx/mach-mx31lilly.c12
-rw-r--r--arch/arm/mach-imx/mach-mx31lite.c16
-rw-r--r--arch/arm/mach-imx/mach-mx31moboard.c17
-rw-r--r--arch/arm/mach-imx/mach-pca100.c13
-rw-r--r--arch/arm/mach-imx/mach-pcm037.c13
-rw-r--r--arch/arm/mach-imx/mach-pcm037_eet.c5
-rw-r--r--arch/arm/mach-imx/mach-pcm043.c13
-rw-r--r--arch/arm/mach-imx/mach-vpr200.c9
-rw-r--r--arch/arm/mach-ixp4xx/common-pci.c2
-rw-r--r--arch/arm/mach-ks8695/board-acs5k.c2
-rw-r--r--arch/arm/mach-meson/Kconfig9
-rw-r--r--arch/arm/mach-meson/meson.c1
-rw-r--r--arch/arm/mach-omap1/board-ams-delta.c107
-rw-r--r--arch/arm/mach-omap1/board-htcherald.c2
-rw-r--r--arch/arm/mach-omap1/board-osk.c10
-rw-r--r--arch/arm/mach-omap1/common.h2
-rw-r--r--arch/arm/mach-omap1/i2c.c2
-rw-r--r--arch/arm/mach-omap1/mcbsp.c2
-rw-r--r--arch/arm/mach-omap2/Makefile1
-rw-r--r--arch/arm/mach-omap2/board-generic.c2
-rw-r--r--arch/arm/mach-omap2/clockdomain.c73
-rw-r--r--arch/arm/mach-omap2/clockdomain.h8
-rw-r--r--arch/arm/mach-omap2/cm33xx.c53
-rw-r--r--arch/arm/mach-omap2/cminst44xx.c43
-rw-r--r--arch/arm/mach-omap2/common.h20
-rw-r--r--arch/arm/mach-omap2/control.c112
-rw-r--r--arch/arm/mach-omap2/control.h61
-rw-r--r--arch/arm/mach-omap2/display.c10
-rw-r--r--arch/arm/mach-omap2/hsmmc.c3
-rw-r--r--arch/arm/mach-omap2/i2c.c1
-rw-r--r--arch/arm/mach-omap2/io.c70
-rw-r--r--arch/arm/mach-omap2/omap-pm-noop.c176
-rw-r--r--arch/arm/mach-omap2/omap-pm.h161
-rw-r--r--arch/arm/mach-omap2/omap_device.c26
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.c21
-rw-r--r--arch/arm/mach-omap2/omap_hwmod.h6
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2420_data.c2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_2430_data.c2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c1
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_33xx_data.c2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c6
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_43xx_data.c1
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_44xx_data.c6
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_54xx_data.c5
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_7xx_data.c8
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_81xx_data.c1
-rw-r--r--arch/arm/mach-omap2/pdata-quirks.c15
-rw-r--r--arch/arm/mach-omap2/pm-debug.c5
-rw-r--r--arch/arm/mach-omap2/pm.c21
-rw-r--r--arch/arm/mach-omap2/pm33xx-core.c4
-rw-r--r--arch/arm/mach-omap2/pm44xx.c13
-rw-r--r--arch/arm/mach-omap2/powerdomain.c87
-rw-r--r--arch/arm/mach-omap2/powerdomain.h7
-rw-r--r--arch/arm/mach-omap2/prm33xx.c31
-rw-r--r--arch/arm/mach-omap2/prm44xx.c104
-rw-r--r--arch/arm/mach-omap2/prm_common.c9
-rw-r--r--arch/arm/mach-omap2/timer.c100
-rw-r--r--arch/arm/mach-pxa/palmz72.c2
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c4
-rw-r--r--arch/arm/mach-pxa/stargate2.c10
-rw-r--r--arch/arm/mach-pxa/viper.c2
-rw-r--r--arch/arm/mach-s3c24xx/h1940-bluetooth.c2
-rw-r--r--arch/arm/mach-s3c24xx/mach-mini2440.c10
-rw-r--r--arch/arm/mach-sa1100/simpad.c2
-rw-r--r--arch/arm/mach-shmobile/Kconfig13
-rw-r--r--arch/arm/mach-shmobile/common.h1
-rw-r--r--arch/arm/mach-shmobile/headsmp-apmu.S22
-rw-r--r--arch/arm/mach-shmobile/setup-rcar-gen2.c5
-rw-r--r--arch/arm/mach-sunxi/Kconfig2
-rw-r--r--arch/arm/mach-sunxi/Makefile2
-rw-r--r--arch/arm/mach-sunxi/headsmp.S81
-rw-r--r--arch/arm/mach-sunxi/mc_smp.c239
-rw-r--r--arch/arm/mach-sunxi/sunxi.c20
-rw-r--r--arch/arm/mach-tegra/tegra.c4
-rw-r--r--arch/arm/mach-ux500/Kconfig53
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c16
-rw-r--r--arch/arm/mach-ux500/db8500-regs.h4
-rw-r--r--arch/arm/mach-vexpress/spc.c2
-rw-r--r--arch/arm/mm/cache-b15-rac.c30
-rw-r--r--arch/arm/mm/dma-mapping.c4
-rw-r--r--arch/arm/mm/pgd.c2
-rw-r--r--arch/arm/plat-omap/Kconfig10
-rw-r--r--arch/arm/plat-samsung/adc.c3
-rw-r--r--arch/arm/plat-samsung/include/plat/map-s5p.h4
-rw-r--r--arch/arm/probes/kprobes/test-core.c5
-rw-r--r--arch/arm/vdso/Makefile3
-rw-r--r--arch/arm/xen/enlighten.c7
-rw-r--r--arch/arm64/Kconfig10
-rw-r--r--arch/arm64/Kconfig.platforms6
-rw-r--r--arch/arm64/Makefile6
-rw-r--r--arch/arm64/boot/dts/Makefile1
-rw-r--r--arch/arm64/boot/dts/allwinner/Makefile5
-rw-r--r--arch/arm64/boot/dts/allwinner/axp803.dtsi5
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts21
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts14
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi2
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts10
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi70
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-axg-s400.dts106
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-axg.dtsi453
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi12
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl.dtsi16
-rw-r--r--arch/arm64/boot/dts/arm/juno-base.dtsi15
-rw-r--r--arch/arm64/boot/dts/arm/juno-motherboard.dtsi18
-rw-r--r--arch/arm64/boot/dts/arm/juno-r1.dts8
-rw-r--r--arch/arm64/boot/dts/arm/juno-r2.dts8
-rw-r--r--arch/arm64/boot/dts/arm/juno.dts4
-rw-r--r--arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts4
-rw-r--r--arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi453
-rw-r--r--arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts5
-rw-r--r--arch/arm64/boot/dts/broadcom/Makefile3
-rw-r--r--arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dts2
-rw-r--r--arch/arm64/boot/dts/exynos/exynos5433.dtsi80
-rw-r--r--arch/arm64/boot/dts/exynos/exynos7.dtsi18
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi10
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi2
-rw-r--r--arch/arm64/boot/dts/hisilicon/hi3660.dtsi147
-rw-r--r--arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts38
-rw-r--r--arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi205
-rw-r--r--arch/arm64/boot/dts/hisilicon/hip06-d03.dts8
-rw-r--r--arch/arm64/boot/dts/hisilicon/hip06.dtsi21
-rw-r--r--arch/arm64/boot/dts/hisilicon/hip07-d05.dts4
-rw-r--r--arch/arm64/boot/dts/hisilicon/hip07.dtsi14
-rw-r--r--arch/arm64/boot/dts/hisilicon/poplar-pinctrl.dtsi98
-rw-r--r--arch/arm64/boot/dts/marvell/Makefile4
-rw-r--r--arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts27
-rw-r--r--arch/arm64/boot/dts/marvell/armada-37xx.dtsi6
-rw-r--r--arch/arm64/boot/dts/marvell/armada-7040-db.dts5
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-db.dts10
-rw-r--r--arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts70
-rw-r--r--arch/arm64/boot/dts/marvell/armada-cp110.dtsi1
-rw-r--r--arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts66
-rw-r--r--arch/arm64/boot/dts/marvell/berlin4ct-stb.dts66
-rw-r--r--arch/arm64/boot/dts/mediatek/mt2712-pinfunc.h1123
-rw-r--r--arch/arm64/boot/dts/mediatek/mt2712e.dtsi46
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts11
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7622.dtsi99
-rw-r--r--arch/arm64/boot/dts/qcom/Makefile1
-rw-r--r--arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi32
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074-hk01.dts62
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074.dtsi313
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916.dtsi18
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts17
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992-pins.dtsi60
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992.dtsi87
-rw-r--r--arch/arm64/boot/dts/qcom/msm8994-smd-rpm.dtsi276
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996.dtsi110
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-mtp.dts15
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845.dtsi327
-rw-r--r--arch/arm64/boot/dts/renesas/Makefile3
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts46
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi144
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts46
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts85
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7795.dtsi2345
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts28
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts28
-rw-r--r--arch/arm64/boot/dts/renesas/r8a7796.dtsi2211
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts28
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts28
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77965.dtsi1465
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970-eagle.dts116
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts137
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77970.dtsi661
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77980-condor.dts81
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts60
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77980.dtsi99
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts65
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77990.dtsi281
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77995-draak.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r8a77995.dtsi722
-rw-r--r--arch/arm64/boot/dts/renesas/salvator-common.dtsi187
-rw-r--r--arch/arm64/boot/dts/renesas/ulcb.dtsi37
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328.dtsi10
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3368.dtsi10
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-firefly.dts8
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi8
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts25
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi4
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts12
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi23
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399.dtsi36
-rw-r--r--arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi5
-rw-r--r--arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi3
-rw-r--r--arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi8
-rw-r--r--arch/arm64/boot/dts/sprd/sc2731.dtsi11
-rw-r--r--arch/arm64/boot/dts/sprd/sc9860.dtsi32
-rw-r--r--arch/arm64/boot/dts/sprd/whale2.dtsi55
-rw-r--r--arch/arm64/boot/dts/synaptics/Makefile4
-rw-r--r--arch/arm64/boot/dts/synaptics/berlin4ct-dmp.dts29
-rw-r--r--arch/arm64/boot/dts/synaptics/berlin4ct-stb.dts29
-rw-r--r--arch/arm64/boot/dts/synaptics/berlin4ct.dtsi (renamed from arch/arm64/boot/dts/marvell/berlin4ct.dtsi)39
-rw-r--r--arch/arm64/configs/defconfig43
-rw-r--r--arch/arm64/crypto/aes-glue.c2
-rw-r--r--arch/arm64/include/asm/cacheflush.h2
-rw-r--r--arch/arm64/include/asm/cpufeature.h29
-rw-r--r--arch/arm64/include/asm/fpsimd.h21
-rw-r--r--arch/arm64/include/asm/kvm_asm.h8
-rw-r--r--arch/arm64/include/asm/kvm_host.h50
-rw-r--r--arch/arm64/include/asm/processor.h15
-rw-r--r--arch/arm64/include/asm/sysreg.h11
-rw-r--r--arch/arm64/include/asm/thread_info.h13
-rw-r--r--arch/arm64/include/uapi/asm/kvm.h1
-rw-r--r--arch/arm64/kernel/armv8_deprecated.c4
-rw-r--r--arch/arm64/kernel/cpufeature.c2
-rw-r--r--arch/arm64/kernel/fpsimd.c177
-rw-r--r--arch/arm64/kernel/process.c2
-rw-r--r--arch/arm64/kernel/ptrace.c1
-rw-r--r--arch/arm64/kernel/smp.c2
-rw-r--r--arch/arm64/kvm/Kconfig1
-rw-r--r--arch/arm64/kvm/Makefile2
-rw-r--r--arch/arm64/kvm/debug.c8
-rw-r--r--arch/arm64/kvm/fpsimd.c128
-rw-r--r--arch/arm64/kvm/hyp/debug-sr.c6
-rw-r--r--arch/arm64/kvm/hyp/entry.S43
-rw-r--r--arch/arm64/kvm/hyp/hyp-entry.S19
-rw-r--r--arch/arm64/kvm/hyp/switch.c124
-rw-r--r--arch/arm64/kvm/hyp/sysreg-sr.c4
-rw-r--r--arch/arm64/kvm/sys_regs.c9
-rw-r--r--arch/arm64/mm/context.c2
-rw-r--r--arch/arm64/mm/dma-mapping.c9
-rw-r--r--arch/arm64/mm/init.c6
-rw-r--r--arch/arm64/mm/proc.S5
-rw-r--r--arch/hexagon/include/asm/pgtable.h1
-rw-r--r--arch/hexagon/kernel/setup.c2
-rw-r--r--arch/hexagon/mm/init.c3
-rw-r--r--arch/ia64/Kconfig1
-rw-r--r--arch/ia64/kernel/mca_drv.c3
-rw-r--r--arch/ia64/kernel/topology.c6
-rw-r--r--arch/ia64/mm/tlb.c5
-rw-r--r--arch/ia64/sn/kernel/io_common.c2
-rw-r--r--arch/ia64/sn/kernel/irq.c3
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c2
-rw-r--r--arch/microblaze/include/asm/cacheflush.h2
-rw-r--r--arch/mips/Kconfig8
-rw-r--r--arch/mips/alchemy/board-gpr.c2
-rw-r--r--arch/mips/alchemy/common/clock.c2
-rw-r--r--arch/mips/alchemy/common/dbdma.c6
-rw-r--r--arch/mips/alchemy/common/platform.c4
-rw-r--r--arch/mips/alchemy/devboards/platform.c4
-rw-r--r--arch/mips/ath79/mach-pb44.c2
-rw-r--r--arch/mips/bcm47xx/board.c2
-rw-r--r--arch/mips/bcm47xx/buttons.c9
-rw-r--r--arch/mips/bcm47xx/leds.c11
-rw-r--r--arch/mips/bcm47xx/setup.c6
-rw-r--r--arch/mips/bmips/dma.c2
-rw-r--r--arch/mips/boot/compressed/Makefile11
-rw-r--r--arch/mips/boot/dts/brcm/Makefile2
-rw-r--r--arch/mips/boot/dts/cavium-octeon/Makefile2
-rw-r--r--arch/mips/boot/dts/ingenic/Makefile2
-rw-r--r--arch/mips/boot/dts/ingenic/jz4740.dtsi8
-rw-r--r--arch/mips/boot/dts/ingenic/jz4780.dtsi5
-rw-r--r--arch/mips/boot/dts/lantiq/Makefile2
-rw-r--r--arch/mips/boot/dts/mscc/Makefile2
-rw-r--r--arch/mips/boot/dts/mscc/ocelot.dtsi88
-rw-r--r--arch/mips/boot/dts/mscc/ocelot_pcb123.dts20
-rw-r--r--arch/mips/boot/dts/mti/Makefile2
-rw-r--r--arch/mips/boot/dts/netlogic/Makefile2
-rw-r--r--arch/mips/boot/dts/pic32/Makefile2
-rw-r--r--arch/mips/boot/dts/ralink/Makefile2
-rw-r--r--arch/mips/configs/qi_lb60_defconfig2
-rw-r--r--arch/mips/dec/time.c12
-rw-r--r--arch/mips/include/asm/cpu-features.h7
-rw-r--r--arch/mips/include/asm/cpu.h2
-rw-r--r--arch/mips/include/asm/io.h2
-rw-r--r--arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h1
-rw-r--r--arch/mips/include/asm/mach-jz4740/platform.h1
-rw-r--r--arch/mips/include/asm/mc146818-time.h4
-rw-r--r--arch/mips/include/asm/mipsregs.h8
-rw-r--r--arch/mips/include/asm/time.h9
-rw-r--r--arch/mips/include/uapi/asm/unistd.h18
-rw-r--r--arch/mips/jz4740/platform.c16
-rw-r--r--arch/mips/jz4740/reset.c31
-rw-r--r--arch/mips/kernel/asm-offsets.c2
-rw-r--r--arch/mips/kernel/cpu-probe.c12
-rw-r--r--arch/mips/kernel/entry.S8
-rw-r--r--arch/mips/kernel/mcount.S27
-rw-r--r--arch/mips/kernel/octeon_switch.S2
-rw-r--r--arch/mips/kernel/perf_event_mipsxx.c91
-rw-r--r--arch/mips/kernel/process.c2
-rw-r--r--arch/mips/kernel/ptrace.c4
-rw-r--r--arch/mips/kernel/ptrace32.c4
-rw-r--r--arch/mips/kernel/r2300_switch.S2
-rw-r--r--arch/mips/kernel/r4k_switch.S2
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/mips/kernel/setup.c4
-rw-r--r--arch/mips/kernel/signal.c3
-rw-r--r--arch/mips/kernel/time.c15
-rw-r--r--arch/mips/kernel/vpe.c2
-rw-r--r--arch/mips/kvm/mips.c2
-rw-r--r--arch/mips/lasat/ds1603.c11
-rw-r--r--arch/mips/lasat/sysctl.c12
-rw-r--r--arch/mips/lib/Makefile3
-rw-r--r--arch/mips/lib/ashldi3.c30
-rw-r--r--arch/mips/lib/ashrdi3.c32
-rw-r--r--arch/mips/lib/cmpdi2.c28
-rw-r--r--arch/mips/lib/lshrdi3.c30
-rw-r--r--arch/mips/lib/memset.S28
-rw-r--r--arch/mips/lib/ucmpdi2.c22
-rw-r--r--arch/mips/loongson64/common/time.c2
-rw-r--r--arch/mips/mm/sc-debugfs.c9
-rw-r--r--arch/mips/mti-malta/malta-time.c2
-rw-r--r--arch/mips/oprofile/op_model_mipsxx.c2
-rw-r--r--arch/mips/sibyte/swarm/rtc_m41t81.c8
-rw-r--r--arch/mips/sibyte/swarm/rtc_xicor1241.c8
-rw-r--r--arch/mips/sibyte/swarm/setup.c18
-rw-r--r--arch/mips/sni/time.c6
-rw-r--r--arch/mips/txx9/rbtx4939/setup.c2
-rw-r--r--arch/parisc/Kconfig2
-rw-r--r--arch/powerpc/Kconfig18
-rw-r--r--arch/powerpc/Makefile14
-rw-r--r--arch/powerpc/include/asm/asm-prototypes.h6
-rw-r--r--arch/powerpc/include/asm/book3s/32/pgalloc.h1
-rw-r--r--arch/powerpc/include/asm/book3s/64/pgtable-4k.h21
-rw-r--r--arch/powerpc/include/asm/book3s/64/pgtable-64k.h9
-rw-r--r--arch/powerpc/include/asm/book3s/64/pgtable.h5
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h37
-rw-r--r--arch/powerpc/include/asm/kvm_book3s_64.h20
-rw-r--r--arch/powerpc/include/asm/kvm_booke.h20
-rw-r--r--arch/powerpc/include/asm/kvm_host.h21
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h17
-rw-r--r--arch/powerpc/include/asm/module.h2
-rw-r--r--arch/powerpc/include/asm/nmi.h2
-rw-r--r--arch/powerpc/include/asm/nohash/32/pgalloc.h1
-rw-r--r--arch/powerpc/include/asm/nohash/64/pgalloc.h1
-rw-r--r--arch/powerpc/include/asm/reg.h1
-rw-r--r--arch/powerpc/include/uapi/asm/kvm.h1
-rw-r--r--arch/powerpc/kernel/asm-offsets.c18
-rw-r--r--arch/powerpc/kernel/dt_cpu_ftrs.c3
-rw-r--r--arch/powerpc/kernel/module_64.c4
-rw-r--r--arch/powerpc/kernel/rtasd.c3
-rw-r--r--arch/powerpc/kernel/setup-common.c12
-rw-r--r--arch/powerpc/kernel/setup_64.c8
-rw-r--r--arch/powerpc/kernel/signal.c4
-rw-r--r--arch/powerpc/kernel/smp.c6
-rw-r--r--arch/powerpc/kernel/stacktrace.c4
-rw-r--r--arch/powerpc/kernel/trace/ftrace.c6
-rw-r--r--arch/powerpc/kernel/vdso.c4
-rw-r--r--arch/powerpc/kvm/Makefile3
-rw-r--r--arch/powerpc/kvm/book3s.c23
-rw-r--r--arch/powerpc/kvm/book3s.h6
-rw-r--r--arch/powerpc/kvm/book3s_32_mmu.c2
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu.c11
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_hv.c5
-rw-r--r--arch/powerpc/kvm/book3s_64_mmu_radix.c348
-rw-r--r--arch/powerpc/kvm/book3s_64_vio.c71
-rw-r--r--arch/powerpc/kvm/book3s_64_vio_hv.c54
-rw-r--r--arch/powerpc/kvm/book3s_emulate.c371
-rw-r--r--arch/powerpc/kvm/book3s_hv.c102
-rw-r--r--arch/powerpc/kvm/book3s_hv_builtin.c21
-rw-r--r--arch/powerpc/kvm/book3s_hv_interrupts.S2
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_mmu.c36
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_xics.c2
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S318
-rw-r--r--arch/powerpc/kvm/book3s_hv_tm.c10
-rw-r--r--arch/powerpc/kvm/book3s_hv_tm_builtin.c10
-rw-r--r--arch/powerpc/kvm/book3s_pr.c482
-rw-r--r--arch/powerpc/kvm/book3s_segment.S13
-rw-r--r--arch/powerpc/kvm/book3s_xive_template.c4
-rw-r--r--arch/powerpc/kvm/booke.c41
-rw-r--r--arch/powerpc/kvm/booke_emulate.c6
-rw-r--r--arch/powerpc/kvm/e500_emulate.c6
-rw-r--r--arch/powerpc/kvm/e500_mmu.c2
-rw-r--r--arch/powerpc/kvm/e500_mmu_host.c8
-rw-r--r--arch/powerpc/kvm/emulate_loadstore.c752
-rw-r--r--arch/powerpc/kvm/powerpc.c313
-rw-r--r--arch/powerpc/kvm/tm.S384
-rw-r--r--arch/powerpc/lib/rheap.c2
-rw-r--r--arch/powerpc/mm/hugetlbpage.c3
-rw-r--r--arch/powerpc/mm/mem.c2
-rw-r--r--arch/powerpc/mm/mmu_context_iommu.c2
-rw-r--r--arch/powerpc/mm/numa.c2
-rw-r--r--arch/powerpc/mm/pgtable-book3s64.c12
-rw-r--r--arch/powerpc/mm/tlb-radix.c98
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c2
-rw-r--r--arch/powerpc/net/bpf_jit_comp64.c2
-rw-r--r--arch/powerpc/oprofile/cell/spu_profiler.c4
-rw-r--r--arch/powerpc/platforms/4xx/hsta_msi.c3
-rw-r--r--arch/powerpc/platforms/4xx/msi.c2
-rw-r--r--arch/powerpc/platforms/4xx/pci.c2
-rw-r--r--arch/powerpc/platforms/powernv/opal-sysparam.c8
-rw-r--r--arch/powerpc/sysdev/mpic.c9
-rw-r--r--arch/powerpc/sysdev/xive/native.c2
-rwxr-xr-xarch/powerpc/tools/gcc-check-mprofile-kernel.sh1
-rw-r--r--arch/riscv/Kconfig20
-rw-r--r--arch/riscv/Makefile3
-rw-r--r--arch/riscv/configs/defconfig1
-rw-r--r--arch/riscv/include/asm/Kbuild1
-rw-r--r--arch/riscv/include/asm/cacheflush.h2
-rw-r--r--arch/riscv/include/asm/perf_event.h84
-rw-r--r--arch/riscv/include/asm/tlbflush.h2
-rw-r--r--arch/riscv/include/asm/uaccess.h8
-rw-r--r--arch/riscv/kernel/Makefile2
-rw-r--r--arch/riscv/kernel/mcount.S2
-rw-r--r--arch/riscv/kernel/module.c12
-rw-r--r--arch/riscv/kernel/perf_event.c485
-rw-r--r--arch/riscv/kernel/riscv_ksyms.c3
-rw-r--r--arch/riscv/kernel/traps.c2
-rw-r--r--arch/riscv/lib/uaccess.S19
-rw-r--r--arch/s390/appldata/appldata_base.c2
-rw-r--r--arch/s390/hypfs/hypfs_diag.c2
-rw-r--r--arch/s390/hypfs/hypfs_diag0c.c3
-rw-r--r--arch/s390/include/asm/css_chars.h62
-rw-r--r--arch/s390/include/asm/ctl_reg.h12
-rw-r--r--arch/s390/include/asm/kvm_host.h1
-rw-r--r--arch/s390/include/asm/mmu.h2
-rw-r--r--arch/s390/include/asm/mmu_context.h2
-rw-r--r--arch/s390/include/asm/pgtable.h4
-rw-r--r--arch/s390/kernel/debug.c6
-rw-r--r--arch/s390/kernel/module.c4
-rw-r--r--arch/s390/kernel/perf_cpum_cf_events.c2
-rw-r--r--arch/s390/kernel/sthyi.c2
-rw-r--r--arch/s390/kernel/vdso.c4
-rw-r--r--arch/s390/kvm/gaccess.c2
-rw-r--r--arch/s390/kvm/guestdbg.c2
-rw-r--r--arch/s390/kvm/interrupt.c20
-rw-r--r--arch/s390/kvm/kvm-s390.c63
-rw-r--r--arch/s390/kvm/kvm-s390.h13
-rw-r--r--arch/s390/kvm/priv.c28
-rw-r--r--arch/s390/kvm/vsie.c10
-rw-r--r--arch/s390/mm/extmem.c2
-rw-r--r--arch/s390/mm/gmap.c6
-rw-r--r--arch/s390/mm/pgtable.c4
-rw-r--r--arch/sh/Kconfig4
-rw-r--r--arch/sh/boards/board-sh7785lcr.c2
-rw-r--r--arch/sh/drivers/dma/dmabrg.c2
-rw-r--r--arch/sh/drivers/pci/pcie-sh7786.c2
-rw-r--r--arch/sh/include/asm/vmlinux.lds.h4
-rw-r--r--arch/sh/kernel/process.c2
-rw-r--r--arch/sh/kernel/process_32.c2
-rw-r--r--arch/sparc/Kconfig2
-rw-r--r--arch/sparc/kernel/nmi.c3
-rw-r--r--arch/sparc/kernel/sys_sparc_64.c8
-rw-r--r--arch/sparc/mm/init_64.c2
-rw-r--r--arch/sparc/net/bpf_jit_comp_32.c2
-rw-r--r--arch/um/Kconfig.um2
-rw-r--r--arch/um/drivers/ubd_kern.c12
-rw-r--r--arch/um/drivers/vector_kern.c32
-rw-r--r--arch/um/drivers/vector_transports.c3
-rw-r--r--arch/um/include/asm/common.lds.S6
-rw-r--r--arch/um/include/shared/init.h5
-rw-r--r--arch/um/os-Linux/main.c12
-rw-r--r--arch/unicore32/include/asm/cacheflush.h2
-rw-r--r--arch/unicore32/kernel/pm.c5
-rw-r--r--arch/x86/Kconfig13
-rw-r--r--arch/x86/Makefile6
-rw-r--r--arch/x86/boot/compressed/eboot.c2
-rw-r--r--arch/x86/entry/common.c2
-rw-r--r--arch/x86/entry/entry_32.S2
-rw-r--r--arch/x86/entry/entry_64.S2
-rw-r--r--arch/x86/entry/vsyscall/vsyscall_64.c2
-rw-r--r--arch/x86/events/amd/iommu.c2
-rw-r--r--arch/x86/events/core.c2
-rw-r--r--arch/x86/events/intel/uncore.c21
-rw-r--r--arch/x86/hyperv/mmu.c28
-rw-r--r--arch/x86/include/asm/barrier.h2
-rw-r--r--arch/x86/include/asm/hyperv-tlfs.h25
-rw-r--r--arch/x86/include/asm/kvm_emulate.h6
-rw-r--r--arch/x86/include/asm/kvm_host.h7
-rw-r--r--arch/x86/include/asm/mshyperv.h2
-rw-r--r--arch/x86/include/asm/processor.h2
-rw-r--r--arch/x86/include/asm/segment.h2
-rw-r--r--arch/x86/include/asm/stackprotector.h6
-rw-r--r--arch/x86/include/asm/vmx.h5
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c60
-rw-r--r--arch/x86/kernel/asm-offsets.c2
-rw-r--r--arch/x86/kernel/asm-offsets_32.c2
-rw-r--r--arch/x86/kernel/asm-offsets_64.c2
-rw-r--r--arch/x86/kernel/cpu/bugs.c4
-rw-r--r--arch/x86/kernel/cpu/cacheinfo.c2
-rw-r--r--arch/x86/kernel/cpu/common.c5
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-severity.c5
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c46
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c2
-rw-r--r--arch/x86/kernel/cpu/microcode/intel.c5
-rw-r--r--arch/x86/kernel/cpu/mtrr/if.c2
-rw-r--r--arch/x86/kernel/head64.c2
-rw-r--r--arch/x86/kernel/head_32.S2
-rw-r--r--arch/x86/kernel/hpet.c6
-rw-r--r--arch/x86/kernel/ksysfs.c2
-rw-r--r--arch/x86/kernel/quirks.c11
-rw-r--r--arch/x86/kernel/signal.c2
-rw-r--r--arch/x86/kernel/traps.c14
-rw-r--r--arch/x86/kvm/cpuid.c11
-rw-r--r--arch/x86/kvm/emulate.c76
-rw-r--r--arch/x86/kvm/hyperv.c171
-rw-r--r--arch/x86/kvm/lapic.c12
-rw-r--r--arch/x86/kvm/lapic.h14
-rw-r--r--arch/x86/kvm/mmu.c78
-rw-r--r--arch/x86/kvm/page_track.c5
-rw-r--r--arch/x86/kvm/svm.c20
-rw-r--r--arch/x86/kvm/trace.h51
-rw-r--r--arch/x86/kvm/vmx.c557
-rw-r--r--arch/x86/kvm/x86.c104
-rw-r--r--arch/x86/kvm/x86.h13
-rw-r--r--arch/x86/mm/init.c4
-rw-r--r--arch/x86/mm/init_32.c2
-rw-r--r--arch/x86/mm/init_64.c22
-rw-r--r--arch/x86/net/bpf_jit_comp.c2
-rw-r--r--arch/x86/net/bpf_jit_comp32.c2
-rw-r--r--arch/x86/pci/xen.c2
-rw-r--r--arch/x86/platform/uv/tlb_uv.c2
-rw-r--r--arch/x86/platform/uv/uv_time.c2
-rw-r--r--arch/x86/xen/enlighten.c7
-rw-r--r--arch/x86/xen/enlighten_pv.c1
-rw-r--r--arch/x86/xen/enlighten_pvh.c1
-rw-r--r--arch/x86/xen/smp_pv.c5
-rw-r--r--arch/xtensa/Kconfig2
-rw-r--r--arch/xtensa/include/asm/cacheflush.h4
-rw-r--r--arch/xtensa/kernel/asm-offsets.c2
-rw-r--r--arch/xtensa/kernel/entry.S2
-rw-r--r--arch/xtensa/kernel/process.c2
-rw-r--r--block/Kconfig2
-rw-r--r--block/bio.c6
-rw-r--r--block/blk-core.c8
-rw-r--r--block/blk-flush.c4
-rw-r--r--block/blk-mq-debugfs.c2
-rw-r--r--block/blk-mq-tag.c29
-rw-r--r--block/blk-mq.c23
-rw-r--r--block/blk-softirq.c1
-rw-r--r--block/blk-tag.c26
-rw-r--r--block/blk-timeout.c1
-rw-r--r--block/blk-zoned.c4
-rw-r--r--block/bsg.c22
-rw-r--r--block/partitions/check.c2
-rw-r--r--block/partitions/ldm.c2
-rw-r--r--block/sed-opal.c4
-rw-r--r--certs/Kconfig2
-rw-r--r--crypto/algif_aead.c4
-rw-r--r--crypto/algif_skcipher.c3
-rw-r--r--crypto/asymmetric_keys/asymmetric_type.c2
-rw-r--r--crypto/asymmetric_keys/signature.c2
-rw-r--r--crypto/morus640.c3
-rw-r--r--crypto/sha3_generic.c2
-rw-r--r--crypto/testmgr.c3
-rw-r--r--drivers/acpi/acpi_lpss.c20
-rw-r--r--drivers/acpi/acpi_platform.c2
-rw-r--r--drivers/acpi/acpi_video.c5
-rw-r--r--drivers/acpi/acpica/dbnames.c1
-rw-r--r--drivers/acpi/acpica/dbobject.c23
-rw-r--r--drivers/acpi/acpica/dsdebug.c12
-rw-r--r--drivers/acpi/acpica/exconfig.c11
-rw-r--r--drivers/acpi/acpica/nsdump.c3
-rw-r--r--drivers/acpi/acpica/psloop.c51
-rw-r--r--drivers/acpi/acpica/psobject.c30
-rw-r--r--drivers/acpi/acpica/pswalk.c34
-rw-r--r--drivers/acpi/acpica/uterror.c10
-rw-r--r--drivers/acpi/acpica/utosi.c1
-rw-r--r--drivers/acpi/apei/erst.c3
-rw-r--r--drivers/acpi/apei/hest.c3
-rw-r--r--drivers/acpi/ec.c20
-rw-r--r--drivers/acpi/fan.c4
-rw-r--r--drivers/acpi/nfit/core.c7
-rw-r--r--drivers/acpi/processor_perflib.c5
-rw-r--r--drivers/acpi/processor_throttling.c5
-rw-r--r--drivers/acpi/sysfs.c6
-rw-r--r--drivers/android/binder_alloc.c4
-rw-r--r--drivers/ata/libata-core.c2
-rw-r--r--drivers/ata/libata-pmp.c2
-rw-r--r--drivers/ata/libata-scsi.c12
-rw-r--r--drivers/ata/sata_mv.c8
-rw-r--r--drivers/atm/fore200e.c3
-rw-r--r--drivers/atm/iphase.c2
-rw-r--r--drivers/atm/solos-pci.c3
-rw-r--r--drivers/auxdisplay/cfag12864b.c4
-rw-r--r--drivers/base/Makefile3
-rw-r--r--drivers/base/core.c15
-rw-r--r--drivers/base/dd.c3
-rw-r--r--drivers/base/firmware_loader/fallback.c2
-rw-r--r--drivers/base/power/common.c43
-rw-r--r--drivers/base/power/domain.c134
-rw-r--r--drivers/base/power/runtime.c27
-rw-r--r--drivers/base/power/sysfs.c2
-rw-r--r--drivers/block/DAC960.c4
-rw-r--r--drivers/block/drbd/drbd_main.c3
-rw-r--r--drivers/block/loop.c3
-rw-r--r--drivers/block/nbd.c42
-rw-r--r--drivers/block/null_blk.c11
-rw-r--r--drivers/block/ps3vram.c5
-rw-r--r--drivers/block/rbd.c11
-rw-r--r--drivers/block/rsxx/core.c3
-rw-r--r--drivers/block/rsxx/dma.c2
-rw-r--r--drivers/block/xen-blkback/xenbus.c3
-rw-r--r--drivers/block/xen-blkfront.c23
-rw-r--r--drivers/block/z2ram.c5
-rw-r--r--drivers/block/zram/zram_drv.c2
-rw-r--r--drivers/bluetooth/hci_nokia.c2
-rw-r--r--drivers/bus/Kconfig1
-rw-r--r--drivers/bus/arm-cci.c2
-rw-r--r--drivers/bus/fsl-mc/fsl-mc-allocator.c6
-rw-r--r--drivers/bus/hisi_lpc.c159
-rw-r--r--drivers/bus/ti-sysc.c388
-rw-r--r--drivers/cdrom/cdrom.c2
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/agp/amd-k7-agp.c3
-rw-r--r--drivers/char/agp/ati-agp.c3
-rw-r--r--drivers/char/agp/compat_ioctl.c8
-rw-r--r--drivers/char/agp/isoch.c3
-rw-r--r--drivers/char/agp/sgi-agp.c6
-rw-r--r--drivers/char/agp/sworks-agp.c2
-rw-r--r--drivers/char/agp/uninorth-agp.c4
-rw-r--r--drivers/char/hw_random/core.c11
-rw-r--r--drivers/char/ipmi/ipmi_ssif.c3
-rw-r--r--drivers/char/raw.c3
-rw-r--r--drivers/char/tpm/tpm2-cmd.c2
-rw-r--r--drivers/char/virtio_console.c18
-rw-r--r--drivers/clk/bcm/clk-bcm2835.c4
-rw-r--r--drivers/clk/clk.c4
-rw-r--r--drivers/clk/ingenic/cgu.h2
-rw-r--r--drivers/clk/renesas/clk-r8a7740.c2
-rw-r--r--drivers/clk/renesas/clk-r8a7779.c2
-rw-r--r--drivers/clk/renesas/clk-rcar-gen2.c2
-rw-r--r--drivers/clk/renesas/clk-rz.c2
-rw-r--r--drivers/clk/st/clkgen-fsyn.c2
-rw-r--r--drivers/clk/st/clkgen-pll.c2
-rw-r--r--drivers/clk/sunxi/clk-usb.c2
-rw-r--r--drivers/clk/tegra/clk.c7
-rw-r--r--drivers/clk/ti/adpll.c6
-rw-r--r--drivers/clk/ti/apll.c2
-rw-r--r--drivers/clk/ti/divider.c4
-rw-r--r--drivers/clk/ti/dpll.c2
-rw-r--r--drivers/clocksource/sh_cmt.c2
-rw-r--r--drivers/clocksource/sh_mtu2.c2
-rw-r--r--drivers/clocksource/sh_tmu.c2
-rw-r--r--drivers/clocksource/timer-stm32.c4
-rw-r--r--drivers/cpufreq/Kconfig.arm2
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c8
-rw-r--r--drivers/cpufreq/arm_big_little.c2
-rw-r--r--drivers/cpufreq/bmips-cpufreq.c2
-rw-r--r--drivers/cpufreq/brcmstb-avs-cpufreq.c2
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c3
-rw-r--r--drivers/cpufreq/cpufreq_governor.c12
-rw-r--r--drivers/cpufreq/ia64-acpi-cpufreq.c4
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c32
-rw-r--r--drivers/cpufreq/intel_pstate.c208
-rw-r--r--drivers/cpufreq/longhaul.c4
-rw-r--r--drivers/cpufreq/pxa3xx-cpufreq.c2
-rw-r--r--drivers/cpufreq/qcom-cpufreq-kryo.c25
-rw-r--r--drivers/cpufreq/s3c24xx-cpufreq.c2
-rw-r--r--drivers/cpufreq/scmi-cpufreq.c4
-rw-r--r--drivers/cpufreq/sfi-cpufreq.c4
-rw-r--r--drivers/cpufreq/spear-cpufreq.c2
-rw-r--r--drivers/cpufreq/ti-cpufreq.c7
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c8
-rw-r--r--drivers/crypto/cavium/nitrox/nitrox_isr.c2
-rw-r--r--drivers/crypto/chelsio/chtls/chtls_io.c7
-rw-r--r--drivers/crypto/inside-secure/safexcel_hash.c2
-rw-r--r--drivers/crypto/marvell/cesa.c2
-rw-r--r--drivers/crypto/marvell/hash.c2
-rw-r--r--drivers/crypto/n2_core.c4
-rw-r--r--drivers/crypto/qat/qat_common/adf_isr.c2
-rw-r--r--drivers/crypto/qat/qat_common/qat_uclo.c5
-rw-r--r--drivers/crypto/stm32/stm32-hash.c5
-rw-r--r--drivers/crypto/talitos.c13
-rw-r--r--drivers/crypto/virtio/virtio_crypto_algs.c2
-rw-r--r--drivers/devfreq/devfreq.c15
-rw-r--r--drivers/devfreq/event/exynos-ppmu.c2
-rw-r--r--drivers/dma/bestcomm/bestcomm.c3
-rw-r--r--drivers/dma/dmaengine.c2
-rw-r--r--drivers/dma/ioat/init.c4
-rw-r--r--drivers/dma/ipu/ipu_idmac.c3
-rw-r--r--drivers/dma/k3dma.c8
-rw-r--r--drivers/dma/mic_x100_dma.c3
-rw-r--r--drivers/dma/mv_xor.c4
-rw-r--r--drivers/dma/mv_xor_v2.c5
-rw-r--r--drivers/dma/pl330.c4
-rw-r--r--drivers/dma/s3c24xx-dma.c6
-rw-r--r--drivers/dma/sh/shdma-base.c5
-rw-r--r--drivers/dma/xilinx/zynqmp_dma.c2
-rw-r--r--drivers/dma/zx_dma.c8
-rw-r--r--drivers/edac/amd64_edac.c2
-rw-r--r--drivers/edac/i7core_edac.c2
-rw-r--r--drivers/extcon/extcon.c24
-rw-r--r--drivers/firewire/core-iso.c4
-rw-r--r--drivers/firewire/net.c2
-rw-r--r--drivers/firmware/arm_scmi/base.c43
-rw-r--r--drivers/firmware/arm_scmi/bus.c22
-rw-r--r--drivers/firmware/arm_scmi/clock.c24
-rw-r--r--drivers/firmware/arm_scmi/common.h22
-rw-r--r--drivers/firmware/arm_scmi/driver.c109
-rw-r--r--drivers/firmware/arm_scmi/perf.c38
-rw-r--r--drivers/firmware/arm_scmi/power.c16
-rw-r--r--drivers/firmware/arm_scmi/sensors.c20
-rw-r--r--drivers/firmware/arm_scpi.c2
-rw-r--r--drivers/firmware/broadcom/bcm47xx_nvram.c2
-rw-r--r--drivers/firmware/dell_rbu.c2
-rw-r--r--drivers/firmware/dmi-id.c2
-rw-r--r--drivers/firmware/dmi_scan.c1
-rw-r--r--drivers/firmware/efi/arm-init.c2
-rw-r--r--drivers/firmware/efi/capsule.c2
-rw-r--r--drivers/firmware/efi/efi-pstore.c27
-rw-r--r--drivers/firmware/efi/libstub/tpm.c2
-rw-r--r--drivers/firmware/efi/runtime-map.c2
-rw-r--r--drivers/firmware/qcom_scm.c3
-rw-r--r--drivers/firmware/ti_sci.c16
-rw-r--r--drivers/firmware/ti_sci.h30
-rw-r--r--drivers/fmc/fmc-sdb.c4
-rw-r--r--drivers/gpio/gpio-adnp.c2
-rw-r--r--drivers/gpio/gpio-aspeed.c4
-rw-r--r--drivers/gpio/gpio-bcm-kona.c7
-rw-r--r--drivers/gpio/gpio-davinci.c4
-rw-r--r--drivers/gpio/gpio-htc-egpio.c4
-rw-r--r--drivers/gpio/gpio-ml-ioh.c2
-rw-r--r--drivers/gpio/gpio-thunderx.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c38
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c41
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_test.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c52
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atom.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/ci_dpm.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/df_v3_6.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/kv_dpm.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v3_1.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dpm.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c4
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c67
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c3
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c45
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/logger.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/basics/vector.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c37
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c3
-rw-r--r--drivers/gpu/drm/amd/display/include/fixed31_32.h2
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.c47
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c3
-rw-r--r--drivers/gpu/drm/amd/display/modules/stats/stats.c12
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/df/df_3_6_sh_mask.h8
-rw-r--r--drivers/gpu/drm/amd/include/atomfirmware.h12
-rw-r--r--drivers/gpu/drm/amd/powerplay/amd_powerplay.c10
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c15
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c4
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c6
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c6
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c74
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c12
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c15
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c4
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c6
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c2
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.c309
-rw-r--r--drivers/gpu/drm/drm_drv.c14
-rw-r--r--drivers/gpu/drm/drm_edid.c3
-rw-r--r--drivers/gpu/drm/drm_hashtab.c2
-rw-r--r--drivers/gpu/drm/drm_memory.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c5
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c2
-rw-r--r--drivers/gpu/drm/gma500/mid_bios.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/cmd_parser.c1
-rw-r--r--drivers/gpu/drm/i915/gvt/display.h2
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.c5
-rw-r--r--drivers/gpu/drm/i915/gvt/handlers.c13
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c34
-rw-r--r--drivers/gpu/drm/i915/gvt/mmio.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/vgpu.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h21
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c74
-rw-r--r--drivers/gpu/drm/i915/i915_gem_context.c2
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c49
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c12
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h5
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c20
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c6
-rw-r--r--drivers/gpu/drm/i915/intel_display.c23
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c72
-rw-r--r--drivers/gpu/drm/i915/intel_dp_mst.c6
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_dsi.c8
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c8
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c2
-rw-r--r--drivers/gpu/drm/i915/intel_hdcp.c2
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c6
-rw-r--r--drivers/gpu/drm/i915/intel_lrc.c18
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c8
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c6
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c1
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c6
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c12
-rw-r--r--drivers/gpu/drm/i915/selftests/intel_uncore.c2
-rw-r--r--drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c17
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c9
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c105
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h27
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c12
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c20
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c16
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c17
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c14
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c24
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy.c4
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c258
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c11
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h9
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h14
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/curs507a.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/wndw.c13
-rw-r--r--drivers/gpu/drm/nouveau/nv84_fence.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvif/fifo.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvif/mmu.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvif/object.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvif/vmm.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/event.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_dmm_tiler.c4
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem.c4
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c7
-rw-r--r--drivers/gpu/drm/qxl/qxl_fb.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_kms.c4
-rw-r--r--drivers/gpu/drm/radeon/atom.c2
-rw-r--r--drivers/gpu/drm/radeon/btc_dpm.c4
-rw-r--r--drivers/gpu/drm/radeon/ci_dpm.c9
-rw-r--r--drivers/gpu/drm/radeon/kv_dpm.c5
-rw-r--r--drivers/gpu/drm/radeon/ni_dpm.c9
-rw-r--r--drivers/gpu/drm/radeon/r600_dpm.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c39
-rw-r--r--drivers/gpu/drm/radeon/radeon_combios.c9
-rw-r--r--drivers/gpu/drm/radeon/radeon_gart.c7
-rw-r--r--drivers/gpu/drm/radeon/radeon_test.c2
-rw-r--r--drivers/gpu/drm/radeon/rs780_dpm.c5
-rw-r--r--drivers/gpu/drm/radeon/rv6xx_dpm.c5
-rw-r--r--drivers/gpu/drm/radeon/rv770_dpm.c5
-rw-r--r--drivers/gpu/drm/radeon/si_dpm.c9
-rw-r--r--drivers/gpu/drm/radeon/sumo_dpm.c5
-rw-r--r--drivers/gpu/drm/radeon/trinity_dpm.c5
-rw-r--r--drivers/gpu/drm/savage/savage_bci.c5
-rw-r--r--drivers/gpu/drm/scheduler/gpu_scheduler.c9
-rw-r--r--drivers/gpu/drm/selftests/test-drm_mm.c24
-rw-r--r--drivers/gpu/drm/shmobile/Kconfig1
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_crtc.c42
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_crtc.h1
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_drv.h2
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_kms.c11
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_kms.h1
-rw-r--r--drivers/gpu/drm/shmobile/shmob_drm_plane.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c25
-rw-r--r--drivers/gpu/drm/tinydrm/repaper.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc.c8
-rw-r--r--drivers/gpu/drm/ttm/ttm_page_alloc_dma.c8
-rw-r--r--drivers/gpu/drm/v3d/Kconfig1
-rw-r--r--drivers/gpu/drm/vc4/vc4_plane.c2
-rw-r--r--drivers/gpu/drm/via/via_dmablit.c2
-rw-r--r--drivers/gpu/vga/Kconfig2
-rw-r--r--drivers/gpu/vga/vgaarb.c2
-rw-r--r--drivers/hid/hid-core.c9
-rw-r--r--drivers/hid/hid-debug.c6
-rw-r--r--drivers/hid/hid-google-hammer.c2
-rw-r--r--drivers/hid/hid-ids.h1
-rw-r--r--drivers/hid/hid-picolcd_fb.c3
-rw-r--r--drivers/hid/hid-sensor-hub.c3
-rw-r--r--drivers/hid/hid-steam.c10
-rw-r--r--drivers/hid/hidraw.c2
-rw-r--r--drivers/hid/intel-ish-hid/ipc/pci-ish.c22
-rw-r--r--drivers/hid/intel-ish-hid/ishtp-hid-client.c4
-rw-r--r--drivers/hid/usbhid/Kconfig2
-rw-r--r--drivers/hid/wacom_sys.c12
-rw-r--r--drivers/hv/hv.c2
-rw-r--r--drivers/hv/ring_buffer.c4
-rw-r--r--drivers/hwmon/acpi_power_meter.c7
-rw-r--r--drivers/hwmon/aspeed-pwm-tacho.c2
-rw-r--r--drivers/hwmon/coretemp.c2
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c7
-rw-r--r--drivers/hwmon/gpio-fan.c8
-rw-r--r--drivers/hwmon/i5k_amb.c5
-rw-r--r--drivers/hwmon/ibmpex.c2
-rw-r--r--drivers/hwmon/ibmpowernv.c9
-rw-r--r--drivers/hwmon/iio_hwmon.c4
-rw-r--r--drivers/hwmon/nct6683.c4
-rw-r--r--drivers/hwmon/nct6775.c6
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c4
-rw-r--r--drivers/hwmon/pmbus/ucd9000.c4
-rw-r--r--drivers/hwmon/pwm-fan.c2
-rw-r--r--drivers/hwspinlock/Kconfig1
-rw-r--r--drivers/hwspinlock/hwspinlock_core.c77
-rw-r--r--drivers/hwspinlock/hwspinlock_internal.h10
-rw-r--r--drivers/hwspinlock/omap_hwspinlock.c10
-rw-r--r--drivers/hwspinlock/qcom_hwspinlock.c10
-rw-r--r--drivers/hwspinlock/sirf_hwspinlock.c3
-rw-r--r--drivers/hwspinlock/sprd_hwspinlock.c10
-rw-r--r--drivers/hwspinlock/u8500_hsem.c10
-rw-r--r--drivers/hwtracing/coresight/coresight-etb10.c4
-rw-r--r--drivers/hwtracing/coresight/of_coresight.c9
-rw-r--r--drivers/i2c/algos/i2c-algo-bit.c4
-rw-r--r--drivers/i2c/algos/i2c-algo-pca.c5
-rw-r--r--drivers/i2c/algos/i2c-algo-pcf.c8
-rw-r--r--drivers/i2c/busses/Kconfig1
-rw-r--r--drivers/i2c/busses/Makefile3
-rw-r--r--drivers/i2c/busses/i2c-amd756-s4882.c4
-rw-r--r--drivers/i2c/busses/i2c-aspeed.c3
-rw-r--r--drivers/i2c/busses/i2c-at91.c12
-rw-r--r--drivers/i2c/busses/i2c-axxia.c31
-rw-r--r--drivers/i2c/busses/i2c-designware-common.c20
-rw-r--r--drivers/i2c/busses/i2c-designware-core.h14
-rw-r--r--drivers/i2c/busses/i2c-designware-master.c8
-rw-r--r--drivers/i2c/busses/i2c-designware-slave.c6
-rw-r--r--drivers/i2c/busses/i2c-diolan-u2c.c11
-rw-r--r--drivers/i2c/busses/i2c-efm32.c3
-rw-r--r--drivers/i2c/busses/i2c-eg20t.c5
-rw-r--r--drivers/i2c/busses/i2c-emev2.c2
-rw-r--r--drivers/i2c/busses/i2c-exynos5.c29
-rw-r--r--drivers/i2c/busses/i2c-gpio.c2
-rw-r--r--drivers/i2c/busses/i2c-hix5hd2.c22
-rw-r--r--drivers/i2c/busses/i2c-i801.c7
-rw-r--r--drivers/i2c/busses/i2c-ibm_iic.c3
-rw-r--r--drivers/i2c/busses/i2c-imx-lpi2c.c16
-rw-r--r--drivers/i2c/busses/i2c-imx.c21
-rw-r--r--drivers/i2c/busses/i2c-kempld.c7
-rw-r--r--drivers/i2c/busses/i2c-mlxcpld.c68
-rw-r--r--drivers/i2c/busses/i2c-mt65xx.c8
-rw-r--r--drivers/i2c/busses/i2c-mxs.c16
-rw-r--r--drivers/i2c/busses/i2c-nforce2-s4985.c4
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c2
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c2
-rw-r--r--drivers/i2c/busses/i2c-ocores.c7
-rw-r--r--drivers/i2c/busses/i2c-omap.c2
-rw-r--r--drivers/i2c/busses/i2c-opal.c4
-rw-r--r--drivers/i2c/busses/i2c-pasemi.c2
-rw-r--r--drivers/i2c/busses/i2c-pca-platform.c2
-rw-r--r--drivers/i2c/busses/i2c-pnx.c21
-rw-r--r--drivers/i2c/busses/i2c-qup.c67
-rw-r--r--drivers/i2c/busses/i2c-rcar.c4
-rw-r--r--drivers/i2c/busses/i2c-riic.c5
-rw-r--r--drivers/i2c/busses/i2c-rk3x.c2
-rw-r--r--drivers/i2c/busses/i2c-robotfuzz-osif.c21
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c2
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c11
-rw-r--r--drivers/i2c/busses/i2c-stm32.c153
-rw-r--r--drivers/i2c/busses/i2c-stm32.h37
-rw-r--r--drivers/i2c/busses/i2c-stm32f7.c1045
-rw-r--r--drivers/i2c/busses/i2c-stu300.c22
-rw-r--r--drivers/i2c/busses/i2c-synquacer.c2
-rw-r--r--drivers/i2c/busses/i2c-tegra.c33
-rw-r--r--drivers/i2c/busses/i2c-xiic.c17
-rw-r--r--drivers/i2c/busses/i2c-xlp9xx.c89
-rw-r--r--drivers/i2c/i2c-core-base.c10
-rw-r--r--drivers/i2c/i2c-core-of.c51
-rw-r--r--drivers/i2c/i2c-core-smbus.c2
-rw-r--r--drivers/i2c/i2c-dev.c2
-rw-r--r--drivers/i2c/i2c-mux.c2
-rw-r--r--drivers/i2c/i2c-stub.c5
-rw-r--r--drivers/i2c/muxes/i2c-demux-pinctrl.c5
-rw-r--r--drivers/i2c/muxes/i2c-mux-gpio.c11
-rw-r--r--drivers/i2c/muxes/i2c-mux-ltc4306.c7
-rw-r--r--drivers/i2c/muxes/i2c-mux-pca954x.c18
-rw-r--r--drivers/i2c/muxes/i2c-mux-reg.c8
-rw-r--r--drivers/ide/hpt366.c2
-rw-r--r--drivers/ide/ide-probe.c5
-rw-r--r--drivers/ide/it821x.c2
-rw-r--r--drivers/iio/adc/at91_adc.c7
-rw-r--r--drivers/iio/adc/max1027.c4
-rw-r--r--drivers/iio/adc/max1363.c6
-rw-r--r--drivers/iio/adc/twl6030-gpadc.c7
-rw-r--r--drivers/iio/dac/ad5592r-base.c5
-rw-r--r--drivers/iio/imu/adis_buffer.c2
-rw-r--r--drivers/iio/inkern.c2
-rw-r--r--drivers/iio/multiplexer/iio-mux.c7
-rw-r--r--drivers/infiniband/core/cache.c5
-rw-r--r--drivers/infiniband/core/cma.c4
-rw-r--r--drivers/infiniband/core/device.c4
-rw-r--r--drivers/infiniband/core/fmr_pool.c5
-rw-r--r--drivers/infiniband/core/iwpm_util.c10
-rw-r--r--drivers/infiniband/core/umem_odp.c16
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c4
-rw-r--r--drivers/infiniband/core/uverbs_main.c14
-rw-r--r--drivers/infiniband/core/verbs.c14
-rw-r--r--drivers/infiniband/hw/cxgb3/cxio_hal.c4
-rw-r--r--drivers/infiniband/hw/cxgb4/device.c7
-rw-r--r--drivers/infiniband/hw/cxgb4/id_table.c4
-rw-r--r--drivers/infiniband/hw/cxgb4/qp.c8
-rw-r--r--drivers/infiniband/hw/hfi1/sdma.c3
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.c2
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_mr.c2
-rw-r--r--drivers/infiniband/hw/mlx4/mad.c3
-rw-r--r--drivers/infiniband/hw/mlx4/main.c12
-rw-r--r--drivers/infiniband/hw/mlx4/mr.c7
-rw-r--r--drivers/infiniband/hw/mlx4/qp.c4
-rw-r--r--drivers/infiniband/hw/mlx5/main.c36
-rw-r--r--drivers/infiniband/hw/mlx5/srq.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_allocator.c18
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c6
-rw-r--r--drivers/infiniband/hw/mthca/mthca_eq.c6
-rw-r--r--drivers/infiniband/hw/mthca/mthca_memfree.c6
-rw-r--r--drivers/infiniband/hw/mthca/mthca_mr.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_profile.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c4
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c2
-rw-r--r--drivers/infiniband/hw/nes/nes_mgt.c3
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c2
-rw-r--r--drivers/infiniband/hw/nes/nes_verbs.c5
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_hw.c2
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_main.c11
-rw-r--r--drivers/infiniband/hw/ocrdma/ocrdma_verbs.c15
-rw-r--r--drivers/infiniband/hw/qedr/main.c4
-rw-r--r--drivers/infiniband/hw/qedr/verbs.c7
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c9
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7220.c9
-rw-r--r--drivers/infiniband/hw/qib/qib_iba7322.c34
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c14
-rw-r--r--drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c2
-rw-r--r--drivers/infiniband/hw/usnic/usnic_vnic.c2
-rw-r--r--drivers/infiniband/sw/rdmavt/qp.c11
-rw-r--r--drivers/infiniband/sw/rxe/rxe_req.c5
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c8
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c10
-rw-r--r--drivers/infiniband/ulp/iser/iser_initiator.c5
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c5
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c9
-rw-r--r--drivers/infiniband/ulp/srpt/ib_srpt.c2
-rw-r--r--drivers/input/Kconfig4
-rw-r--r--drivers/input/joystick/Kconfig14
-rw-r--r--drivers/input/joystick/iforce/Kconfig4
-rw-r--r--drivers/input/joystick/joydump.c2
-rw-r--r--drivers/input/joystick/walkera0701.c2
-rw-r--r--drivers/input/keyboard/Kconfig9
-rw-r--r--drivers/input/keyboard/Makefile1
-rw-r--r--drivers/input/keyboard/clps711x-keypad.c4
-rw-r--r--drivers/input/keyboard/matrix_keypad.c6
-rw-r--r--drivers/input/keyboard/mtk-pmic-keys.c339
-rw-r--r--drivers/input/keyboard/omap4-keypad.c3
-rw-r--r--drivers/input/keyboard/samsung-keypad.c2
-rw-r--r--drivers/input/matrix-keymap.c4
-rw-r--r--drivers/input/misc/Kconfig4
-rw-r--r--drivers/input/misc/rotary_encoder.c6
-rw-r--r--drivers/input/mouse/Kconfig6
-rw-r--r--drivers/input/mouse/alps.c2
-rw-r--r--drivers/input/rmi4/rmi_driver.c9
-rw-r--r--drivers/input/rmi4/rmi_f11.c15
-rw-r--r--drivers/input/rmi4/rmi_f12.c15
-rw-r--r--drivers/input/rmi4/rmi_f54.c2
-rw-r--r--drivers/input/rmi4/rmi_spi.c9
-rw-r--r--drivers/input/serio/Kconfig4
-rw-r--r--drivers/input/touchscreen/wm97xx-core.c2
-rw-r--r--drivers/iommu/Kconfig1
-rw-r--r--drivers/iommu/amd_iommu.c68
-rw-r--r--drivers/iommu/arm-smmu.c2
-rw-r--r--drivers/iommu/dmar.c2
-rw-r--r--drivers/iommu/intel-iommu.c4
-rw-r--r--drivers/iommu/omap-iommu.c2
-rw-r--r--drivers/iommu/rockchip-iommu.c2
-rw-r--r--drivers/iommu/tegra-gart.c2
-rw-r--r--drivers/ipack/carriers/tpci200.c4
-rw-r--r--drivers/irqchip/irq-alpine-msi.c3
-rw-r--r--drivers/irqchip/irq-gic-v2m.c4
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c81
-rw-r--r--drivers/irqchip/irq-gic-v3.c5
-rw-r--r--drivers/irqchip/irq-imgpdc.c2
-rw-r--r--drivers/irqchip/irq-ls-scfg-msi.c10
-rw-r--r--drivers/irqchip/irq-mvebu-gicp.c8
-rw-r--r--drivers/irqchip/irq-partition-percpu.c2
-rw-r--r--drivers/irqchip/irq-s3c24xx.c2
-rw-r--r--drivers/isdn/capi/capi.c2
-rw-r--r--drivers/isdn/capi/capidrv.c3
-rw-r--r--drivers/isdn/gigaset/capi.c6
-rw-r--r--drivers/isdn/gigaset/common.c4
-rw-r--r--drivers/isdn/gigaset/i4l.c2
-rw-r--r--drivers/isdn/hardware/avm/b1.c2
-rw-r--r--drivers/isdn/hisax/fsm.c4
-rw-r--r--drivers/isdn/hisax/hfc_2bds0.c2
-rw-r--r--drivers/isdn/hisax/hfc_2bs0.c3
-rw-r--r--drivers/isdn/hisax/netjet.c12
-rw-r--r--drivers/isdn/i4l/isdn_bsdcomp.c5
-rw-r--r--drivers/isdn/i4l/isdn_common.c10
-rw-r--r--drivers/isdn/mISDN/fsm.c6
-rw-r--r--drivers/leds/leds-adp5520.c2
-rw-r--r--drivers/leds/leds-apu.c4
-rw-r--r--drivers/leds/leds-cr0014114.c3
-rw-r--r--drivers/leds/leds-da9052.c4
-rw-r--r--drivers/leds/leds-lp5521.c4
-rw-r--r--drivers/leds/leds-lp5523.c4
-rw-r--r--drivers/leds/leds-lp5562.c4
-rw-r--r--drivers/leds/leds-lp55xx-common.c2
-rw-r--r--drivers/leds/leds-lp8501.c4
-rw-r--r--drivers/leds/leds-lt3593.c4
-rw-r--r--drivers/leds/leds-mc13783.c4
-rw-r--r--drivers/leds/leds-mlxcpld.c6
-rw-r--r--drivers/leds/leds-netxbig.c16
-rw-r--r--drivers/leds/leds-ns2.c7
-rw-r--r--drivers/leds/leds-pca955x.c8
-rw-r--r--drivers/leds/leds-pca963x.c6
-rw-r--r--drivers/leds/leds-tca6507.c4
-rw-r--r--drivers/lightnvm/Kconfig2
-rw-r--r--drivers/lightnvm/pblk-gc.c2
-rw-r--r--drivers/lightnvm/pblk-init.c8
-rw-r--r--drivers/lightnvm/pblk-rb.c2
-rw-r--r--drivers/lightnvm/pblk-recovery.c2
-rw-r--r--drivers/mailbox/hi6220-mailbox.c8
-rw-r--r--drivers/mailbox/mailbox-sti.c4
-rw-r--r--drivers/mailbox/omap-mailbox.c10
-rw-r--r--drivers/mailbox/pcc.c3
-rw-r--r--drivers/mailbox/ti-msgmgr.c4
-rw-r--r--drivers/md/Kconfig11
-rw-r--r--drivers/md/Makefile1
-rw-r--r--drivers/md/bcache/Kconfig2
-rw-r--r--drivers/md/bcache/btree.c2
-rw-r--r--drivers/md/bcache/extents.c2
-rw-r--r--drivers/md/bcache/super.c11
-rw-r--r--drivers/md/bcache/sysfs.c3
-rw-r--r--drivers/md/dm-bio-prison-v1.c2
-rw-r--r--drivers/md/dm-bio-prison-v2.c2
-rw-r--r--drivers/md/dm-cache-policy-smq.c4
-rw-r--r--drivers/md/dm-cache-target.c61
-rw-r--r--drivers/md/dm-core.h38
-rw-r--r--drivers/md/dm-crypt.c31
-rw-r--r--drivers/md/dm-integrity.c18
-rw-r--r--drivers/md/dm-ioctl.c3
-rw-r--r--drivers/md/dm-kcopyd.c3
-rw-r--r--drivers/md/dm-region-hash.c15
-rw-r--r--drivers/md/dm-snap.c9
-rw-r--r--drivers/md/dm-stats.c4
-rw-r--r--drivers/md/dm-switch.c3
-rw-r--r--drivers/md/dm-table.c2
-rw-r--r--drivers/md/dm-thin.c9
-rw-r--r--drivers/md/dm-verity-target.c5
-rw-r--r--drivers/md/dm-writecache.c2305
-rw-r--r--drivers/md/dm-zoned-target.c2
-rw-r--r--drivers/md/md-bitmap.c6
-rw-r--r--drivers/md/md-cluster.c6
-rw-r--r--drivers/md/md-multipath.c3
-rw-r--r--drivers/md/raid0.c10
-rw-r--r--drivers/md/raid1.c13
-rw-r--r--drivers/md/raid10.c15
-rw-r--r--drivers/md/raid5.c15
-rw-r--r--drivers/media/common/v4l2-tpg/v4l2-tpg-core.c15
-rw-r--r--drivers/media/dvb-core/dmxdev.c3
-rw-r--r--drivers/media/dvb-core/dvb_demux.c6
-rw-r--r--drivers/media/dvb-core/dvb_ringbuffer.c2
-rw-r--r--drivers/media/dvb-frontends/Kconfig18
-rw-r--r--drivers/media/dvb-frontends/dib3000.h2
-rw-r--r--drivers/media/dvb-frontends/dib3000mb.c2
-rw-r--r--drivers/media/dvb-frontends/dib7000p.c4
-rw-r--r--drivers/media/dvb-frontends/dib8000.c4
-rw-r--r--drivers/media/dvb-frontends/dib9000.c4
-rw-r--r--drivers/media/dvb-frontends/eds1547.h2
-rw-r--r--drivers/media/dvb-frontends/nxt200x.c4
-rw-r--r--drivers/media/dvb-frontends/or51211.c2
-rw-r--r--drivers/media/dvb-frontends/sp8870.c2
-rw-r--r--drivers/media/dvb-frontends/sp887x.c2
-rw-r--r--drivers/media/dvb-frontends/tda1004x.c4
-rw-r--r--drivers/media/dvb-frontends/tda10071.c2
-rw-r--r--drivers/media/dvb-frontends/z0194a.h2
-rw-r--r--drivers/media/i2c/max2175.c6
-rw-r--r--drivers/media/i2c/s5k5baf.c2
-rw-r--r--drivers/media/pci/bt8xx/Kconfig2
-rw-r--r--drivers/media/pci/bt8xx/bttv-risc.c3
-rw-r--r--drivers/media/pci/cx18/cx18-dvb.c2
-rw-r--r--drivers/media/pci/cx18/cx18-streams.c4
-rw-r--r--drivers/media/pci/cx23885/cx23885-alsa.c2
-rw-r--r--drivers/media/pci/cx23885/cx23885-cards.c2
-rw-r--r--drivers/media/pci/cx25821/cx25821-alsa.c2
-rw-r--r--drivers/media/pci/cx88/cx88-alsa.c2
-rw-r--r--drivers/media/pci/ivtv/ivtvfb.c2
-rw-r--r--drivers/media/pci/meye/Kconfig2
-rw-r--r--drivers/media/pci/meye/meye.c2
-rw-r--r--drivers/media/pci/pt1/pt1.c2
-rw-r--r--drivers/media/pci/saa7134/saa7134-alsa.c2
-rw-r--r--drivers/media/pci/ttpci/Kconfig2
-rw-r--r--drivers/media/pci/ttpci/av7110_ipack.c2
-rw-r--r--drivers/media/platform/am437x/am437x-vpfe.c6
-rw-r--r--drivers/media/platform/davinci/vpif_capture.c10
-rw-r--r--drivers/media/platform/marvell-ccic/mmp-driver.c2
-rw-r--r--drivers/media/platform/pxa_camera.c4
-rw-r--r--drivers/media/platform/qcom/camss-8x16/camss-csid.c8
-rw-r--r--drivers/media/platform/qcom/camss-8x16/camss-csiphy.c11
-rw-r--r--drivers/media/platform/qcom/camss-8x16/camss-ispif.c9
-rw-r--r--drivers/media/platform/qcom/camss-8x16/camss-vfe.c8
-rw-r--r--drivers/media/platform/qcom/camss-8x16/camss.c3
-rw-r--r--drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c2
-rw-r--r--drivers/media/platform/soc_camera/soc_camera.c3
-rw-r--r--drivers/media/platform/via-camera.c5
-rw-r--r--drivers/media/platform/vivid/vivid-core.c9
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.c3
-rw-r--r--drivers/media/platform/xilinx/xilinx-vipp.c2
-rw-r--r--drivers/media/radio/Kconfig12
-rw-r--r--drivers/media/radio/si470x/Kconfig2
-rw-r--r--drivers/media/radio/wl128x/Kconfig2
-rw-r--r--drivers/media/rc/ir-rx51.c17
-rw-r--r--drivers/media/usb/au0828/au0828-video.c6
-rw-r--r--drivers/media/usb/cpia2/cpia2_usb.c3
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-audio.c2
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-core.c8
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-vbi.c4
-rw-r--r--drivers/media/usb/dvb-usb-v2/Kconfig2
-rw-r--r--drivers/media/usb/dvb-usb-v2/dvb_usb_core.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/gl861.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/lmedm04.c4
-rw-r--r--drivers/media/usb/dvb-usb-v2/lmedm04.h2
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.c2
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.h2
-rw-r--r--drivers/media/usb/dvb-usb/Kconfig2
-rw-r--r--drivers/media/usb/dvb-usb/a800.c2
-rw-r--r--drivers/media/usb/dvb-usb/af9005-fe.c2
-rw-r--r--drivers/media/usb/dvb-usb/af9005-remote.c2
-rw-r--r--drivers/media/usb/dvb-usb/af9005.c2
-rw-r--r--drivers/media/usb/dvb-usb/af9005.h2
-rw-r--r--drivers/media/usb/dvb-usb/az6027.c2
-rw-r--r--drivers/media/usb/dvb-usb/cxusb.c2
-rw-r--r--drivers/media/usb/dvb-usb/dibusb-common.c2
-rw-r--r--drivers/media/usb/dvb-usb/dibusb-mb.c2
-rw-r--r--drivers/media/usb/dvb-usb/dibusb-mc-common.c2
-rw-r--r--drivers/media/usb/dvb-usb/dibusb-mc.c2
-rw-r--r--drivers/media/usb/dvb-usb/dibusb.h2
-rw-r--r--drivers/media/usb/dvb-usb/digitv.c2
-rw-r--r--drivers/media/usb/dvb-usb/dtt200u-fe.c2
-rw-r--r--drivers/media/usb/dvb-usb/dtt200u.c2
-rw-r--r--drivers/media/usb/dvb-usb/dtt200u.h2
-rw-r--r--drivers/media/usb/dvb-usb/dvb-usb-firmware.c2
-rw-r--r--drivers/media/usb/dvb-usb/dvb-usb-init.c2
-rw-r--r--drivers/media/usb/dvb-usb/dw2102.c6
-rw-r--r--drivers/media/usb/dvb-usb/friio-fe.c2
-rw-r--r--drivers/media/usb/dvb-usb/friio.c2
-rw-r--r--drivers/media/usb/dvb-usb/friio.h2
-rw-r--r--drivers/media/usb/dvb-usb/gp8psk.c4
-rw-r--r--drivers/media/usb/dvb-usb/gp8psk.h2
-rw-r--r--drivers/media/usb/dvb-usb/m920x.c2
-rw-r--r--drivers/media/usb/dvb-usb/nova-t-usb2.c2
-rw-r--r--drivers/media/usb/dvb-usb/opera1.c4
-rw-r--r--drivers/media/usb/dvb-usb/ttusb2.c2
-rw-r--r--drivers/media/usb/dvb-usb/ttusb2.h2
-rw-r--r--drivers/media/usb/dvb-usb/umt-010.c2
-rw-r--r--drivers/media/usb/dvb-usb/vp702x-fe.c2
-rw-r--r--drivers/media/usb/dvb-usb/vp702x.c2
-rw-r--r--drivers/media/usb/dvb-usb/vp7045-fe.c2
-rw-r--r--drivers/media/usb/dvb-usb/vp7045.c2
-rw-r--r--drivers/media/usb/dvb-usb/vp7045.h2
-rw-r--r--drivers/media/usb/go7007/go7007-fw.c2
-rw-r--r--drivers/media/usb/go7007/go7007-usb.c3
-rw-r--r--drivers/media/usb/gspca/m5602/Kconfig2
-rw-r--r--drivers/media/usb/gspca/t613.c2
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-hdw.c2
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-std.c2
-rw-r--r--drivers/media/usb/stk1160/stk1160-core.c5
-rw-r--r--drivers/media/usb/stk1160/stk1160-video.c6
-rw-r--r--drivers/media/usb/stkwebcam/stk-webcam.c5
-rw-r--r--drivers/media/usb/tm6000/tm6000-video.c13
-rw-r--r--drivers/media/usb/ttusb-dec/Kconfig6
-rw-r--r--drivers/media/usb/usbtv/usbtv-video.c2
-rw-r--r--drivers/media/usb/usbvision/usbvision-video.c3
-rw-r--r--drivers/media/usb/uvc/uvc_video.c4
-rw-r--r--drivers/media/usb/zr364xx/Kconfig2
-rw-r--r--drivers/media/v4l2-core/v4l2-event.c3
-rw-r--r--drivers/media/v4l2-core/v4l2-flash-led-class.c7
-rw-r--r--drivers/media/v4l2-core/videobuf-dma-sg.c7
-rw-r--r--drivers/memory/Kconfig10
-rw-r--r--drivers/memory/Makefile1
-rw-r--r--drivers/memory/brcmstb_dpfe.c42
-rw-r--r--drivers/memory/of_memory.c4
-rw-r--r--drivers/memory/omap-gpmc.c4
-rw-r--r--drivers/memory/tegra/Makefile1
-rw-r--r--drivers/memory/tegra/mc.c362
-rw-r--r--drivers/memory/tegra/mc.h22
-rw-r--r--drivers/memory/tegra/tegra114.c33
-rw-r--r--drivers/memory/tegra/tegra124.c48
-rw-r--r--drivers/memory/tegra/tegra20.c296
-rw-r--r--drivers/memory/tegra/tegra210.c53
-rw-r--r--drivers/memory/tegra/tegra30.c35
-rw-r--r--drivers/memory/tegra20-mc.c254
-rw-r--r--drivers/memory/ti-aemif.c60
-rw-r--r--drivers/memstick/core/ms_block.c6
-rw-r--r--drivers/message/fusion/lsi/mpi_cnfg.h4
-rw-r--r--drivers/message/fusion/mptbase.c2
-rw-r--r--drivers/message/fusion/mptfc.c2
-rw-r--r--drivers/message/fusion/mptlan.c9
-rw-r--r--drivers/message/fusion/mptsas.c2
-rw-r--r--drivers/mfd/Makefile1
-rw-r--r--drivers/mfd/ab8500-debugfs.c15
-rw-r--r--drivers/mfd/abx500-core.c25
-rw-r--r--drivers/mfd/arizona-core.c53
-rw-r--r--drivers/mfd/asic3.c3
-rw-r--r--drivers/mfd/atmel-smc.c1
-rw-r--r--drivers/mfd/axp20x.c252
-rw-r--r--drivers/mfd/cros_ec.c41
-rw-r--r--drivers/mfd/cros_ec_acpi_gpe.c103
-rw-r--r--drivers/mfd/cros_ec_dev.c52
-rw-r--r--drivers/mfd/cros_ec_i2c.c17
-rw-r--r--drivers/mfd/da9062-core.c462
-rw-r--r--drivers/mfd/htc-i2cpld.c8
-rw-r--r--drivers/mfd/intel-lpss-pci.c25
-rw-r--r--drivers/mfd/intel-lpss.c8
-rw-r--r--drivers/mfd/janz-cmodio.c4
-rw-r--r--drivers/mfd/jz4740-adc.c4
-rw-r--r--drivers/mfd/max8997.c4
-rw-r--r--drivers/mfd/mfd-core.c2
-rw-r--r--drivers/mfd/motorola-cpcap.c6
-rw-r--r--drivers/mfd/mt6397-core.c26
-rw-r--r--drivers/mfd/omap-usb-host.c24
-rw-r--r--drivers/mfd/omap-usb-tll.c60
-rw-r--r--drivers/mfd/pcf50633-core.c7
-rw-r--r--drivers/mfd/qcom-spmi-pmic.c6
-rw-r--r--drivers/mfd/rave-sp.c118
-rw-r--r--drivers/mfd/rc5t583.c6
-rw-r--r--drivers/mfd/si476x-i2c.c6
-rw-r--r--drivers/mfd/sm501.c34
-rw-r--r--drivers/mfd/smsc-ece1099.c7
-rw-r--r--drivers/mfd/sprd-sc27xx-spi.c8
-rw-r--r--drivers/mfd/stm32-timers.c201
-rw-r--r--drivers/mfd/syscon.c2
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c5
-rw-r--r--drivers/mfd/timberdale.c10
-rw-r--r--drivers/mfd/tps65090.c4
-rw-r--r--drivers/mfd/tps6586x.c4
-rw-r--r--drivers/mfd/tps65910.c18
-rw-r--r--drivers/mfd/tps65911-comparator.c17
-rw-r--r--drivers/mfd/tps68470.c10
-rw-r--r--drivers/mfd/tps80031.c4
-rw-r--r--drivers/mfd/twl-core.c7
-rw-r--r--drivers/mfd/twl6030-irq.c4
-rw-r--r--drivers/mfd/viperboard.c4
-rw-r--r--drivers/mfd/wm8994-core.c7
-rw-r--r--drivers/mfd/wm97xx-core.c2
-rw-r--r--drivers/misc/altera-stapl/altera.c6
-rw-r--r--drivers/misc/cxl/guest.c2
-rw-r--r--drivers/misc/cxl/of.c2
-rw-r--r--drivers/misc/eeprom/at24.c71
-rw-r--r--drivers/misc/eeprom/idt_89hpesx.c2
-rw-r--r--drivers/misc/genwqe/card_ddcb.c9
-rw-r--r--drivers/misc/sgi-xp/xpc_main.c8
-rw-r--r--drivers/misc/sgi-xp/xpc_partition.c2
-rw-r--r--drivers/misc/sgi-xp/xpnet.c5
-rw-r--r--drivers/misc/sram.c6
-rw-r--r--drivers/misc/vmw_vmci/vmci_queue_pair.c6
-rw-r--r--drivers/mmc/host/sdhci-omap.c6
-rw-r--r--drivers/mtd/ar7part.c2
-rw-r--r--drivers/mtd/bcm47xxpart.c2
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c9
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0002.c7
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0020.c5
-rw-r--r--drivers/mtd/devices/docg3.c4
-rw-r--r--drivers/mtd/ftl.c15
-rw-r--r--drivers/mtd/inftlmount.c6
-rw-r--r--drivers/mtd/lpddr/lpddr_cmds.c2
-rw-r--r--drivers/mtd/maps/physmap_of_core.c4
-rw-r--r--drivers/mtd/maps/vmu-flash.c8
-rw-r--r--drivers/mtd/mtdconcat.c5
-rw-r--r--drivers/mtd/mtdoops.c6
-rw-r--r--drivers/mtd/mtdswap.c6
-rw-r--r--drivers/mtd/nand/onenand/onenand_base.c6
-rw-r--r--drivers/mtd/nand/raw/davinci_nand.c6
-rw-r--r--drivers/mtd/nand/raw/nand_bch.c2
-rw-r--r--drivers/mtd/nand/raw/nandsim.c7
-rw-r--r--drivers/mtd/nand/raw/qcom_nandc.c4
-rw-r--r--drivers/mtd/nand/raw/s3c2410.c2
-rw-r--r--drivers/mtd/nftlmount.c7
-rw-r--r--drivers/mtd/ofpart.c4
-rw-r--r--drivers/mtd/parsers/parser_trx.c2
-rw-r--r--drivers/mtd/parsers/sharpslpart.c5
-rw-r--r--drivers/mtd/rfd_ftl.c3
-rw-r--r--drivers/mtd/sm_ftl.c6
-rw-r--r--drivers/mtd/ssfdc.c5
-rw-r--r--drivers/mtd/tests/pagetest.c2
-rw-r--r--drivers/mtd/tests/stresstest.c2
-rw-r--r--drivers/mtd/ubi/build.c4
-rw-r--r--drivers/mtd/ubi/eba.c125
-rw-r--r--drivers/mtd/ubi/fastmap.c20
-rw-r--r--drivers/mtd/ubi/ubi-media.h22
-rw-r--r--drivers/mtd/ubi/ubi.h11
-rw-r--r--drivers/mtd/ubi/vmt.c1
-rw-r--r--drivers/mtd/ubi/vtbl.c16
-rw-r--r--drivers/mtd/ubi/wl.c6
-rw-r--r--drivers/net/bonding/bond_main.c2
-rw-r--r--drivers/net/bonding/bond_options.c1
-rw-r--r--drivers/net/can/grcan.c4
-rw-r--r--drivers/net/can/slcan.c2
-rw-r--r--drivers/net/dsa/b53/b53_common.c8
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_ethtool.c8
-rw-r--r--drivers/net/ethernet/amd/lance.c8
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c11
-rw-r--r--drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c4
-rw-r--r--drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c4
-rw-r--r--drivers/net/ethernet/atheros/atlx/atl2.c4
-rw-r--r--drivers/net/ethernet/broadcom/bcm63xx_enet.c4
-rw-r--r--drivers/net/ethernet/broadcom/bnx2.c9
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c13
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c4
-rw-r--r--drivers/net/ethernet/broadcom/cnic.c10
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c5
-rw-r--r--drivers/net/ethernet/brocade/bna/bnad.c4
-rw-r--r--drivers/net/ethernet/calxeda/xgmac.c4
-rw-r--r--drivers/net/ethernet/cavium/liquidio/octeon_droq.c9
-rw-r--r--drivers/net/ethernet/cavium/liquidio/request_manager.c5
-rw-r--r--drivers/net/ethernet/cavium/thunder/nic.h2
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_main.c50
-rw-r--r--drivers/net/ethernet/cavium/thunder/nicvf_queues.c4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c7
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c10
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c3
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c4
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/sge.c2
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_clsf.c3
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c12
-rw-r--r--drivers/net/ethernet/cortina/gemini.c4
-rw-r--r--drivers/net/ethernet/ethoc.c3
-rw-r--r--drivers/net/ethernet/faraday/ftgmac100.c4
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_eth.c2
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.c12
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c4
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_enet.c3
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.c6
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c5
-rw-r--r--drivers/net/ethernet/ibm/ibmveth.c2
-rw-r--r--drivers/net/ethernet/intel/Kconfig8
-rw-r--r--drivers/net/ethernet/intel/e1000/e1000_ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/e1000e/netdev.c2
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_txrx.c7
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c16
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c7
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c5
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_main.c5
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c34
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c8
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c25
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h6
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ethtool.c8
-rw-r--r--drivers/net/ethernet/jme.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/alloc.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c21
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/icm.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/resource_tracker.c26
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c48
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c4
-rw-r--r--drivers/net/ethernet/micrel/ksz884x.c2
-rw-r--r--drivers/net/ethernet/moxa/moxart_ether.c8
-rw-r--r--drivers/net/ethernet/mscc/ocelot.c2
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-config.c21
-rw-r--r--drivers/net/ethernet/neterion/vxge/vxge-main.c4
-rw-r--r--drivers/net/ethernet/netronome/nfp/abm/main.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/main.c1
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/metadata.c3
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c2
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net.h4
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c4
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c7
-rw-r--r--drivers/net/ethernet/ni/nixge.c5
-rw-r--r--drivers/net/ethernet/nvidia/forcedeth.c6
-rw-r--r--drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c2
-rw-r--r--drivers/net/ethernet/pasemi/pasemi_mac.c10
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dcbx.c11
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_debug.c5
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dev.c16
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_init_ops.c4
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.c4
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_ll2.c11
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_main.c12
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.c6
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_filter.c5
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c5
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c15
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c8
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_main.c3
-rw-r--r--drivers/net/ethernet/qualcomm/emac/emac-sgmii.c1
-rw-r--r--drivers/net/ethernet/sfc/ef10.c3
-rw-r--r--drivers/net/ethernet/sfc/falcon/farch.c3
-rw-r--r--drivers/net/ethernet/sfc/farch.c3
-rw-r--r--drivers/net/ethernet/socionext/netsec.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig12
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c7
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c18
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.c9
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c38
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c4
-rw-r--r--drivers/net/ethernet/sun/sungem.c22
-rw-r--r--drivers/net/ethernet/ti/cpsw.c9
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c15
-rw-r--r--drivers/net/ethernet/ti/netcp_ethss.c24
-rw-r--r--drivers/net/ethernet/toshiba/ps3_gelic_wireless.c5
-rw-r--r--drivers/net/ethernet/xilinx/xilinx_emaclite.c12
-rw-r--r--drivers/net/fddi/skfp/skfddi.c55
-rw-r--r--drivers/net/gtp.c6
-rw-r--r--drivers/net/hamradio/bpqether.c8
-rw-r--r--drivers/net/hippi/rrunner.c2
-rw-r--r--drivers/net/hyperv/Kconfig1
-rw-r--r--drivers/net/hyperv/hyperv_net.h31
-rw-r--r--drivers/net/hyperv/netvsc.c18
-rw-r--r--drivers/net/hyperv/netvsc_drv.c249
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c1
-rw-r--r--drivers/net/net_failover.c2
-rw-r--r--drivers/net/phy/dp83640.c5
-rw-r--r--drivers/net/phy/dp83848.c35
-rw-r--r--drivers/net/phy/mdio-gpio.c3
-rw-r--r--drivers/net/phy/phy_led_triggers.c6
-rw-r--r--drivers/net/ppp/bsd_comp.c4
-rw-r--r--drivers/net/ppp/pptp.c2
-rw-r--r--drivers/net/slip/slip.c2
-rw-r--r--drivers/net/tap.c5
-rw-r--r--drivers/net/team/team.c5
-rw-r--r--drivers/net/tun.c3
-rw-r--r--drivers/net/usb/asix_common.c8
-rw-r--r--drivers/net/usb/ax88179_178a.c4
-rw-r--r--drivers/net/usb/cdc_ncm.c7
-rw-r--r--drivers/net/usb/smsc95xx.c2
-rw-r--r--drivers/net/usb/usbnet.c4
-rw-r--r--drivers/net/virtio_net.c15
-rw-r--r--drivers/net/wan/fsl_ucc_hdlc.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c3
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_paprd.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c4
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c7
-rw-r--r--drivers/net/wireless/broadcom/b43/phy_n.c2
-rw-r--r--drivers/net/wireless/broadcom/b43legacy/main.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c7
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c8
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c5
-rw-r--r--drivers/net/wireless/cisco/airo.c2
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2100.c11
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2200.c10
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.c13
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/scan.c2
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_info.c5
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_ioctl.c4
-rw-r--r--drivers/net/wireless/intersil/p54/eeprom.c12
-rw-r--r--drivers/net/wireless/intersil/prism54/oid_mgt.c2
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c11
-rw-r--r--drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sdio.c9
-rw-r--r--drivers/net/wireless/mediatek/mt76/mac80211.c2
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/commands.c2
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00debug.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/efuse.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c2
-rw-r--r--drivers/net/wireless/st/cw1200/queue.c10
-rw-r--r--drivers/net/wireless/st/cw1200/scan.c6
-rw-r--r--drivers/net/wireless/zydas/zd1211rw/zd_mac.c3
-rw-r--r--drivers/net/xen-netback/xenbus.c4
-rw-r--r--drivers/net/xen-netfront.c4
-rw-r--r--drivers/nfc/fdp/i2c.c4
-rw-r--r--drivers/ntb/hw/amd/ntb_hw_amd.c4
-rw-r--r--drivers/ntb/hw/idt/ntb_hw_idt.c2
-rw-r--r--drivers/ntb/hw/intel/Makefile1
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_gen1.c (renamed from drivers/ntb/hw/intel/ntb_hw_intel.c)717
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_gen1.h182
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_gen3.c597
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_gen3.h110
-rw-r--r--drivers/ntb/hw/intel/ntb_hw_intel.h203
-rw-r--r--drivers/ntb/ntb_transport.c10
-rw-r--r--drivers/nvme/host/core.c49
-rw-r--r--drivers/nvme/host/fabrics.c86
-rw-r--r--drivers/nvme/host/fabrics.h14
-rw-r--r--drivers/nvme/host/fc.c150
-rw-r--r--drivers/nvme/host/multipath.c4
-rw-r--r--drivers/nvme/host/nvme.h3
-rw-r--r--drivers/nvme/host/pci.c44
-rw-r--r--drivers/nvme/host/rdma.c111
-rw-r--r--drivers/nvme/target/admin-cmd.c4
-rw-r--r--drivers/nvme/target/core.c8
-rw-r--r--drivers/nvme/target/loop.c7
-rw-r--r--drivers/nvmem/rockchip-efuse.c6
-rw-r--r--drivers/nvmem/sunxi_sid.c2
-rw-r--r--drivers/of/platform.c3
-rw-r--r--drivers/of/unittest.c2
-rw-r--r--drivers/opp/core.c2
-rw-r--r--drivers/opp/ti-opp-supply.c4
-rw-r--r--drivers/oprofile/event_buffer.c2
-rw-r--r--drivers/parport/Kconfig6
-rw-r--r--drivers/pci/Kconfig4
-rw-r--r--drivers/pci/Makefile6
-rw-r--r--drivers/pci/cadence/Kconfig27
-rw-r--r--drivers/pci/cadence/Makefile4
-rw-r--r--drivers/pci/controller/Kconfig (renamed from drivers/pci/host/Kconfig)31
-rw-r--r--drivers/pci/controller/Makefile (renamed from drivers/pci/host/Makefile)6
-rw-r--r--drivers/pci/controller/dwc/Kconfig (renamed from drivers/pci/dwc/Kconfig)0
-rw-r--r--drivers/pci/controller/dwc/Makefile (renamed from drivers/pci/dwc/Makefile)0
-rw-r--r--drivers/pci/controller/dwc/pci-dra7xx.c (renamed from drivers/pci/dwc/pci-dra7xx.c)6
-rw-r--r--drivers/pci/controller/dwc/pci-exynos.c (renamed from drivers/pci/dwc/pci-exynos.c)0
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c (renamed from drivers/pci/dwc/pci-imx6.c)0
-rw-r--r--drivers/pci/controller/dwc/pci-keystone-dw.c (renamed from drivers/pci/dwc/pci-keystone-dw.c)0
-rw-r--r--drivers/pci/controller/dwc/pci-keystone.c (renamed from drivers/pci/dwc/pci-keystone.c)0
-rw-r--r--drivers/pci/controller/dwc/pci-keystone.h (renamed from drivers/pci/dwc/pci-keystone.h)0
-rw-r--r--drivers/pci/controller/dwc/pci-layerscape.c (renamed from drivers/pci/dwc/pci-layerscape.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-armada8k.c (renamed from drivers/pci/dwc/pcie-armada8k.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-artpec6.c (renamed from drivers/pci/dwc/pcie-artpec6.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-ep.c (renamed from drivers/pci/dwc/pcie-designware-ep.c)8
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-host.c (renamed from drivers/pci/dwc/pcie-designware-host.c)2
-rw-r--r--drivers/pci/controller/dwc/pcie-designware-plat.c (renamed from drivers/pci/dwc/pcie-designware-plat.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.c (renamed from drivers/pci/dwc/pcie-designware.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.h (renamed from drivers/pci/dwc/pcie-designware.h)0
-rw-r--r--drivers/pci/controller/dwc/pcie-hisi.c (renamed from drivers/pci/dwc/pcie-hisi.c)2
-rw-r--r--drivers/pci/controller/dwc/pcie-histb.c (renamed from drivers/pci/dwc/pcie-histb.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-kirin.c (renamed from drivers/pci/dwc/pcie-kirin.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c (renamed from drivers/pci/dwc/pcie-qcom.c)0
-rw-r--r--drivers/pci/controller/dwc/pcie-spear13xx.c (renamed from drivers/pci/dwc/pcie-spear13xx.c)0
-rw-r--r--drivers/pci/controller/pci-aardvark.c (renamed from drivers/pci/host/pci-aardvark.c)0
-rw-r--r--drivers/pci/controller/pci-ftpci100.c (renamed from drivers/pci/host/pci-ftpci100.c)0
-rw-r--r--drivers/pci/controller/pci-host-common.c (renamed from drivers/pci/host/pci-host-common.c)0
-rw-r--r--drivers/pci/controller/pci-host-generic.c (renamed from drivers/pci/host/pci-host-generic.c)0
-rw-r--r--drivers/pci/controller/pci-hyperv.c (renamed from drivers/pci/host/pci-hyperv.c)0
-rw-r--r--drivers/pci/controller/pci-mvebu.c (renamed from drivers/pci/host/pci-mvebu.c)0
-rw-r--r--drivers/pci/controller/pci-rcar-gen2.c (renamed from drivers/pci/host/pci-rcar-gen2.c)0
-rw-r--r--drivers/pci/controller/pci-tegra.c (renamed from drivers/pci/host/pci-tegra.c)0
-rw-r--r--drivers/pci/controller/pci-thunder-ecam.c (renamed from drivers/pci/host/pci-thunder-ecam.c)0
-rw-r--r--drivers/pci/controller/pci-thunder-pem.c (renamed from drivers/pci/host/pci-thunder-pem.c)0
-rw-r--r--drivers/pci/controller/pci-v3-semi.c (renamed from drivers/pci/host/pci-v3-semi.c)0
-rw-r--r--drivers/pci/controller/pci-versatile.c (renamed from drivers/pci/host/pci-versatile.c)0
-rw-r--r--drivers/pci/controller/pci-xgene-msi.c (renamed from drivers/pci/host/pci-xgene-msi.c)0
-rw-r--r--drivers/pci/controller/pci-xgene.c (renamed from drivers/pci/host/pci-xgene.c)0
-rw-r--r--drivers/pci/controller/pcie-altera-msi.c (renamed from drivers/pci/host/pcie-altera-msi.c)0
-rw-r--r--drivers/pci/controller/pcie-altera.c (renamed from drivers/pci/host/pcie-altera.c)0
-rw-r--r--drivers/pci/controller/pcie-cadence-ep.c (renamed from drivers/pci/cadence/pcie-cadence-ep.c)3
-rw-r--r--drivers/pci/controller/pcie-cadence-host.c (renamed from drivers/pci/cadence/pcie-cadence-host.c)0
-rw-r--r--drivers/pci/controller/pcie-cadence.c (renamed from drivers/pci/cadence/pcie-cadence.c)0
-rw-r--r--drivers/pci/controller/pcie-cadence.h (renamed from drivers/pci/cadence/pcie-cadence.h)0
-rw-r--r--drivers/pci/controller/pcie-iproc-bcma.c (renamed from drivers/pci/host/pcie-iproc-bcma.c)0
-rw-r--r--drivers/pci/controller/pcie-iproc-msi.c (renamed from drivers/pci/host/pcie-iproc-msi.c)0
-rw-r--r--drivers/pci/controller/pcie-iproc-platform.c (renamed from drivers/pci/host/pcie-iproc-platform.c)0
-rw-r--r--drivers/pci/controller/pcie-iproc.c (renamed from drivers/pci/host/pcie-iproc.c)0
-rw-r--r--drivers/pci/controller/pcie-iproc.h (renamed from drivers/pci/host/pcie-iproc.h)0
-rw-r--r--drivers/pci/controller/pcie-mediatek.c (renamed from drivers/pci/host/pcie-mediatek.c)0
-rw-r--r--drivers/pci/controller/pcie-mobiveil.c (renamed from drivers/pci/host/pcie-mobiveil.c)0
-rw-r--r--drivers/pci/controller/pcie-rcar.c (renamed from drivers/pci/host/pcie-rcar.c)0
-rw-r--r--drivers/pci/controller/pcie-rockchip-ep.c (renamed from drivers/pci/host/pcie-rockchip-ep.c)2
-rw-r--r--drivers/pci/controller/pcie-rockchip-host.c (renamed from drivers/pci/host/pcie-rockchip-host.c)0
-rw-r--r--drivers/pci/controller/pcie-rockchip.c (renamed from drivers/pci/host/pcie-rockchip.c)0
-rw-r--r--drivers/pci/controller/pcie-rockchip.h (renamed from drivers/pci/host/pcie-rockchip.h)0
-rw-r--r--drivers/pci/controller/pcie-tango.c (renamed from drivers/pci/host/pcie-tango.c)0
-rw-r--r--drivers/pci/controller/pcie-xilinx-nwl.c (renamed from drivers/pci/host/pcie-xilinx-nwl.c)0
-rw-r--r--drivers/pci/controller/pcie-xilinx.c (renamed from drivers/pci/host/pcie-xilinx.c)0
-rw-r--r--drivers/pci/controller/vmd.c (renamed from drivers/pci/host/vmd.c)0
-rw-r--r--drivers/pci/msi.c4
-rw-r--r--drivers/pci/pci-sysfs.c2
-rw-r--r--drivers/pci/pcie/Kconfig41
-rw-r--r--drivers/pci/pcie/Makefile3
-rw-r--r--drivers/pci/pcie/aer.c1377
-rw-r--r--drivers/pci/pcie/aer/Kconfig29
-rw-r--r--drivers/pci/pcie/aer/Kconfig.debug19
-rw-r--r--drivers/pci/pcie/aer/Makefile13
-rw-r--r--drivers/pci/pcie/aer/aerdrv.c371
-rw-r--r--drivers/pci/pcie/aer/aerdrv.h95
-rw-r--r--drivers/pci/pcie/aer/aerdrv_acpi.c141
-rw-r--r--drivers/pci/pcie/aer/aerdrv_core.c496
-rw-r--r--drivers/pci/pcie/aer/aerdrv_errprint.c260
-rw-r--r--drivers/pci/pcie/aer/ecrc.c117
-rw-r--r--drivers/pci/pcie/aer_inject.c (renamed from drivers/pci/pcie/aer/aer_inject.c)3
-rw-r--r--drivers/pci/pcie/dpc.c1
-rw-r--r--drivers/pci/pcie/portdrv.h15
-rw-r--r--drivers/pcmcia/cistpl.c4
-rw-r--r--drivers/pcmcia/pd6729.c2
-rw-r--r--drivers/pinctrl/actions/pinctrl-owl.c2
-rw-r--r--drivers/pinctrl/bcm/pinctrl-bcm2835.c4
-rw-r--r--drivers/pinctrl/berlin/berlin.c10
-rw-r--r--drivers/pinctrl/devicetree.c7
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.c18
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx1-core.c23
-rw-r--r--drivers/pinctrl/freescale/pinctrl-mxs.c20
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt7622.c6
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.c5
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-37xx.c21
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-xp.c4
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-mvebu.c16
-rw-r--r--drivers/pinctrl/pinctrl-at91-pio4.c39
-rw-r--r--drivers/pinctrl/pinctrl-at91.c34
-rw-r--r--drivers/pinctrl/pinctrl-axp209.c7
-rw-r--r--drivers/pinctrl/pinctrl-digicolor.c5
-rw-r--r--drivers/pinctrl/pinctrl-ingenic.c4
-rw-r--r--drivers/pinctrl/pinctrl-lantiq.c3
-rw-r--r--drivers/pinctrl/pinctrl-lpc18xx.c5
-rw-r--r--drivers/pinctrl/pinctrl-ocelot.c3
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c24
-rw-r--r--drivers/pinctrl/pinctrl-single.c40
-rw-r--r--drivers/pinctrl/pinctrl-st.c31
-rw-r--r--drivers/pinctrl/pinctrl-xway.c4
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.c5
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c17
-rw-r--r--drivers/pinctrl/sh-pfc/core.c6
-rw-r--r--drivers/pinctrl/sh-pfc/gpio.c7
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c8
-rw-r--r--drivers/pinctrl/sirf/pinctrl-sirf.c2
-rw-r--r--drivers/pinctrl/spear/pinctrl-plgpio.c4
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear.c2
-rw-r--r--drivers/pinctrl/sprd/pinctrl-sprd.c19
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c22
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra.c6
-rw-r--r--drivers/pinctrl/ti/pinctrl-ti-iodelay.c6
-rw-r--r--drivers/pinctrl/vt8500/pinctrl-wmt.c2
-rw-r--r--drivers/pinctrl/zte/pinctrl-zx.c6
-rw-r--r--drivers/platform/chrome/cros_ec_debugfs.c20
-rw-r--r--drivers/platform/mellanox/mlxreg-hotplug.c57
-rw-r--r--drivers/platform/x86/Kconfig2
-rw-r--r--drivers/platform/x86/acer-wmi.c1
-rw-r--r--drivers/platform/x86/alienware-wmi.c6
-rw-r--r--drivers/platform/x86/apple-gmux.c2
-rw-r--r--drivers/platform/x86/asus-laptop.c3
-rw-r--r--drivers/platform/x86/asus-wireless.c2
-rw-r--r--drivers/platform/x86/asus-wmi.c3
-rw-r--r--drivers/platform/x86/dell-laptop.c17
-rw-r--r--drivers/platform/x86/dell-smbios-base.c5
-rw-r--r--drivers/platform/x86/dell-wmi.c16
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c47
-rw-r--r--drivers/platform/x86/ideapad-laptop.c66
-rw-r--r--drivers/platform/x86/intel_ips.c12
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c4
-rw-r--r--drivers/platform/x86/mlx-platform.c289
-rw-r--r--drivers/platform/x86/panasonic-laptop.c2
-rw-r--r--drivers/platform/x86/samsung-laptop.c3
-rw-r--r--drivers/platform/x86/silead_dmi.c101
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c32
-rw-r--r--drivers/power/supply/charger-manager.c29
-rw-r--r--drivers/power/supply/power_supply_core.c4
-rw-r--r--drivers/power/supply/wm97xx_battery.c2
-rw-r--r--drivers/power/supply/z2_battery.c2
-rw-r--r--drivers/powercap/powercap_sys.c9
-rw-r--r--drivers/ptp/ptp_chardev.c4
-rw-r--r--drivers/ptp/ptp_qoriq.c2
-rw-r--r--drivers/pwm/Kconfig2
-rw-r--r--drivers/pwm/pwm-atmel-tcb.c6
-rw-r--r--drivers/pwm/pwm-lp3943.c2
-rw-r--r--drivers/pwm/pwm-lpss-platform.c5
-rw-r--r--drivers/pwm/pwm-lpss.c30
-rw-r--r--drivers/pwm/pwm-lpss.h2
-rw-r--r--drivers/pwm/pwm-meson.c4
-rw-r--r--drivers/pwm/pwm-rcar.c3
-rw-r--r--drivers/pwm/pwm-stm32.c255
-rw-r--r--drivers/rapidio/devices/rio_mport_cdev.c2
-rw-r--r--drivers/rapidio/rio-scan.c6
-rw-r--r--drivers/regulator/act8865-regulator.c7
-rw-r--r--drivers/regulator/as3711-regulator.c6
-rw-r--r--drivers/regulator/bcm590xx-regulator.c6
-rw-r--r--drivers/regulator/da9063-regulator.c4
-rw-r--r--drivers/regulator/gpio-regulator.c10
-rw-r--r--drivers/regulator/max1586.c6
-rw-r--r--drivers/regulator/max8660.c6
-rw-r--r--drivers/regulator/max8997-regulator.c5
-rw-r--r--drivers/regulator/max8998.c5
-rw-r--r--drivers/regulator/mc13xxx-regulator-core.c2
-rw-r--r--drivers/regulator/pbias-regulator.c5
-rw-r--r--drivers/regulator/rc5t583-regulator.c6
-rw-r--r--drivers/regulator/s2mps11.c6
-rw-r--r--drivers/regulator/s5m8767.c10
-rw-r--r--drivers/regulator/ti-abb-regulator.c4
-rw-r--r--drivers/regulator/tps65090-regulator.c10
-rw-r--r--drivers/regulator/tps65217-regulator.c5
-rw-r--r--drivers/regulator/tps65218-regulator.c5
-rw-r--r--drivers/regulator/tps65910-regulator.c18
-rw-r--r--drivers/regulator/tps80031-regulator.c4
-rw-r--r--drivers/remoteproc/Kconfig1
-rw-r--r--drivers/remoteproc/da8xx_remoteproc.c12
-rw-r--r--drivers/remoteproc/qcom_q6v5_pil.c203
-rw-r--r--drivers/reset/reset-ti-syscon.c3
-rw-r--r--drivers/reset/reset-uniphier.c13
-rw-r--r--drivers/rpmsg/Kconfig3
-rw-r--r--drivers/rpmsg/qcom_glink_native.c10
-rw-r--r--drivers/rpmsg/qcom_glink_native.h10
-rw-r--r--drivers/rpmsg/qcom_glink_rpm.c10
-rw-r--r--drivers/rpmsg/qcom_glink_smem.c10
-rw-r--r--drivers/rpmsg/qcom_smd.c96
-rw-r--r--drivers/rpmsg/rpmsg_char.c10
-rw-r--r--drivers/rpmsg/rpmsg_core.c49
-rw-r--r--drivers/rpmsg/rpmsg_internal.h10
-rw-r--r--drivers/rpmsg/virtio_rpmsg_bus.c10
-rw-r--r--drivers/rtc/Kconfig2
-rw-r--r--drivers/rtc/interface.c5
-rw-r--r--drivers/rtc/nvmem.c2
-rw-r--r--drivers/rtc/rtc-88pm80x.c58
-rw-r--r--drivers/rtc/rtc-ab-b5ze-s3.c30
-rw-r--r--drivers/rtc/rtc-at91rm9200.c2
-rw-r--r--drivers/rtc/rtc-bq4802.c6
-rw-r--r--drivers/rtc/rtc-brcmstb-waketimer.c20
-rw-r--r--drivers/rtc/rtc-cmos.c155
-rw-r--r--drivers/rtc/rtc-cros-ec.c23
-rw-r--r--drivers/rtc/rtc-ds1216.c6
-rw-r--r--drivers/rtc/rtc-ds1307.c2
-rw-r--r--drivers/rtc/rtc-ds1511.c9
-rw-r--r--drivers/rtc/rtc-ds1553.c15
-rw-r--r--drivers/rtc/rtc-ds1685.c66
-rw-r--r--drivers/rtc/rtc-ds1742.c8
-rw-r--r--drivers/rtc/rtc-ftrtc010.c36
-rw-r--r--drivers/rtc/rtc-lpc32xx.c16
-rw-r--r--drivers/rtc/rtc-ls1x.c32
-rw-r--r--drivers/rtc/rtc-m48t59.c41
-rw-r--r--drivers/rtc/rtc-mrst.c45
-rw-r--r--drivers/rtc/rtc-mt6397.c7
-rw-r--r--drivers/rtc/rtc-mv.c3
-rw-r--r--drivers/rtc/rtc-mxc.c34
-rw-r--r--drivers/rtc/rtc-mxc_v2.c29
-rw-r--r--drivers/rtc/rtc-pcap.c15
-rw-r--r--drivers/rtc/rtc-pxa.c2
-rw-r--r--drivers/rtc/rtc-rx8581.c210
-rw-r--r--drivers/rtc/rtc-sc27xx.c63
-rw-r--r--drivers/rtc/rtc-sh.c15
-rw-r--r--drivers/rtc/rtc-snvs.c13
-rw-r--r--drivers/rtc/rtc-st-lpc.c26
-rw-r--r--drivers/rtc/rtc-stk17ta8.c15
-rw-r--r--drivers/rtc/rtc-stm32.c339
-rw-r--r--drivers/rtc/rtc-sun6i.c4
-rw-r--r--drivers/rtc/rtc-sunxi.c23
-rw-r--r--drivers/rtc/rtc-test.c208
-rw-r--r--drivers/rtc/rtc-tps6586x.c55
-rw-r--r--drivers/rtc/rtc-tps65910.c26
-rw-r--r--drivers/rtc/rtc-vr41xx.c35
-rw-r--r--drivers/rtc/rtc-zynqmp.c10
-rw-r--r--drivers/s390/block/dasd.c171
-rw-r--r--drivers/s390/block/dasd_alias.c6
-rw-r--r--drivers/s390/block/dasd_diag.c3
-rw-r--r--drivers/s390/block/dasd_eckd.c46
-rw-r--r--drivers/s390/block/dasd_eer.c14
-rw-r--r--drivers/s390/block/dasd_fba.c6
-rw-r--r--drivers/s390/block/dasd_int.h26
-rw-r--r--drivers/s390/block/dcssblk.c6
-rw-r--r--drivers/s390/char/keyboard.c2
-rw-r--r--drivers/s390/char/sclp_sd.c2
-rw-r--r--drivers/s390/char/tty3270.c3
-rw-r--r--drivers/s390/char/vmur.c2
-rw-r--r--drivers/s390/char/zcore.c2
-rw-r--r--drivers/s390/cio/Makefile1
-rw-r--r--drivers/s390/cio/qdio_setup.c2
-rw-r--r--drivers/s390/cio/qdio_thinint.c5
-rw-r--r--drivers/s390/cio/vfio_ccw_cp.c140
-rw-r--r--drivers/s390/cio/vfio_ccw_drv.c5
-rw-r--r--drivers/s390/cio/vfio_ccw_fsm.c17
-rw-r--r--drivers/s390/cio/vfio_ccw_trace.h54
-rw-r--r--drivers/s390/crypto/pkey_api.c8
-rw-r--r--drivers/s390/net/ctcm_main.c2
-rw-r--r--drivers/s390/net/qeth_core_main.c27
-rw-r--r--drivers/s390/scsi/zfcp_dbf.c90
-rw-r--r--drivers/s390/scsi/zfcp_dbf.h21
-rw-r--r--drivers/s390/scsi/zfcp_erp.c194
-rw-r--r--drivers/s390/scsi/zfcp_ext.h16
-rw-r--r--drivers/s390/scsi/zfcp_fc.c11
-rw-r--r--drivers/s390/scsi/zfcp_fc.h22
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c61
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h6
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c141
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c5
-rw-r--r--drivers/sbus/char/oradax.c2
-rw-r--r--drivers/scsi/3w-9xxx.c5
-rw-r--r--drivers/scsi/3w-xxxx.c3
-rw-r--r--drivers/scsi/BusLogic.c2
-rw-r--r--drivers/scsi/Kconfig14
-rw-r--r--drivers/scsi/Makefile3
-rw-r--r--drivers/scsi/a100u2w.c13
-rw-r--r--drivers/scsi/aacraid/aachba.c2
-rw-r--r--drivers/scsi/aacraid/commctrl.c4
-rw-r--r--drivers/scsi/aacraid/linit.c4
-rw-r--r--drivers/scsi/aha1542.c3
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c11
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_core.c4
-rw-r--r--drivers/scsi/aic94xx/aic94xx_hwi.c12
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c2
-rw-r--r--drivers/scsi/am53c974.c13
-rw-r--r--drivers/scsi/arm/queue.c2
-rw-r--r--drivers/scsi/be2iscsi/be_main.c54
-rw-r--r--drivers/scsi/bfa/bfad_attr.c2
-rw-r--r--drivers/scsi/bfa/bfad_bsg.c5
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_fcoe.c2
-rw-r--r--drivers/scsi/bnx2fc/bnx2fc_io.c8
-rw-r--r--drivers/scsi/csiostor/csio_wr.c4
-rw-r--r--drivers/scsi/cxlflash/Kconfig2
-rw-r--r--drivers/scsi/cxlflash/Makefile4
-rw-r--r--drivers/scsi/cxlflash/backend.h55
-rw-r--r--drivers/scsi/cxlflash/common.h12
-rw-r--r--drivers/scsi/cxlflash/cxl_hw.c13
-rw-r--r--drivers/scsi/cxlflash/lunmgt.c4
-rw-r--r--drivers/scsi/cxlflash/main.c97
-rw-r--r--drivers/scsi/cxlflash/main.h21
-rw-r--r--drivers/scsi/cxlflash/ocxl_hw.c1436
-rw-r--r--drivers/scsi/cxlflash/ocxl_hw.h77
-rw-r--r--drivers/scsi/cxlflash/sislite.h41
-rw-r--r--drivers/scsi/cxlflash/superpipe.c23
-rw-r--r--drivers/scsi/cxlflash/vlun.c3
-rw-r--r--drivers/scsi/dpt_i2o.c21
-rw-r--r--drivers/scsi/esas2r/esas2r_init.c16
-rw-r--r--drivers/scsi/esas2r/esas2r_ioctl.c2
-rw-r--r--drivers/scsi/esas2r/esas2r_main.c2
-rw-r--r--drivers/scsi/fcoe/fcoe_ctlr.c4
-rw-r--r--drivers/scsi/fnic/fnic_debugfs.c7
-rw-r--r--drivers/scsi/fnic/fnic_trace.c15
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas.h52
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_main.c638
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v1_hw.c164
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v2_hw.c284
-rw-r--r--drivers/scsi/hisi_sas/hisi_sas_v3_hw.c452
-rw-r--r--drivers/scsi/hpsa.c46
-rw-r--r--drivers/scsi/ipr.c18
-rw-r--r--drivers/scsi/ips.c78
-rw-r--r--drivers/scsi/ips.h11
-rw-r--r--drivers/scsi/isci/init.c11
-rw-r--r--drivers/scsi/iscsi_tcp.c1
-rw-r--r--drivers/scsi/libiscsi.c2
-rw-r--r--drivers/scsi/libsas/sas_ata.c5
-rw-r--r--drivers/scsi/libsas/sas_discover.c1
-rw-r--r--drivers/scsi/libsas/sas_expander.c2
-rw-r--r--drivers/scsi/lpfc/lpfc.h9
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c124
-rw-r--r--drivers/scsi/lpfc/lpfc_bsg.c20
-rw-r--r--drivers/scsi/lpfc/lpfc_ct.c10
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c98
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_hbadisc.c7
-rw-r--r--drivers/scsi/lpfc/lpfc_hw4.h7
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c160
-rw-r--r--drivers/scsi/lpfc/lpfc_mem.c5
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c35
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.c238
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.h17
-rw-r--r--drivers/scsi/lpfc/lpfc_nvmet.h6
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c33
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c166
-rw-r--r--drivers/scsi/lpfc/lpfc_version.h4
-rw-r--r--drivers/scsi/lpfc/lpfc_vport.c2
-rw-r--r--drivers/scsi/mac53c94.c5
-rw-r--r--drivers/scsi/megaraid.c6
-rw-r--r--drivers/scsi/megaraid/megaraid_mm.c10
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.h4
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c35
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_fusion.c20
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2.h9
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h30
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_init.h2
-rw-r--r--drivers/scsi/mpt3sas/mpi/mpi2_ioc.h7
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c478
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h60
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.c33
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_ctl.h2
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_scsih.c491
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_warpdrive.c3
-rw-r--r--drivers/scsi/mvumi.c20
-rw-r--r--drivers/scsi/osd/osd_initiator.c16
-rw-r--r--drivers/scsi/osst.c8
-rw-r--r--drivers/scsi/pm8001/pm8001_ctl.c2
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c2
-rw-r--r--drivers/scsi/pmcraid.c5
-rw-r--r--drivers/scsi/qedf/drv_fcoe_fw_funcs.c2
-rw-r--r--drivers/scsi/qedf/drv_fcoe_fw_funcs.h2
-rw-r--r--drivers/scsi/qedf/drv_scsi_fw_funcs.c2
-rw-r--r--drivers/scsi/qedf/drv_scsi_fw_funcs.h2
-rw-r--r--drivers/scsi/qedf/qedf.h6
-rw-r--r--drivers/scsi/qedf/qedf_attr.c2
-rw-r--r--drivers/scsi/qedf/qedf_dbg.c4
-rw-r--r--drivers/scsi/qedf/qedf_dbg.h2
-rw-r--r--drivers/scsi/qedf/qedf_debugfs.c2
-rw-r--r--drivers/scsi/qedf/qedf_els.c35
-rw-r--r--drivers/scsi/qedf/qedf_fip.c5
-rw-r--r--drivers/scsi/qedf/qedf_hsi.h2
-rw-r--r--drivers/scsi/qedf/qedf_io.c87
-rw-r--r--drivers/scsi/qedf/qedf_main.c130
-rw-r--r--drivers/scsi/qedf/qedf_version.h6
-rw-r--r--drivers/scsi/qedi/qedi_main.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h3
-rw-r--r--drivers/scsi/qla2xxx/qla_gs.c41
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c118
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c13
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c8
-rw-r--r--drivers/scsi/qla2xxx/qla_nx.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c18
-rw-r--r--drivers/scsi/qla2xxx/qla_target.c202
-rw-r--r--drivers/scsi/qla2xxx/qla_target.h4
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c41
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c2
-rw-r--r--drivers/scsi/qlogicpti.c6
-rw-r--r--drivers/scsi/scsi_debug.c5
-rw-r--r--drivers/scsi/scsi_debugfs.c2
-rw-r--r--drivers/scsi/scsi_devinfo.c31
-rw-r--r--drivers/scsi/scsi_dh.c5
-rw-r--r--drivers/scsi/scsi_error.c7
-rw-r--r--drivers/scsi/scsi_lib.c4
-rw-r--r--drivers/scsi/scsi_sysfs.c2
-rw-r--r--drivers/scsi/scsi_transport_fc.c2
-rw-r--r--drivers/scsi/scsi_transport_sas.c4
-rw-r--r--drivers/scsi/sd.h12
-rw-r--r--drivers/scsi/sd_zbc.c14
-rw-r--r--drivers/scsi/ses.c2
-rw-r--r--drivers/scsi/sg.c4
-rw-r--r--drivers/scsi/smartpqi/smartpqi_init.c10
-rw-r--r--drivers/scsi/snic/snic_scsi.c6
-rw-r--r--drivers/scsi/st.c11
-rw-r--r--drivers/scsi/storvsc_drv.c85
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c2
-rw-r--r--drivers/scsi/ufs/ufshcd-pltfrm.c4
-rw-r--r--drivers/scsi/ufs/ufshcd.c312
-rw-r--r--drivers/scsi/ufs/ufshcd.h21
-rw-r--r--drivers/scsi/virtio_scsi.c7
-rw-r--r--drivers/scsi/wd719x.c13
-rw-r--r--drivers/scsi/xen-scsifront.c33
-rw-r--r--drivers/scsi/zorro_esp.c1172
-rw-r--r--drivers/sh/clk/cpg.c2
-rw-r--r--drivers/sh/intc/core.c10
-rw-r--r--drivers/sh/maple/maple.c2
-rw-r--r--drivers/slimbus/qcom-ctrl.c2
-rw-r--r--drivers/soc/Makefile2
-rw-r--r--drivers/soc/bcm/raspberrypi-power.c6
-rw-r--r--drivers/soc/fsl/qbman/qman.c5
-rw-r--r--drivers/soc/imx/gpc.c18
-rw-r--r--drivers/soc/imx/gpcv2.c22
-rw-r--r--drivers/soc/mediatek/mtk-infracfg.c46
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c13
-rw-r--r--drivers/soc/mediatek/mtk-scpsys.c175
-rw-r--r--drivers/soc/qcom/Kconfig18
-rw-r--r--drivers/soc/qcom/Makefile2
-rw-r--r--drivers/soc/qcom/cmd-db.c317
-rw-r--r--drivers/soc/qcom/mdt_loader.c4
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c748
-rw-r--r--drivers/soc/qcom/qmi_interface.c5
-rw-r--r--drivers/soc/qcom/smd-rpm.c1
-rw-r--r--drivers/soc/qcom/smem.c77
-rw-r--r--drivers/soc/renesas/Kconfig13
-rw-r--r--drivers/soc/renesas/Makefile2
-rw-r--r--drivers/soc/renesas/r8a77470-sysc.c29
-rw-r--r--drivers/soc/renesas/r8a77990-sysc.c68
-rw-r--r--drivers/soc/renesas/r8a77995-sysc.c3
-rw-r--r--drivers/soc/renesas/rcar-rst.c2
-rw-r--r--drivers/soc/renesas/rcar-sysc.c6
-rw-r--r--drivers/soc/renesas/rcar-sysc.h2
-rw-r--r--drivers/soc/renesas/renesas-soc.c16
-rw-r--r--drivers/soc/rockchip/pm_domains.c117
-rw-r--r--drivers/soc/samsung/pm_domains.c90
-rw-r--r--drivers/soc/ti/knav_qmss.h14
-rw-r--r--drivers/soc/ti/knav_qmss_acc.c6
-rw-r--r--drivers/soc/ti/knav_qmss_queue.c60
-rw-r--r--drivers/soundwire/stream.c8
-rw-r--r--drivers/spi/spi-davinci.c7
-rw-r--r--drivers/spi/spi-ep93xx.c4
-rw-r--r--drivers/spi/spi-gpio.c5
-rw-r--r--drivers/spi/spi-imx.c5
-rw-r--r--drivers/spi/spi-oc-tiny.c4
-rw-r--r--drivers/spi/spi-pl022.c2
-rw-r--r--drivers/spi/spi.c2
-rw-r--r--drivers/staging/android/ion/ion_heap.c3
-rw-r--r--drivers/staging/fbtft/fbtft-core.c4
-rw-r--r--drivers/staging/fbtft/fbtft.h1
-rw-r--r--drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt2
-rw-r--r--drivers/staging/greybus/audio_topology.c2
-rw-r--r--drivers/staging/greybus/camera.c5
-rw-r--r--drivers/staging/media/bcm2048/TODO2
-rw-r--r--drivers/staging/media/imx/imx-media-dev.c6
-rw-r--r--drivers/staging/media/zoran/Kconfig2
-rw-r--r--drivers/staging/media/zoran/zoran_driver.c5
-rw-r--r--drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c26
-rw-r--r--drivers/staging/rtl8188eu/core/rtw_mlme.c2
-rw-r--r--drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c5
-rw-r--r--drivers/staging/rtl8192u/r8192U_core.c4
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme.c2
-rw-r--r--drivers/staging/rtlwifi/efuse.c4
-rw-r--r--drivers/staging/rts5208/ms.c2
-rw-r--r--drivers/staging/rts5208/rtsx_chip.c6
-rw-r--r--drivers/staging/unisys/visorhba/visorhba_main.c2
-rw-r--r--drivers/target/target_core_configfs.c25
-rw-r--r--drivers/target/target_core_file.c137
-rw-r--r--drivers/target/target_core_file.h1
-rw-r--r--drivers/target/target_core_internal.h1
-rw-r--r--drivers/target/target_core_pscsi.c26
-rw-r--r--drivers/target/target_core_transport.c68
-rw-r--r--drivers/target/target_core_user.c165
-rw-r--r--drivers/thermal/imx_thermal.c306
-rw-r--r--drivers/thermal/int340x_thermal/acpi_thermal_rel.c4
-rw-r--r--drivers/thermal/int340x_thermal/int340x_thermal_zone.c13
-rw-r--r--drivers/thermal/int340x_thermal/processor_thermal_device.c4
-rw-r--r--drivers/thermal/mtk_thermal.c40
-rw-r--r--drivers/thermal/of-thermal.c23
-rw-r--r--drivers/thermal/qcom-spmi-temp-alarm.c92
-rw-r--r--drivers/thermal/qcom/tsens.c12
-rw-r--r--drivers/thermal/rcar_gen3_thermal.c17
-rw-r--r--drivers/thermal/rcar_thermal.c158
-rw-r--r--drivers/thermal/samsung/exynos_tmu.c959
-rw-r--r--drivers/thermal/samsung/exynos_tmu.h75
-rw-r--r--drivers/thermal/tegra/soctherm.c39
-rw-r--r--drivers/thermal/thermal-generic-adc.c5
-rw-r--r--drivers/thermal/thermal_core.c11
-rw-r--r--drivers/thermal/thermal_core.h30
-rw-r--r--drivers/thermal/thermal_helpers.c5
-rw-r--r--drivers/thermal/thermal_hwmon.c17
-rw-r--r--drivers/thermal/thermal_hwmon.h17
-rw-r--r--drivers/thermal/thermal_sysfs.c81
-rw-r--r--drivers/thermal/ti-soc-thermal/omap5-thermal-data.c2
-rw-r--r--drivers/thermal/uniphier_thermal.c4
-rw-r--r--drivers/thermal/x86_pkg_temp_thermal.c3
-rw-r--r--drivers/tty/ehv_bytechan.c2
-rw-r--r--drivers/tty/goldfish.c5
-rw-r--r--drivers/tty/hvc/hvc_iucv.c2
-rw-r--r--drivers/tty/hvc/hvcs.c3
-rw-r--r--drivers/tty/isicom.c2
-rw-r--r--drivers/tty/serial/atmel_serial.c5
-rw-r--r--drivers/tty/serial/pch_uart.c2
-rw-r--r--drivers/tty/serial/rp2.c2
-rw-r--r--drivers/tty/serial/serial_core.c2
-rw-r--r--drivers/tty/serial/sunsab.c5
-rw-r--r--drivers/tty/tty_io.c15
-rw-r--r--drivers/tty/vt/consolemap.c7
-rw-r--r--drivers/tty/vt/keyboard.c4
-rw-r--r--drivers/tty/vt/selection.c3
-rw-r--r--drivers/uio/uio_pruss.c2
-rw-r--r--drivers/usb/core/devio.c7
-rw-r--r--drivers/usb/core/hub.c2
-rw-r--r--drivers/usb/core/message.c6
-rw-r--r--drivers/usb/dwc2/hcd.c11
-rw-r--r--drivers/usb/gadget/function/f_fs.c2
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.c2
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_ep.c6
-rw-r--r--drivers/usb/gadget/udc/fsl_udc_core.c2
-rw-r--r--drivers/usb/gadget/udc/renesas_usb3.c3
-rw-r--r--drivers/usb/host/ehci-sched.c5
-rw-r--r--drivers/usb/host/fhci-tds.c2
-rw-r--r--drivers/usb/host/imx21-hcd.c4
-rw-r--r--drivers/usb/host/ohci-dbg.c2
-rw-r--r--drivers/usb/host/xhci-mem.c4
-rw-r--r--drivers/usb/misc/ldusb.c9
-rw-r--r--drivers/usb/misc/sisusbvga/sisusb_con.c2
-rw-r--r--drivers/usb/mon/mon_bin.c3
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c2
-rw-r--r--drivers/usb/renesas_usbhs/pipe.c3
-rw-r--r--drivers/usb/serial/iuu_phoenix.c4
-rw-r--r--drivers/usb/storage/alauda.c2
-rw-r--r--drivers/usb/storage/ene_ub6250.c16
-rw-r--r--drivers/usb/storage/sddr09.c4
-rw-r--r--drivers/usb/storage/sddr55.c6
-rw-r--r--drivers/usb/wusbcore/wa-rpipe.c3
-rw-r--r--drivers/uwb/est.c2
-rw-r--r--drivers/uwb/i1480/dfu/usb.c2
-rw-r--r--drivers/vfio/mdev/mdev_core.c102
-rw-r--r--drivers/vfio/mdev/mdev_private.h2
-rw-r--r--drivers/vfio/mdev/mdev_sysfs.c14
-rw-r--r--drivers/vfio/platform/vfio_platform_common.c30
-rw-r--r--drivers/vfio/vfio.c11
-rw-r--r--drivers/vfio/vfio_iommu_type1.c73
-rw-r--r--drivers/vhost/net.c8
-rw-r--r--drivers/vhost/scsi.c17
-rw-r--r--drivers/vhost/test.c2
-rw-r--r--drivers/vhost/vhost.c17
-rw-r--r--drivers/vhost/vringh.c2
-rw-r--r--drivers/video/backlight/Kconfig13
-rw-r--r--drivers/video/backlight/Makefile2
-rw-r--r--drivers/video/backlight/adp8860_bl.c2
-rw-r--r--drivers/video/backlight/adp8870_bl.c2
-rw-r--r--drivers/video/backlight/as3711_bl.c45
-rw-r--r--drivers/video/backlight/generic_bl.c5
-rw-r--r--drivers/video/backlight/lp855x_bl.c2
-rw-r--r--drivers/video/backlight/max8925_bl.c4
-rw-r--r--drivers/video/backlight/otm3225a.c252
-rw-r--r--drivers/video/backlight/pandora_bl.c25
-rw-r--r--drivers/video/backlight/pwm_bl.c34
-rw-r--r--drivers/video/backlight/rave-sp-backlight.c82
-rw-r--r--drivers/video/backlight/tps65217_bl.c4
-rw-r--r--drivers/video/console/sticore.c2
-rw-r--r--drivers/video/fbdev/Kconfig48
-rw-r--r--drivers/video/fbdev/Makefile4
-rw-r--r--drivers/video/fbdev/aty/aty128fb.c2
-rw-r--r--drivers/video/fbdev/aty/radeon_pm.c8
-rw-r--r--drivers/video/fbdev/au1100fb.c4
-rw-r--r--drivers/video/fbdev/au1200fb.c2
-rw-r--r--drivers/video/fbdev/auo_k1900fb.c204
-rw-r--r--drivers/video/fbdev/auo_k1901fb.c257
-rw-r--r--drivers/video/fbdev/auo_k190x.c1195
-rw-r--r--drivers/video/fbdev/auo_k190x.h129
-rw-r--r--drivers/video/fbdev/broadsheetfb.c2
-rw-r--r--drivers/video/fbdev/core/bitblit.c4
-rw-r--r--drivers/video/fbdev/core/fb_defio.c4
-rw-r--r--drivers/video/fbdev/core/fbcon.c3
-rw-r--r--drivers/video/fbdev/core/fbcon_ccw.c7
-rw-r--r--drivers/video/fbdev/core/fbcon_cw.c7
-rw-r--r--drivers/video/fbdev/core/fbcon_rotate.c2
-rw-r--r--drivers/video/fbdev/core/fbcon_ud.c4
-rw-r--r--drivers/video/fbdev/core/fbmem.c7
-rw-r--r--drivers/video/fbdev/core/fbmon.c9
-rw-r--r--drivers/video/fbdev/imxfb.c2
-rw-r--r--drivers/video/fbdev/mb862xx/mb862xxfb_accel.c2
-rw-r--r--drivers/video/fbdev/mmp/fb/mmpfb.c9
-rw-r--r--drivers/video/fbdev/mmp/hw/mmp_ctrl.c8
-rw-r--r--drivers/video/fbdev/mxsfb.c2
-rw-r--r--drivers/video/fbdev/nvidia/nvidia.c4
-rw-r--r--drivers/video/fbdev/omap/lcd_ams_delta.c4
-rw-r--r--drivers/video/fbdev/omap/lcd_h3.c4
-rw-r--r--drivers/video/fbdev/omap/lcd_htcherald.c4
-rw-r--r--drivers/video/fbdev/omap/lcd_inn1510.c4
-rw-r--r--drivers/video/fbdev/omap/lcd_inn1610.c4
-rw-r--r--drivers/video/fbdev/omap/lcd_osk.c4
-rw-r--r--drivers/video/fbdev/omap/lcd_palmte.c4
-rw-r--r--drivers/video/fbdev/omap/lcd_palmtt.c4
-rw-r--r--drivers/video/fbdev/omap/lcd_palmz71.c4
-rw-r--r--drivers/video/fbdev/omap/omapfb_main.c2
-rw-r--r--drivers/video/fbdev/omap2/omapfb/Kconfig1
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c18
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/manager.c4
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/overlay.c4
-rw-r--r--drivers/video/fbdev/omap2/omapfb/vrfb.c4
-rw-r--r--drivers/video/fbdev/pvr2fb.c2
-rw-r--r--drivers/video/fbdev/pxafb.c8
-rw-r--r--drivers/video/fbdev/riva/fbdev.c2
-rw-r--r--drivers/video/fbdev/savage/savagefb_driver.c8
-rw-r--r--drivers/video/fbdev/sh_mobile_lcdcfb.c77
-rw-r--r--drivers/video/fbdev/sh_mobile_lcdcfb.h1
-rw-r--r--drivers/video/fbdev/sh_mobile_meram.c758
-rw-r--r--drivers/video/fbdev/skeletonfb.c8
-rw-r--r--drivers/video/fbdev/sm501fb.c3
-rw-r--r--drivers/video/fbdev/uvesafb.c10
-rw-r--r--drivers/video/fbdev/via/global.h6
-rw-r--r--drivers/video/fbdev/via/hw.c1
-rw-r--r--drivers/video/fbdev/via/via-core.c1
-rw-r--r--drivers/video/fbdev/via/via_clock.c2
-rw-r--r--drivers/video/fbdev/via/viafbdev.c4
-rw-r--r--drivers/video/fbdev/w100fb.c3
-rw-r--r--drivers/video/fbdev/xen-fbfront.c2
-rw-r--r--drivers/video/of_display_timing.c5
-rw-r--r--drivers/virt/fsl_hypervisor.c2
-rw-r--r--drivers/virt/vboxguest/vboxguest_core.c7
-rw-r--r--drivers/virtio/virtio_pci_common.c37
-rw-r--r--drivers/virtio/virtio_pci_modern.c14
-rw-r--r--drivers/virtio/virtio_ring.c2
-rw-r--r--drivers/watchdog/cadence_wdt.c6
-rw-r--r--drivers/watchdog/da9062_wdt.c10
-rw-r--r--drivers/watchdog/da9063_wdt.c73
-rw-r--r--drivers/watchdog/hpwdt.c2
-rw-r--r--drivers/watchdog/jz4740_wdt.c42
-rw-r--r--drivers/watchdog/mena21_wdt.c18
-rw-r--r--drivers/watchdog/of_xilinx_wdt.c6
-rw-r--r--drivers/watchdog/renesas_wdt.c2
-rw-r--r--drivers/watchdog/sp805_wdt.c14
-rw-r--r--drivers/watchdog/wdat_wdt.c6
-rw-r--r--drivers/xen/Makefile2
-rw-r--r--drivers/xen/arm-device.c6
-rw-r--r--drivers/xen/events/events_base.c2
-rw-r--r--drivers/xen/evtchn.c2
-rw-r--r--drivers/xen/grant-table.c11
-rw-r--r--drivers/xen/manage.c18
-rw-r--r--drivers/xen/privcmd-buf.c210
-rw-r--r--drivers/xen/privcmd.c9
-rw-r--r--drivers/xen/privcmd.h3
-rw-r--r--drivers/xen/xen-pciback/pciback_ops.c2
-rw-r--r--drivers/xen/xen-scsiback.c16
-rw-r--r--fs/9p/fid.c2
-rw-r--r--fs/Kconfig1
-rw-r--r--fs/Kconfig.binfmt2
-rw-r--r--fs/Makefile1
-rw-r--r--fs/adfs/inode.c7
-rw-r--r--fs/adfs/super.c2
-rw-r--r--fs/afs/Makefile4
-rw-r--r--fs/afs/addr_list.c2
-rw-r--r--fs/afs/callback.c110
-rw-r--r--fs/afs/cell.c24
-rw-r--r--fs/afs/cmservice.c9
-rw-r--r--fs/afs/dynroot.c126
-rw-r--r--fs/afs/fsclient.c102
-rw-r--r--fs/afs/internal.h75
-rw-r--r--fs/afs/main.c35
-rw-r--r--fs/afs/netdevices.c6
-rw-r--r--fs/afs/proc.c793
-rw-r--r--fs/afs/rxrpc.c2
-rw-r--r--fs/afs/server.c2
-rw-r--r--fs/afs/super.c68
-rw-r--r--fs/aio.c4
-rw-r--r--fs/attr.c14
-rw-r--r--fs/autofs/Kconfig11
-rw-r--r--fs/autofs/init.c1
-rw-r--r--fs/autofs4/Kconfig46
-rw-r--r--fs/autofs4/Makefile9
-rw-r--r--fs/bad_inode.c2
-rw-r--r--fs/befs/ChangeLog2
-rw-r--r--fs/binfmt_elf.c19
-rw-r--r--fs/binfmt_elf_fdpic.c3
-rw-r--r--fs/binfmt_misc.c2
-rw-r--r--fs/block_dev.c3
-rw-r--r--fs/btrfs/check-integrity.c4
-rw-r--r--fs/btrfs/ctree.h2
-rw-r--r--fs/btrfs/extent_io.c4
-rw-r--r--fs/btrfs/file.c6
-rw-r--r--fs/btrfs/inode.c34
-rw-r--r--fs/btrfs/ioctl.c8
-rw-r--r--fs/btrfs/root-tree.c4
-rw-r--r--fs/btrfs/scrub.c2
-rw-r--r--fs/btrfs/transaction.c2
-rw-r--r--fs/ceph/addr.c24
-rw-r--r--fs/ceph/cache.c4
-rw-r--r--fs/ceph/caps.c166
-rw-r--r--fs/ceph/dir.c2
-rw-r--r--fs/ceph/file.c7
-rw-r--r--fs/ceph/inode.c153
-rw-r--r--fs/ceph/mds_client.c12
-rw-r--r--fs/ceph/snap.c6
-rw-r--r--fs/ceph/super.c35
-rw-r--r--fs/ceph/xattr.c60
-rw-r--r--fs/cifs/asn1.c2
-rw-r--r--fs/cifs/cache.c4
-rw-r--r--fs/cifs/cifs_debug.c29
-rw-r--r--fs/cifs/cifsacl.c4
-rw-r--r--fs/cifs/cifsacl.h14
-rw-r--r--fs/cifs/cifsencrypt.c27
-rw-r--r--fs/cifs/cifsfs.c22
-rw-r--r--fs/cifs/cifsglob.h46
-rw-r--r--fs/cifs/cifsproto.h10
-rw-r--r--fs/cifs/cifssmb.c10
-rw-r--r--fs/cifs/connect.c40
-rw-r--r--fs/cifs/file.c2
-rw-r--r--fs/cifs/fscache.c8
-rw-r--r--fs/cifs/inode.c41
-rw-r--r--fs/cifs/link.c6
-rw-r--r--fs/cifs/misc.c30
-rw-r--r--fs/cifs/smb2file.c3
-rw-r--r--fs/cifs/smb2inode.c3
-rw-r--r--fs/cifs/smb2misc.c21
-rw-r--r--fs/cifs/smb2ops.c346
-rw-r--r--fs/cifs/smb2pdu.c363
-rw-r--r--fs/cifs/smb2pdu.h23
-rw-r--r--fs/cifs/smb2proto.h8
-rw-r--r--fs/cifs/smb2transport.c10
-rw-r--r--fs/cifs/smbdirect.c128
-rw-r--r--fs/cifs/smbdirect.h2
-rw-r--r--fs/cifs/trace.h3
-rw-r--r--fs/cifs/transport.c207
-rw-r--r--fs/coda/coda_linux.c12
-rw-r--r--fs/configfs/inode.c12
-rw-r--r--fs/cramfs/inode.c2
-rw-r--r--fs/crypto/bio.c35
-rw-r--r--fs/crypto/crypto.c8
-rw-r--r--fs/crypto/fscrypt_private.h1
-rw-r--r--fs/debugfs/inode.c4
-rw-r--r--fs/dlm/lockspace.c2
-rw-r--r--fs/eventfd.c4
-rw-r--r--fs/eventpoll.c15
-rw-r--r--fs/exofs/inode.c4
-rw-r--r--fs/exofs/ore.c84
-rw-r--r--fs/exofs/ore_raid.c75
-rw-r--r--fs/exofs/super.c23
-rw-r--r--fs/ext2/ext2.h2
-rw-r--r--fs/ext2/super.c10
-rw-r--r--fs/ext4/ext4.h34
-rw-r--r--fs/ext4/extents.c8
-rw-r--r--fs/ext4/ialloc.c4
-rw-r--r--fs/ext4/namei.c2
-rw-r--r--fs/ext4/readpage.c2
-rw-r--r--fs/ext4/resize.c10
-rw-r--r--fs/ext4/super.c6
-rw-r--r--fs/f2fs/checkpoint.c152
-rw-r--r--fs/f2fs/data.c399
-rw-r--r--fs/f2fs/debug.c6
-rw-r--r--fs/f2fs/dir.c76
-rw-r--r--fs/f2fs/extent_cache.c22
-rw-r--r--fs/f2fs/f2fs.h470
-rw-r--r--fs/f2fs/file.c353
-rw-r--r--fs/f2fs/gc.c183
-rw-r--r--fs/f2fs/gc.h2
-rw-r--r--fs/f2fs/inline.c78
-rw-r--r--fs/f2fs/inode.c127
-rw-r--r--fs/f2fs/namei.c71
-rw-r--r--fs/f2fs/node.c297
-rw-r--r--fs/f2fs/recovery.c65
-rw-r--r--fs/f2fs/segment.c636
-rw-r--r--fs/f2fs/segment.h31
-rw-r--r--fs/f2fs/shrinker.c4
-rw-r--r--fs/f2fs/super.c218
-rw-r--r--fs/f2fs/sysfs.c63
-rw-r--r--fs/f2fs/xattr.c26
-rw-r--r--fs/fat/inode.c28
-rw-r--r--fs/fat/namei_msdos.c21
-rw-r--r--fs/fat/namei_vfat.c24
-rw-r--r--fs/fuse/dev.c15
-rw-r--r--fs/fuse/inode.c2
-rw-r--r--fs/gfs2/dir.c12
-rw-r--r--fs/gfs2/glock.c3
-rw-r--r--fs/gfs2/glops.c4
-rw-r--r--fs/gfs2/quota.c2
-rw-r--r--fs/gfs2/rgrp.c5
-rw-r--r--fs/gfs2/super.c2
-rw-r--r--fs/hfs/inode.c4
-rw-r--r--fs/hfsplus/inode.c12
-rw-r--r--fs/hostfs/hostfs_kern.c12
-rw-r--r--fs/hpfs/dnode.c3
-rw-r--r--fs/hpfs/map.c2
-rw-r--r--fs/inode.c58
-rw-r--r--fs/iomap.c6
-rw-r--r--fs/jbd2/revoke.c2
-rw-r--r--fs/jffs2/acl.c3
-rw-r--r--fs/jffs2/acl.h1
-rw-r--r--fs/jffs2/dir.c18
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/fs.c12
-rw-r--r--fs/jffs2/wbuf.c2
-rw-r--r--fs/jfs/jfs_dmap.c2
-rw-r--r--fs/jfs/jfs_dtree.c9
-rw-r--r--fs/jfs/jfs_unicode.c2
-rw-r--r--fs/jfs/xattr.c10
-rw-r--r--fs/kernfs/dir.c4
-rw-r--r--fs/kernfs/inode.c8
-rw-r--r--fs/locks.c2
-rw-r--r--fs/mbcache.c5
-rw-r--r--fs/namei.c33
-rw-r--r--fs/nfs/callback_proc.c47
-rw-r--r--fs/nfs/client.c3
-rw-r--r--fs/nfs/delegation.c88
-rw-r--r--fs/nfs/dir.c51
-rw-r--r--fs/nfs/export.c2
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayout.c24
-rw-r--r--fs/nfs/flexfilelayout/flexfilelayoutdev.c3
-rw-r--r--fs/nfs/fscache-index.c4
-rw-r--r--fs/nfs/fscache.c12
-rw-r--r--fs/nfs/inode.c165
-rw-r--r--fs/nfs/nfs2xdr.c25
-rw-r--r--fs/nfs/nfs3proc.c13
-rw-r--r--fs/nfs/nfs3xdr.c8
-rw-r--r--fs/nfs/nfs42proc.c6
-rw-r--r--fs/nfs/nfs4_fs.h27
-rw-r--r--fs/nfs/nfs4idmap.c5
-rw-r--r--fs/nfs/nfs4proc.c424
-rw-r--r--fs/nfs/nfs4state.c8
-rw-r--r--fs/nfs/nfs4xdr.c72
-rw-r--r--fs/nfs/pnfs.c331
-rw-r--r--fs/nfs/pnfs.h33
-rw-r--r--fs/nfs/proc.c13
-rw-r--r--fs/nfs/unlink.c20
-rw-r--r--fs/nfs/write.c10
-rw-r--r--fs/nfsd/blocklayout.c26
-rw-r--r--fs/nfsd/cache.h5
-rw-r--r--fs/nfsd/export.c5
-rw-r--r--fs/nfsd/nfs3xdr.c14
-rw-r--r--fs/nfsd/nfs4recover.c5
-rw-r--r--fs/nfsd/nfs4state.c25
-rw-r--r--fs/nfsd/nfs4xdr.c14
-rw-r--r--fs/nfsd/nfscache.c9
-rw-r--r--fs/nfsd/nfsxdr.c2
-rw-r--r--fs/notify/dnotify/dnotify.c8
-rw-r--r--fs/notify/fanotify/fanotify.c46
-rw-r--r--fs/notify/fdinfo.c6
-rw-r--r--fs/notify/fsnotify.c138
-rw-r--r--fs/notify/fsnotify.h6
-rw-r--r--fs/notify/group.c2
-rw-r--r--fs/notify/inotify/inotify.h2
-rw-r--r--fs/notify/inotify/inotify_fsnotify.c6
-rw-r--r--fs/notify/inotify/inotify_user.c10
-rw-r--r--fs/notify/mark.c52
-rw-r--r--fs/ntfs/compress.c2
-rw-r--r--fs/ntfs/inode.c30
-rw-r--r--fs/ocfs2/cluster/tcp.c2
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c2
-rw-r--r--fs/ocfs2/dlmglue.c20
-rw-r--r--fs/ocfs2/file.c6
-rw-r--r--fs/ocfs2/journal.c2
-rw-r--r--fs/ocfs2/sysfile.c9
-rw-r--r--fs/orangefs/devorangefs-req.c54
-rw-r--r--fs/orangefs/inode.c2
-rw-r--r--fs/orangefs/orangefs-kernel.h2
-rw-r--r--fs/orangefs/orangefs-sysfs.c2
-rw-r--r--fs/overlayfs/inode.c2
-rw-r--r--fs/overlayfs/namei.c2
-rw-r--r--fs/overlayfs/overlayfs.h2
-rw-r--r--fs/proc/base.c40
-rw-r--r--fs/proc/generic.c26
-rw-r--r--fs/proc/inode.c5
-rw-r--r--fs/proc/internal.h20
-rw-r--r--fs/proc/proc_net.c92
-rw-r--r--fs/proc/proc_sysctl.c2
-rw-r--r--fs/proc/root.c3
-rw-r--r--fs/proc/task_mmu.c2
-rw-r--r--fs/proc/uptime.c2
-rw-r--r--fs/pstore/platform.c2
-rw-r--r--fs/pstore/ram.c18
-rw-r--r--fs/quota/dquot.c7
-rw-r--r--fs/read_write.c4
-rw-r--r--fs/reiserfs/bitmap.c2
-rw-r--r--fs/reiserfs/inode.c3
-rw-r--r--fs/reiserfs/journal.c13
-rw-r--r--fs/reiserfs/namei.c2
-rw-r--r--fs/reiserfs/resize.c3
-rw-r--r--fs/reiserfs/xattr.c4
-rw-r--r--fs/select.c2
-rw-r--r--fs/signalfd.c50
-rw-r--r--fs/splice.c151
-rw-r--r--fs/ubifs/dir.c4
-rw-r--r--fs/ubifs/file.c34
-rw-r--r--fs/ubifs/gc.c2
-rw-r--r--fs/ubifs/journal.c10
-rw-r--r--fs/ubifs/log.c6
-rw-r--r--fs/ubifs/lpt.c25
-rw-r--r--fs/ubifs/lpt_commit.c2
-rw-r--r--fs/ubifs/replay.c5
-rw-r--r--fs/ubifs/super.c3
-rw-r--r--fs/ubifs/tnc.c5
-rw-r--r--fs/ubifs/tnc_commit.c5
-rw-r--r--fs/ubifs/ubifs.h4
-rw-r--r--fs/ubifs/xattr.c2
-rw-r--r--fs/udf/balloc.c5
-rw-r--r--fs/udf/directory.c8
-rw-r--r--fs/udf/ialloc.c4
-rw-r--r--fs/udf/inode.c67
-rw-r--r--fs/udf/namei.c14
-rw-r--r--fs/udf/super.c24
-rw-r--r--fs/udf/udfdecl.h13
-rw-r--r--fs/udf/udftime.c9
-rw-r--r--fs/ufs/super.c4
-rw-r--r--fs/xfs/Makefile15
-rw-r--r--fs/xfs/kmem.c14
-rw-r--r--fs/xfs/kmem.h14
-rw-r--r--fs/xfs/libxfs/xfs_ag_resv.c16
-rw-r--r--fs/xfs/libxfs/xfs_ag_resv.h16
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c95
-rw-r--r--fs/xfs/libxfs/xfs_alloc.h18
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.c15
-rw-r--r--fs/xfs/libxfs/xfs_alloc_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_attr.c14
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.c21
-rw-r--r--fs/xfs/libxfs/xfs_attr_leaf.h14
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.c14
-rw-r--r--fs/xfs/libxfs/xfs_attr_remote.h14
-rw-r--r--fs/xfs/libxfs/xfs_attr_sf.h14
-rw-r--r--fs/xfs/libxfs/xfs_bit.c14
-rw-r--r--fs/xfs/libxfs/xfs_bit.h14
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c54
-rw-r--r--fs/xfs/libxfs/xfs_bmap.h14
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.c14
-rw-r--r--fs/xfs/libxfs/xfs_bmap_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_btree.c171
-rw-r--r--fs/xfs/libxfs/xfs_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.c24
-rw-r--r--fs/xfs/libxfs/xfs_da_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_da_format.c14
-rw-r--r--fs/xfs/libxfs/xfs_da_format.h14
-rw-r--r--fs/xfs/libxfs/xfs_defer.c16
-rw-r--r--fs/xfs/libxfs/xfs_defer.h16
-rw-r--r--fs/xfs/libxfs/xfs_dir2.c14
-rw-r--r--fs/xfs/libxfs/xfs_dir2.h14
-rw-r--r--fs/xfs/libxfs/xfs_dir2_block.c22
-rw-r--r--fs/xfs/libxfs/xfs_dir2_data.c122
-rw-r--r--fs/xfs/libxfs/xfs_dir2_leaf.c26
-rw-r--r--fs/xfs/libxfs/xfs_dir2_node.c17
-rw-r--r--fs/xfs/libxfs/xfs_dir2_priv.h14
-rw-r--r--fs/xfs/libxfs/xfs_dir2_sf.c14
-rw-r--r--fs/xfs/libxfs/xfs_dquot_buf.c14
-rw-r--r--fs/xfs/libxfs/xfs_errortag.h15
-rw-r--r--fs/xfs/libxfs/xfs_format.h14
-rw-r--r--fs/xfs/libxfs/xfs_fs.h14
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c160
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.h21
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c14
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_iext_tree.c10
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.c34
-rw-r--r--fs/xfs/libxfs/xfs_inode_buf.h14
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.c14
-rw-r--r--fs/xfs/libxfs/xfs_inode_fork.h14
-rw-r--r--fs/xfs/libxfs/xfs_log_format.h14
-rw-r--r--fs/xfs/libxfs/xfs_log_recover.h14
-rw-r--r--fs/xfs/libxfs/xfs_log_rlimit.c14
-rw-r--r--fs/xfs/libxfs/xfs_quota_defs.h14
-rw-r--r--fs/xfs/libxfs/xfs_refcount.c63
-rw-r--r--fs/xfs/libxfs/xfs_refcount.h16
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.c17
-rw-r--r--fs/xfs/libxfs/xfs_refcount_btree.h16
-rw-r--r--fs/xfs/libxfs/xfs_rmap.c55
-rw-r--r--fs/xfs/libxfs/xfs_rmap.h16
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.c15
-rw-r--r--fs/xfs/libxfs/xfs_rmap_btree.h14
-rw-r--r--fs/xfs/libxfs/xfs_rtbitmap.c26
-rw-r--r--fs/xfs/libxfs/xfs_sb.c40
-rw-r--r--fs/xfs/libxfs/xfs_sb.h14
-rw-r--r--fs/xfs/libxfs/xfs_shared.h14
-rw-r--r--fs/xfs/libxfs/xfs_symlink_remote.c14
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.c30
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.h14
-rw-r--r--fs/xfs/libxfs/xfs_trans_space.h14
-rw-r--r--fs/xfs/libxfs/xfs_types.c173
-rw-r--r--fs/xfs/libxfs/xfs_types.h33
-rw-r--r--fs/xfs/mrlock.h14
-rw-r--r--fs/xfs/scrub/agheader.c18
-rw-r--r--fs/xfs/scrub/agheader_repair.c16
-rw-r--r--fs/xfs/scrub/alloc.c16
-rw-r--r--fs/xfs/scrub/attr.c16
-rw-r--r--fs/xfs/scrub/bmap.c16
-rw-r--r--fs/xfs/scrub/btree.c16
-rw-r--r--fs/xfs/scrub/btree.h16
-rw-r--r--fs/xfs/scrub/common.c16
-rw-r--r--fs/xfs/scrub/common.h16
-rw-r--r--fs/xfs/scrub/dabtree.c16
-rw-r--r--fs/xfs/scrub/dabtree.h16
-rw-r--r--fs/xfs/scrub/dir.c16
-rw-r--r--fs/xfs/scrub/ialloc.c16
-rw-r--r--fs/xfs/scrub/inode.c16
-rw-r--r--fs/xfs/scrub/parent.c16
-rw-r--r--fs/xfs/scrub/quota.c16
-rw-r--r--fs/xfs/scrub/refcount.c16
-rw-r--r--fs/xfs/scrub/repair.c16
-rw-r--r--fs/xfs/scrub/repair.h16
-rw-r--r--fs/xfs/scrub/rmap.c16
-rw-r--r--fs/xfs/scrub/rtbitmap.c16
-rw-r--r--fs/xfs/scrub/scrub.c16
-rw-r--r--fs/xfs/scrub/scrub.h16
-rw-r--r--fs/xfs/scrub/symlink.c16
-rw-r--r--fs/xfs/scrub/trace.c16
-rw-r--r--fs/xfs/scrub/trace.h16
-rw-r--r--fs/xfs/scrub/xfs_scrub.h16
-rw-r--r--fs/xfs/xfs.h14
-rw-r--r--fs/xfs/xfs_acl.c14
-rw-r--r--fs/xfs/xfs_acl.h14
-rw-r--r--fs/xfs/xfs_aops.c25
-rw-r--r--fs/xfs/xfs_aops.h14
-rw-r--r--fs/xfs/xfs_attr.h14
-rw-r--r--fs/xfs/xfs_attr_inactive.c14
-rw-r--r--fs/xfs/xfs_attr_list.c19
-rw-r--r--fs/xfs/xfs_bmap_item.c16
-rw-r--r--fs/xfs/xfs_bmap_item.h16
-rw-r--r--fs/xfs/xfs_bmap_util.c26
-rw-r--r--fs/xfs/xfs_bmap_util.h14
-rw-r--r--fs/xfs/xfs_buf.c15
-rw-r--r--fs/xfs/xfs_buf.h14
-rw-r--r--fs/xfs/xfs_buf_item.c16
-rw-r--r--fs/xfs/xfs_buf_item.h14
-rw-r--r--fs/xfs/xfs_dir2_readdir.c14
-rw-r--r--fs/xfs/xfs_discard.c14
-rw-r--r--fs/xfs/xfs_dquot.c14
-rw-r--r--fs/xfs/xfs_dquot.h14
-rw-r--r--fs/xfs/xfs_dquot_item.c14
-rw-r--r--fs/xfs/xfs_dquot_item.h14
-rw-r--r--fs/xfs/xfs_error.c19
-rw-r--r--fs/xfs/xfs_error.h23
-rw-r--r--fs/xfs/xfs_export.c29
-rw-r--r--fs/xfs/xfs_export.h14
-rw-r--r--fs/xfs/xfs_extent_busy.c14
-rw-r--r--fs/xfs/xfs_extent_busy.h14
-rw-r--r--fs/xfs/xfs_extfree_item.c14
-rw-r--r--fs/xfs/xfs_extfree_item.h14
-rw-r--r--fs/xfs/xfs_file.c14
-rw-r--r--fs/xfs/xfs_filestream.c14
-rw-r--r--fs/xfs/xfs_filestream.h14
-rw-r--r--fs/xfs/xfs_fsmap.c16
-rw-r--r--fs/xfs/xfs_fsmap.h16
-rw-r--r--fs/xfs/xfs_fsops.c14
-rw-r--r--fs/xfs/xfs_fsops.h14
-rw-r--r--fs/xfs/xfs_globals.c14
-rw-r--r--fs/xfs/xfs_icache.c14
-rw-r--r--fs/xfs/xfs_icache.h14
-rw-r--r--fs/xfs/xfs_icreate_item.c14
-rw-r--r--fs/xfs/xfs_icreate_item.h14
-rw-r--r--fs/xfs/xfs_inode.c37
-rw-r--r--fs/xfs/xfs_inode.h14
-rw-r--r--fs/xfs/xfs_inode_item.c14
-rw-r--r--fs/xfs/xfs_inode_item.h14
-rw-r--r--fs/xfs/xfs_ioctl.c33
-rw-r--r--fs/xfs/xfs_ioctl.h14
-rw-r--r--fs/xfs/xfs_ioctl32.c14
-rw-r--r--fs/xfs/xfs_ioctl32.h14
-rw-r--r--fs/xfs/xfs_iomap.c20
-rw-r--r--fs/xfs/xfs_iomap.h18
-rw-r--r--fs/xfs/xfs_iops.c24
-rw-r--r--fs/xfs/xfs_iops.h14
-rw-r--r--fs/xfs/xfs_itable.c16
-rw-r--r--fs/xfs/xfs_itable.h14
-rw-r--r--fs/xfs/xfs_linux.h36
-rw-r--r--fs/xfs/xfs_log.c18
-rw-r--r--fs/xfs/xfs_log.h14
-rw-r--r--fs/xfs/xfs_log_cil.c14
-rw-r--r--fs/xfs/xfs_log_priv.h14
-rw-r--r--fs/xfs/xfs_log_recover.c67
-rw-r--r--fs/xfs/xfs_message.c14
-rw-r--r--fs/xfs/xfs_mount.c21
-rw-r--r--fs/xfs/xfs_mount.h16
-rw-r--r--fs/xfs/xfs_mru_cache.c14
-rw-r--r--fs/xfs/xfs_mru_cache.h14
-rw-r--r--fs/xfs/xfs_ondisk.h14
-rw-r--r--fs/xfs/xfs_qm.c14
-rw-r--r--fs/xfs/xfs_qm.h14
-rw-r--r--fs/xfs/xfs_qm_bhv.c14
-rw-r--r--fs/xfs/xfs_qm_syscalls.c14
-rw-r--r--fs/xfs/xfs_quota.h14
-rw-r--r--fs/xfs/xfs_quotaops.c14
-rw-r--r--fs/xfs/xfs_refcount_item.c16
-rw-r--r--fs/xfs/xfs_refcount_item.h16
-rw-r--r--fs/xfs/xfs_reflink.c16
-rw-r--r--fs/xfs/xfs_reflink.h16
-rw-r--r--fs/xfs/xfs_rmap_item.c16
-rw-r--r--fs/xfs/xfs_rmap_item.h16
-rw-r--r--fs/xfs/xfs_rtalloc.c24
-rw-r--r--fs/xfs/xfs_rtalloc.h14
-rw-r--r--fs/xfs/xfs_stats.c14
-rw-r--r--fs/xfs/xfs_stats.h14
-rw-r--r--fs/xfs/xfs_super.c16
-rw-r--r--fs/xfs/xfs_super.h14
-rw-r--r--fs/xfs/xfs_symlink.c14
-rw-r--r--fs/xfs/xfs_symlink.h14
-rw-r--r--fs/xfs/xfs_sysctl.c14
-rw-r--r--fs/xfs/xfs_sysctl.h14
-rw-r--r--fs/xfs/xfs_sysfs.c14
-rw-r--r--fs/xfs/xfs_sysfs.h14
-rw-r--r--fs/xfs/xfs_trace.c14
-rw-r--r--fs/xfs/xfs_trace.h14
-rw-r--r--fs/xfs/xfs_trans.c14
-rw-r--r--fs/xfs/xfs_trans.h14
-rw-r--r--fs/xfs/xfs_trans_ail.c14
-rw-r--r--fs/xfs/xfs_trans_bmap.c16
-rw-r--r--fs/xfs/xfs_trans_buf.c14
-rw-r--r--fs/xfs/xfs_trans_dquot.c14
-rw-r--r--fs/xfs/xfs_trans_extfree.c14
-rw-r--r--fs/xfs/xfs_trans_inode.c16
-rw-r--r--fs/xfs/xfs_trans_priv.h14
-rw-r--r--fs/xfs/xfs_trans_refcount.c16
-rw-r--r--fs/xfs/xfs_trans_rmap.c16
-rw-r--r--fs/xfs/xfs_xattr.c14
-rw-r--r--include/acpi/acoutput.h4
-rw-r--r--include/acpi/acpixf.h2
-rw-r--r--include/acpi/actbl2.h25
-rw-r--r--include/acpi/actypes.h1
-rw-r--r--include/acpi/processor.h3
-rw-r--r--include/asm-generic/qspinlock_types.h2
-rw-r--r--include/dt-bindings/memory/tegra114-mc.h17
-rw-r--r--include/dt-bindings/memory/tegra124-mc.h25
-rw-r--r--include/dt-bindings/memory/tegra20-mc.h21
-rw-r--r--include/dt-bindings/memory/tegra210-mc.h31
-rw-r--r--include/dt-bindings/memory/tegra30-mc.h19
-rw-r--r--include/dt-bindings/power/px30-power.h27
-rw-r--r--include/dt-bindings/power/r8a77470-sysc.h22
-rw-r--r--include/dt-bindings/power/r8a77990-sysc.h26
-rw-r--r--include/dt-bindings/power/rk3036-power.h13
-rw-r--r--include/dt-bindings/power/rk3128-power.h14
-rw-r--r--include/dt-bindings/power/rk3228-power.h21
-rw-r--r--include/keys/asymmetric-subtype.h2
-rw-r--r--include/keys/asymmetric-type.h2
-rw-r--r--include/kvm/arm_vgic.h17
-rw-r--r--include/linux/assoc_array.h2
-rw-r--r--include/linux/assoc_array_priv.h2
-rw-r--r--include/linux/atmdev.h15
-rw-r--r--include/linux/backing-dev-defs.h2
-rw-r--r--include/linux/backlight.h4
-rw-r--r--include/linux/blk-mq.h2
-rw-r--r--include/linux/blkdev.h4
-rw-r--r--include/linux/bpf.h12
-rw-r--r--include/linux/ceph/ceph_fs.h1
-rw-r--r--include/linux/ceph/osd_client.h8
-rw-r--r--include/linux/ceph/osdmap.h8
-rw-r--r--include/linux/circ_buf.h2
-rw-r--r--include/linux/dma-contiguous.h2
-rw-r--r--include/linux/filter.h79
-rw-r--r--include/linux/fs.h24
-rw-r--r--include/linux/fscrypt_notsupp.h13
-rw-r--r--include/linux/fscrypt_supp.h5
-rw-r--r--include/linux/fsnotify_backend.h79
-rw-r--r--include/linux/ftrace.h2
-rw-r--r--include/linux/hwspinlock.h68
-rw-r--r--include/linux/hyperv.h12
-rw-r--r--include/linux/i2c-pnx.h38
-rw-r--r--include/linux/i2c.h12
-rw-r--r--include/linux/irq.h1
-rw-r--r--include/linux/irqdesc.h5
-rw-r--r--include/linux/kcov.h14
-rw-r--r--include/linux/kernel.h2
-rw-r--r--include/linux/kvm_host.h19
-rw-r--r--include/linux/libata.h2
-rw-r--r--include/linux/linkage.h12
-rw-r--r--include/linux/log2.h35
-rw-r--r--include/linux/memcontrol.h26
-rw-r--r--include/linux/memory.h1
-rw-r--r--include/linux/mfd/arizona/pdata.h3
-rw-r--r--include/linux/mfd/as3711.h4
-rw-r--r--include/linux/mfd/axp20x.h10
-rw-r--r--include/linux/mfd/cros_ec.h20
-rw-r--r--include/linux/mfd/rave-sp.h1
-rw-r--r--include/linux/mfd/stm32-timers.h70
-rw-r--r--include/linux/mfd/syscon/exynos4-pmu.h21
-rw-r--r--include/linux/mfd/syscon/exynos5-pmu.h19
-rw-r--r--include/linux/mfd/tps65218.h4
-rw-r--r--include/linux/mfd/tps68470.h17
-rw-r--r--include/linux/mm.h5
-rw-r--r--include/linux/mod_devicetable.h1
-rw-r--r--include/linux/namei.h1
-rw-r--r--include/linux/netfilter.h2
-rw-r--r--include/linux/netfilter/ipset/ip_set_timeout.h20
-rw-r--r--include/linux/nfs_fs_sb.h2
-rw-r--r--include/linux/nfs_xdr.h17
-rw-r--r--include/linux/platform_data/i2c-gpio.h (renamed from include/linux/i2c-gpio.h)0
-rw-r--r--include/linux/platform_data/i2c-mux-gpio.h (renamed from include/linux/i2c-mux-gpio.h)0
-rw-r--r--include/linux/platform_data/i2c-ocores.h (renamed from include/linux/i2c-ocores.h)0
-rw-r--r--include/linux/platform_data/i2c-omap.h (renamed from include/linux/i2c-omap.h)0
-rw-r--r--include/linux/platform_data/i2c-pca-platform.h (renamed from include/linux/i2c-pca-platform.h)0
-rw-r--r--include/linux/platform_data/i2c-xiic.h (renamed from include/linux/i2c-xiic.h)0
-rw-r--r--include/linux/platform_data/media/ir-rx51.h9
-rw-r--r--include/linux/platform_data/mlxreg.h3
-rw-r--r--include/linux/platform_data/mtd-davinci.h10
-rw-r--r--include/linux/platform_data/sc18is602.h2
-rw-r--r--include/linux/platform_data/shmob_drm.h4
-rw-r--r--include/linux/platform_data/spi-imx.h29
-rw-r--r--include/linux/platform_data/ti-aemif.h25
-rw-r--r--include/linux/platform_data/ti-sysc.h1
-rw-r--r--include/linux/pm_domain.h15
-rw-r--r--include/linux/pm_runtime.h6
-rw-r--r--include/linux/proc_fs.h12
-rw-r--r--include/linux/pstore.h2
-rw-r--r--include/linux/pwm_backlight.h2
-rw-r--r--include/linux/qcom-geni-se.h425
-rw-r--r--include/linux/rculist.h13
-rw-r--r--include/linux/rculist_nulls.h2
-rw-r--r--include/linux/refcount.h4
-rw-r--r--include/linux/rpmsg.h27
-rw-r--r--include/linux/rpmsg/qcom_glink.h2
-rw-r--r--include/linux/rtc.h2
-rw-r--r--include/linux/sched.h33
-rw-r--r--include/linux/scmi_protocol.h18
-rw-r--r--include/linux/slab.h1
-rw-r--r--include/linux/soc/qcom/smem.h2
-rw-r--r--include/linux/soc/ti/ti_sci_protocol.h10
-rw-r--r--include/linux/spinlock.h5
-rw-r--r--include/linux/stackprotector.h2
-rw-r--r--include/linux/stat.h8
-rw-r--r--include/linux/ste_modem_shm.h56
-rw-r--r--include/linux/string_helpers.h1
-rw-r--r--include/linux/sunrpc/rpc_rdma.h1
-rw-r--r--include/linux/sunrpc/svc_rdma.h95
-rw-r--r--include/linux/sunrpc/xprt.h6
-rw-r--r--include/linux/sunrpc/xprtrdma.h1
-rw-r--r--include/linux/thermal.h17
-rw-r--r--include/linux/thread_info.h11
-rw-r--r--include/linux/tracepoint.h2
-rw-r--r--include/linux/virtio_net.h11
-rw-r--r--include/linux/virtio_ring.h4
-rw-r--r--include/net/ip6_fib.h5
-rw-r--r--include/net/ip_vs.h30
-rw-r--r--include/net/netfilter/nf_conntrack_count.h3
-rw-r--r--include/net/netfilter/nft_dup.h10
-rw-r--r--include/net/sctp/structs.h5
-rw-r--r--include/net/tls.h6
-rw-r--r--include/net/transp_v6.h11
-rw-r--r--include/net/udp.h5
-rw-r--r--include/rdma/ib_verbs.h18
-rw-r--r--include/scsi/scsi_device.h2
-rw-r--r--include/scsi/scsi_devinfo.h75
-rw-r--r--include/soc/qcom/cmd-db.h45
-rw-r--r--include/soc/tegra/cpuidle.h2
-rw-r--r--include/soc/tegra/mc.h37
-rw-r--r--include/target/target_core_base.h1
-rw-r--r--include/trace/events/rpcrdma.h660
-rw-r--r--include/uapi/linux/aio_abi.h2
-rw-r--r--include/uapi/linux/if_xdp.h4
-rw-r--r--include/uapi/linux/kvm.h5
-rw-r--r--include/uapi/linux/nbd.h3
-rw-r--r--include/uapi/linux/netfilter/nf_conntrack_common.h2
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h30
-rw-r--r--include/uapi/linux/nl80211.h28
-rw-r--r--include/uapi/linux/prctl.h2
-rw-r--r--include/uapi/linux/rpmsg.h9
-rw-r--r--include/uapi/linux/target_core_user.h11
-rw-r--r--include/uapi/linux/usb/audio.h8
-rw-r--r--include/uapi/linux/virtio_config.h16
-rw-r--r--include/video/auo_k190xfb.h107
-rw-r--r--include/video/sh_mobile_lcdc.h3
-rw-r--r--include/video/sh_mobile_meram.h95
-rw-r--r--include/xen/interface/io/kbdif.h2
-rw-r--r--include/xen/xen.h6
-rw-r--r--init/Kconfig19
-rw-r--r--ipc/sem.c20
-rw-r--r--ipc/shm.c2
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/audit_fsnotify.c5
-rw-r--r--kernel/audit_tree.c12
-rw-r--r--kernel/audit_watch.c5
-rw-r--r--kernel/bpf/btf.c8
-rw-r--r--kernel/bpf/core.c69
-rw-r--r--kernel/bpf/devmap.c14
-rw-r--r--kernel/bpf/inode.c14
-rw-r--r--kernel/bpf/lpm_trie.c5
-rw-r--r--kernel/bpf/syscall.c12
-rw-r--r--kernel/bpf/verifier.c58
-rw-r--r--kernel/cgroup/cgroup-v1.c4
-rw-r--r--kernel/cgroup/cpuset.c7
-rw-r--r--kernel/configs/android-recommended.config2
-rw-r--r--kernel/configs/tiny.config4
-rw-r--r--kernel/debug/kdb/kdb_main.c13
-rw-r--r--kernel/dma/Kconfig50
-rw-r--r--kernel/dma/Makefile11
-rw-r--r--kernel/dma/coherent.c (renamed from drivers/base/dma-coherent.c)0
-rw-r--r--kernel/dma/contiguous.c (renamed from drivers/base/dma-contiguous.c)0
-rw-r--r--kernel/dma/debug.c (renamed from lib/dma-debug.c)0
-rw-r--r--kernel/dma/direct.c (renamed from lib/dma-direct.c)0
-rw-r--r--kernel/dma/mapping.c (renamed from drivers/base/dma-mapping.c)2
-rw-r--r--kernel/dma/noncoherent.c (renamed from lib/dma-noncoherent.c)0
-rw-r--r--kernel/dma/swiotlb.c (renamed from lib/swiotlb.c)0
-rw-r--r--kernel/dma/virt.c (renamed from lib/dma-virt.c)2
-rw-r--r--kernel/events/ring_buffer.c3
-rw-r--r--kernel/events/uprobes.c3
-rw-r--r--kernel/fail_function.c2
-rw-r--r--kernel/fork.c10
-rw-r--r--kernel/gcov/Kconfig17
-rw-r--r--kernel/gcov/Makefile2
-rw-r--r--kernel/irq/debugfs.c1
-rw-r--r--kernel/kcov.c21
-rw-r--r--kernel/kexec_core.c4
-rw-r--r--kernel/kexec_file.c2
-rw-r--r--kernel/locking/lockdep.c12
-rw-r--r--kernel/locking/locktorture.c14
-rw-r--r--kernel/locking/rwsem.c1
-rw-r--r--kernel/module.c4
-rw-r--r--kernel/panic.c2
-rw-r--r--kernel/power/main.c5
-rw-r--r--kernel/power/swap.c6
-rw-r--r--kernel/rcu/rcutorture.c5
-rw-r--r--kernel/relay.c5
-rw-r--r--kernel/rseq.c7
-rw-r--r--kernel/sched/core.c4
-rw-r--r--kernel/sched/fair.c4
-rw-r--r--kernel/sched/rt.c4
-rw-r--r--kernel/sched/topology.c2
-rw-r--r--kernel/softirq.c6
-rw-r--r--kernel/sysctl.c3
-rw-r--r--kernel/time/hrtimer.c2
-rw-r--r--kernel/time/posix-cpu-timers.c2
-rw-r--r--kernel/time/time.c6
-rw-r--r--kernel/trace/Kconfig16
-rw-r--r--kernel/trace/ftrace.c28
-rw-r--r--kernel/trace/trace.c18
-rw-r--r--kernel/trace/trace_events_filter.c16
-rw-r--r--kernel/trace/tracing_map.c2
-rw-r--r--kernel/umh.c3
-rw-r--r--kernel/user_namespace.c5
-rw-r--r--kernel/workqueue.c3
-rw-r--r--lib/Kconfig61
-rw-r--r--lib/Kconfig.debug47
-rw-r--r--lib/Makefile24
-rw-r--r--lib/argv_split.c2
-rw-r--r--lib/dec_and_lock.c16
-rw-r--r--lib/interval_tree_test.c5
-rw-r--r--lib/kfifo.c2
-rw-r--r--lib/lru_cache.c2
-rw-r--r--lib/mpi/mpiutil.c4
-rw-r--r--lib/rbtree_test.c2
-rw-r--r--lib/reed_solomon/reed_solomon.c6
-rw-r--r--lib/refcount.c28
-rw-r--r--lib/sbitmap.c2
-rw-r--r--lib/scatterlist.c3
-rw-r--r--lib/test_firmware.c10
-rw-r--r--lib/test_kmod.c5
-rw-r--r--lib/test_overflow.c2
-rw-r--r--lib/test_printf.c7
-rw-r--r--lib/test_rhashtable.c13
-rw-r--r--lib/ucmpdi2.c2
-rw-r--r--mm/backing-dev.c20
-rw-r--r--mm/cleancache.c10
-rw-r--r--mm/cma_debug.c25
-rw-r--r--mm/compaction.c2
-rw-r--r--mm/dmapool.c2
-rw-r--r--mm/failslab.c2
-rw-r--r--mm/frontswap.c11
-rw-r--r--mm/gup_benchmark.c2
-rw-r--r--mm/huge_memory.c4
-rw-r--r--mm/hugetlb.c3
-rw-r--r--mm/ksm.c14
-rw-r--r--mm/memblock.c9
-rw-r--r--mm/memcontrol.c10
-rw-r--r--mm/mremap.c4
-rw-r--r--mm/oom_kill.c2
-rw-r--r--mm/page_alloc.c2
-rw-r--r--mm/page_idle.c2
-rw-r--r--mm/page_owner.c4
-rw-r--r--mm/percpu-stats.c2
-rw-r--r--mm/shmem.c9
-rw-r--r--mm/slab.c3
-rw-r--r--mm/slab_common.c37
-rw-r--r--mm/slub.c19
-rw-r--r--mm/swap_slots.c4
-rw-r--r--mm/swap_state.c2
-rw-r--r--mm/swapfile.c7
-rw-r--r--mm/vmalloc.c4
-rw-r--r--mm/zsmalloc.c5
-rw-r--r--mm/zswap.c38
-rw-r--r--net/9p/protocol.c11
-rw-r--r--net/9p/trans_virtio.c3
-rw-r--r--net/atm/br2684.c3
-rw-r--r--net/atm/clip.c3
-rw-r--r--net/atm/common.c3
-rw-r--r--net/atm/lec.c3
-rw-r--r--net/atm/mpc.c5
-rw-r--r--net/atm/pppoatm.c3
-rw-r--r--net/atm/raw.c4
-rw-r--r--net/bluetooth/hci_core.c2
-rw-r--r--net/bluetooth/l2cap_core.c2
-rw-r--r--net/bpfilter/.gitignore1
-rw-r--r--net/bpfilter/Makefile6
-rw-r--r--net/bpfilter/bpfilter_kern.c10
-rw-r--r--net/bridge/br_fdb.c4
-rw-r--r--net/bridge/br_multicast.c2
-rw-r--r--net/bridge/netfilter/ebtables.c36
-rw-r--r--net/bridge/netfilter/nft_reject_bridge.c2
-rw-r--r--net/can/bcm.c13
-rw-r--r--net/ceph/messenger.c31
-rw-r--r--net/ceph/osd_client.c216
-rw-r--r--net/ceph/osdmap.c24
-rw-r--r--net/ceph/pagevec.c4
-rw-r--r--net/core/dev.c6
-rw-r--r--net/core/ethtool.c12
-rw-r--r--net/core/filter.c21
-rw-r--r--net/core/neighbour.c10
-rw-r--r--net/core/pktgen.c3
-rw-r--r--net/core/sock.c15
-rw-r--r--net/dcb/dcbnl.c3
-rw-r--r--net/dccp/ccids/ccid2.c3
-rw-r--r--net/dsa/tag_trailer.c3
-rw-r--r--net/ieee802154/nl-phy.c2
-rw-r--r--net/ipv4/fib_frontend.c2
-rw-r--r--net/ipv4/inet_hashtables.c4
-rw-r--r--net/ipv4/ip_output.c3
-rw-r--r--net/ipv4/ip_tunnel.c4
-rw-r--r--net/ipv4/netfilter/ip_tables.c1
-rw-r--r--net/ipv4/route.c5
-rw-r--r--net/ipv4/tcp.c12
-rw-r--r--net/ipv4/tcp_ipv4.c4
-rw-r--r--net/ipv4/tcp_offload.c2
-rw-r--r--net/ipv4/udp.c2
-rw-r--r--net/ipv4/udp_diag.c2
-rw-r--r--net/ipv6/addrconf.c2
-rw-r--r--net/ipv6/datagram.c6
-rw-r--r--net/ipv6/icmp.c2
-rw-r--r--net/ipv6/ila/ila_xlat.c3
-rw-r--r--net/ipv6/inet6_hashtables.c4
-rw-r--r--net/ipv6/ip6_fib.c10
-rw-r--r--net/ipv6/ip6_output.c3
-rw-r--r--net/ipv6/netfilter/ip6_tables.c1
-rw-r--r--net/ipv6/route.c3
-rw-r--r--net/ipv6/tcp_ipv6.c4
-rw-r--r--net/ipv6/udp.c3
-rw-r--r--net/l2tp/l2tp_netlink.c6
-rw-r--r--net/l2tp/l2tp_ppp.c28
-rw-r--r--net/mac80211/chan.c2
-rw-r--r--net/mac80211/main.c14
-rw-r--r--net/mac80211/rc80211_minstrel.c4
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c4
-rw-r--r--net/mac80211/scan.c2
-rw-r--r--net/mac80211/util.c5
-rw-r--r--net/ncsi/ncsi-aen.c10
-rw-r--r--net/ncsi/ncsi-manage.c49
-rw-r--r--net/netfilter/ipset/ip_set_hash_gen.h5
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c4
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c2
-rw-r--r--net/netfilter/nf_conncount.c13
-rw-r--r--net/netfilter/nf_conntrack_netlink.c3
-rw-r--r--net/netfilter/nf_conntrack_proto.c3
-rw-r--r--net/netfilter/nf_nat_core.c5
-rw-r--r--net/netfilter/nf_tables_api.c42
-rw-r--r--net/netfilter/nf_tables_core.c3
-rw-r--r--net/netfilter/nfnetlink.c10
-rw-r--r--net/netfilter/nfnetlink_cthelper.c5
-rw-r--r--net/netfilter/nft_chain_filter.c5
-rw-r--r--net/netfilter/nft_connlimit.c2
-rw-r--r--net/netfilter/nft_dynset.c4
-rw-r--r--net/netfilter/nft_log.c10
-rw-r--r--net/netfilter/nft_set_rbtree.c2
-rw-r--r--net/netfilter/nft_socket.c1
-rw-r--r--net/netfilter/x_tables.c2
-rw-r--r--net/netfilter/xt_CT.c10
-rw-r--r--net/netfilter/xt_connmark.c2
-rw-r--r--net/netfilter/xt_set.c10
-rw-r--r--net/netlink/genetlink.c10
-rw-r--r--net/netrom/af_netrom.c2
-rw-r--r--net/openvswitch/datapath.c5
-rw-r--r--net/openvswitch/vport.c2
-rw-r--r--net/packet/af_packet.c6
-rw-r--r--net/rds/ib.c3
-rw-r--r--net/rds/ib_cm.c6
-rw-r--r--net/rds/info.c2
-rw-r--r--net/rds/loop.c1
-rw-r--r--net/rds/rds.h5
-rw-r--r--net/rds/recv.c5
-rw-r--r--net/rose/af_rose.c3
-rw-r--r--net/rxrpc/rxkad.c2
-rw-r--r--net/sched/act_ife.c12
-rw-r--r--net/sched/act_simple.c15
-rw-r--r--net/sched/sch_blackhole.c2
-rw-r--r--net/sched/sch_fq_codel.c7
-rw-r--r--net/sched/sch_hhf.c9
-rw-r--r--net/sctp/auth.c5
-rw-r--r--net/sctp/output.c28
-rw-r--r--net/sctp/protocol.c2
-rw-r--r--net/smc/af_smc.c12
-rw-r--r--net/smc/smc_wr.c6
-rw-r--r--net/socket.c18
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c3
-rw-r--r--net/sunrpc/auth_gss/gss_rpc_upcall.c6
-rw-r--r--net/sunrpc/cache.c2
-rw-r--r--net/sunrpc/clnt.c1
-rw-r--r--net/sunrpc/xprt.c23
-rw-r--r--net/sunrpc/xprtrdma/backchannel.c107
-rw-r--r--net/sunrpc/xprtrdma/fmr_ops.c26
-rw-r--r--net/sunrpc/xprtrdma/frwr_ops.c33
-rw-r--r--net/sunrpc/xprtrdma/module.c5
-rw-r--r--net/sunrpc/xprtrdma/rpc_rdma.c73
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma.c3
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_backchannel.c55
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c439
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_rw.c133
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_sendto.c510
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_transport.c481
-rw-r--r--net/sunrpc/xprtrdma/transport.c68
-rw-r--r--net/sunrpc/xprtrdma/verbs.c292
-rw-r--r--net/sunrpc/xprtrdma/xprt_rdma.h28
-rw-r--r--net/sunrpc/xprtsock.c4
-rw-r--r--net/tipc/netlink_compat.c5
-rw-r--r--net/tls/tls_main.c2
-rw-r--r--net/tls/tls_sw.c51
-rw-r--r--net/wireless/core.c1
-rw-r--r--net/wireless/nl80211.c4
-rw-r--r--net/wireless/util.c2
-rw-r--r--net/xdp/xdp_umem.c9
-rw-r--r--net/xdp/xsk.c5
-rw-r--r--samples/Kconfig31
-rw-r--r--samples/vfio-mdev/Makefile3
-rw-r--r--samples/vfio-mdev/mbochs.c1406
-rw-r--r--samples/vfio-mdev/mdpy-defs.h22
-rw-r--r--samples/vfio-mdev/mdpy-fb.c232
-rw-r--r--samples/vfio-mdev/mdpy.c807
-rw-r--r--scripts/Kconfig.include3
-rw-r--r--scripts/Makefile.build2
-rw-r--r--scripts/Makefile.gcc-plugins91
-rw-r--r--scripts/Makefile.kcov10
-rwxr-xr-xscripts/clang-version.sh18
-rwxr-xr-xscripts/documentation-file-ref-check56
-rw-r--r--scripts/gcc-plugins/Makefile5
-rwxr-xr-xscripts/gcc-x86_32-has-stack-protector.sh7
-rwxr-xr-xscripts/gcc-x86_64-has-stack-protector.sh5
-rwxr-xr-xscripts/kconfig/streamline_config.pl4
-rw-r--r--security/apparmor/audit.c90
-rw-r--r--security/apparmor/domain.c2
-rw-r--r--security/apparmor/include/audit.h6
-rw-r--r--security/apparmor/include/label.h2
-rw-r--r--security/apparmor/include/path.h33
-rw-r--r--security/apparmor/include/secid.h17
-rw-r--r--security/apparmor/label.c15
-rw-r--r--security/apparmor/lib.c2
-rw-r--r--security/apparmor/lsm.c50
-rw-r--r--security/apparmor/match.c2
-rw-r--r--security/apparmor/mount.c2
-rw-r--r--security/apparmor/policy.c7
-rw-r--r--security/apparmor/policy_unpack.c2
-rw-r--r--security/apparmor/resource.c2
-rw-r--r--security/apparmor/secid.c151
-rw-r--r--security/device_cgroup.c2
-rw-r--r--security/keys/trusted.c2
-rw-r--r--security/selinux/hooks.c2
-rw-r--r--security/selinux/ss/services.c2
-rw-r--r--sound/core/Kconfig4
-rw-r--r--sound/core/pcm_compat.c2
-rw-r--r--sound/core/pcm_native.c4
-rw-r--r--sound/core/seq/seq_memory.c3
-rw-r--r--sound/core/seq/seq_midi_emul.c2
-rw-r--r--sound/drivers/Kconfig4
-rw-r--r--sound/firewire/fireface/ff-protocol-ff400.c2
-rw-r--r--sound/firewire/packets-buffer.c2
-rw-r--r--sound/oss/dmasound/dmasound_core.c2
-rw-r--r--sound/pci/Kconfig10
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c7
-rw-r--r--sound/pci/cs46xx/dsp_spos.c9
-rw-r--r--sound/pci/ctxfi/ctatc.c18
-rw-r--r--sound/pci/ctxfi/ctdaio.c3
-rw-r--r--sound/pci/ctxfi/ctmixer.c5
-rw-r--r--sound/pci/ctxfi/ctsrc.c2
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c9
-rw-r--r--sound/pci/emu10k1/emufx.c8
-rw-r--r--sound/pci/emu10k1/emupcm.c4
-rw-r--r--sound/pci/emu10k1/p16v.c2
-rw-r--r--sound/pci/fm801.c16
-rw-r--r--sound/pci/hda/hda_codec.c4
-rw-r--r--sound/pci/hda/hda_proc.c5
-rw-r--r--sound/pci/hda/patch_ca0132.c4
-rw-r--r--sound/pci/hda/patch_conexant.c2
-rw-r--r--sound/pci/hda/patch_realtek.c3
-rw-r--r--sound/pci/lx6464es/lx6464es.c7
-rw-r--r--sound/pci/maestro3.c5
-rw-r--r--sound/pci/sonicvibes.c12
-rw-r--r--sound/pci/trident/trident_main.c4
-rw-r--r--sound/pci/via82xx.c4
-rw-r--r--sound/pci/via82xx_modem.c4
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c4
-rw-r--r--sound/soc/au1x/dbdma2.c4
-rw-r--r--sound/soc/codecs/hdmi-codec.c2
-rw-r--r--sound/soc/codecs/rt5645.c5
-rw-r--r--sound/soc/codecs/wm8904.c5
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c20
-rw-r--r--sound/soc/codecs/wm8994.c4
-rw-r--r--sound/soc/codecs/wm_adsp.c2
-rw-r--r--sound/soc/davinci/davinci-mcasp.c14
-rw-r--r--sound/soc/generic/audio-graph-card.c4
-rw-r--r--sound/soc/generic/audio-graph-scu-card.c4
-rw-r--r--sound/soc/generic/simple-card.c8
-rw-r--r--sound/soc/generic/simple-scu-card.c4
-rw-r--r--sound/soc/img/img-i2s-in.c4
-rw-r--r--sound/soc/img/img-i2s-out.c4
-rw-r--r--sound/soc/intel/common/sst-ipc.c4
-rw-r--r--sound/soc/intel/skylake/skl-topology.c20
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-afe-pcm.c3
-rw-r--r--sound/soc/omap/ams-delta.c38
-rw-r--r--sound/soc/pxa/mmp-sspa.c4
-rw-r--r--sound/soc/rockchip/rk3399_gru_sound.c2
-rw-r--r--sound/soc/sh/rcar/cmd.c2
-rw-r--r--sound/soc/sh/rcar/core.c4
-rw-r--r--sound/soc/sh/rcar/ctu.c2
-rw-r--r--sound/soc/sh/rcar/dvc.c2
-rw-r--r--sound/soc/sh/rcar/mix.c2
-rw-r--r--sound/soc/sh/rcar/src.c2
-rw-r--r--sound/soc/sh/rcar/ssi.c2
-rw-r--r--sound/soc/sh/rcar/ssiu.c2
-rw-r--r--sound/soc/soc-core.c10
-rw-r--r--sound/soc/soc-dapm.c2
-rw-r--r--sound/soc/soc-topology.c2
-rw-r--r--sound/soc/uniphier/aio-cpu.c10
-rw-r--r--sound/usb/6fire/pcm.c10
-rw-r--r--sound/usb/caiaq/audio.c7
-rw-r--r--sound/usb/card.h1
-rw-r--r--sound/usb/format.c10
-rw-r--r--sound/usb/line6/capture.c4
-rw-r--r--sound/usb/line6/pcm.c6
-rw-r--r--sound/usb/line6/playback.c4
-rw-r--r--sound/usb/mixer.c47
-rw-r--r--sound/usb/pcm.c2
-rw-r--r--sound/usb/quirks-table.h5
-rw-r--r--sound/usb/quirks.c19
-rw-r--r--sound/usb/usx2y/usbusx2y.c4
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c7
-rw-r--r--tools/bpf/bpftool/perf.c5
-rw-r--r--tools/bpf/bpftool/prog.c4
-rw-r--r--tools/include/uapi/linux/kvm.h4
-rw-r--r--tools/include/uapi/linux/prctl.h2
-rw-r--r--tools/lib/api/fs/fs.c2
-rw-r--r--tools/objtool/check.c1
-rw-r--r--tools/perf/util/bpf-prologue.c2
-rw-r--r--tools/power/cpupower/bench/parse.c2
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c15
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c35
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h9
-rw-r--r--tools/power/pm-graph/config/custom-timeline-functions.cfg4
-rw-r--r--tools/power/x86/turbostat/turbostat.82
-rw-r--r--tools/power/x86/turbostat/turbostat.c240
-rw-r--r--tools/testing/selftests/bpf/Makefile4
-rw-r--r--tools/testing/selftests/bpf/config10
-rw-r--r--tools/testing/selftests/bpf/get_cgroup_id_kern.c14
-rw-r--r--tools/testing/selftests/bpf/get_cgroup_id_user.c12
-rwxr-xr-xtools/testing/selftests/bpf/test_offload.py12
-rwxr-xr-xtools/testing/selftests/bpf/test_tunnel.sh26
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c58
-rw-r--r--tools/testing/selftests/cgroup/cgroup_util.c4
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc8
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc7
-rwxr-xr-xtools/testing/selftests/pstore/pstore_post_reboot_tests5
-rw-r--r--tools/testing/selftests/rseq/param_test.c24
-rw-r--r--tools/testing/selftests/rseq/rseq-arm.h1
-rw-r--r--tools/testing/selftests/rseq/rseq-mips.h725
-rw-r--r--tools/testing/selftests/rseq/rseq.h2
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/rseq/run_param_test.sh0
-rw-r--r--tools/testing/selftests/sparc64/Makefile20
-rw-r--r--tools/testing/selftests/sparc64/drivers/Makefile2
-rwxr-xr-xtools/testing/selftests/static_keys/test_static_keys.sh13
-rw-r--r--tools/testing/selftests/sync/config4
-rwxr-xr-xtools/testing/selftests/sysctl/sysctl.sh20
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/actions/ife.json2
-rwxr-xr-xtools/testing/selftests/user/test_user_copy.sh7
-rw-r--r--tools/testing/selftests/vm/compaction_test.c4
-rw-r--r--tools/testing/selftests/vm/mlock2-tests.c12
-rwxr-xr-xtools/testing/selftests/vm/run_vmtests5
-rw-r--r--tools/testing/selftests/vm/userfaultfd.c4
-rwxr-xr-xtools/testing/selftests/zram/zram.sh5
-rwxr-xr-xtools/testing/selftests/zram/zram_lib.sh5
-rw-r--r--virt/kvm/Kconfig5
-rw-r--r--virt/kvm/arm/arm.c32
-rw-r--r--virt/kvm/arm/mmu.c2
-rw-r--r--virt/kvm/arm/vgic/vgic-debug.c17
-rw-r--r--virt/kvm/arm/vgic/vgic-init.c100
-rw-r--r--virt/kvm/arm/vgic/vgic-kvm-device.c53
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio-v3.c112
-rw-r--r--virt/kvm/arm/vgic/vgic-v3.c104
-rw-r--r--virt/kvm/arm/vgic/vgic-v4.c2
-rw-r--r--virt/kvm/arm/vgic/vgic.h46
-rw-r--r--virt/kvm/kvm_main.c105
3920 files changed, 76591 insertions, 40556 deletions
diff --git a/Documentation/ABI/obsolete/sysfs-gpio b/Documentation/ABI/obsolete/sysfs-gpio
index 32513dc..40d41ea 100644
--- a/Documentation/ABI/obsolete/sysfs-gpio
+++ b/Documentation/ABI/obsolete/sysfs-gpio
@@ -11,7 +11,7 @@ Description:
Kernel code may export it for complete or partial access.
GPIOs are identified as they are inside the kernel, using integers in
- the range 0..INT_MAX. See Documentation/gpio/gpio.txt for more information.
+ the range 0..INT_MAX. See Documentation/gpio for more information.
/sys/class/gpio
/export ... asks the kernel to export a GPIO to userspace
diff --git a/Documentation/ABI/testing/sysfs-bus-rpmsg b/Documentation/ABI/testing/sysfs-bus-rpmsg
index 189e419..990fcc4 100644
--- a/Documentation/ABI/testing/sysfs-bus-rpmsg
+++ b/Documentation/ABI/testing/sysfs-bus-rpmsg
@@ -73,3 +73,23 @@ Description:
This sysfs entry tells us whether the channel is a local
server channel that is announced (values are either
true or false).
+
+What: /sys/bus/rpmsg/devices/.../driver_override
+Date: April 2018
+KernelVersion: 4.18
+Contact: Bjorn Andersson <bjorn.andersson@linaro.org>
+Description:
+ Every rpmsg device is a communication channel with a remote
+ processor. Channels are identified by a textual name (see
+ /sys/bus/rpmsg/devices/.../name above) and have a local
+ ("source") rpmsg address, and remote ("destination") rpmsg
+ address.
+
+ The listening entity (or client) which communicates with a
+ remote processor is referred as rpmsg driver. The rpmsg device
+ and rpmsg driver are matched based on rpmsg device name and
+ rpmsg driver ID table.
+
+ This sysfs entry allows the rpmsg driver for a rpmsg device
+ to be specified which will override standard OF, ID table
+ and name matching.
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index bd4975e..9c5e7732 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -238,9 +238,6 @@ Description: Discover and change clock speed of CPUs
See files in Documentation/cpu-freq/ for more information.
- In particular, read Documentation/cpu-freq/user-guide.txt
- to learn how to control the knobs.
-
What: /sys/devices/system/cpu/cpu#/cpufreq/freqdomain_cpus
Date: June 2013
diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index 540553c..9b01233 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -101,6 +101,7 @@ Date: February 2015
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
Description:
Controls the trimming rate in batch mode.
+ <deprecated>
What: /sys/fs/f2fs/<disk>/cp_interval
Date: October 2015
@@ -140,7 +141,7 @@ Contact: "Shuoran Liu" <liushuoran@huawei.com>
Description:
Shows total written kbytes issued to disk.
-What: /sys/fs/f2fs/<disk>/feature
+What: /sys/fs/f2fs/<disk>/features
Date: July 2017
Contact: "Jaegeuk Kim" <jaegeuk@kernel.org>
Description:
diff --git a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
index 597a2f3..1b31be3 100644
--- a/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
+++ b/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
@@ -25,3 +25,16 @@ Description:
Control touchpad mode.
* 1 -> Switched On
* 0 -> Switched Off
+
+What: /sys/bus/pci/devices/<bdf>/<device>/VPC2004:00/fn_lock
+Date: May 2018
+KernelVersion: 4.18
+Contact: "Oleg Keri <ezhi99@gmail.com>"
+Description:
+ Control fn-lock mode.
+ * 1 -> Switched On
+ * 0 -> Switched Off
+
+ For example:
+ # echo "0" > \
+ /sys/bus/pci/devices/0000:00:1f.0/PNP0C09:00/VPC2004:00/fn_lock
diff --git a/Documentation/acpi/method-customizing.txt b/Documentation/acpi/method-customizing.txt
index a3f598e..7235da9 100644
--- a/Documentation/acpi/method-customizing.txt
+++ b/Documentation/acpi/method-customizing.txt
@@ -16,7 +16,8 @@ control method rather than override the entire DSDT, because kernel
rebuild/reboot is not needed and test result can be got in minutes.
Note: Only ACPI METHOD can be overridden, any other object types like
- "Device", "OperationRegion", are not recognized.
+ "Device", "OperationRegion", are not recognized. Methods
+ declared inside scope operators are also not supported.
Note: The same ACPI control method can be overridden for many times,
and it's always the latest one that used by Linux/kernel.
Note: To get the ACPI debug object output (Store (AAAA, Debug)),
@@ -32,8 +33,6 @@ Note: To get the ACPI debug object output (Store (AAAA, Debug)),
DefinitionBlock ("", "SSDT", 1, "", "", 0x20080715)
{
- External (ACON)
-
Method (\_SB_.AC._PSR, 0, NotSerialized)
{
Store ("In AC _PSR", Debug)
@@ -42,9 +41,10 @@ Note: To get the ACPI debug object output (Store (AAAA, Debug)),
}
Note that the full pathname of the method in ACPI namespace
should be used.
- And remember to use "External" to declare external objects.
e) assemble the file to generate the AML code of the method.
- e.g. "iasl psr.asl" (psr.aml is generated as a result)
+ e.g. "iasl -vw 6084 psr.asl" (psr.aml is generated as a result)
+ If parameter "-vw 6084" is not supported by your iASL compiler,
+ please try a newer version.
f) mount debugfs by "mount -t debugfs none /sys/kernel/debug"
g) override the old method via the debugfs by running
"cat /tmp/psr.aml > /sys/kernel/debug/acpi/custom_method"
diff --git a/Documentation/admin-guide/LSM/apparmor.rst b/Documentation/admin-guide/LSM/apparmor.rst
index 3e9734b..6cf81bb 100644
--- a/Documentation/admin-guide/LSM/apparmor.rst
+++ b/Documentation/admin-guide/LSM/apparmor.rst
@@ -44,8 +44,8 @@ Links
Mailing List - apparmor@lists.ubuntu.com
-Wiki - http://apparmor.wiki.kernel.org/
+Wiki - http://wiki.apparmor.net
-User space tools - https://launchpad.net/apparmor
+User space tools - https://gitlab.com/apparmor
-Kernel module - git://git.kernel.org/pub/scm/linux/kernel/git/jj/apparmor-dev.git
+Kernel module - git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 638342d..efc7aa7 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -256,7 +256,7 @@
(may crash computer or cause data corruption)
ALSA [HW,ALSA]
- See Documentation/sound/alsa/alsa-parameters.txt
+ See Documentation/sound/alsa-configuration.rst
alignment= [KNL,ARM]
Allow the default userspace alignment fault handler
@@ -2926,9 +2926,6 @@
This will also cause panics on machine check exceptions.
Useful together with panic=30 to trigger a reboot.
- OSS [HW,OSS]
- See Documentation/sound/oss/oss-parameters.txt
-
page_owner= [KNL] Boot-time page_owner enabling option.
Storage of the information about who allocated
each page is disabled in default. With this switch,
@@ -4335,7 +4332,7 @@
[FTRACE] Set and start specified trace events in order
to facilitate early boot debugging. The event-list is a
comma separated list of trace events to enable. See
- also Documentation/trace/events.txt
+ also Documentation/trace/events.rst
trace_options=[option-list]
[FTRACE] Enable or disable tracer options at boot.
@@ -4350,7 +4347,7 @@
trace_options=stacktrace
- See also Documentation/trace/ftrace.txt "trace options"
+ See also Documentation/trace/ftrace.rst "trace options"
section.
tp_printk[FTRACE]
diff --git a/Documentation/admin-guide/pm/intel_pstate.rst b/Documentation/admin-guide/pm/intel_pstate.rst
index ab2fe0e..8b91649 100644
--- a/Documentation/admin-guide/pm/intel_pstate.rst
+++ b/Documentation/admin-guide/pm/intel_pstate.rst
@@ -410,7 +410,7 @@ argument is passed to the kernel in the command line.
That only is supported in some configurations, though (for example, if
the `HWP feature is enabled in the processor <Active Mode With HWP_>`_,
the operation mode of the driver cannot be changed), and if it is not
- supported in the current configuration, writes to this attribute with
+ supported in the current configuration, writes to this attribute will
fail with an appropriate error.
Interpretation of Policy Attributes
diff --git a/Documentation/arm/OMAP/README b/Documentation/arm/OMAP/README
index 75645c4..90c6c57 100644
--- a/Documentation/arm/OMAP/README
+++ b/Documentation/arm/OMAP/README
@@ -5,3 +5,7 @@ KERNEL NEW DEPENDENCIES
v4.3+ Update is needed for custom .config files to make sure
CONFIG_REGULATOR_PBIAS is enabled for MMC1 to work
properly.
+
+v4.18+ Update is needed for custom .config files to make sure
+ CONFIG_MMC_SDHCI_OMAP is enabled for all MMC instances
+ to work in DRA7 and K2G based boards.
diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt
index 8692702..207eca5 100644
--- a/Documentation/block/biodoc.txt
+++ b/Documentation/block/biodoc.txt
@@ -752,18 +752,6 @@ completion of the request to the block layer. This means ending tag
operations before calling end_that_request_last()! For an example of a user
of these helpers, see the IDE tagged command queueing support.
-Certain hardware conditions may dictate a need to invalidate the block tag
-queue. For instance, on IDE any tagged request error needs to clear both
-the hardware and software block queue and enable the driver to sanely restart
-all the outstanding requests. There's a third helper to do that:
-
- blk_queue_invalidate_tags(struct request_queue *q)
-
- Clear the internal block tag queue and re-add all the pending requests
- to the request queue. The driver will receive them again on the
- next request_fn run, just like it did the first time it encountered
- them.
-
3.2.5.2 Tag info
Some block functions exist to query current tag status or to go from a
@@ -805,8 +793,7 @@ Internally, block manages tags in the blk_queue_tag structure:
Most of the above is simple and straight forward, however busy_list may need
a bit of explaining. Normally we don't care too much about request ordering,
but in the event of any barrier requests in the tag queue we need to ensure
-that requests are restarted in the order they were queue. This may happen
-if the driver needs to use blk_queue_invalidate_tags().
+that requests are restarted in the order they were queue.
3.3 I/O Submission
diff --git a/Documentation/core-api/kernel-api.rst b/Documentation/core-api/kernel-api.rst
index 8e44aea..76fe2d0f 100644
--- a/Documentation/core-api/kernel-api.rst
+++ b/Documentation/core-api/kernel-api.rst
@@ -284,7 +284,7 @@ Resources Management
MTRR Handling
-------------
-.. kernel-doc:: arch/x86/kernel/cpu/mtrr/main.c
+.. kernel-doc:: arch/x86/kernel/cpu/mtrr/mtrr.c
:export:
Security Framework
diff --git a/Documentation/crypto/crypto_engine.rst b/Documentation/crypto/crypto_engine.rst
index 8272ac9..1d56221 100644
--- a/Documentation/crypto/crypto_engine.rst
+++ b/Documentation/crypto/crypto_engine.rst
@@ -8,11 +8,13 @@ The crypto engine API (CE), is a crypto queue manager.
Requirement
-----------
-You have to put at start of your tfm_ctx the struct crypto_engine_ctx
-struct your_tfm_ctx {
+You have to put at start of your tfm_ctx the struct crypto_engine_ctx::
+
+ struct your_tfm_ctx {
struct crypto_engine_ctx enginectx;
...
-};
+ };
+
Why: Since CE manage only crypto_async_request, it cannot know the underlying
request_type and so have access only on the TFM.
So using container_of for accessing __ctx is impossible.
diff --git a/Documentation/device-mapper/writecache.txt b/Documentation/device-mapper/writecache.txt
new file mode 100644
index 0000000..4424fa2
--- /dev/null
+++ b/Documentation/device-mapper/writecache.txt
@@ -0,0 +1,68 @@
+The writecache target caches writes on persistent memory or on SSD. It
+doesn't cache reads because reads are supposed to be cached in page cache
+in normal RAM.
+
+When the device is constructed, the first sector should be zeroed or the
+first sector should contain valid superblock from previous invocation.
+
+Constructor parameters:
+1. type of the cache device - "p" or "s"
+ p - persistent memory
+ s - SSD
+2. the underlying device that will be cached
+3. the cache device
+4. block size (4096 is recommended; the maximum block size is the page
+ size)
+5. the number of optional parameters (the parameters with an argument
+ count as two)
+ high_watermark n (default: 50)
+ start writeback when the number of used blocks reach this
+ watermark
+ low_watermark x (default: 45)
+ stop writeback when the number of used blocks drops below
+ this watermark
+ writeback_jobs n (default: unlimited)
+ limit the number of blocks that are in flight during
+ writeback. Setting this value reduces writeback
+ throughput, but it may improve latency of read requests
+ autocommit_blocks n (default: 64 for pmem, 65536 for ssd)
+ when the application writes this amount of blocks without
+ issuing the FLUSH request, the blocks are automatically
+ commited
+ autocommit_time ms (default: 1000)
+ autocommit time in milliseconds. The data is automatically
+ commited if this time passes and no FLUSH request is
+ received
+ fua (by default on)
+ applicable only to persistent memory - use the FUA flag
+ when writing data from persistent memory back to the
+ underlying device
+ nofua
+ applicable only to persistent memory - don't use the FUA
+ flag when writing back data and send the FLUSH request
+ afterwards
+ - some underlying devices perform better with fua, some
+ with nofua. The user should test it
+
+Status:
+1. error indicator - 0 if there was no error, otherwise error number
+2. the number of blocks
+3. the number of free blocks
+4. the number of blocks under writeback
+
+Messages:
+ flush
+ flush the cache device. The message returns successfully
+ if the cache device was flushed without an error
+ flush_on_suspend
+ flush the cache device on next suspend. Use this message
+ when you are going to remove the cache device. The proper
+ sequence for removing the cache device is:
+ 1. send the "flush_on_suspend" message
+ 2. load an inactive table with a linear target that maps
+ to the underlying device
+ 3. suspend the device
+ 4. ask for status and verify that there are no errors
+ 5. resume the device, so that it will use the linear
+ target
+ 6. the cache device is now inactive and it can be deleted
diff --git a/Documentation/devicetree/bindings/arm/amlogic.txt b/Documentation/devicetree/bindings/arm/amlogic.txt
index f747f47..6988056 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.txt
+++ b/Documentation/devicetree/bindings/arm/amlogic.txt
@@ -25,6 +25,10 @@ Boards with the Amlogic Meson8b SoC shall have the following properties:
Required root node property:
compatible: "amlogic,meson8b";
+Boards with the Amlogic Meson8m2 SoC shall have the following properties:
+ Required root node property:
+ compatible: "amlogic,meson8m2";
+
Boards with the Amlogic Meson GXBaby SoC shall have the following properties:
Required root node property:
compatible: "amlogic,meson-gxbb";
@@ -54,6 +58,8 @@ Board compatible values (alphabetically, grouped by SoC):
- "hardkernel,odroid-c1" (Meson8b)
- "tronfy,mxq" (Meson8b)
+ - "tronsmart,mxiii-plus" (Meson8m2)
+
- "amlogic,p200" (Meson gxbb)
- "amlogic,p201" (Meson gxbb)
- "friendlyarm,nanopi-k2" (Meson gxbb)
diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt
index 3e3efa0..1e3e29a 100644
--- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt
+++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm2835.txt
@@ -34,6 +34,10 @@ Raspberry Pi 3 Model B
Required root node properties:
compatible = "raspberrypi,3-model-b", "brcm,bcm2837";
+Raspberry Pi 3 Model B+
+Required root node properties:
+compatible = "raspberrypi,3-model-b-plus", "brcm,bcm2837";
+
Raspberry Pi Compute Module
Required root node properties:
compatible = "raspberrypi,compute-module", "brcm,bcm2835";
diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
index 14510b2..bdadc3d 100644
--- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
+++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
@@ -21,8 +21,6 @@ Required root node properties:
- "samsung,smdk5420" - for Exynos5420-based Samsung SMDK5420 eval board.
- "samsung,tm2" - for Exynos5433-based Samsung TM2 board.
- "samsung,tm2e" - for Exynos5433-based Samsung TM2E board.
- - "samsung,sd5v1" - for Exynos5440-based Samsung board.
- - "samsung,ssdk5440" - for Exynos5440-based Samsung board.
* Other companies Exynos SoC based
* FriendlyARM
diff --git a/Documentation/devicetree/bindings/arm/shmobile.txt b/Documentation/devicetree/bindings/arm/shmobile.txt
index d3d1df9..d8cf740 100644
--- a/Documentation/devicetree/bindings/arm/shmobile.txt
+++ b/Documentation/devicetree/bindings/arm/shmobile.txt
@@ -21,6 +21,8 @@ SoCs:
compatible = "renesas,r8a7744"
- RZ/G1E (R8A77450)
compatible = "renesas,r8a7745"
+ - RZ/G1C (R8A77470)
+ compatible = "renesas,r8a77470"
- R-Car M1A (R8A77781)
compatible = "renesas,r8a7778"
- R-Car H1 (R8A77790)
@@ -45,6 +47,8 @@ SoCs:
compatible = "renesas,r8a77970"
- R-Car V3H (R8A77980)
compatible = "renesas,r8a77980"
+ - R-Car E3 (R8A77990)
+ compatible = "renesas,r8a77990"
- R-Car D3 (R8A77995)
compatible = "renesas,r8a77995"
@@ -67,6 +71,8 @@ Boards:
compatible = "renesas,draak", "renesas,r8a77995"
- Eagle (RTP0RC77970SEB0010S)
compatible = "renesas,eagle", "renesas,r8a77970"
+ - Ebisu (RTP0RC77990SEB0010S)
+ compatible = "renesas,ebisu", "renesas,r8a77990"
- Genmai (RTK772100BC00000BR)
compatible = "renesas,genmai", "renesas,r7s72100"
- GR-Peach (X28A-M01-E/F)
@@ -78,6 +84,8 @@ Boards:
compatible = "renesas,h3ulcb", "renesas,r8a7795"
- Henninger
compatible = "renesas,henninger", "renesas,r8a7791"
+ - iWave Systems RZ/G1C Single Board Computer (iW-RainboW-G23S)
+ compatible = "iwave,g23s", "renesas,r8a77470"
- iWave Systems RZ/G1E SODIMM SOM Development Platform (iW-RainboW-G22D)
compatible = "iwave,g22d", "iwave,g22m", "renesas,r8a7745"
- iWave Systems RZ/G1E SODIMM System On Module (iW-RainboW-G22M-SM)
@@ -108,7 +116,7 @@ Boards:
compatible = "renesas,salvator-x", "renesas,r8a7795"
- Salvator-X (RTP0RC7796SIPB0011S)
compatible = "renesas,salvator-x", "renesas,r8a7796"
- - Salvator-X (RTP0RC7796SIPB0011S (M3N))
+ - Salvator-X (RTP0RC7796SIPB0011S (M3-N))
compatible = "renesas,salvator-x", "renesas,r8a77965"
- Salvator-XS (Salvator-X 2nd version, RTP0RC7795SIPB0012S)
compatible = "renesas,salvator-xs", "renesas,r8a7795"
@@ -124,6 +132,8 @@ Boards:
compatible = "renesas,sk-rzg1m", "renesas,r8a7743"
- Stout (ADAS Starterkit, Y-R-CAR-ADAS-SKH2-BOARD)
compatible = "renesas,stout", "renesas,r8a7790"
+ - V3HSK (Y-ASK-RCAR-V3H-WS10)
+ compatible = "renesas,v3hsk", "renesas,r8a77980"
- V3MSK (Y-ASK-RCAR-V3M-WS10)
compatible = "renesas,v3msk", "renesas,r8a77970"
- Wheat (RTP0RC7792ASKB0000JE)
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt
deleted file mode 100644
index bdf1a61..0000000
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-NVIDIA Tegra30 MC(Memory Controller)
-
-Required properties:
-- compatible : "nvidia,tegra30-mc"
-- reg : Should contain 4 register ranges(address and length); see the
- example below. Note that the MC registers are interleaved with the
- SMMU registers, and hence must be represented as multiple ranges.
-- interrupts : Should contain MC General interrupt.
-
-Example:
- memory-controller {
- compatible = "nvidia,tegra30-mc";
- reg = <0x7000f000 0x010
- 0x7000f03c 0x1b4
- 0x7000f200 0x028
- 0x7000f284 0x17c>;
- interrupts = <0 77 0x04>;
- };
diff --git a/Documentation/devicetree/bindings/bus/ti-sysc.txt b/Documentation/devicetree/bindings/bus/ti-sysc.txt
index 2957a9a..d8ed5b7 100644
--- a/Documentation/devicetree/bindings/bus/ti-sysc.txt
+++ b/Documentation/devicetree/bindings/bus/ti-sysc.txt
@@ -79,7 +79,11 @@ Optional properties:
mode as for example omap4 L4_CFG_CLKCTRL
- clock-names should contain at least "fck", and optionally also "ick"
- depending on the SoC and the interconnect target module
+ depending on the SoC and the interconnect target module,
+ some interconnect target modules also need additional
+ optional clocks that can be specified as listed in TRM
+ for the related CLKCTRL register bits 8 to 15 such as
+ "dbclk" or "clk32k" depending on their role
- ti,hwmods optional TI interconnect module name to use legacy
hwmod platform data
diff --git a/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt b/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt
index e2b377e..e950599 100644
--- a/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt
+++ b/Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt
@@ -10,9 +10,6 @@ Required Properties:
"amlogic,gxl-clkc" for GXL and GXM SoC,
"amlogic,axg-clkc" for AXG SoC.
-- reg: physical base address of the clock controller and length of memory
- mapped region.
-
- #clock-cells: should be 1.
Each clock is assigned an identifier and client nodes can use this identifier
@@ -20,13 +17,22 @@ to specify the clock which they consume. All available clocks are defined as
preprocessor macros in the dt-bindings/clock/gxbb-clkc.h header and can be
used in device tree sources.
+Parent node should have the following properties :
+- compatible: "syscon", "simple-mfd, and "amlogic,meson-gx-hhi-sysctrl" or
+ "amlogic,meson-axg-hhi-sysctrl"
+- reg: base address and size of the HHI system control register space.
+
Example: Clock controller node:
- clkc: clock-controller@c883c000 {
+sysctrl: system-controller@0 {
+ compatible = "amlogic,meson-gx-hhi-sysctrl", "syscon", "simple-mfd";
+ reg = <0 0 0 0x400>;
+
+ clkc: clock-controller {
#clock-cells = <1>;
compatible = "amlogic,gxbb-clkc";
- reg = <0x0 0xc883c000 0x0 0x3db>;
};
+};
Example: UART controller node that consumes the clock generated by the clock
controller:
diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
index 7364953..45ac19b 100644
--- a/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
+++ b/Documentation/devicetree/bindings/clock/st/st,clkgen.txt
@@ -31,10 +31,10 @@ This binding uses the common clock binding[1].
Each subnode should use the binding described in [2]..[7]
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[3] Documentation/devicetree/bindings/clock/st,clkgen-mux.txt
-[4] Documentation/devicetree/bindings/clock/st,clkgen-pll.txt
-[7] Documentation/devicetree/bindings/clock/st,quadfs.txt
-[8] Documentation/devicetree/bindings/clock/st,flexgen.txt
+[3] Documentation/devicetree/bindings/clock/st/st,clkgen-mux.txt
+[4] Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt
+[7] Documentation/devicetree/bindings/clock/st/st,quadfs.txt
+[8] Documentation/devicetree/bindings/clock/st/st,flexgen.txt
Required properties:
diff --git a/Documentation/devicetree/bindings/clock/ti/gate.txt b/Documentation/devicetree/bindings/clock/ti/gate.txt
index 03f8fde..56d603c 100644
--- a/Documentation/devicetree/bindings/clock/ti/gate.txt
+++ b/Documentation/devicetree/bindings/clock/ti/gate.txt
@@ -10,7 +10,7 @@ will be controlled instead and the corresponding hw-ops for
that is used.
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[2] Documentation/devicetree/bindings/clock/gate-clock.txt
+[2] Documentation/devicetree/bindings/clock/gpio-gate-clock.txt
[3] Documentation/devicetree/bindings/clock/ti/clockdomain.txt
Required properties:
diff --git a/Documentation/devicetree/bindings/clock/ti/interface.txt b/Documentation/devicetree/bindings/clock/ti/interface.txt
index 3111a40..3f47040 100644
--- a/Documentation/devicetree/bindings/clock/ti/interface.txt
+++ b/Documentation/devicetree/bindings/clock/ti/interface.txt
@@ -9,7 +9,7 @@ companion clock finding (match corresponding functional gate
clock) and hardware autoidle enable / disable.
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[2] Documentation/devicetree/bindings/clock/gate-clock.txt
+[2] Documentation/devicetree/bindings/clock/gpio-gate-clock.txt
Required properties:
- compatible : shall be one of:
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt
index d36f07e..0551c78 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-mediatek.txt
@@ -8,7 +8,7 @@ Required properties:
"intermediate" - A parent of "cpu" clock which is used as "intermediate" clock
source (usually MAINPLL) when the original CPU PLL is under
transition and not stable yet.
- Please refer to Documentation/devicetree/bindings/clk/clock-bindings.txt for
+ Please refer to Documentation/devicetree/bindings/clock/clock-bindings.txt for
generic clock consumer properties.
- operating-points-v2: Please refer to Documentation/devicetree/bindings/opp/opp.txt
for detail.
diff --git a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
index d6d2833..fc2bcbe 100644
--- a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
+++ b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
@@ -12,7 +12,7 @@ Required properties:
- clocks: Phandles for clock specified in "clock-names" property
- clock-names : The name of clock used by the DFI, must be
"pclk_ddr_mon";
-- operating-points-v2: Refer to Documentation/devicetree/bindings/power/opp.txt
+- operating-points-v2: Refer to Documentation/devicetree/bindings/opp/opp.txt
for details.
- center-supply: DMC supply node.
- status: Marks the node enabled/disabled.
diff --git a/Documentation/devicetree/bindings/display/bridge/tda998x.txt b/Documentation/devicetree/bindings/display/bridge/tda998x.txt
index 1a4eaca..f5a02f6 100644
--- a/Documentation/devicetree/bindings/display/bridge/tda998x.txt
+++ b/Documentation/devicetree/bindings/display/bridge/tda998x.txt
@@ -30,7 +30,7 @@ Optional properties:
- nxp,calib-gpios: calibration GPIO, which must correspond with the
gpio used for the TDA998x interrupt pin.
-[1] Documentation/sound/alsa/soc/DAI.txt
+[1] Documentation/sound/soc/dai.rst
[2] include/dt-bindings/display/tda998x.h
Example:
diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
index 7b40054..fcf6979 100644
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.txt
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
@@ -11,9 +11,10 @@ Required properties:
* "qcom,scm-msm8660" for MSM8660 platforms
* "qcom,scm-msm8690" for MSM8690 platforms
* "qcom,scm-msm8996" for MSM8996 platforms
+ * "qcom,scm-ipq4019" for IPQ4019 platforms
* "qcom,scm" for later processors (MSM8916, APQ8084, MSM8974, etc)
- clocks: One to three clocks may be required based on compatible.
- * No clock required for "qcom,scm-msm8996"
+ * No clock required for "qcom,scm-msm8996", "qcom,scm-ipq4019"
* Only core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660", and "qcom,scm-msm8960"
* Core, iface, and bus clocks required for "qcom,scm"
- clock-names: Must contain "core" for the core clock, "iface" for the interface
diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt b/Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt
index 039219d..18a2cde 100644
--- a/Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt
+++ b/Documentation/devicetree/bindings/gpu/arm,mali-midgard.txt
@@ -34,7 +34,7 @@ Optional properties:
- mali-supply : Phandle to regulator for the Mali device. Refer to
Documentation/devicetree/bindings/regulator/regulator.txt for details.
-- operating-points-v2 : Refer to Documentation/devicetree/bindings/power/opp.txt
+- operating-points-v2 : Refer to Documentation/devicetree/bindings/opp/opp.txt
for details.
diff --git a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt
index c1f65d1..63cd911 100644
--- a/Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt
+++ b/Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt
@@ -44,7 +44,7 @@ Optional properties:
- memory-region:
Memory region to allocate from, as defined in
- Documentation/devicetree/bindi/reserved-memory/reserved-memory.txt
+ Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
- mali-supply:
Phandle to regulator for the Mali device, as defined in
diff --git a/Documentation/devicetree/bindings/i2c/i2c-davinci.txt b/Documentation/devicetree/bindings/i2c/i2c-davinci.txt
index 64e6e65..b745f37 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-davinci.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-davinci.txt
@@ -24,7 +24,7 @@ Recommended properties :
- clock-frequency : desired I2C bus clock frequency in Hz.
- ti,has-pfunc: boolean; if defined, it indicates that SoC supports PFUNC
registers. PFUNC registers allow to switch I2C pins to function as
- GPIOs, so they can by toggled manually.
+ GPIOs, so they can be toggled manually.
Example (enbw_cmc board):
i2c@1c22000 {
diff --git a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
index 4a7811e..7ce8fae 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-rcar.txt
@@ -15,6 +15,7 @@ Required properties:
"renesas,i2c-r8a7796" if the device is a part of a R8A7796 SoC.
"renesas,i2c-r8a77965" if the device is a part of a R8A77965 SoC.
"renesas,i2c-r8a77970" if the device is a part of a R8A77970 SoC.
+ "renesas,i2c-r8a77980" if the device is a part of a R8A77980 SoC.
"renesas,i2c-r8a77995" if the device is a part of a R8A77995 SoC.
"renesas,rcar-gen1-i2c" for a generic R-Car Gen1 compatible device.
"renesas,rcar-gen2-i2c" for a generic R-Car Gen2 or RZ/G1 compatible
diff --git a/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
index 89b3250..66ae46d 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt
@@ -8,9 +8,7 @@ Required properties:
(b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
(c) "samsung, s3c2440-hdmiphy-i2c", for s3c2440-like i2c used
inside HDMIPHY block found on several samsung SoCs
- (d) "samsung, exynos5440-i2c", for s3c2440-like i2c used
- on EXYNOS5440 which does not need GPIO configuration.
- (e) "samsung, exynos5-sata-phy-i2c", for s3c2440-like i2c used as
+ (d) "samsung, exynos5-sata-phy-i2c", for s3c2440-like i2c used as
a host to SATA PHY controller on an internal bus.
- reg: physical base address of the controller and length of memory mapped
region.
diff --git a/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt b/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt
new file mode 100644
index 0000000..2888d07
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/mtk-pmic-keys.txt
@@ -0,0 +1,43 @@
+MediaTek MT6397/MT6323 PMIC Keys Device Driver
+
+There are two key functions provided by MT6397/MT6323 PMIC, pwrkey
+and homekey. The key functions are defined as the subnode of the function
+node provided by MT6397/MT6323 PMIC that is being defined as one kind
+of Muti-Function Device (MFD)
+
+For MT6397/MT6323 MFD bindings see:
+Documentation/devicetree/bindings/mfd/mt6397.txt
+
+Required properties:
+- compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys"
+- linux,keycodes: See Documentation/devicetree/bindings/input/keys.txt
+
+Optional Properties:
+- wakeup-source: See Documentation/devicetree/bindings/power/wakeup-source.txt
+- mediatek,long-press-mode: Long press key shutdown setting, 1 for
+ pwrkey only, 2 for pwrkey/homekey together, others for disabled.
+- power-off-time-sec: See Documentation/devicetree/bindings/input/keys.txt
+
+Example:
+
+ pmic: mt6397 {
+ compatible = "mediatek,mt6397";
+
+ ...
+
+ mt6397keys: mt6397keys {
+ compatible = "mediatek,mt6397-keys";
+ mediatek,long-press-mode = <1>;
+ power-off-time-sec = <0>;
+
+ power {
+ linux,keycodes = <116>;
+ wakeup-source;
+ };
+
+ home {
+ linux,keycodes = <114>;
+ };
+ };
+
+ };
diff --git a/Documentation/devicetree/bindings/input/rmi4/rmi_2d_sensor.txt b/Documentation/devicetree/bindings/input/rmi4/rmi_2d_sensor.txt
index f2c30c8..9afffbd 100644
--- a/Documentation/devicetree/bindings/input/rmi4/rmi_2d_sensor.txt
+++ b/Documentation/devicetree/bindings/input/rmi4/rmi_2d_sensor.txt
@@ -12,7 +12,7 @@ Additional documentation for F11 can be found at:
http://www.synaptics.com/sites/default/files/511-000136-01-Rev-E-RMI4-Interfacing-Guide.pdf
Optional Touch Properties:
-Description in Documentation/devicetree/bindings/input/touch
+Description in Documentation/devicetree/bindings/input/touchscreen
- touchscreen-inverted-x
- touchscreen-inverted-y
- touchscreen-swapped-x-y
diff --git a/Documentation/devicetree/bindings/input/rotary-encoder.txt b/Documentation/devicetree/bindings/input/rotary-encoder.txt
index f99fe5c..a644408 100644
--- a/Documentation/devicetree/bindings/input/rotary-encoder.txt
+++ b/Documentation/devicetree/bindings/input/rotary-encoder.txt
@@ -28,7 +28,7 @@ Deprecated properties:
This property is deprecated. Instead, a 'steps-per-period ' value should
be used, such as "rotary-encoder,steps-per-period = <2>".
-See Documentation/input/rotary-encoder.txt for more information.
+See Documentation/input/devices/rotary-encoder.rst for more information.
Example:
diff --git a/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt b/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
index 764db86..3108109 100644
--- a/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
+++ b/Documentation/devicetree/bindings/leds/backlight/pwm-backlight.txt
@@ -17,6 +17,10 @@ Optional properties:
"pwms" property (see PWM binding[0])
- enable-gpios: contains a single GPIO specifier for the GPIO which enables
and disables the backlight (see GPIO binding[1])
+ - post-pwm-on-delay-ms: Delay in ms between setting an initial (non-zero) PWM
+ and enabling the backlight using GPIO.
+ - pwm-off-delay-ms: Delay in ms between disabling the backlight using GPIO
+ and setting PWM value to 0.
[0]: Documentation/devicetree/bindings/pwm/pwm.txt
[1]: Documentation/devicetree/bindings/gpio/gpio.txt
@@ -32,4 +36,6 @@ Example:
power-supply = <&vdd_bl_reg>;
enable-gpios = <&gpio 58 0>;
+ post-pwm-on-delay-ms = <10>;
+ pwm-off-delay-ms = <10>;
};
diff --git a/Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.txt b/Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.txt
new file mode 100644
index 0000000..ff5c921
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/backlight/zii,rave-sp-backlight.txt
@@ -0,0 +1,23 @@
+Zodiac Inflight Innovations RAVE Supervisory Processor Backlight Bindings
+
+RAVE SP backlight device is a "MFD cell" device corresponding to
+backlight functionality of RAVE Supervisory Processor. It is expected
+that its Device Tree node is specified as a child of the node
+corresponding to the parent RAVE SP device (as documented in
+Documentation/devicetree/bindings/mfd/zii,rave-sp.txt)
+
+Required properties:
+
+- compatible: Should be "zii,rave-sp-backlight"
+
+Example:
+
+ rave-sp {
+ compatible = "zii,rave-sp-rdu1";
+ current-speed = <38400>;
+
+ backlight {
+ compatible = "zii,rave-sp-backlight";
+ };
+ }
+
diff --git a/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt b/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt
index c7888d6..880d4d7 100644
--- a/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt
+++ b/Documentation/devicetree/bindings/media/stih407-c8sectpfe.txt
@@ -28,7 +28,7 @@ See: Documentation/devicetree/bindings/clock/clock-bindings.txt
- pinctrl-names : a pinctrl state named tsin%d-serial or tsin%d-parallel (where %d is tsin-num)
must be defined for each tsin child node.
- pinctrl-0 : phandle referencing pin configuration for this tsin configuration
-See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Required properties (tsin (child) node):
diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt
index f9632ba..7d60a50 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-mc.txt
@@ -6,11 +6,21 @@ Required properties:
example below. Note that the MC registers are interleaved with the
GART registers, and hence must be represented as multiple ranges.
- interrupts : Should contain MC General interrupt.
+- #reset-cells : Should be 1. This cell represents memory client module ID.
+ The assignments may be found in header file <dt-bindings/memory/tegra20-mc.h>
+ or in the TRM documentation.
Example:
- memory-controller@7000f000 {
+ mc: memory-controller@7000f000 {
compatible = "nvidia,tegra20-mc";
reg = <0x7000f000 0x024
0x7000f03c 0x3c4>;
interrupts = <0 77 0x04>;
+ #reset-cells = <1>;
+ };
+
+ video-codec@6001a000 {
+ compatible = "nvidia,tegra20-vde";
+ ...
+ resets = <&mc TEGRA20_MC_RESET_VDE>;
};
diff --git a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt
index 14968b0..a878b59 100644
--- a/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.txt
@@ -12,6 +12,9 @@ Required properties:
- clock-names: Must include the following entries:
- mc: the module's clock input
- interrupts: The interrupt outputs from the controller.
+- #reset-cells : Should be 1. This cell represents memory client module ID.
+ The assignments may be found in header file <dt-bindings/memory/tegra30-mc.h>
+ or in the TRM documentation.
Required properties for Tegra30, Tegra114, Tegra124, Tegra132 and Tegra210:
- #iommu-cells: Should be 1. The single cell of the IOMMU specifier defines
@@ -72,12 +75,14 @@ Example SoC include file:
interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
#iommu-cells = <1>;
+ #reset-cells = <1>;
};
sdhci@700b0000 {
compatible = "nvidia,tegra124-sdhci";
...
iommus = <&mc TEGRA_SWGROUP_SDMMC1A>;
+ resets = <&mc TEGRA124_MC_RESET_SDMMC1>;
};
};
diff --git a/Documentation/devicetree/bindings/mfd/arizona.txt b/Documentation/devicetree/bindings/mfd/arizona.txt
index bdd0176..a014afb 100644
--- a/Documentation/devicetree/bindings/mfd/arizona.txt
+++ b/Documentation/devicetree/bindings/mfd/arizona.txt
@@ -50,7 +50,7 @@ Required properties:
Optional properties:
- - wlf,reset : GPIO specifier for the GPIO controlling /RESET
+ - reset-gpios : GPIO specifier for the GPIO controlling /RESET
- clocks: Should reference the clocks supplied on MCLK1 and MCLK2
- clock-names: Should contains two strings:
@@ -70,6 +70,10 @@ Optional properties:
Documentation/devicetree/bindings/regulator/regulator.txt
(wm5102, wm5110, wm8280, wm8997, wm8998, wm1814)
+Deprecated properties:
+
+ - wlf,reset : GPIO specifier for the GPIO controlling /RESET
+
Also see child specific device properties:
Regulator - ../regulator/arizona-regulator.txt
Extcon - ../extcon/extcon-arizona.txt
diff --git a/Documentation/devicetree/bindings/mfd/as3722.txt b/Documentation/devicetree/bindings/mfd/as3722.txt
index 0b2a609..5297b22 100644
--- a/Documentation/devicetree/bindings/mfd/as3722.txt
+++ b/Documentation/devicetree/bindings/mfd/as3722.txt
@@ -46,7 +46,7 @@ is required:
Following properties are require if pin control setting is required
at boot.
- pinctrl-names: A pinctrl state named "default" be defined, using the
- bindings in pinctrl/pinctrl-binding.txt.
+ bindings in pinctrl/pinctrl-bindings.txt.
- pinctrl[0...n]: Properties to contain the phandle that refer to
different nodes of pin control settings. These nodes represents
the pin control setting of state 0 to state n. Each of these
diff --git a/Documentation/devicetree/bindings/mfd/da9063.txt b/Documentation/devicetree/bindings/mfd/da9063.txt
index 05b21bc..443e682 100644
--- a/Documentation/devicetree/bindings/mfd/da9063.txt
+++ b/Documentation/devicetree/bindings/mfd/da9063.txt
@@ -1,4 +1,4 @@
-* Dialog DA9063 Power Management Integrated Circuit (PMIC)
+* Dialog DA9063/DA9063L Power Management Integrated Circuit (PMIC)
DA9093 consists of a large and varied group of sub-devices (I2C Only):
@@ -6,14 +6,14 @@ Device Supply Names Description
------ ------------ -----------
da9063-regulator : : LDOs & BUCKs
da9063-onkey : : On Key
-da9063-rtc : : Real-Time Clock
+da9063-rtc : : Real-Time Clock (DA9063 only)
da9063-watchdog : : Watchdog
======
Required properties:
-- compatible : Should be "dlg,da9063"
+- compatible : Should be "dlg,da9063" or "dlg,da9063l"
- reg : Specifies the I2C slave address (this defaults to 0x58 but it can be
modified to match the chip's OTP settings).
- interrupt-parent : Specifies the reference to the interrupt controller for
@@ -23,8 +23,8 @@ Required properties:
Sub-nodes:
-- regulators : This node defines the settings for the LDOs and BUCKs. The
- DA9063 regulators are bound using their names listed below:
+- regulators : This node defines the settings for the LDOs and BUCKs.
+ The DA9063(L) regulators are bound using their names listed below:
bcore1 : BUCK CORE1
bcore2 : BUCK CORE2
@@ -32,16 +32,16 @@ Sub-nodes:
bmem : BUCK MEM
bio : BUCK IO
bperi : BUCK PERI
- ldo1 : LDO_1
- ldo2 : LDO_2
+ ldo1 : LDO_1 (DA9063 only)
+ ldo2 : LDO_2 (DA9063 only)
ldo3 : LDO_3
- ldo4 : LDO_4
- ldo5 : LDO_5
- ldo6 : LDO_6
+ ldo4 : LDO_4 (DA9063 only)
+ ldo5 : LDO_5 (DA9063 only)
+ ldo6 : LDO_6 (DA9063 only)
ldo7 : LDO_7
ldo8 : LDO_8
ldo9 : LDO_9
- ldo10 : LDO_10
+ ldo10 : LDO_10 (DA9063 only)
ldo11 : LDO_11
The component follows the standard regulator framework and the bindings
@@ -49,8 +49,9 @@ Sub-nodes:
Documentation/devicetree/bindings/regulator/regulator.txt
- rtc : This node defines settings for the Real-Time Clock associated with
- the DA9063. There are currently no entries in this binding, however
- compatible = "dlg,da9063-rtc" should be added if a node is created.
+ the DA9063 only. The RTC is not present in DA9063L. There are currently
+ no entries in this binding, however compatible = "dlg,da9063-rtc" should
+ be added if a node is created.
- onkey : This node defines the OnKey settings for controlling the key
functionality of the device. The node should contain the compatible property
@@ -65,8 +66,9 @@ Sub-nodes:
and KEY_SLEEP.
- watchdog : This node defines settings for the Watchdog timer associated
- with the DA9063. There are currently no entries in this binding, however
- compatible = "dlg,da9063-watchdog" should be added if a node is created.
+ with the DA9063 and DA9063L. There are currently no entries in this
+ binding, however compatible = "dlg,da9063-watchdog" should be added
+ if a node is created.
Example:
diff --git a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
index 15bc885..c639705 100644
--- a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
+++ b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt
@@ -12,6 +12,30 @@ Required properties:
- spi-max-frequency : Typically set to 3000000
- spi-cs-high : SPI chip select direction
+Optional subnodes:
+
+The sub-functions of CPCAP get their own node with their own compatible values,
+which are described in the following files:
+
+- ../power/supply/cpcap-battery.txt
+- ../power/supply/cpcap-charger.txt
+- ../regulator/cpcap-regulator.txt
+- ../phy/phy-cpcap-usb.txt
+- ../input/cpcap-pwrbutton.txt
+- ../rtc/cpcap-rtc.txt
+- ../leds/leds-cpcap.txt
+- ../iio/adc/cpcap-adc.txt
+
+The only exception is the audio codec. Instead of a compatible value its
+node must be named "audio-codec".
+
+Required properties for the audio-codec subnode:
+
+- #sound-dai-cells = <1>;
+
+The audio-codec provides two DAIs. The first one is connected to the
+Stereo HiFi DAC and the second one is connected to the Voice DAC.
+
Example:
&mcspi1 {
@@ -26,6 +50,24 @@ Example:
#size-cells = <0>;
spi-max-frequency = <3000000>;
spi-cs-high;
+
+ audio-codec {
+ #sound-dai-cells = <1>;
+
+ /* HiFi */
+ port@0 {
+ endpoint {
+ remote-endpoint = <&cpu_dai1>;
+ };
+ };
+
+ /* Voice */
+ port@1 {
+ endpoint {
+ remote-endpoint = <&cpu_dai2>;
+ };
+ };
+ };
};
};
diff --git a/Documentation/devicetree/bindings/mfd/mt6397.txt b/Documentation/devicetree/bindings/mfd/mt6397.txt
index 522a3bb..0ebd08a 100644
--- a/Documentation/devicetree/bindings/mfd/mt6397.txt
+++ b/Documentation/devicetree/bindings/mfd/mt6397.txt
@@ -7,11 +7,12 @@ MT6397/MT6323 is a multifunction device with the following sub modules:
- GPIO
- Clock
- LED
+- Keys
It is interfaced to host controller using SPI interface by a proprietary hardware
called PMIC wrapper or pwrap. MT6397/MT6323 MFD is a child device of pwrap.
See the following for pwarp node definitions:
-Documentation/devicetree/bindings/soc/pwrap.txt
+Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
This document describes the binding for MFD device and its sub module.
@@ -40,6 +41,11 @@ Optional subnodes:
- compatible: "mediatek,mt6323-led"
see Documentation/devicetree/bindings/leds/leds-mt6323.txt
+- keys
+ Required properties:
+ - compatible: "mediatek,mt6397-keys" or "mediatek,mt6323-keys"
+ see Documentation/devicetree/bindings/input/mtk-pmic-keys.txt
+
Example:
pwrap: pwrap@1000f000 {
compatible = "mediatek,mt8135-pwrap";
diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt
index 6ac06c1..1437062 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt
+++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.txt
@@ -29,6 +29,9 @@ Required properties:
"qcom,pm8916",
"qcom,pm8004",
"qcom,pm8909",
+ "qcom,pm8998",
+ "qcom,pmi8998",
+ "qcom,pm8005",
or generalized "qcom,spmi-pmic".
- reg: Specifies the SPMI USID slave address for this device.
For more information see:
diff --git a/Documentation/devicetree/bindings/mfd/stm32-timers.txt b/Documentation/devicetree/bindings/mfd/stm32-timers.txt
index 1db6e00..0e900b5 100644
--- a/Documentation/devicetree/bindings/mfd/stm32-timers.txt
+++ b/Documentation/devicetree/bindings/mfd/stm32-timers.txt
@@ -19,6 +19,11 @@ Required parameters:
Optional parameters:
- resets: Phandle to the parent reset controller.
See ../reset/st,stm32-rcc.txt
+- dmas: List of phandle to dma channels that can be used for
+ this timer instance. There may be up to 7 dma channels.
+- dma-names: List of dma names. Must match 'dmas' property. Valid
+ names are: "ch1", "ch2", "ch3", "ch4", "up", "trig",
+ "com".
Optional subnodes:
- pwm: See ../pwm/pwm-stm32.txt
@@ -44,3 +49,18 @@ Example:
reg = <0>;
};
};
+
+Example with all dmas:
+ timer@40010000 {
+ ...
+ dmas = <&dmamux1 11 0x400 0x0>,
+ <&dmamux1 12 0x400 0x0>,
+ <&dmamux1 13 0x400 0x0>,
+ <&dmamux1 14 0x400 0x0>,
+ <&dmamux1 15 0x400 0x0>,
+ <&dmamux1 16 0x400 0x0>,
+ <&dmamux1 17 0x400 0x0>;
+ dma-names = "ch1", "ch2", "ch3", "ch4", "up", "trig", "com";
+ ...
+ child nodes...
+ };
diff --git a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
index dd2c065..daa091c 100644
--- a/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
+++ b/Documentation/devicetree/bindings/mfd/sun6i-prcm.txt
@@ -8,8 +8,8 @@ Required properties:
- reg: The PRCM registers range
The prcm node may contain several subdevices definitions:
- - see Documentation/devicetree/clk/sunxi.txt for clock devices
- - see Documentation/devicetree/reset/allwinner,sunxi-clock-reset.txt for reset
+ - see Documentation/devicetree/bindings/clock/sunxi.txt for clock devices
+ - see Documentation/devicetree/bindings/reset/allwinner,sunxi-clock-reset.txt for reset
controller devices
diff --git a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
index a58c173..0419a63 100644
--- a/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
+++ b/Documentation/devicetree/bindings/mmc/exynos-dw-mshc.txt
@@ -62,7 +62,7 @@ Required properties for a slot (Deprecated - Recommend to use one slot per host)
rest of the gpios (depending on the bus-width property) are the data lines in
no particular order. The format of the gpio specifier depends on the gpio
controller.
-(Deprecated - Refer to Documentation/devicetree/binding/pinctrl/samsung-pinctrl.txt)
+(Deprecated - Refer to Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt)
Example:
diff --git a/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt b/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt
index 3149297..f064528 100644
--- a/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt
+++ b/Documentation/devicetree/bindings/mmc/microchip,sdhci-pic32.txt
@@ -12,7 +12,7 @@ Required properties:
See: Documentation/devicetree/bindings/clock/clock-bindings.txt
- pinctrl-names: A pinctrl state names "default" must be defined.
- pinctrl-0: Phandle referencing pin configuration of the SDHCI controller.
- See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+ See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Example:
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-st.txt b/Documentation/devicetree/bindings/mmc/sdhci-st.txt
index 6b3d40c..ccf82b4 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-st.txt
+++ b/Documentation/devicetree/bindings/mmc/sdhci-st.txt
@@ -20,7 +20,7 @@ Required properties:
- pinctrl-names: A pinctrl state names "default" must be defined.
- pinctrl-0: Phandle referencing pin configuration of the sd/emmc controller.
- See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+ See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
- reg: This must provide the host controller base address and it can also
contain the FlashSS Top register for TX/RX delay used by the driver
diff --git a/Documentation/devicetree/bindings/net/dsa/ksz.txt b/Documentation/devicetree/bindings/net/dsa/ksz.txt
index fd23904..a700943 100644
--- a/Documentation/devicetree/bindings/net/dsa/ksz.txt
+++ b/Documentation/devicetree/bindings/net/dsa/ksz.txt
@@ -6,7 +6,7 @@ Required properties:
- compatible: For external switch chips, compatible string must be exactly one
of: "microchip,ksz9477"
-See Documentation/devicetree/bindings/dsa/dsa.txt for a list of additional
+See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional
required and optional properties.
Examples:
diff --git a/Documentation/devicetree/bindings/net/dsa/mt7530.txt b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
index a9bc27b..aa3527f 100644
--- a/Documentation/devicetree/bindings/net/dsa/mt7530.txt
+++ b/Documentation/devicetree/bindings/net/dsa/mt7530.txt
@@ -31,7 +31,7 @@ Required properties for the child nodes within ports container:
- phy-mode: String, must be either "trgmii" or "rgmii" for port labeled
"cpu".
-See Documentation/devicetree/bindings/dsa/dsa.txt for a list of additional
+See Documentation/devicetree/bindings/net/dsa/dsa.txt for a list of additional
required, optional properties and how the integrated switch subnodes must
be specified.
diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
index d695437..e319fe5 100644
--- a/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
+++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
@@ -4,6 +4,7 @@ Required properties:
- compatible: Should be one of the following:
"allwinner,sun4i-a10-sid"
"allwinner,sun7i-a20-sid"
+ "allwinner,sun8i-a83t-sid"
"allwinner,sun8i-h3-sid"
"allwinner,sun50i-a64-sid"
diff --git a/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt b/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt
index d5e22fc..0df79d9 100644
--- a/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt
+++ b/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt
@@ -18,7 +18,7 @@ Optional properties:
Data cells:
Data cells are child nodes of eerpom node, bindings for which are
-documented in Documentation/bindings/nvmem/nvmem.txt
+documented in Documentation/devicetree/bindings/nvmem/nvmem.txt
Example:
diff --git a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
index 7bf9df0..0dcb87d 100644
--- a/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
@@ -3,7 +3,7 @@ HiSilicon Hip05 and Hip06 PCIe host bridge DT description
HiSilicon PCIe host controller is based on the Synopsys DesignWare PCI core.
It shares common functions with the PCIe DesignWare core driver and inherits
common properties defined in
-Documentation/devicetree/bindings/pci/designware-pci.txt.
+Documentation/devicetree/bindings/pci/designware-pcie.txt.
Additional properties are described here:
diff --git a/Documentation/devicetree/bindings/pci/kirin-pcie.txt b/Documentation/devicetree/bindings/pci/kirin-pcie.txt
index 6e217c6..6bbe438 100644
--- a/Documentation/devicetree/bindings/pci/kirin-pcie.txt
+++ b/Documentation/devicetree/bindings/pci/kirin-pcie.txt
@@ -3,7 +3,7 @@ HiSilicon Kirin SoCs PCIe host DT description
Kirin PCIe host controller is based on the Synopsys DesignWare PCI core.
It shares common functions with the PCIe DesignWare core driver and
inherits common properties defined in
-Documentation/devicetree/bindings/pci/designware-pci.txt.
+Documentation/devicetree/bindings/pci/designware-pcie.txt.
Additional properties are described here:
diff --git a/Documentation/devicetree/bindings/pci/pci-keystone.txt b/Documentation/devicetree/bindings/pci/pci-keystone.txt
index 7e05487..3d4a209 100644
--- a/Documentation/devicetree/bindings/pci/pci-keystone.txt
+++ b/Documentation/devicetree/bindings/pci/pci-keystone.txt
@@ -3,9 +3,9 @@ TI Keystone PCIe interface
Keystone PCI host Controller is based on the Synopsys DesignWare PCI
hardware version 3.65. It shares common functions with the PCIe DesignWare
core driver and inherits common properties defined in
-Documentation/devicetree/bindings/pci/designware-pci.txt
+Documentation/devicetree/bindings/pci/designware-pcie.txt
-Please refer to Documentation/devicetree/bindings/pci/designware-pci.txt
+Please refer to Documentation/devicetree/bindings/pci/designware-pcie.txt
for the details of DesignWare DT bindings. Additional properties are
described here as well as properties that are not applicable.
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-max77620.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-max77620.txt
index ad4fce3..511fc23 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-max77620.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-max77620.txt
@@ -11,9 +11,9 @@ Optional Pinmux properties:
--------------------------
Following properties are required if default setting of pins are required
at boot.
-- pinctrl-names: A pinctrl state named per <pinctrl-binding.txt>.
+- pinctrl-names: A pinctrl state named per <pinctrl-bindings.txt>.
- pinctrl[0...n]: Properties to contain the phandle for pinctrl states per
- <pinctrl-binding.txt>.
+ <pinctrl-bindings.txt>.
The pin configurations are defined as child of the pinctrl states node. Each
sub-node have following properties:
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
index a677145..625a22e 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
@@ -101,9 +101,9 @@ Optional Pinmux properties:
--------------------------
Following properties are required if default setting of pins are required
at boot.
-- pinctrl-names: A pinctrl state named per <pinctrl-binding.txt>.
+- pinctrl-names: A pinctrl state named per <pinctrl-bindings.txt>.
- pinctrl[0...n]: Properties to contain the phandle for pinctrl states per
- <pinctrl-binding.txt>.
+ <pinctrl-bindings.txt>.
The pin configurations are defined as child of the pinctrl states node. Each
sub-node have following properties:
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-rk805.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-rk805.txt
index eee3dc2..cbcbd31 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-rk805.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-rk805.txt
@@ -10,9 +10,9 @@ Optional Pinmux properties:
--------------------------
Following properties are required if default setting of pins are required
at boot.
-- pinctrl-names: A pinctrl state named per <pinctrl-binding.txt>.
+- pinctrl-names: A pinctrl state named per <pinctrl-bindings.txt>.
- pinctrl[0...n]: Properties to contain the phandle for pinctrl states per
- <pinctrl-binding.txt>.
+ <pinctrl-bindings.txt>.
The pin configurations are defined as child of the pinctrl states node. Each
sub-node have following properties:
diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
index b31d6bb..726ec28 100644
--- a/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
+++ b/Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
@@ -14,7 +14,7 @@ Required properties:
datasheet
- 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.
+ See Documentation/devicetree/bindings/clock/clock-bindings.txt for details.
- clock-names: Must include the following entries:
- ipg
diff --git a/Documentation/devicetree/bindings/power/pd-samsung.txt b/Documentation/devicetree/bindings/power/pd-samsung.txt
index 549f7de..92ef355 100644
--- a/Documentation/devicetree/bindings/power/pd-samsung.txt
+++ b/Documentation/devicetree/bindings/power/pd-samsung.txt
@@ -15,23 +15,13 @@ Required Properties:
Optional Properties:
- label: Human readable string with domain name. Will be visible in userspace
to let user to distinguish between multiple domains in SoC.
-- clocks: List of clock handles. The parent clocks of the input clocks to the
- devices in this power domain are set to oscclk before power gating
- and restored back after powering on a domain. This is required for
- all domains which are powered on and off and not required for unused
- domains.
-- clock-names: The following clocks can be specified:
- - oscclk: Oscillator clock.
- - clkN: Input clocks to the devices in this power domain. These clocks
- will be reparented to oscclk before switching power domain off.
- Their original parent will be brought back after turning on
- the domain. Maximum of 4 clocks (N = 0 to 3) are supported.
- - asbN: Clocks required by asynchronous bridges (ASB) present in
- the power domain. These clock should be enabled during power
- domain on/off operations.
- power-domains: phandle pointing to the parent power domain, for more details
see Documentation/devicetree/bindings/power/power_domain.txt
+Deprecated Properties:
+- clocks
+- clock-names
+
Node of a device using power domains must have a power-domains property
defined with a phandle to respective power domain.
@@ -47,8 +37,6 @@ Example:
mfc_pd: power-domain@10044060 {
compatible = "samsung,exynos4210-pd";
reg = <0x10044060 0x20>;
- clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_USER_ACLK333>;
- clock-names = "oscclk", "clk0";
#power-domain-cells = <0>;
label = "MFC";
};
diff --git a/Documentation/devicetree/bindings/power/power_domain.txt b/Documentation/devicetree/bindings/power/power_domain.txt
index 4733f76..9b387f8 100644
--- a/Documentation/devicetree/bindings/power/power_domain.txt
+++ b/Documentation/devicetree/bindings/power/power_domain.txt
@@ -111,8 +111,8 @@ Example 3:
==PM domain consumers==
Required properties:
- - power-domains : A phandle and PM domain specifier as defined by bindings of
- the power controller specified by phandle.
+ - power-domains : A list of PM domain specifiers, as defined by bindings of
+ the power controller that is the PM domain provider.
Example:
@@ -122,9 +122,18 @@ Example:
power-domains = <&power 0>;
};
-The node above defines a typical PM domain consumer device, which is located
-inside a PM domain with index 0 of a power controller represented by a node
-with the label "power".
+ leaky-device@12351000 {
+ compatible = "foo,i-leak-current";
+ reg = <0x12351000 0x1000>;
+ power-domains = <&power 0>, <&power 1> ;
+ };
+
+The first example above defines a typical PM domain consumer device, which is
+located inside a PM domain with index 0 of a power controller represented by a
+node with the label "power".
+In the second example the consumer device are partitioned across two PM domains,
+the first with index 0 and the second with index 1, of a power controller that
+is represented by a node with the label "power.
Optional properties:
- required-opps: This contains phandle to an OPP node in another device's OPP
diff --git a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
index ab399e5..180ae65 100644
--- a/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
+++ b/Documentation/devicetree/bindings/power/renesas,rcar-sysc.txt
@@ -9,6 +9,7 @@ Required properties:
- compatible: Must contain exactly one of the following:
- "renesas,r8a7743-sysc" (RZ/G1M)
- "renesas,r8a7745-sysc" (RZ/G1E)
+ - "renesas,r8a77470-sysc" (RZ/G1C)
- "renesas,r8a7779-sysc" (R-Car H1)
- "renesas,r8a7790-sysc" (R-Car H2)
- "renesas,r8a7791-sysc" (R-Car M2-W)
@@ -20,6 +21,7 @@ Required properties:
- "renesas,r8a77965-sysc" (R-Car M3-N)
- "renesas,r8a77970-sysc" (R-Car V3M)
- "renesas,r8a77980-sysc" (R-Car V3H)
+ - "renesas,r8a77990-sysc" (R-Car E3)
- "renesas,r8a77995-sysc" (R-Car D3)
- reg: Address start and address range for the device.
- #power-domain-cells: Must be 1.
diff --git a/Documentation/devicetree/bindings/power/supply/ab8500/btemp.txt b/Documentation/devicetree/bindings/power/supply/ab8500/btemp.txt
index 0ba1bcc..f181e46 100644
--- a/Documentation/devicetree/bindings/power/supply/ab8500/btemp.txt
+++ b/Documentation/devicetree/bindings/power/supply/ab8500/btemp.txt
@@ -13,4 +13,4 @@ Required Properties:
};
For information on battery specific node, Ref:
-Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
+Documentation/devicetree/bindings/power/supply/ab8500/fg.txt
diff --git a/Documentation/devicetree/bindings/power/supply/ab8500/chargalg.txt b/Documentation/devicetree/bindings/power/supply/ab8500/chargalg.txt
index ef53283..56636f9 100644
--- a/Documentation/devicetree/bindings/power/supply/ab8500/chargalg.txt
+++ b/Documentation/devicetree/bindings/power/supply/ab8500/chargalg.txt
@@ -13,4 +13,4 @@ ab8500_chargalg {
};
For information on battery specific node, Ref:
-Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
+Documentation/devicetree/bindings/power/supply/ab8500/fg.txt
diff --git a/Documentation/devicetree/bindings/power/supply/ab8500/charger.txt b/Documentation/devicetree/bindings/power/supply/ab8500/charger.txt
index 6bdbb08..24ada03e 100644
--- a/Documentation/devicetree/bindings/power/supply/ab8500/charger.txt
+++ b/Documentation/devicetree/bindings/power/supply/ab8500/charger.txt
@@ -22,4 +22,4 @@ Required Properties:
};
For information on battery specific node, Ref:
-Documentation/devicetree/bindings/power_supply/ab8500/fg.txt
+Documentation/devicetree/bindings/power/supply/ab8500/fg.txt
diff --git a/Documentation/devicetree/bindings/power/wakeup-source.txt b/Documentation/devicetree/bindings/power/wakeup-source.txt
index 5d254ab..cfd7465 100644
--- a/Documentation/devicetree/bindings/power/wakeup-source.txt
+++ b/Documentation/devicetree/bindings/power/wakeup-source.txt
@@ -22,7 +22,7 @@ List of legacy properties and respective binding document
3. "has-tpo" Documentation/devicetree/bindings/rtc/rtc-opal.txt
4. "linux,wakeup" Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt
Documentation/devicetree/bindings/mfd/tc3589x.txt
- Documentation/devicetree/bindings/input/ads7846.txt
+ Documentation/devicetree/bindings/input/touchscreen/ads7846.txt
5. "linux,keypad-wakeup" Documentation/devicetree/bindings/input/qcom,pm8xxx-keypad.txt
6. "linux,input-wakeup" Documentation/devicetree/bindings/input/samsung-keypad.txt
7. "nvidia,wakeup-source" Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt
diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
index 00d3d58..d901824 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,q6v5.txt
@@ -11,6 +11,7 @@ on the Qualcomm Hexagon core.
"qcom,msm8916-mss-pil",
"qcom,msm8974-mss-pil"
"qcom,msm8996-mss-pil"
+ "qcom,sdm845-mss-pil"
- reg:
Usage: required
diff --git a/Documentation/devicetree/bindings/reserved-memory/qcom,cmd-db.txt b/Documentation/devicetree/bindings/reserved-memory/qcom,cmd-db.txt
new file mode 100644
index 0000000..6839553
--- /dev/null
+++ b/Documentation/devicetree/bindings/reserved-memory/qcom,cmd-db.txt
@@ -0,0 +1,37 @@
+Command DB
+---------
+
+Command DB is a database that provides a mapping between resource key and the
+resource address for a system resource managed by a remote processor. The data
+is stored in a shared memory region and is loaded by the remote processor.
+
+Some of the Qualcomm Technologies Inc SoC's have hardware accelerators for
+controlling shared resources. Depending on the board configuration the shared
+resource properties may change. These properties are dynamically probed by the
+remote processor and made available in the shared memory.
+
+The bindings for Command DB is specified in the reserved-memory section in
+devicetree. The devicetree representation of the command DB driver should be:
+
+Properties:
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: Should be "qcom,cmd-db"
+
+- reg:
+ Usage: required
+ Value type: <prop encoded array>
+ Definition: The register address that points to the actual location of
+ the Command DB in memory.
+
+Example:
+
+ reserved-memory {
+ [...]
+ reserved-memory@85fe0000 {
+ reg = <0x0 0x85fe0000 0x0 0x20000>;
+ compatible = "qcom,cmd-db";
+ no-map;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/reset/renesas,rst.txt b/Documentation/devicetree/bindings/reset/renesas,rst.txt
index 294a0da..67e83b0 100644
--- a/Documentation/devicetree/bindings/reset/renesas,rst.txt
+++ b/Documentation/devicetree/bindings/reset/renesas,rst.txt
@@ -17,6 +17,7 @@ Required properties:
Examples with soctypes are:
- "renesas,r8a7743-rst" (RZ/G1M)
- "renesas,r8a7745-rst" (RZ/G1E)
+ - "renesas,r8a77470-rst" (RZ/G1C)
- "renesas,r8a7778-reset-wdt" (R-Car M1A)
- "renesas,r8a7779-reset-wdt" (R-Car H1)
- "renesas,r8a7790-rst" (R-Car H2)
@@ -29,6 +30,7 @@ Required properties:
- "renesas,r8a77965-rst" (R-Car M3-N)
- "renesas,r8a77970-rst" (R-Car V3M)
- "renesas,r8a77980-rst" (R-Car V3H)
+ - "renesas,r8a77990-rst" (R-Car E3)
- "renesas,r8a77995-rst" (R-Car D3)
- reg: Address start and address range for the device.
diff --git a/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt b/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
index 627b295..aaac797 100644
--- a/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
+++ b/Documentation/devicetree/bindings/rng/brcm,bcm2835.txt
@@ -14,11 +14,16 @@ Optional properties:
- clocks : phandle to clock-controller plus clock-specifier pair
- clock-names : "ipsec" as a clock name
+Optional properties:
+
+- interrupts: specify the interrupt for the RNG block
+
Example:
rng {
- compatible = "brcm,bcm2835-rng";
- reg = <0x7e104000 0x10>;
+ compatible = "brcm,bcm2835-rng";
+ reg = <0x7e104000 0x10>;
+ interrupts = <2 29>;
};
rng@18033000 {
diff --git a/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt b/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt
index 5cbc0b1..811124a 100644
--- a/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt
+++ b/Documentation/devicetree/bindings/rtc/nxp,rtc-2123.txt
@@ -9,7 +9,7 @@ Optional properties:
Example:
-rtc: nxp,rtc-pcf2123@3 {
+pcf2123: rtc@3 {
compatible = "nxp,rtc-pcf2123"
reg = <3>
spi-cs-high;
diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
index a66692a..c920e27 100644
--- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
+++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
@@ -1,23 +1,29 @@
STM32 Real Time Clock
Required properties:
-- compatible: can be either "st,stm32-rtc" or "st,stm32h7-rtc", depending on
- the device is compatible with stm32(f4/f7) or stm32h7.
+- compatible: can be one of the following:
+ - "st,stm32-rtc" for devices compatible with stm32(f4/f7).
+ - "st,stm32h7-rtc" for devices compatible with stm32h7.
+ - "st,stm32mp1-rtc" for devices compatible with stm32mp1.
- reg: address range of rtc register set.
- clocks: can use up to two clocks, depending on part used:
- "rtc_ck": RTC clock source.
- It is required on stm32(f4/f7) and stm32h7.
- "pclk": RTC APB interface clock.
It is not present on stm32(f4/f7).
- It is required on stm32h7.
+ It is required on stm32(h7/mp1).
- clock-names: must be "rtc_ck" and "pclk".
- It is required only on stm32h7.
+ It is required on stm32(h7/mp1).
- interrupt-parent: phandle for the interrupt controller.
-- interrupts: rtc alarm interrupt.
-- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain
- (RTC registers) write protection.
+ It is required on stm32(f4/f7/h7).
+- interrupts: rtc alarm interrupt. On stm32mp1, a second interrupt is required
+ for rtc alarm wakeup interrupt.
+- st,syscfg: phandle/offset/mask triplet. The phandle to pwrcfg used to
+ access control register at offset, and change the dbp (Disable Backup
+ Protection) bit represented by the mask, mandatory to disable/enable backup
+ domain (RTC registers) write protection.
+ It is required on stm32(f4/f7/h7).
-Optional properties (to override default rtc_ck parent clock):
+Optional properties (to override default rtc_ck parent clock on stm32(f4/f7/h7):
- assigned-clocks: reference to the rtc_ck clock entry.
- assigned-clock-parents: phandle of the new parent clock of rtc_ck.
@@ -31,7 +37,7 @@ Example:
assigned-clock-parents = <&rcc 1 CLK_LSE>;
interrupt-parent = <&exti>;
interrupts = <17 1>;
- st,syscfg = <&pwrcfg>;
+ st,syscfg = <&pwrcfg 0x00 0x100>;
};
rtc: rtc@58004000 {
@@ -44,5 +50,14 @@ Example:
interrupt-parent = <&exti>;
interrupts = <17 1>;
interrupt-names = "alarm";
- st,syscfg = <&pwrcfg>;
+ st,syscfg = <&pwrcfg 0x00 0x100>;
+ };
+
+ rtc: rtc@5c004000 {
+ compatible = "st,stm32mp1-rtc";
+ reg = <0x5c004000 0x400>;
+ clocks = <&rcc RTCAPB>, <&rcc RTC>;
+ clock-names = "pclk", "rtc_ck";
+ interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_NONE>,
+ <&exti 19 1>;
};
diff --git a/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt b/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
index 7a34345..c8dd440 100644
--- a/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
+++ b/Documentation/devicetree/bindings/serial/microchip,pic32-uart.txt
@@ -8,7 +8,7 @@ Required properties:
See: Documentation/devicetree/bindings/clock/clock-bindings.txt
- pinctrl-names: A pinctrl state names "default" must be defined.
- pinctrl-0: Phandle referencing pin configuration of the UART peripheral.
- See: Documentation/devicetree/bindings/pinctrl/pinctrl-binding.txt
+ See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
Optional properties:
- cts-gpios: CTS pin for UART
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.txt
new file mode 100644
index 0000000..d330c73
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,geni-se.txt
@@ -0,0 +1,119 @@
+Qualcomm Technologies, Inc. GENI Serial Engine QUP Wrapper Controller
+
+Generic Interface (GENI) based Qualcomm Universal Peripheral (QUP) wrapper
+is a programmable module for supporting a wide range of serial interfaces
+like UART, SPI, I2C, I3C, etc. A single QUP module can provide upto 8 Serial
+Interfaces, using its internal Serial Engines. The GENI Serial Engine QUP
+Wrapper controller is modeled as a node with zero or more child nodes each
+representing a serial engine.
+
+Required properties:
+- compatible: Must be "qcom,geni-se-qup".
+- reg: Must contain QUP register address and length.
+- clock-names: Must contain "m-ahb" and "s-ahb".
+- clocks: AHB clocks needed by the device.
+
+Required properties if child node exists:
+- #address-cells: Must be <1> for Serial Engine Address
+- #size-cells: Must be <1> for Serial Engine Address Size
+- ranges: Must be present
+
+Properties for children:
+
+A GENI based QUP wrapper controller node can contain 0 or more child nodes
+representing serial devices. These serial devices can be a QCOM UART, I2C
+controller, SPI controller, or some combination of aforementioned devices.
+Please refer below the child node definitions for the supported serial
+interface protocols.
+
+Qualcomm Technologies Inc. GENI Serial Engine based I2C Controller
+
+Required properties:
+- compatible: Must be "qcom,geni-i2c".
+- reg: Must contain QUP register address and length.
+- interrupts: Must contain I2C interrupt.
+- clock-names: Must contain "se".
+- clocks: Serial engine core clock needed by the device.
+- #address-cells: Must be <1> for I2C device address.
+- #size-cells: Must be <0> as I2C addresses have no size component.
+
+Optional property:
+- clock-frequency: Desired I2C bus clock frequency in Hz.
+ When missing default to 400000Hz.
+
+Child nodes should conform to I2C bus binding as described in i2c.txt.
+
+Qualcomm Technologies Inc. GENI Serial Engine based UART Controller
+
+Required properties:
+- compatible: Must be "qcom,geni-debug-uart".
+- reg: Must contain UART register location and length.
+- interrupts: Must contain UART core interrupts.
+- clock-names: Must contain "se".
+- clocks: Serial engine core clock needed by the device.
+
+Qualcomm Technologies Inc. GENI Serial Engine based SPI Controller
+
+Required properties:
+- compatible: Must contain "qcom,geni-spi".
+- reg: Must contain SPI register location and length.
+- interrupts: Must contain SPI controller interrupts.
+- clock-names: Must contain "se".
+- clocks: Serial engine core clock needed by the device.
+- spi-max-frequency: Specifies maximum SPI clock frequency, units - Hz.
+- #address-cells: Must be <1> to define a chip select address on
+ the SPI bus.
+- #size-cells: Must be <0>.
+
+SPI slave nodes must be children of the SPI master node and conform to SPI bus
+binding as described in Documentation/devicetree/bindings/spi/spi-bus.txt.
+
+Example:
+ geniqup@8c0000 {
+ compatible = "qcom,geni-se-qup";
+ reg = <0x8c0000 0x6000>;
+ clock-names = "m-ahb", "s-ahb";
+ clocks = <&clock_gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+ <&clock_gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ i2c0: i2c@a94000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0xa94000 0x4000>;
+ interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "se";
+ clocks = <&clock_gcc GCC_QUPV3_WRAP0_S5_CLK>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&qup_1_i2c_5_active>;
+ pinctrl-1 = <&qup_1_i2c_5_sleep>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ uart0: serial@a88000 {
+ compatible = "qcom,geni-debug-uart";
+ reg = <0xa88000 0x7000>;
+ interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "se";
+ clocks = <&clock_gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&qup_1_uart_3_active>;
+ pinctrl-1 = <&qup_1_uart_3_sleep>;
+ };
+
+ spi0: spi@a84000 {
+ compatible = "qcom,geni-spi";
+ reg = <0xa84000 0x4000>;
+ interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "se";
+ clocks = <&clock_gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&qup_1_spi_2_active>;
+ pinctrl-1 = <&qup_1_spi_2_sleep>;
+ spi-max-frequency = <19200000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ }
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt
index a48049c..89e1cb9 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt
@@ -22,6 +22,7 @@ resources.
"qcom,rpm-apq8084"
"qcom,rpm-msm8916"
"qcom,rpm-msm8974"
+ "qcom,rpm-msm8998"
- qcom,smd-channels:
Usage: required
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt
index ea1dc75..234ae22 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt
@@ -22,9 +22,15 @@ The edge is described by the following properties:
Definition: should specify the IRQ used by the remote processor to
signal this processor about communication related updates
-- qcom,ipc:
+- mboxes:
Usage: required
Value type: <prop-encoded-array>
+ Definition: reference to the associated doorbell in APCS, as described
+ in mailbox/mailbox.txt
+
+- qcom,ipc:
+ Usage: required, unless mboxes is specified
+ Value type: <prop-encoded-array>
Definition: three entries specifying the outgoing ipc bit used for
signaling the remote processor:
- phandle to a syscon node representing the apcs registers
diff --git a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
index 301d2a9..5d49d0a 100644
--- a/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
+++ b/Documentation/devicetree/bindings/soc/rockchip/power_domain.txt
@@ -5,6 +5,10 @@ powered up/down by software based on different application scenes to save power.
Required properties for power domain controller:
- compatible: Should be one of the following.
+ "rockchip,px30-power-controller" - for PX30 SoCs.
+ "rockchip,rk3036-power-controller" - for RK3036 SoCs.
+ "rockchip,rk3128-power-controller" - for RK3128 SoCs.
+ "rockchip,rk3228-power-controller" - for RK3228 SoCs.
"rockchip,rk3288-power-controller" - for RK3288 SoCs.
"rockchip,rk3328-power-controller" - for RK3328 SoCs.
"rockchip,rk3366-power-controller" - for RK3366 SoCs.
@@ -17,6 +21,10 @@ Required properties for power domain controller:
Required properties for power domain sub nodes:
- reg: index of the power domain, should use macros in:
+ "include/dt-bindings/power/px30-power.h" - for PX30 type power domain.
+ "include/dt-bindings/power/rk3036-power.h" - for RK3036 type power domain.
+ "include/dt-bindings/power/rk3128-power.h" - for RK3128 type power domain.
+ "include/dt-bindings/power/rk3228-power.h" - for RK3228 type power domain.
"include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain.
"include/dt-bindings/power/rk3328-power.h" - for RK3328 type power domain.
"include/dt-bindings/power/rk3366-power.h" - for RK3366 type power domain.
@@ -93,6 +101,10 @@ Node of a device using power domains must have a power-domains property,
containing a phandle to the power device node and an index specifying which
power domain to use.
The index should use macros in:
+ "include/dt-bindings/power/px30-power.h" - for px30 type power domain.
+ "include/dt-bindings/power/rk3036-power.h" - for rk3036 type power domain.
+ "include/dt-bindings/power/rk3128-power.h" - for rk3128 type power domain.
+ "include/dt-bindings/power/rk3128-power.h" - for rk3228 type power domain.
"include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain.
"include/dt-bindings/power/rk3328-power.h" - for rk3328 type power domain.
"include/dt-bindings/power/rk3366-power.h" - for rk3366 type power domain.
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
index 4bda520..58c3413 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
+++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.txt
@@ -18,7 +18,7 @@ Required properties:
See Documentation/devicetree/bindings/dma/stm32-dma.txt.
- dma-names: Identifier for each DMA request line. Must be "tx" and "rx".
- pinctrl-names: should contain only value "default"
- - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
+ - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
Optional properties:
- resets: Reference to a reset controller asserting the reset controller
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
index f301cdf..3a3fc50 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
+++ b/Documentation/devicetree/bindings/sound/st,stm32-sai.txt
@@ -37,7 +37,7 @@ SAI subnodes required properties:
"tx": if sai sub-block is configured as playback DAI
"rx": if sai sub-block is configured as capture DAI
- pinctrl-names: should contain only value "default"
- - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/pinctrl-stm32.txt
+ - pinctrl-0: see Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt
SAI subnodes Optional properties:
- st,sync: specify synchronization mode.
diff --git a/Documentation/devicetree/bindings/spi/spi-st-ssc.txt b/Documentation/devicetree/bindings/spi/spi-st-ssc.txt
index fe54959..1bdc470 100644
--- a/Documentation/devicetree/bindings/spi/spi-st-ssc.txt
+++ b/Documentation/devicetree/bindings/spi/spi-st-ssc.txt
@@ -9,7 +9,7 @@ Required properties:
- clocks : Must contain an entry for each name in clock-names
See ../clk/*
- pinctrl-names : Uses "default", can use "sleep" if provided
- See ../pinctrl/pinctrl-binding.txt
+ See ../pinctrl/pinctrl-bindings.txt
Optional properties:
- cs-gpios : List of GPIO chip selects
diff --git a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
index b957acf..ad648d9 100644
--- a/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/exynos-thermal.txt
@@ -12,7 +12,6 @@
"samsung,exynos5420-tmu-ext-triminfo" for TMU channels 2, 3 and 4
Exynos5420 (Must pass triminfo base and triminfo clock)
"samsung,exynos5433-tmu"
- "samsung,exynos5440-tmu"
"samsung,exynos7-tmu"
- interrupt-parent : The phandle for the interrupt controller
- reg : Address range of the thermal registers. For soc's which has multiple
@@ -68,18 +67,7 @@ Example 1):
#thermal-sensor-cells = <0>;
};
-Example 2):
-
- tmuctrl_0: tmuctrl@160118 {
- compatible = "samsung,exynos5440-tmu";
- reg = <0x160118 0x230>, <0x160368 0x10>;
- interrupts = <0 58 0>;
- clocks = <&clock 21>;
- clock-names = "tmu_apbif";
- #thermal-sensor-cells = <0>;
- };
-
-Example 3): (In case of Exynos5420 "with misplaced TRIMINFO register")
+Example 2): (In case of Exynos5420 "with misplaced TRIMINFO register")
tmu_cpu2: tmu@10068000 {
compatible = "samsung,exynos5420-tmu-ext-triminfo";
reg = <0x10068000 0x100>, <0x1006c000 0x4>;
diff --git a/Documentation/devicetree/bindings/thermal/imx-thermal.txt b/Documentation/devicetree/bindings/thermal/imx-thermal.txt
index 379eb76..823e417 100644
--- a/Documentation/devicetree/bindings/thermal/imx-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/imx-thermal.txt
@@ -1,8 +1,13 @@
* Temperature Monitor (TEMPMON) on Freescale i.MX SoCs
Required properties:
-- compatible : "fsl,imx6q-tempmon" for i.MX6Q, "fsl,imx6sx-tempmon" for i.MX6SX.
- i.MX6SX has two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC,
+- compatible : must be one of following:
+ - "fsl,imx6q-tempmon" for i.MX6Q,
+ - "fsl,imx6sx-tempmon" for i.MX6SX,
+ - "fsl,imx7d-tempmon" for i.MX7S/D.
+- interrupts : the interrupt output of the controller:
+ i.MX6Q has one IRQ which will be triggered when temperature is higher than high threshold,
+ i.MX6SX and i.MX7S/D have two more IRQs than i.MX6Q, one is IRQ_LOW and the other is IRQ_PANIC,
when temperature is below than low threshold, IRQ_LOW will be triggered, when temperature
is higher than panic threshold, system will auto reboot by SRC module.
- fsl,tempmon : phandle pointer to system controller that contains TEMPMON
diff --git a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
index 0d73ea5..41d6a44 100644
--- a/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/mediatek-thermal.txt
@@ -12,6 +12,7 @@ Required properties:
- "mediatek,mt8173-thermal" : For MT8173 family of SoCs
- "mediatek,mt2701-thermal" : For MT2701 family of SoCs
- "mediatek,mt2712-thermal" : For MT2712 family of SoCs
+ - "mediatek,mt7622-thermal" : For MT7622 SoC
- reg: Address range of the thermal controller
- interrupts: IRQ for the thermal controller
- clocks, clock-names: Clocks needed for the thermal controller. required
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
index 292ed89..06195e8 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.txt
@@ -8,6 +8,7 @@ Required properties:
- reg: Address range of the thermal registers
- #thermal-sensor-cells : Should be 1. See ./thermal.txt for a description.
+- #qcom,sensors: Number of sensors in tsens block
- Refer to Documentation/devicetree/bindings/nvmem/nvmem.txt to know how to specify
nvmem cells
diff --git a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt
index 39e7d4e..cfa154b 100644
--- a/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/rcar-gen3-thermal.txt
@@ -9,6 +9,7 @@ Required properties:
Examples with soctypes are:
- "renesas,r8a7795-thermal" (R-Car H3)
- "renesas,r8a7796-thermal" (R-Car M3-W)
+ - "renesas,r8a77965-thermal" (R-Car M3-N)
- reg : Address ranges of the thermal registers. Each sensor
needs one address range. Sorting must be done in
increasing order according to datasheet, i.e.
@@ -18,7 +19,7 @@ Required properties:
Optional properties:
-- interrupts : interrupts routed to the TSC (3 for H3 and M3-W)
+- interrupts : interrupts routed to the TSC (3 for H3, M3-W and M3-N)
- power-domain : Must contain a reference to the power domain. This
property is mandatory if the thermal sensor instance
is part of a controllable power domain.
diff --git a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt
index 349e635..67c563f 100644
--- a/Documentation/devicetree/bindings/thermal/rcar-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/rcar-thermal.txt
@@ -3,7 +3,8 @@
Required properties:
- compatible : "renesas,thermal-<soctype>",
"renesas,rcar-gen2-thermal" (with thermal-zone) or
- "renesas,rcar-thermal" (without thermal-zone) as fallback.
+ "renesas,rcar-thermal" (without thermal-zone) as
+ fallback except R-Car D3.
Examples with soctypes are:
- "renesas,thermal-r8a73a4" (R-Mobile APE6)
- "renesas,thermal-r8a7743" (RZ/G1M)
@@ -12,13 +13,15 @@ Required properties:
- "renesas,thermal-r8a7791" (R-Car M2-W)
- "renesas,thermal-r8a7792" (R-Car V2H)
- "renesas,thermal-r8a7793" (R-Car M2-N)
+ - "renesas,thermal-r8a77995" (R-Car D3)
- reg : Address range of the thermal registers.
The 1st reg will be recognized as common register
if it has "interrupts".
Option properties:
-- interrupts : use interrupt
+- interrupts : If present should contain 3 interrupts for
+ R-Car D3 or 1 interrupt otherwise.
Example (non interrupt support):
diff --git a/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt b/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt
index 686c0b4..ceb92a9 100644
--- a/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt
+++ b/Documentation/devicetree/bindings/thermal/uniphier-thermal.txt
@@ -8,6 +8,7 @@ Required properties:
- compatible :
- "socionext,uniphier-pxs2-thermal" : For UniPhier PXs2 SoC
- "socionext,uniphier-ld20-thermal" : For UniPhier LD20 SoC
+ - "socionext,uniphier-pxs3-thermal" : For UniPhier PXs3 SoC
- interrupts : IRQ for the temperature alarm
- #thermal-sensor-cells : Should be 0. See ./thermal.txt for details.
diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.txt b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
index d740989..b40add2 100644
--- a/Documentation/devicetree/bindings/timer/renesas,cmt.txt
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.txt
@@ -22,6 +22,10 @@ Required Properties:
- "renesas,r8a73a4-cmt0" for the 32-bit CMT0 device included in r8a73a4.
- "renesas,r8a73a4-cmt1" for the 48-bit CMT1 device included in r8a73a4.
+ - "renesas,r8a7743-cmt0" for the 32-bit CMT0 device included in r8a7743.
+ - "renesas,r8a7743-cmt1" for the 48-bit CMT1 device included in r8a7743.
+ - "renesas,r8a7745-cmt0" for the 32-bit CMT0 device included in r8a7745.
+ - "renesas,r8a7745-cmt1" for the 48-bit CMT1 device included in r8a7745.
- "renesas,r8a7790-cmt0" for the 32-bit CMT0 device included in r8a7790.
- "renesas,r8a7790-cmt1" for the 48-bit CMT1 device included in r8a7790.
- "renesas,r8a7791-cmt0" for the 32-bit CMT0 device included in r8a7791.
@@ -31,10 +35,12 @@ Required Properties:
- "renesas,r8a7794-cmt0" for the 32-bit CMT0 device included in r8a7794.
- "renesas,r8a7794-cmt1" for the 48-bit CMT1 device included in r8a7794.
- - "renesas,rcar-gen2-cmt0" for 32-bit CMT0 devices included in R-Car Gen2.
- - "renesas,rcar-gen2-cmt1" for 48-bit CMT1 devices included in R-Car Gen2.
- These are fallbacks for r8a73a4 and all the R-Car Gen2
- entries listed above.
+ - "renesas,rcar-gen2-cmt0" for 32-bit CMT0 devices included in R-Car Gen2
+ and RZ/G1.
+ - "renesas,rcar-gen2-cmt1" for 48-bit CMT1 devices included in R-Car Gen2
+ and RZ/G1.
+ These are fallbacks for r8a73a4, R-Car Gen2 and RZ/G1 entries
+ listed above.
- reg: base address and length of the registers block for the timer module.
- interrupts: interrupt-specifier for the timer, one per channel.
diff --git a/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt b/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt
index 50a3153..252a05c 100644
--- a/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/rockchip,dwc3.txt
@@ -16,7 +16,7 @@ A child node must exist to represent the core DWC3 IP block. The name of
the node is not important. The content of the node is defined in dwc3.txt.
Phy documentation is provided in the following places:
-Documentation/devicetree/bindings/phy/rockchip,dwc3-usb-phy.txt
+Documentation/devicetree/bindings/phy/qcom-dwc3-usb-phy.txt
Example device nodes:
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 4b38f33..7cad066 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -58,6 +58,7 @@ bosch Bosch Sensortec GmbH
boundary Boundary Devices Inc.
brcm Broadcom Corporation
buffalo Buffalo, Inc.
+bticino Bticino International
calxeda Calxeda
capella Capella Microsystems, Inc
cascoda Cascoda, Ltd.
@@ -285,6 +286,7 @@ pine64 Pine64
pixcir PIXCIR MICROELECTRONICS Co., Ltd
plathome Plat'Home Co., Ltd.
plda PLDA
+portwell Portwell Inc.
poslab Poslab Technology Co., Ltd.
powervr PowerVR (deprecated, use img)
probox2 PROBOX2 (by W2COMP Co., Ltd.)
diff --git a/Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt b/Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt
index cb44918..ce1cb72 100644
--- a/Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/ingenic,jz4740-wdt.txt
@@ -3,10 +3,15 @@ Ingenic Watchdog Timer (WDT) Controller for JZ4740 & JZ4780
Required properties:
compatible: "ingenic,jz4740-watchdog" or "ingenic,jz4780-watchdog"
reg: Register address and length for watchdog registers
+clocks: phandle to the RTC clock
+clock-names: should be "rtc"
Example:
watchdog: jz4740-watchdog@10002000 {
compatible = "ingenic,jz4740-watchdog";
- reg = <0x10002000 0x100>;
+ reg = <0x10002000 0x10>;
+
+ clocks = <&cgu JZ4740_CLK_RTC>;
+ clock-names = "rtc";
};
diff --git a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt
index 74b2f03..f24d802 100644
--- a/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt
+++ b/Documentation/devicetree/bindings/watchdog/renesas-wdt.txt
@@ -1,18 +1,27 @@
Renesas Watchdog Timer (WDT) Controller
Required properties:
-- compatible : Should be "renesas,<soctype>-wdt", and
- "renesas,rcar-gen3-wdt" or "renesas,rza-wdt" as fallback.
+ - compatible : Must be "renesas,<soctype>-wdt", followed by a generic
+ fallback compatible string when compatible with the generic
+ version.
Examples with soctypes are:
- - "renesas,r7s72100-wdt" (RZ/A1)
+ - "renesas,r8a7743-wdt" (RZ/G1M)
+ - "renesas,r8a7745-wdt" (RZ/G1E)
+ - "renesas,r8a7790-wdt" (R-Car H2)
+ - "renesas,r8a7791-wdt" (R-Car M2-W)
+ - "renesas,r8a7792-wdt" (R-Car V2H)
+ - "renesas,r8a7793-wdt" (R-Car M2-N)
+ - "renesas,r8a7794-wdt" (R-Car E2)
- "renesas,r8a7795-wdt" (R-Car H3)
- "renesas,r8a7796-wdt" (R-Car M3-W)
+ - "renesas,r8a77965-wdt" (R-Car M3-N)
- "renesas,r8a77970-wdt" (R-Car V3M)
- "renesas,r8a77995-wdt" (R-Car D3)
-
- When compatible with the generic version, nodes must list the SoC-specific
- version corresponding to the platform first, followed by the generic
- version.
+ - "renesas,r7s72100-wdt" (RZ/A1)
+ The generic compatible string must be:
+ - "renesas,rza-wdt" for RZ/A
+ - "renesas,rcar-gen2-wdt" for R-Car Gen2 and RZ/G
+ - "renesas,rcar-gen3-wdt" for R-Car Gen3
- reg : Should contain WDT registers location and length
- clocks : the clock feeding the watchdog timer.
diff --git a/Documentation/driver-api/gpio/consumer.rst b/Documentation/driver-api/gpio/consumer.rst
index c71a50d..aa03f38 100644
--- a/Documentation/driver-api/gpio/consumer.rst
+++ b/Documentation/driver-api/gpio/consumer.rst
@@ -57,7 +57,7 @@ device that displays digits), an additional index argument can be specified::
enum gpiod_flags flags)
For a more detailed description of the con_id parameter in the DeviceTree case
-see Documentation/gpio/board.txt
+see Documentation/driver-api/gpio/board.rst
The flags parameter is used to optionally specify a direction and initial value
for the GPIO. Values can be:
diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst
index f4180e7..6d9f2f9 100644
--- a/Documentation/driver-api/index.rst
+++ b/Documentation/driver-api/index.rst
@@ -36,6 +36,7 @@ available subsections can be seen below.
edac
scsi
libata
+ target
mtdnand
miscellaneous
w1
diff --git a/Documentation/driver-api/infrastructure.rst b/Documentation/driver-api/infrastructure.rst
index bee1b9a..6172f3c 100644
--- a/Documentation/driver-api/infrastructure.rst
+++ b/Documentation/driver-api/infrastructure.rst
@@ -49,10 +49,10 @@ Device Drivers Base
Device Drivers DMA Management
-----------------------------
-.. kernel-doc:: drivers/base/dma-coherent.c
+.. kernel-doc:: kernel/dma/coherent.c
:export:
-.. kernel-doc:: drivers/base/dma-mapping.c
+.. kernel-doc:: kernel/dma/mapping.c
:export:
Device drivers PnP support
diff --git a/Documentation/driver-api/scsi.rst b/Documentation/driver-api/scsi.rst
index 31ad0fe..64b231d 100644
--- a/Documentation/driver-api/scsi.rst
+++ b/Documentation/driver-api/scsi.rst
@@ -334,5 +334,5 @@ todo
~~~~
Parallel (fast/wide/ultra) SCSI, USB, SATA, SAS, Fibre Channel,
-FireWire, ATAPI devices, Infiniband, I2O, iSCSI, Parallel ports,
+FireWire, ATAPI devices, Infiniband, I2O, Parallel ports,
netlink...
diff --git a/Documentation/driver-api/target.rst b/Documentation/driver-api/target.rst
new file mode 100644
index 0000000..4363611
--- /dev/null
+++ b/Documentation/driver-api/target.rst
@@ -0,0 +1,64 @@
+=================================
+target and iSCSI Interfaces Guide
+=================================
+
+Introduction and Overview
+=========================
+
+TBD
+
+Target core device interfaces
+=============================
+
+.. kernel-doc:: drivers/target/target_core_device.c
+ :export:
+
+Target core transport interfaces
+================================
+
+.. kernel-doc:: drivers/target/target_core_transport.c
+ :export:
+
+Target-supported userspace I/O
+==============================
+
+.. kernel-doc:: drivers/target/target_core_user.c
+ :doc: Userspace I/O
+
+.. kernel-doc:: include/uapi/linux/target_core_user.h
+ :doc: Ring Design
+
+iSCSI helper functions
+======================
+
+.. kernel-doc:: drivers/scsi/libiscsi.c
+ :export:
+
+
+iSCSI boot information
+======================
+
+.. kernel-doc:: drivers/scsi/iscsi_boot_sysfs.c
+ :export:
+
+
+iSCSI transport class
+=====================
+
+The file drivers/scsi/scsi_transport_iscsi.c defines transport
+attributes for the iSCSI class, which sends SCSI packets over TCP/IP
+connections.
+
+.. kernel-doc:: drivers/scsi/scsi_transport_iscsi.c
+ :export:
+
+
+iSCSI TCP interfaces
+====================
+
+.. kernel-doc:: drivers/scsi/iscsi_tcp.c
+ :internal:
+
+.. kernel-doc:: drivers/scsi/libiscsi_tcp.c
+ :export:
+
diff --git a/Documentation/features/debug/stackprotector/arch-support.txt b/Documentation/features/debug/stackprotector/arch-support.txt
index 74b89a9..954ac1c 100644
--- a/Documentation/features/debug/stackprotector/arch-support.txt
+++ b/Documentation/features/debug/stackprotector/arch-support.txt
@@ -1,6 +1,6 @@
#
# Feature name: stackprotector
-# Kconfig: HAVE_CC_STACKPROTECTOR
+# Kconfig: HAVE_STACKPROTECTOR
# description: arch supports compiler driven stack overflow protection
#
-----------------------
diff --git a/Documentation/filesystems/ceph.txt b/Documentation/filesystems/ceph.txt
index d7f011d..8bf6224 100644
--- a/Documentation/filesystems/ceph.txt
+++ b/Documentation/filesystems/ceph.txt
@@ -105,15 +105,13 @@ Mount Options
address its connection to the monitor originates from.
wsize=X
- Specify the maximum write size in bytes. By default there is no
- maximum. Ceph will normally size writes based on the file stripe
- size.
+ Specify the maximum write size in bytes. Default: 16 MB.
rsize=X
- Specify the maximum read size in bytes. Default: 64 MB.
+ Specify the maximum read size in bytes. Default: 16 MB.
rasize=X
- Specify the maximum readahead. Default: 8 MB.
+ Specify the maximum readahead size in bytes. Default: 8 MB.
mount_timeout=X
Specify the timeout value for mount (in seconds), in the case
diff --git a/Documentation/filesystems/cifs/AUTHORS b/Documentation/filesystems/cifs/AUTHORS
index 9f4f87e..75865da 100644
--- a/Documentation/filesystems/cifs/AUTHORS
+++ b/Documentation/filesystems/cifs/AUTHORS
@@ -42,9 +42,11 @@ Jeff Layton (many, many fixes, as well as great work on the cifs Kerberos code)
Scott Lovenberg
Pavel Shilovsky (for great work adding SMB2 support, and various SMB3 features)
Aurelien Aptel (for DFS SMB3 work and some key bug fixes)
-Ronnie Sahlberg (for SMB3 xattr work and bug fixes)
+Ronnie Sahlberg (for SMB3 xattr work, bug fixes, and lots of great work on compounding)
Shirish Pargaonkar (for many ACL patches over the years)
Sachin Prabhu (many bug fixes, including for reconnect, copy offload and security)
+Paulo Alcantara
+Long Li (some great work on RDMA, SMB Direct)
Test case and Bug Report contributors
@@ -58,5 +60,4 @@ mention to the Stanford Checker (SWAT) which pointed out many minor
bugs in error paths. Valuable suggestions also have come from Al Viro
and Dave Miller.
-And thanks to the IBM LTC and Power test teams and SuSE testers for
-finding multiple bugs during excellent stress test runs.
+And thanks to the IBM LTC and Power test teams and SuSE and Citrix and RedHat testers for finding multiple bugs during excellent stress test runs.
diff --git a/Documentation/filesystems/cifs/CHANGES b/Documentation/filesystems/cifs/CHANGES
index bc0025c..455e1cc 100644
--- a/Documentation/filesystems/cifs/CHANGES
+++ b/Documentation/filesystems/cifs/CHANGES
@@ -1,3 +1,6 @@
+See https://wiki.samba.org/index.php/LinuxCIFSKernel for
+more current information.
+
Version 1.62
------------
Add sockopt=TCP_NODELAY mount option. EA (xattr) routines hardened
diff --git a/Documentation/filesystems/cifs/TODO b/Documentation/filesystems/cifs/TODO
index c5adf14..852499a 100644
--- a/Documentation/filesystems/cifs/TODO
+++ b/Documentation/filesystems/cifs/TODO
@@ -9,14 +9,14 @@ is a partial list of the known problems and missing features:
a) SMB3 (and SMB3.02) missing optional features:
- multichannel (started), integration with RDMA
- - directory leases (improved metadata caching)
- - T10 copy offload (copy chunk, and "Duplicate Extents" ioctl
+ - directory leases (improved metadata caching), started (root dir only)
+ - T10 copy offload ie "ODX" (copy chunk, and "Duplicate Extents" ioctl
currently the only two server side copy mechanisms supported)
b) improved sparse file support
c) Directory entry caching relies on a 1 second timer, rather than
-using Directory Leases
+using Directory Leases, currently only the root file handle is cached longer
d) quota support (needs minor kernel change since quota calls
to make it to network filesystems or deviceless filesystems)
@@ -42,6 +42,8 @@ mount or a per server basis to client UIDs or nobody if no mapping
exists. Also better integration with winbind for resolving SID owners
k) Add tools to take advantage of more smb3 specific ioctls and features
+(passthrough ioctl/fsctl for sending various SMB3 fsctls to the server
+is in progress)
l) encrypted file support
@@ -71,9 +73,8 @@ t) split cifs and smb3 support into separate modules so legacy (and less
secure) CIFS dialect can be disabled in environments that don't need it
and simplify the code.
-u) Finish up SMB3.1.1 dialect support
-
-v) POSIX Extensions for SMB3.1.1
+v) POSIX Extensions for SMB3.1.1 (started, create and mkdir support added
+so far).
KNOWN BUGS
====================================
@@ -92,8 +93,8 @@ Misc testing to do
1) check out max path names and max path name components against various server
types. Try nested symlinks (8 deep). Return max path name in stat -f information
-2) Improve xfstest's cifs enablement and adapt xfstests where needed to test
-cifs better
+2) Improve xfstest's cifs/smb3 enablement and adapt xfstests where needed to test
+cifs/smb3 better
3) Additional performance testing and optimization using iozone and similar -
there are some easy changes that can be done to parallelize sequential writes,
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
index 12a147c..69f8de9 100644
--- a/Documentation/filesystems/f2fs.txt
+++ b/Documentation/filesystems/f2fs.txt
@@ -182,13 +182,15 @@ whint_mode=%s Control which write hints are passed down to block
passes down hints with its policy.
alloc_mode=%s Adjust block allocation policy, which supports "reuse"
and "default".
-fsync_mode=%s Control the policy of fsync. Currently supports "posix"
- and "strict". In "posix" mode, which is default, fsync
- will follow POSIX semantics and does a light operation
- to improve the filesystem performance. In "strict" mode,
- fsync will be heavy and behaves in line with xfs, ext4
- and btrfs, where xfstest generic/342 will pass, but the
- performance will regress.
+fsync_mode=%s Control the policy of fsync. Currently supports "posix",
+ "strict", and "nobarrier". In "posix" mode, which is
+ default, fsync will follow POSIX semantics and does a
+ light operation to improve the filesystem performance.
+ In "strict" mode, fsync will be heavy and behaves in line
+ with xfs, ext4 and btrfs, where xfstest generic/342 will
+ pass, but the performance will regress. "nobarrier" is
+ based on "posix", but doesn't issue flush command for
+ non-atomic files likewise "nobarrier" mount option.
test_dummy_encryption Enable dummy encryption, which provides a fake fscrypt
context. The fake fscrypt context is used by xfstests.
diff --git a/Documentation/hwmon/ina2xx b/Documentation/hwmon/ina2xx
index cfd31d9..72d16f0 100644
--- a/Documentation/hwmon/ina2xx
+++ b/Documentation/hwmon/ina2xx
@@ -53,7 +53,7 @@ bus supply voltage.
The shunt value in micro-ohms can be set via platform data or device tree at
compile-time or via the shunt_resistor attribute in sysfs at run-time. Please
-refer to the Documentation/devicetree/bindings/i2c/ina2xx.txt for bindings
+refer to the Documentation/devicetree/bindings/hwmon/ina2xx.txt for bindings
if the device tree is used.
Additionally ina226 supports update_interval attribute as described in
diff --git a/Documentation/i2c/busses/i2c-mlxcpld b/Documentation/i2c/busses/i2c-mlxcpld
index 4e46c44..925904a 100644
--- a/Documentation/i2c/busses/i2c-mlxcpld
+++ b/Documentation/i2c/busses/i2c-mlxcpld
@@ -20,6 +20,10 @@ The next transaction types are supported:
- Write Byte/Block.
Registers:
+CPBLTY 0x0 - capability reg.
+ Bits [6:5] - transaction length. b01 - 72B is supported,
+ 36B in other case.
+ Bit 7 - SMBus block read support.
CTRL 0x1 - control reg.
Resets all the registers.
HALF_CYC 0x4 - cycle reg.
diff --git a/Documentation/i2c/busses/i2c-ocores b/Documentation/i2c/busses/i2c-ocores
index 9e1dfe7..4e713f4 100644
--- a/Documentation/i2c/busses/i2c-ocores
+++ b/Documentation/i2c/busses/i2c-ocores
@@ -18,7 +18,7 @@ Usage
i2c-ocores uses the platform bus, so you need to provide a struct
platform_device with the base address and interrupt number. The
dev.platform_data of the device should also point to a struct
-ocores_i2c_platform_data (see linux/i2c-ocores.h) describing the
+ocores_i2c_platform_data (see linux/platform_data/i2c-ocores.h) describing the
distance between registers and the input clock speed.
There is also a possibility to attach a list of i2c_board_info which
the i2c-ocores driver will add to the bus upon creation.
diff --git a/Documentation/i2c/muxes/i2c-mux-gpio b/Documentation/i2c/muxes/i2c-mux-gpio
index 7a8d7d2..893ecdf 100644
--- a/Documentation/i2c/muxes/i2c-mux-gpio
+++ b/Documentation/i2c/muxes/i2c-mux-gpio
@@ -30,12 +30,12 @@ i2c-mux-gpio uses the platform bus, so you need to provide a struct
platform_device with the platform_data pointing to a struct
i2c_mux_gpio_platform_data with the I2C adapter number of the master
bus, the number of bus segments to create and the GPIO pins used
-to control it. See include/linux/i2c-mux-gpio.h for details.
+to control it. See include/linux/platform_data/i2c-mux-gpio.h for details.
E.G. something like this for a MUX providing 4 bus segments
controlled through 3 GPIO pins:
-#include <linux/i2c-mux-gpio.h>
+#include <linux/platform_data/i2c-mux-gpio.h>
#include <linux/platform_device.h>
static const unsigned myboard_gpiomux_gpios[] = {
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index a12488d..480c860 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -151,7 +151,7 @@ Code Seq#(hex) Include File Comments
'J' 00-1F drivers/scsi/gdth_ioctl.h
'K' all linux/kd.h
'L' 00-1F linux/loop.h conflict!
-'L' 10-1F drivers/scsi/mpt2sas/mpt2sas_ctl.h conflict!
+'L' 10-1F drivers/scsi/mpt3sas/mpt3sas_ctl.h conflict!
'L' 20-2F linux/lightnvm.h
'L' E0-FF linux/ppdd.h encrypted disk device driver
<http://linux01.gwdg.de/~alatham/ppdd.html>
diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
index 0e966e8..3534a84 100644
--- a/Documentation/kbuild/kconfig-language.txt
+++ b/Documentation/kbuild/kconfig-language.txt
@@ -473,6 +473,24 @@ config option to 'y' no matter the dependencies.
The dependencies are moved to the symbol GENERIC_IOMAP and we avoid the
situation where select forces a symbol equals to 'y'.
+Adding features that need compiler support
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are several features that need compiler support. The recommended way
+to describe the dependency on the compiler feature is to use "depends on"
+followed by a test macro.
+
+config STACKPROTECTOR
+ bool "Stack Protector buffer overflow detection"
+ depends on $(cc-option,-fstack-protector)
+ ...
+
+If you need to expose a compiler capability to makefiles and/or C source files,
+CC_HAS_ is the recommended prefix for the config option.
+
+config CC_HAS_STACKPROTECTOR_NONE
+ def_bool $(cc-option,-fno-stack-protector)
+
Build as module only
~~~~~~~~~~~~~~~~~~~~
To restrict a component build to module-only, qualify its config symbol
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt
index 22208bf..cb3b0de 100644
--- a/Documentation/kprobes.txt
+++ b/Documentation/kprobes.txt
@@ -724,8 +724,8 @@ migrate your tool to one of the following options:
See following documents:
- - Documentation/trace/kprobetrace.txt
- - Documentation/trace/events.txt
+ - Documentation/trace/kprobetrace.rst
+ - Documentation/trace/events.rst
- tools/perf/Documentation/perf-probe.txt
diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt
index 00b6dfe..6cced88 100644
--- a/Documentation/laptops/thinkpad-acpi.txt
+++ b/Documentation/laptops/thinkpad-acpi.txt
@@ -540,8 +540,10 @@ Events that are propagated by the driver to userspace:
0x6021 ALARM: a sensor is too hot
0x6022 ALARM: a sensor is extremely hot
0x6030 System thermal table changed
+0x6032 Thermal Control command set completion (DYTC, Windows)
0x6040 Nvidia Optimus/AC adapter related (TO BE VERIFIED)
0x60C0 X1 Yoga 2016, Tablet mode status changed
+0x60F0 Thermal Transformation changed (GMTS, Windows)
Battery nearly empty alarms are a last resort attempt to get the
operating system to hibernate or shutdown cleanly (0x2313), or shutdown
diff --git a/Documentation/maintainer/pull-requests.rst b/Documentation/maintainer/pull-requests.rst
index a19db34..22b271d 100644
--- a/Documentation/maintainer/pull-requests.rst
+++ b/Documentation/maintainer/pull-requests.rst
@@ -41,7 +41,7 @@ named ``char-misc-next``, you would be using the following command::
that will create a signed tag called ``char-misc-4.15-rc1`` based on the
last commit in the ``char-misc-next`` branch, and sign it with your gpg key
-(see :ref:`Documentation/maintainer/configure_git.rst <configuregit>`).
+(see :ref:`Documentation/maintainer/configure-git.rst <configuregit>`).
Linus will only accept pull requests based on a signed tag. Other
maintainers may differ.
diff --git a/Documentation/networking/can.rst b/Documentation/networking/can.rst
index d23c51a..2fd0b51 100644
--- a/Documentation/networking/can.rst
+++ b/Documentation/networking/can.rst
@@ -164,7 +164,7 @@ The Linux network devices (by default) just can handle the
transmission and reception of media dependent frames. Due to the
arbitration on the CAN bus the transmission of a low prio CAN-ID
may be delayed by the reception of a high prio CAN frame. To
-reflect the correct [*]_ traffic on the node the loopback of the sent
+reflect the correct [#f1]_ traffic on the node the loopback of the sent
data has to be performed right after a successful transmission. If
the CAN network interface is not capable of performing the loopback for
some reason the SocketCAN core can do this task as a fallback solution.
@@ -175,7 +175,7 @@ networking behaviour for CAN applications. Due to some requests from
the RT-SocketCAN group the loopback optionally may be disabled for each
separate socket. See sockopts from the CAN RAW sockets in :ref:`socketcan-raw-sockets`.
-.. [*] you really like to have this when you're running analyser
+.. [#f1] you really like to have this when you're running analyser
tools like 'candump' or 'cansniffer' on the (same) node.
diff --git a/Documentation/riscv/pmu.txt b/Documentation/riscv/pmu.txt
new file mode 100644
index 0000000..b29f03a
--- /dev/null
+++ b/Documentation/riscv/pmu.txt
@@ -0,0 +1,249 @@
+Supporting PMUs on RISC-V platforms
+==========================================
+Alan Kao <alankao@andestech.com>, Mar 2018
+
+Introduction
+------------
+
+As of this writing, perf_event-related features mentioned in The RISC-V ISA
+Privileged Version 1.10 are as follows:
+(please check the manual for more details)
+
+* [m|s]counteren
+* mcycle[h], cycle[h]
+* minstret[h], instret[h]
+* mhpeventx, mhpcounterx[h]
+
+With such function set only, porting perf would require a lot of work, due to
+the lack of the following general architectural performance monitoring features:
+
+* Enabling/Disabling counters
+ Counters are just free-running all the time in our case.
+* Interrupt caused by counter overflow
+ No such feature in the spec.
+* Interrupt indicator
+ It is not possible to have many interrupt ports for all counters, so an
+ interrupt indicator is required for software to tell which counter has
+ just overflowed.
+* Writing to counters
+ There will be an SBI to support this since the kernel cannot modify the
+ counters [1]. Alternatively, some vendor considers to implement
+ hardware-extension for M-S-U model machines to write counters directly.
+
+This document aims to provide developers a quick guide on supporting their
+PMUs in the kernel. The following sections briefly explain perf' mechanism
+and todos.
+
+You may check previous discussions here [1][2]. Also, it might be helpful
+to check the appendix for related kernel structures.
+
+
+1. Initialization
+-----------------
+
+*riscv_pmu* is a global pointer of type *struct riscv_pmu*, which contains
+various methods according to perf's internal convention and PMU-specific
+parameters. One should declare such instance to represent the PMU. By default,
+*riscv_pmu* points to a constant structure *riscv_base_pmu*, which has very
+basic support to a baseline QEMU model.
+
+Then he/she can either assign the instance's pointer to *riscv_pmu* so that
+the minimal and already-implemented logic can be leveraged, or invent his/her
+own *riscv_init_platform_pmu* implementation.
+
+In other words, existing sources of *riscv_base_pmu* merely provide a
+reference implementation. Developers can flexibly decide how many parts they
+can leverage, and in the most extreme case, they can customize every function
+according to their needs.
+
+
+2. Event Initialization
+-----------------------
+
+When a user launches a perf command to monitor some events, it is first
+interpreted by the userspace perf tool into multiple *perf_event_open*
+system calls, and then each of them calls to the body of *event_init*
+member function that was assigned in the previous step. In *riscv_base_pmu*'s
+case, it is *riscv_event_init*.
+
+The main purpose of this function is to translate the event provided by user
+into bitmap, so that HW-related control registers or counters can directly be
+manipulated. The translation is based on the mappings and methods provided in
+*riscv_pmu*.
+
+Note that some features can be done in this stage as well:
+
+(1) interrupt setting, which is stated in the next section;
+(2) privilege level setting (user space only, kernel space only, both);
+(3) destructor setting. Normally it is sufficient to apply *riscv_destroy_event*;
+(4) tweaks for non-sampling events, which will be utilized by functions such as
+*perf_adjust_period*, usually something like the follows:
+
+if (!is_sampling_event(event)) {
+ hwc->sample_period = x86_pmu.max_period;
+ hwc->last_period = hwc->sample_period;
+ local64_set(&hwc->period_left, hwc->sample_period);
+}
+
+In the case of *riscv_base_pmu*, only (3) is provided for now.
+
+
+3. Interrupt
+------------
+
+3.1. Interrupt Initialization
+
+This often occurs at the beginning of the *event_init* method. In common
+practice, this should be a code segment like
+
+int x86_reserve_hardware(void)
+{
+ int err = 0;
+
+ if (!atomic_inc_not_zero(&pmc_refcount)) {
+ mutex_lock(&pmc_reserve_mutex);
+ if (atomic_read(&pmc_refcount) == 0) {
+ if (!reserve_pmc_hardware())
+ err = -EBUSY;
+ else
+ reserve_ds_buffers();
+ }
+ if (!err)
+ atomic_inc(&pmc_refcount);
+ mutex_unlock(&pmc_reserve_mutex);
+ }
+
+ return err;
+}
+
+And the magic is in *reserve_pmc_hardware*, which usually does atomic
+operations to make implemented IRQ accessible from some global function pointer.
+*release_pmc_hardware* serves the opposite purpose, and it is used in event
+destructors mentioned in previous section.
+
+(Note: From the implementations in all the architectures, the *reserve/release*
+pair are always IRQ settings, so the *pmc_hardware* seems somehow misleading.
+It does NOT deal with the binding between an event and a physical counter,
+which will be introduced in the next section.)
+
+3.2. IRQ Structure
+
+Basically, a IRQ runs the following pseudo code:
+
+for each hardware counter that triggered this overflow
+
+ get the event of this counter
+
+ // following two steps are defined as *read()*,
+ // check the section Reading/Writing Counters for details.
+ count the delta value since previous interrupt
+ update the event->count (# event occurs) by adding delta, and
+ event->hw.period_left by subtracting delta
+
+ if the event overflows
+ sample data
+ set the counter appropriately for the next overflow
+
+ if the event overflows again
+ too frequently, throttle this event
+ fi
+ fi
+
+end for
+
+However as of this writing, none of the RISC-V implementations have designed an
+interrupt for perf, so the details are to be completed in the future.
+
+4. Reading/Writing Counters
+---------------------------
+
+They seem symmetric but perf treats them quite differently. For reading, there
+is a *read* interface in *struct pmu*, but it serves more than just reading.
+According to the context, the *read* function not only reads the content of the
+counter (event->count), but also updates the left period to the next interrupt
+(event->hw.period_left).
+
+But the core of perf does not need direct write to counters. Writing counters
+is hidden behind the abstraction of 1) *pmu->start*, literally start counting so one
+has to set the counter to a good value for the next interrupt; 2) inside the IRQ
+it should set the counter to the same resonable value.
+
+Reading is not a problem in RISC-V but writing would need some effort, since
+counters are not allowed to be written by S-mode.
+
+
+5. add()/del()/start()/stop()
+-----------------------------
+
+Basic idea: add()/del() adds/deletes events to/from a PMU, and start()/stop()
+starts/stop the counter of some event in the PMU. All of them take the same
+arguments: *struct perf_event *event* and *int flag*.
+
+Consider perf as a state machine, then you will find that these functions serve
+as the state transition process between those states.
+Three states (event->hw.state) are defined:
+
+* PERF_HES_STOPPED: the counter is stopped
+* PERF_HES_UPTODATE: the event->count is up-to-date
+* PERF_HES_ARCH: arch-dependent usage ... we don't need this for now
+
+A normal flow of these state transitions are as follows:
+
+* A user launches a perf event, resulting in calling to *event_init*.
+* When being context-switched in, *add* is called by the perf core, with a flag
+ PERF_EF_START, which means that the event should be started after it is added.
+ At this stage, a general event is bound to a physical counter, if any.
+ The state changes to PERF_HES_STOPPED and PERF_HES_UPTODATE, because it is now
+ stopped, and the (software) event count does not need updating.
+** *start* is then called, and the counter is enabled.
+ With flag PERF_EF_RELOAD, it writes an appropriate value to the counter (check
+ previous section for detail).
+ Nothing is written if the flag does not contain PERF_EF_RELOAD.
+ The state now is reset to none, because it is neither stopped nor updated
+ (the counting already started)
+* When being context-switched out, *del* is called. It then checks out all the
+ events in the PMU and calls *stop* to update their counts.
+** *stop* is called by *del*
+ and the perf core with flag PERF_EF_UPDATE, and it often shares the same
+ subroutine as *read* with the same logic.
+ The state changes to PERF_HES_STOPPED and PERF_HES_UPTODATE, again.
+
+** Life cycle of these two pairs: *add* and *del* are called repeatedly as
+ tasks switch in-and-out; *start* and *stop* is also called when the perf core
+ needs a quick stop-and-start, for instance, when the interrupt period is being
+ adjusted.
+
+Current implementation is sufficient for now and can be easily extended to
+features in the future.
+
+A. Related Structures
+---------------------
+
+* struct pmu: include/linux/perf_event.h
+* struct riscv_pmu: arch/riscv/include/asm/perf_event.h
+
+ Both structures are designed to be read-only.
+
+ *struct pmu* defines some function pointer interfaces, and most of them take
+*struct perf_event* as a main argument, dealing with perf events according to
+perf's internal state machine (check kernel/events/core.c for details).
+
+ *struct riscv_pmu* defines PMU-specific parameters. The naming follows the
+convention of all other architectures.
+
+* struct perf_event: include/linux/perf_event.h
+* struct hw_perf_event
+
+ The generic structure that represents perf events, and the hardware-related
+details.
+
+* struct riscv_hw_events: arch/riscv/include/asm/perf_event.h
+
+ The structure that holds the status of events, has two fixed members:
+the number of events and the array of the events.
+
+References
+----------
+
+[1] https://github.com/riscv/riscv-linux/pull/124
+[2] https://groups.google.com/a/groups.riscv.org/forum/#!topic/sw-dev/f19TmCNP6yA
diff --git a/Documentation/security/self-protection.rst b/Documentation/security/self-protection.rst
index 0f53826..e1ca698 100644
--- a/Documentation/security/self-protection.rst
+++ b/Documentation/security/self-protection.rst
@@ -156,7 +156,7 @@ The classic stack buffer overflow involves writing past the expected end
of a variable stored on the stack, ultimately writing a controlled value
to the stack frame's stored return address. The most widely used defense
is the presence of a stack canary between the stack variables and the
-return address (``CONFIG_CC_STACKPROTECTOR``), which is verified just before
+return address (``CONFIG_STACKPROTECTOR``), which is verified just before
the function returns. Other defenses include things like shadow stacks.
Stack depth overflow
diff --git a/Documentation/sphinx/rstFlatTable.py b/Documentation/sphinx/rstFlatTable.py
index 25feb0d..2019a55 100755
--- a/Documentation/sphinx/rstFlatTable.py
+++ b/Documentation/sphinx/rstFlatTable.py
@@ -53,8 +53,6 @@ from docutils.utils import SystemMessagePropagation
# common globals
# ==============================================================================
-# The version numbering follows numbering of the specification
-# (Documentation/books/kernel-doc-HOWTO).
__version__ = '1.0'
PY3 = sys.version_info[0] == 3
diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight.txt
index 1d74ad0..efbc832 100644
--- a/Documentation/trace/coresight.txt
+++ b/Documentation/trace/coresight.txt
@@ -426,5 +426,5 @@ root@genericarmv8:~#
Details on how to use the generic STM API can be found here [2].
[1]. Documentation/ABI/testing/sysfs-bus-coresight-devices-stm
-[2]. Documentation/trace/stm.txt
+[2]. Documentation/trace/stm.rst
[3]. https://github.com/Linaro/perf-opencsd
diff --git a/Documentation/trace/events.rst b/Documentation/trace/events.rst
index 1afae55..696dc69 100644
--- a/Documentation/trace/events.rst
+++ b/Documentation/trace/events.rst
@@ -8,7 +8,7 @@ Event Tracing
1. Introduction
===============
-Tracepoints (see Documentation/trace/tracepoints.txt) can be used
+Tracepoints (see Documentation/trace/tracepoints.rst) can be used
without creating custom kernel modules to register probe functions
using the event tracing infrastructure.
diff --git a/Documentation/trace/ftrace-uses.rst b/Documentation/trace/ftrace-uses.rst
index 00283b6..1fbc698 100644
--- a/Documentation/trace/ftrace-uses.rst
+++ b/Documentation/trace/ftrace-uses.rst
@@ -199,7 +199,7 @@ If @buf is NULL and reset is set, all functions will be enabled for tracing.
The @buf can also be a glob expression to enable all functions that
match a specific pattern.
-See Filter Commands in :file:`Documentation/trace/ftrace.txt`.
+See Filter Commands in :file:`Documentation/trace/ftrace.rst`.
To just trace the schedule function:
diff --git a/Documentation/trace/histogram.txt b/Documentation/trace/histogram.txt
index b13771c..7ffea6a 100644
--- a/Documentation/trace/histogram.txt
+++ b/Documentation/trace/histogram.txt
@@ -7,7 +7,7 @@
Histogram triggers are special event triggers that can be used to
aggregate trace event data into histograms. For information on
- trace events and event triggers, see Documentation/trace/events.txt.
+ trace events and event triggers, see Documentation/trace/events.rst.
2. Histogram Trigger Command
@@ -1729,35 +1729,35 @@ If a variable isn't a key variable or prefixed with 'vals=', the
associated event field will be saved in a variable but won't be summed
as a value:
- # echo 'hist:keys=next_pid:ts1=common_timestamp ... >> event/trigger
+ # echo 'hist:keys=next_pid:ts1=common_timestamp ...' >> event/trigger
Multiple variables can be assigned at the same time. The below would
result in both ts0 and b being created as variables, with both
common_timestamp and field1 additionally being summed as values:
- # echo 'hist:keys=pid:vals=$ts0,$b:ts0=common_timestamp,b=field1 ... >> \
+ # echo 'hist:keys=pid:vals=$ts0,$b:ts0=common_timestamp,b=field1 ...' >> \
event/trigger
Note that variable assignments can appear either preceding or
following their use. The command below behaves identically to the
command above:
- # echo 'hist:keys=pid:ts0=common_timestamp,b=field1:vals=$ts0,$b ... >> \
+ # echo 'hist:keys=pid:ts0=common_timestamp,b=field1:vals=$ts0,$b ...' >> \
event/trigger
Any number of variables not bound to a 'vals=' prefix can also be
assigned by simply separating them with colons. Below is the same
thing but without the values being summed in the histogram:
- # echo 'hist:keys=pid:ts0=common_timestamp:b=field1 ... >> event/trigger
+ # echo 'hist:keys=pid:ts0=common_timestamp:b=field1 ...' >> event/trigger
Variables set as above can be referenced and used in expressions on
another event.
For example, here's how a latency can be calculated:
- # echo 'hist:keys=pid,prio:ts0=common_timestamp ... >> event1/trigger
- # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp-$ts0 ... >> event2/trigger
+ # echo 'hist:keys=pid,prio:ts0=common_timestamp ...' >> event1/trigger
+ # echo 'hist:keys=next_pid:wakeup_lat=common_timestamp-$ts0 ...' >> event2/trigger
In the first line above, the event's timetamp is saved into the
variable ts0. In the next line, ts0 is subtracted from the second
@@ -1766,7 +1766,7 @@ yet another variable, 'wakeup_lat'. The hist trigger below in turn
makes use of the wakeup_lat variable to compute a combined latency
using the same key and variable from yet another event:
- # echo 'hist:key=pid:wakeupswitch_lat=$wakeup_lat+$switchtime_lat ... >> event3/trigger
+ # echo 'hist:key=pid:wakeupswitch_lat=$wakeup_lat+$switchtime_lat ...' >> event3/trigger
2.2.2 Synthetic Events
----------------------
@@ -1807,10 +1807,11 @@ the command that defined it with a '!':
At this point, there isn't yet an actual 'wakeup_latency' event
instantiated in the event subsytem - for this to happen, a 'hist
trigger action' needs to be instantiated and bound to actual fields
-and variables defined on other events (see Section 6.3.3 below).
+and variables defined on other events (see Section 2.2.3 below on
+how that is done using hist trigger 'onmatch' action). Once that is
+done, the 'wakeup_latency' synthetic event instance is created.
-Once that is done, an event instance is created, and a histogram can
-be defined using it:
+A histogram can now be defined for the new synthetic event:
# echo 'hist:keys=pid,prio,lat.log2:sort=pid,lat' >> \
/sys/kernel/debug/tracing/events/synthetic/wakeup_latency/trigger
@@ -1960,7 +1961,7 @@ hist trigger specification.
back to that pid, the timestamp difference is calculated. If the
resulting latency, stored in wakeup_lat, exceeds the current
maximum latency, the values specified in the save() fields are
- recoreded:
+ recorded:
# echo 'hist:keys=pid:ts0=common_timestamp.usecs \
if comm=="cyclictest"' >> \
diff --git a/Documentation/trace/intel_th.rst b/Documentation/trace/intel_th.rst
index 990f132..19e2d63 100644
--- a/Documentation/trace/intel_th.rst
+++ b/Documentation/trace/intel_th.rst
@@ -38,7 +38,7 @@ description is at Documentation/ABI/testing/sysfs-bus-intel_th-devices-gth.
STH registers an stm class device, through which it provides interface
to userspace and kernelspace software trace sources. See
-Documentation/trace/stm.txt for more information on that.
+Documentation/trace/stm.rst for more information on that.
MSU can be configured to collect trace data into a system memory
buffer, which can later on be read from its device nodes via read() or
diff --git a/Documentation/trace/tracepoint-analysis.rst b/Documentation/trace/tracepoint-analysis.rst
index a4d3ff2..716326b9 100644
--- a/Documentation/trace/tracepoint-analysis.rst
+++ b/Documentation/trace/tracepoint-analysis.rst
@@ -6,7 +6,7 @@ Notes on Analysing Behaviour Using Events and Tracepoints
1. Introduction
===============
-Tracepoints (see Documentation/trace/tracepoints.txt) can be used without
+Tracepoints (see Documentation/trace/tracepoints.rst) can be used without
creating custom kernel modules to register probe functions using the event
tracing infrastructure.
@@ -55,7 +55,7 @@ simple case of::
3.1 System-Wide Event Enabling
------------------------------
-See Documentation/trace/events.txt for a proper description on how events
+See Documentation/trace/events.rst for a proper description on how events
can be enabled system-wide. A short example of enabling all events related
to page allocation would look something like::
@@ -112,7 +112,7 @@ at that point.
3.4 Local Event Enabling
------------------------
-Documentation/trace/ftrace.txt describes how to enable events on a per-thread
+Documentation/trace/ftrace.rst describes how to enable events on a per-thread
basis using set_ftrace_pid.
3.5 Local Event Enablement with PCL
@@ -137,7 +137,7 @@ basis using PCL such as follows.
4. Event Filtering
==================
-Documentation/trace/ftrace.txt covers in-depth how to filter events in
+Documentation/trace/ftrace.rst covers in-depth how to filter events in
ftrace. Obviously using grep and awk of trace_pipe is an option as well
as any script reading trace_pipe.
diff --git a/Documentation/translations/ja_JP/howto.rst b/Documentation/translations/ja_JP/howto.rst
index 8d7ed0c..f311638 100644
--- a/Documentation/translations/ja_JP/howto.rst
+++ b/Documentation/translations/ja_JP/howto.rst
@@ -1,5 +1,5 @@
NOTE:
-This is a version of Documentation/HOWTO translated into Japanese.
+This is a version of Documentation/process/howto.rst translated into Japanese.
This document is maintained by Tsugikazu Shibata <tshibata@ab.jp.nec.com>
If you find any difference between this document and the original file or
a problem with the translation, please contact the maintainer of this file.
@@ -109,7 +109,7 @@ linux-api@vger.kernel.org に送ることを勧めます。
ています。 カーネルに関して初めての人はここからスタートすると良い
でしょう。
- :ref:`Documentation/Process/changes.rst <changes>`
+ :ref:`Documentation/process/changes.rst <changes>`
このファイルはカーネルをうまく生成(訳注 build )し、走らせるのに最
小限のレベルで必要な数々のソフトウェアパッケージの一覧を示してい
ます。
diff --git a/Documentation/translations/ko_KR/howto.rst b/Documentation/translations/ko_KR/howto.rst
index 624654b..a8197e0 100644
--- a/Documentation/translations/ko_KR/howto.rst
+++ b/Documentation/translations/ko_KR/howto.rst
@@ -160,7 +160,7 @@ mtk.manpages@gmail.com의 메인테이너에게 보낼 것을 권장한다.
독특한 행동에 관하여 흔히 있는 오해들과 혼란들을 해소하고 있기
때문이다.
- :ref:`Documentation/process/stable_kernel_rules.rst <stable_kernel_rules>`
+ :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
이 문서는 안정적인 커널 배포가 이루어지는 규칙을 설명하고 있으며
여러분들이 이러한 배포들 중 하나에 변경을 하길 원한다면
무엇을 해야 하는지를 설명한다.
diff --git a/Documentation/translations/zh_CN/SubmittingDrivers b/Documentation/translations/zh_CN/SubmittingDrivers
index 929385e..15e7356 100644
--- a/Documentation/translations/zh_CN/SubmittingDrivers
+++ b/Documentation/translations/zh_CN/SubmittingDrivers
@@ -107,7 +107,7 @@ Linux 2.6:
程序测试的指导,请参阅
Documentation/power/drivers-testing.txt。有关驱动程序电
源管理问题相对全面的概述,请参阅
- Documentation/power/admin-guide/devices.rst。
+ Documentation/driver-api/pm/devices.rst。
管理: 如果一个驱动程序的作者还在进行有效的维护,那么通常除了那
些明显正确且不需要任何检查的补丁以外,其他所有的补丁都会
diff --git a/Documentation/translations/zh_CN/gpio.txt b/Documentation/translations/zh_CN/gpio.txt
index 4f8bf30..4cb1ba8 100644
--- a/Documentation/translations/zh_CN/gpio.txt
+++ b/Documentation/translations/zh_CN/gpio.txt
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/gpio.txt
+Chinese translated version of Documentation/gpio
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -10,7 +10,7 @@ Maintainer: Grant Likely <grant.likely@secretlab.ca>
Linus Walleij <linus.walleij@linaro.org>
Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
---------------------------------------------------------------------
-Documentation/gpio.txt 的中文翻译
+Documentation/gpio 的中文翻译
如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
diff --git a/Documentation/translations/zh_CN/io_ordering.txt b/Documentation/translations/zh_CN/io_ordering.txt
index e592daf..1f8127b 100644
--- a/Documentation/translations/zh_CN/io_ordering.txt
+++ b/Documentation/translations/zh_CN/io_ordering.txt
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/io_orderings.txt
+Chinese translated version of Documentation/io_ordering.txt
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
diff --git a/Documentation/translations/zh_CN/magic-number.txt b/Documentation/translations/zh_CN/magic-number.txt
index e9db693..7159cec 100644
--- a/Documentation/translations/zh_CN/magic-number.txt
+++ b/Documentation/translations/zh_CN/magic-number.txt
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/magic-number.txt
+Chinese translated version of Documentation/process/magic-number.rst
If you have any comment or update to the content, please post to LKML directly.
However, if you have problem communicating in English you can also ask the
@@ -7,7 +7,7 @@ translation is outdated or there is problem with translation.
Chinese maintainer: Jia Wei Wei <harryxiyou@gmail.com>
---------------------------------------------------------------------
-Documentation/magic-number.txt的中文翻译
+Documentation/process/magic-number.rst的中文翻译
如果想评论或更新本文的内容,请直接发信到LKML。如果你使用英文交流有困难的话,也可
以向中文版维护者求助。如果本翻译更新不及时或者翻译存在问题,请联系中文版维护者。
diff --git a/Documentation/translations/zh_CN/video4linux/omap3isp.txt b/Documentation/translations/zh_CN/video4linux/omap3isp.txt
index 67ffbf3..e9f2937 100644
--- a/Documentation/translations/zh_CN/video4linux/omap3isp.txt
+++ b/Documentation/translations/zh_CN/video4linux/omap3isp.txt
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/video4linux/omap3isp.txt
+Chinese translated version of Documentation/media/v4l-drivers/omap3isp.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -11,7 +11,7 @@ Maintainer: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
David Cohen <dacohen@gmail.com>
Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
---------------------------------------------------------------------
-Documentation/video4linux/omap3isp.txt 的中文翻译
+Documentation/media/v4l-drivers/omap3isp.rst 的中文翻译
如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
diff --git a/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt b/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
index c77c0f0..66c7c56 100644
--- a/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
+++ b/Documentation/translations/zh_CN/video4linux/v4l2-framework.txt
@@ -1,4 +1,4 @@
-Chinese translated version of Documentation/video4linux/v4l2-framework.txt
+Chinese translated version of Documentation/media/media_kapi.rst
If you have any comment or update to the content, please contact the
original document maintainer directly. However, if you have a problem
@@ -9,7 +9,7 @@ or if there is a problem with the translation.
Maintainer: Mauro Carvalho Chehab <mchehab@kernel.org>
Chinese maintainer: Fu Wei <tekkamanninja@gmail.com>
---------------------------------------------------------------------
-Documentation/video4linux/v4l2-framework.txt 的中文翻译
+Documentation/media/media_kapi.rst 的中文翻译
如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
@@ -777,7 +777,7 @@ v4l2 核心 API 提供了一个处理视频缓冲的标准方法(称为“videob
线性 DMA(videobuf-dma-contig)以及大多用于 USB 设备的用 vmalloc
分配的缓冲(videobuf-vmalloc)。
-请参阅 Documentation/video4linux/videobuf,以获得更多关于 videobuf
+请参阅 Documentation/media/kapi/v4l2-videobuf.rst,以获得更多关于 videobuf
层的使用信息。
v4l2_fh 结构体
diff --git a/Documentation/vfio-mediated-device.txt b/Documentation/vfio-mediated-device.txt
index 1b39503..c3f69bc 100644
--- a/Documentation/vfio-mediated-device.txt
+++ b/Documentation/vfio-mediated-device.txt
@@ -145,6 +145,11 @@ The functions in the mdev_parent_ops structure are as follows:
* create: allocate basic resources in a driver for a mediated device
* remove: free resources in a driver when a mediated device is destroyed
+(Note that mdev-core provides no implicit serialization of create/remove
+callbacks per mdev parent device, per mdev type, or any other categorization.
+Vendor drivers are expected to be fully asynchronous in this respect or
+provide their own internal resource protection.)
+
The callbacks in the mdev_parent_ops structure are as follows:
* open: open callback of mediated device
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 758bf40..d10944e 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -1269,12 +1269,18 @@ struct kvm_cpuid_entry2 {
__u32 padding[3];
};
-This ioctl returns x86 cpuid features which are supported by both the hardware
-and kvm. Userspace can use the information returned by this ioctl to
-construct cpuid information (for KVM_SET_CPUID2) that is consistent with
-hardware, kernel, and userspace capabilities, and with user requirements (for
-example, the user may wish to constrain cpuid to emulate older hardware,
-or for feature consistency across a cluster).
+This ioctl returns x86 cpuid features which are supported by both the
+hardware and kvm in its default configuration. Userspace can use the
+information returned by this ioctl to construct cpuid information (for
+KVM_SET_CPUID2) that is consistent with hardware, kernel, and
+userspace capabilities, and with user requirements (for example, the
+user may wish to constrain cpuid to emulate older hardware, or for
+feature consistency across a cluster).
+
+Note that certain capabilities, such as KVM_CAP_X86_DISABLE_EXITS, may
+expose cpuid features (e.g. MONITOR) which are not supported by kvm in
+its default configuration. If userspace enables such capabilities, it
+is responsible for modifying the results of this ioctl appropriately.
Userspace invokes KVM_GET_SUPPORTED_CPUID by passing a kvm_cpuid2 structure
with the 'nent' field indicating the number of entries in the variable-size
@@ -4603,3 +4609,12 @@ Architectures: s390
This capability indicates that kvm will implement the interfaces to handle
reset, migration and nested KVM for branch prediction blocking. The stfle
facility 82 should not be provided to the guest without this capability.
+
+8.18 KVM_CAP_HYPERV_TLBFLUSH
+
+Architectures: x86
+
+This capability indicates that KVM supports paravirtualized Hyper-V TLB Flush
+hypercalls:
+HvFlushVirtualAddressSpace, HvFlushVirtualAddressSpaceEx,
+HvFlushVirtualAddressList, HvFlushVirtualAddressListEx.
diff --git a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
index 9293b45..2408ab7 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic-v3.txt
@@ -27,16 +27,42 @@ Groups:
VCPU and all of the redistributor pages are contiguous.
Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
This address needs to be 64K aligned.
+
+ KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION (rw, 64-bit)
+ The attribute data pointed to by kvm_device_attr.addr is a __u64 value:
+ bits: | 63 .... 52 | 51 .... 16 | 15 - 12 |11 - 0
+ values: | count | base | flags | index
+ - index encodes the unique redistributor region index
+ - flags: reserved for future use, currently 0
+ - base field encodes bits [51:16] of the guest physical base address
+ of the first redistributor in the region.
+ - count encodes the number of redistributors in the region. Must be
+ greater than 0.
+ There are two 64K pages for each redistributor in the region and
+ redistributors are laid out contiguously within the region. Regions
+ are filled with redistributors in the index order. The sum of all
+ region count fields must be greater than or equal to the number of
+ VCPUs. Redistributor regions must be registered in the incremental
+ index order, starting from index 0.
+ The characteristics of a specific redistributor region can be read
+ by presetting the index field in the attr data.
+ Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
+
+ It is invalid to mix calls with KVM_VGIC_V3_ADDR_TYPE_REDIST and
+ KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION attributes.
+
Errors:
-E2BIG: Address outside of addressable IPA range
- -EINVAL: Incorrectly aligned address
+ -EINVAL: Incorrectly aligned address, bad redistributor region
+ count/index, mixed redistributor region attribute usage
-EEXIST: Address already configured
+ -ENOENT: Attempt to read the characteristics of a non existing
+ redistributor region
-ENXIO: The group or attribute is unknown/unsupported for this device
or hardware support is missing.
-EFAULT: Invalid user pointer for attr->addr.
-
KVM_DEV_ARM_VGIC_GRP_DIST_REGS
KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
Attributes:
diff --git a/Documentation/virtual/kvm/mmu.txt b/Documentation/virtual/kvm/mmu.txt
index f50d45b..e507a9e 100644
--- a/Documentation/virtual/kvm/mmu.txt
+++ b/Documentation/virtual/kvm/mmu.txt
@@ -49,8 +49,8 @@ The mmu supports first-generation mmu hardware, which allows an atomic switch
of the current paging mode and cr3 during guest entry, as well as
two-dimensional paging (AMD's NPT and Intel's EPT). The emulated hardware
it exposes is the traditional 2/3/4 level x86 mmu, with support for global
-pages, pae, pse, pse36, cr0.wp, and 1GB pages. Work is in progress to support
-exposing NPT capable hardware on NPT capable hosts.
+pages, pae, pse, pse36, cr0.wp, and 1GB pages. Emulated hardware also
+able to expose NPT capable hardware on NPT capable hosts.
Translation
===========
@@ -465,5 +465,5 @@ Further reading
===============
- NPT presentation from KVM Forum 2008
- http://www.linux-kvm.org/wiki/images/c/c8/KvmForum2008%24kdf2008_21.pdf
+ http://www.linux-kvm.org/images/c/c8/KvmForum2008%24kdf2008_21.pdf
diff --git a/Documentation/virtual/kvm/nested-vmx.txt b/Documentation/virtual/kvm/nested-vmx.txt
index 8ed937d..97eb135 100644
--- a/Documentation/virtual/kvm/nested-vmx.txt
+++ b/Documentation/virtual/kvm/nested-vmx.txt
@@ -31,17 +31,6 @@ L0, the guest hypervisor, which we call L1, and its nested guest, which we
call L2.
-Known limitations
------------------
-
-The current code supports running Linux guests under KVM guests.
-Only 64-bit guest hypervisors are supported.
-
-Additional patches for running Windows under guest KVM, and Linux under
-guest VMware server, and support for nested EPT, are currently running in
-the lab, and will be sent as follow-on patchsets.
-
-
Running nested VMX
------------------
diff --git a/MAINTAINERS b/MAINTAINERS
index 70cd162..6cfd167 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1419,6 +1419,7 @@ M: Shawn Guo <shawnguo@kernel.org>
M: Sascha Hauer <s.hauer@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
R: Fabio Estevam <fabio.estevam@nxp.com>
+R: NXP Linux Team <linux-imx@nxp.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux.git
@@ -1731,7 +1732,8 @@ F: arch/arm/mach-npcm/
F: arch/arm/boot/dts/nuvoton-npcm*
F: include/dt-bindings/clock/nuvoton,npcm7xx-clks.h
F: drivers/*/*npcm*
-F: Documentation/*/*npcm*
+F: Documentation/devicetree/bindings/*/*npcm*
+F: Documentation/devicetree/bindings/*/*/*npcm*
ARM/NUVOTON W90X900 ARM ARCHITECTURE
M: Wan ZongShun <mcuos.com@gmail.com>
@@ -1829,7 +1831,7 @@ F: drivers/spi/spi-qup.c
F: drivers/tty/serial/msm_serial.c
F: drivers/*/pm8???-*
F: drivers/mfd/ssbi.c
-F: drivers/firmware/qcom_scm.c
+F: drivers/firmware/qcom_scm*
T: git git://git.kernel.org/pub/scm/linux/kernel/git/agross/linux.git
ARM/RADISYS ENP2611 MACHINE SUPPORT
@@ -2606,6 +2608,7 @@ BACKLIGHT CLASS/SUBSYSTEM
M: Lee Jones <lee.jones@linaro.org>
M: Daniel Thompson <daniel.thompson@linaro.org>
M: Jingoo Han <jingoohan1@gmail.com>
+L: dri-devel@lists.freedesktop.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lee/backlight.git
S: Maintained
F: drivers/video/backlight/
@@ -3077,7 +3080,7 @@ M: Clemens Ladisch <clemens@ladisch.de>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
T: git git://git.alsa-project.org/alsa-kernel.git
S: Maintained
-F: Documentation/sound/alsa/Bt87x.txt
+F: Documentation/sound/cards/bt87x.rst
F: sound/pci/bt87x.c
BT8XXGPIO DRIVER
@@ -3373,7 +3376,7 @@ M: David Howells <dhowells@redhat.com>
M: David Woodhouse <dwmw2@infradead.org>
L: keyrings@vger.kernel.org
S: Maintained
-F: Documentation/module-signing.txt
+F: Documentation/admin-guide/module-signing.rst
F: certs/
F: scripts/sign-file.c
F: scripts/extract-cert.c
@@ -4357,12 +4360,7 @@ L: iommu@lists.linux-foundation.org
T: git git://git.infradead.org/users/hch/dma-mapping.git
W: http://git.infradead.org/users/hch/dma-mapping.git
S: Supported
-F: lib/dma-debug.c
-F: lib/dma-direct.c
-F: lib/dma-noncoherent.c
-F: lib/dma-virt.c
-F: drivers/base/dma-mapping.c
-F: drivers/base/dma-coherent.c
+F: kernel/dma/
F: include/asm-generic/dma-mapping.h
F: include/linux/dma-direct.h
F: include/linux/dma-mapping.h
@@ -4511,7 +4509,7 @@ DRM DRIVER FOR ILITEK ILI9225 PANELS
M: David Lechner <david@lechnology.com>
S: Maintained
F: drivers/gpu/drm/tinydrm/ili9225.c
-F: Documentation/devicetree/bindings/display/ili9225.txt
+F: Documentation/devicetree/bindings/display/ilitek,ili9225.txt
DRM DRIVER FOR INTEL I810 VIDEO CARDS
S: Orphan / Obsolete
@@ -4597,13 +4595,13 @@ DRM DRIVER FOR SITRONIX ST7586 PANELS
M: David Lechner <david@lechnology.com>
S: Maintained
F: drivers/gpu/drm/tinydrm/st7586.c
-F: Documentation/devicetree/bindings/display/st7586.txt
+F: Documentation/devicetree/bindings/display/sitronix,st7586.txt
DRM DRIVER FOR SITRONIX ST7735R PANELS
M: David Lechner <david@lechnology.com>
S: Maintained
F: drivers/gpu/drm/tinydrm/st7735r.c
-F: Documentation/devicetree/bindings/display/st7735r.txt
+F: Documentation/devicetree/bindings/display/sitronix,st7735r.txt
DRM DRIVER FOR TDFX VIDEO CARDS
S: Orphan / Obsolete
@@ -4636,7 +4634,6 @@ F: drivers/gpu/drm/
F: drivers/gpu/vga/
F: Documentation/devicetree/bindings/display/
F: Documentation/devicetree/bindings/gpu/
-F: Documentation/devicetree/bindings/video/
F: Documentation/gpu/
F: include/drm/
F: include/uapi/drm/
@@ -4681,7 +4678,7 @@ M: Boris Brezillon <boris.brezillon@bootlin.com>
L: dri-devel@lists.freedesktop.org
S: Supported
F: drivers/gpu/drm/atmel-hlcdc/
-F: Documentation/devicetree/bindings/drm/atmel/
+F: Documentation/devicetree/bindings/display/atmel/
T: git git://anongit.freedesktop.org/drm/drm-misc
DRM DRIVERS FOR BRIDGE CHIPS
@@ -4712,7 +4709,7 @@ S: Supported
F: drivers/gpu/drm/fsl-dcu/
F: Documentation/devicetree/bindings/display/fsl,dcu.txt
F: Documentation/devicetree/bindings/display/fsl,tcon.txt
-F: Documentation/devicetree/bindings/display/panel/nec,nl4827hc19_05b.txt
+F: Documentation/devicetree/bindings/display/panel/nec,nl4827hc19-05b.txt
DRM DRIVERS FOR FREESCALE IMX
M: Philipp Zabel <p.zabel@pengutronix.de>
@@ -4822,7 +4819,7 @@ M: Eric Anholt <eric@anholt.net>
S: Supported
F: drivers/gpu/drm/v3d/
F: include/uapi/drm/v3d_drm.h
-F: Documentation/devicetree/bindings/display/brcm,bcm-v3d.txt
+F: Documentation/devicetree/bindings/gpu/brcm,bcm-v3d.txt
T: git git://anongit.freedesktop.org/drm/drm-misc
DRM DRIVERS FOR VC4
@@ -5733,7 +5730,7 @@ M: Madalin Bucur <madalin.bucur@nxp.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/ethernet/freescale/fman
-F: Documentation/devicetree/bindings/powerpc/fsl/fman.txt
+F: Documentation/devicetree/bindings/net/fsl-fman.txt
FREESCALE QORIQ PTP CLOCK DRIVER
M: Yangbo Lu <yangbo.lu@nxp.com>
@@ -5951,14 +5948,14 @@ GENERIC GPIO I2C DRIVER
M: Haavard Skinnemoen <hskinnemoen@gmail.com>
S: Supported
F: drivers/i2c/busses/i2c-gpio.c
-F: include/linux/i2c-gpio.h
+F: include/linux/platform_data/i2c-gpio.h
GENERIC GPIO I2C MULTIPLEXER DRIVER
M: Peter Korsgaard <peter.korsgaard@barco.com>
L: linux-i2c@vger.kernel.org
S: Supported
F: drivers/i2c/muxes/i2c-mux-gpio.c
-F: include/linux/i2c-mux-gpio.h
+F: include/linux/platform_data/i2c-mux-gpio.h
F: Documentation/i2c/muxes/i2c-mux-gpio
GENERIC HDLC (WAN) DRIVERS
@@ -6499,7 +6496,7 @@ L: linux-mm@kvack.org
S: Maintained
F: mm/hmm*
F: include/linux/hmm*
-F: Documentation/vm/hmm.txt
+F: Documentation/vm/hmm.rst
HOST AP DRIVER
M: Jouni Malinen <j@w1.fi>
@@ -6618,7 +6615,7 @@ F: arch/x86/hyperv
F: drivers/hid/hid-hyperv.c
F: drivers/hv/
F: drivers/input/serio/hyperv-keyboard.c
-F: drivers/pci/host/pci-hyperv.c
+F: drivers/pci/controller/pci-hyperv.c
F: drivers/net/hyperv/
F: drivers/scsi/storvsc_drv.c
F: drivers/uio/uio_hv_generic.c
@@ -6964,7 +6961,7 @@ IIO MULTIPLEXER
M: Peter Rosin <peda@axentia.se>
L: linux-iio@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/iio/multiplexer/iio-mux.txt
+F: Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt
F: drivers/iio/multiplexer/iio-mux.c
IIO SUBSYSTEM AND DRIVERS
@@ -7399,7 +7396,7 @@ F: drivers/platform/x86/intel-wmi-thunderbolt.c
INTEL(R) TRACE HUB
M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
S: Supported
-F: Documentation/trace/intel_th.txt
+F: Documentation/trace/intel_th.rst
F: drivers/hwtracing/intel_th/
INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
@@ -7423,7 +7420,7 @@ M: Linus Walleij <linus.walleij@linaro.org>
L: linux-iio@vger.kernel.org
S: Maintained
F: drivers/iio/gyro/mpu3050*
-F: Documentation/devicetree/bindings/iio/gyroscope/inv,mpu3050.txt
+F: Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.txt
IOC3 ETHERNET DRIVER
M: Ralf Baechle <ralf@linux-mips.org>
@@ -8446,7 +8443,6 @@ L: linux-scsi@vger.kernel.org
W: http://www.avagotech.com/support/
S: Supported
F: drivers/message/fusion/
-F: drivers/scsi/mpt2sas/
F: drivers/scsi/mpt3sas/
LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers
@@ -8699,7 +8695,7 @@ M: Guenter Roeck <linux@roeck-us.net>
L: linux-hwmon@vger.kernel.org
S: Maintained
F: Documentation/hwmon/max6697
-F: Documentation/devicetree/bindings/i2c/max6697.txt
+F: Documentation/devicetree/bindings/hwmon/max6697.txt
F: drivers/hwmon/max6697.c
F: include/linux/platform_data/max6697.h
@@ -9079,7 +9075,7 @@ M: Martin Donnelly <martin.donnelly@ge.com>
M: Martyn Welch <martyn.welch@collabora.co.uk>
S: Maintained
F: drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c
-F: Documentation/devicetree/bindings/video/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt
+F: Documentation/devicetree/bindings/display/bridge/megachips-stdpxxxx-ge-b850v3-fw.txt
MEGARAID SCSI/SAS DRIVERS
M: Kashyap Desai <kashyap.desai@broadcom.com>
@@ -9416,10 +9412,12 @@ F: drivers/usb/image/microtek.*
MIPS
M: Ralf Baechle <ralf@linux-mips.org>
+M: Paul Burton <paul.burton@mips.com>
M: James Hogan <jhogan@kernel.org>
L: linux-mips@linux-mips.org
W: http://www.linux-mips.org/
T: git git://git.linux-mips.org/pub/scm/ralf/linux.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
Q: http://patchwork.linux-mips.org/project/linux-mips/list/
S: Supported
F: Documentation/devicetree/bindings/mips/
@@ -9521,7 +9519,7 @@ M: Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/mobiveil-pcie.txt
-F: drivers/pci/host/pcie-mobiveil.c
+F: drivers/pci/controller/pcie-mobiveil.c
MODULE SUPPORT
M: Jessica Yu <jeyu@kernel.org>
@@ -9662,7 +9660,7 @@ F: include/uapi/linux/mmc/
MULTIPLEXER SUBSYSTEM
M: Peter Rosin <peda@axentia.se>
S: Maintained
-F: Documentation/ABI/testing/mux/sysfs-class-mux*
+F: Documentation/ABI/testing/sysfs-class-mux*
F: Documentation/devicetree/bindings/mux/
F: include/linux/dt-bindings/mux/
F: include/linux/mux/
@@ -9693,7 +9691,7 @@ MXSFB DRM DRIVER
M: Marek Vasut <marex@denx.de>
S: Supported
F: drivers/gpu/drm/mxsfb/
-F: Documentation/devicetree/bindings/display/mxsfb-drm.txt
+F: Documentation/devicetree/bindings/display/mxsfb.txt
MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
M: Chris Lee <christopher.lee@cspi.com>
@@ -9753,6 +9751,11 @@ L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/scsi/NCR_D700.*
+NCSI LIBRARY:
+M: Samuel Mendoza-Jonas <sam@mendozajonas.com>
+S: Maintained
+F: net/ncsi/
+
NCT6775 HARDWARE MONITOR DRIVER
M: Guenter Roeck <linux@roeck-us.net>
L: linux-hwmon@vger.kernel.org
@@ -10241,7 +10244,7 @@ F: arch/powerpc/include/asm/pnv-ocxl.h
F: drivers/misc/ocxl/
F: include/misc/ocxl*
F: include/uapi/misc/ocxl.h
-F: Documentation/accelerators/ocxl.txt
+F: Documentation/accelerators/ocxl.rst
OMAP AUDIO SUPPORT
M: Peter Ujfalusi <peter.ujfalusi@ti.com>
@@ -10270,18 +10273,16 @@ F: arch/arm/boot/dts/*am5*
F: arch/arm/boot/dts/*dra7*
OMAP DISPLAY SUBSYSTEM and FRAMEBUFFER SUPPORT (DSS2)
-M: Tomi Valkeinen <tomi.valkeinen@ti.com>
L: linux-omap@vger.kernel.org
L: linux-fbdev@vger.kernel.org
-S: Maintained
+S: Orphan
F: drivers/video/fbdev/omap2/
F: Documentation/arm/OMAP/DSS
OMAP FRAMEBUFFER SUPPORT
-M: Tomi Valkeinen <tomi.valkeinen@ti.com>
L: linux-fbdev@vger.kernel.org
L: linux-omap@vger.kernel.org
-S: Maintained
+S: Orphan
F: drivers/video/fbdev/omap/
OMAP GENERAL PURPOSE MEMORY CONTROLLER SUPPORT
@@ -10389,7 +10390,7 @@ F: arch/arm/mach-omap1/
F: arch/arm/plat-omap/
F: arch/arm/configs/omap1_defconfig
F: drivers/i2c/busses/i2c-omap.c
-F: include/linux/i2c-omap.h
+F: include/linux/platform_data/i2c-omap.h
OMAP2+ SUPPORT
M: Tony Lindgren <tony@atomide.com>
@@ -10421,7 +10422,7 @@ F: drivers/regulator/tps65218-regulator.c
F: drivers/regulator/tps65910-regulator.c
F: drivers/regulator/twl-regulator.c
F: drivers/regulator/twl6030-regulator.c
-F: include/linux/i2c-omap.h
+F: include/linux/platform_data/i2c-omap.h
ONION OMEGA2+ BOARD
M: Harvey Hunt <harveyhuntnexus@gmail.com>
@@ -10725,7 +10726,7 @@ PARALLEL LCD/KEYPAD PANEL DRIVER
M: Willy Tarreau <willy@haproxy.com>
M: Ksenija Stanojevic <ksenija.stanojevic@gmail.com>
S: Odd Fixes
-F: Documentation/misc-devices/lcd-panel-cgram.txt
+F: Documentation/auxdisplay/lcd-panel-cgram.txt
F: drivers/misc/panel.c
PARALLEL PORT SUBSYSTEM
@@ -10826,7 +10827,7 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/pci/aardvark-pci.txt
-F: drivers/pci/host/pci-aardvark.c
+F: drivers/pci/controller/pci-aardvark.c
PCI DRIVER FOR ALTERA PCIE IP
M: Ley Foon Tan <lftan@altera.com>
@@ -10834,7 +10835,7 @@ L: rfi@lists.rocketboards.org (moderated for non-subscribers)
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/altera-pcie.txt
-F: drivers/pci/host/pcie-altera.c
+F: drivers/pci/controller/pcie-altera.c
PCI DRIVER FOR APPLIEDMICRO XGENE
M: Tanmay Inamdar <tinamdar@apm.com>
@@ -10842,7 +10843,7 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: Documentation/devicetree/bindings/pci/xgene-pci.txt
-F: drivers/pci/host/pci-xgene.c
+F: drivers/pci/controller/pci-xgene.c
PCI DRIVER FOR ARM VERSATILE PLATFORM
M: Rob Herring <robh@kernel.org>
@@ -10850,7 +10851,7 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: Documentation/devicetree/bindings/pci/versatile.txt
-F: drivers/pci/host/pci-versatile.c
+F: drivers/pci/controller/pci-versatile.c
PCI DRIVER FOR ARMADA 8K
M: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
@@ -10858,14 +10859,14 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: Documentation/devicetree/bindings/pci/pci-armada8k.txt
-F: drivers/pci/dwc/pcie-armada8k.c
+F: drivers/pci/controller/dwc/pcie-armada8k.c
PCI DRIVER FOR CADENCE PCIE IP
M: Alan Douglas <adouglas@cadence.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/cdns,*.txt
-F: drivers/pci/cadence/pcie-cadence*
+F: drivers/pci/controller/pcie-cadence*
PCI DRIVER FOR FREESCALE LAYERSCAPE
M: Minghuan Lian <minghuan.Lian@nxp.com>
@@ -10875,7 +10876,7 @@ L: linuxppc-dev@lists.ozlabs.org
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org
S: Maintained
-F: drivers/pci/dwc/*layerscape*
+F: drivers/pci/controller/dwc/*layerscape*
PCI DRIVER FOR GENERIC OF HOSTS
M: Will Deacon <will.deacon@arm.com>
@@ -10883,8 +10884,8 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/pci/host-generic-pci.txt
-F: drivers/pci/host/pci-host-common.c
-F: drivers/pci/host/pci-host-generic.c
+F: drivers/pci/controller/pci-host-common.c
+F: drivers/pci/controller/pci-host-generic.c
PCI DRIVER FOR IMX6
M: Richard Zhu <hongxing.zhu@nxp.com>
@@ -10893,14 +10894,14 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
-F: drivers/pci/dwc/*imx6*
+F: drivers/pci/controller/dwc/*imx6*
PCI DRIVER FOR INTEL VOLUME MANAGEMENT DEVICE (VMD)
M: Keith Busch <keith.busch@intel.com>
M: Jonathan Derrick <jonathan.derrick@intel.com>
L: linux-pci@vger.kernel.org
S: Supported
-F: drivers/pci/host/vmd.c
+F: drivers/pci/controller/vmd.c
PCI DRIVER FOR MICROSEMI SWITCHTEC
M: Kurt Schwemmer <kurt.schwemmer@microsemi.com>
@@ -10920,7 +10921,7 @@ M: Jason Cooper <jason@lakedaemon.net>
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: drivers/pci/host/*mvebu*
+F: drivers/pci/controller/*mvebu*
PCI DRIVER FOR NVIDIA TEGRA
M: Thierry Reding <thierry.reding@gmail.com>
@@ -10928,14 +10929,14 @@ L: linux-tegra@vger.kernel.org
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/nvidia,tegra20-pcie.txt
-F: drivers/pci/host/pci-tegra.c
+F: drivers/pci/controller/pci-tegra.c
PCI DRIVER FOR RENESAS R-CAR
M: Simon Horman <horms@verge.net.au>
L: linux-pci@vger.kernel.org
L: linux-renesas-soc@vger.kernel.org
S: Maintained
-F: drivers/pci/host/*rcar*
+F: drivers/pci/controller/*rcar*
PCI DRIVER FOR SAMSUNG EXYNOS
M: Jingoo Han <jingoohan1@gmail.com>
@@ -10943,7 +10944,7 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
S: Maintained
-F: drivers/pci/dwc/pci-exynos.c
+F: drivers/pci/controller/dwc/pci-exynos.c
PCI DRIVER FOR SYNOPSYS DESIGNWARE
M: Jingoo Han <jingoohan1@gmail.com>
@@ -10951,7 +10952,7 @@ M: Joao Pinto <Joao.Pinto@synopsys.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/designware-pcie.txt
-F: drivers/pci/dwc/*designware*
+F: drivers/pci/controller/dwc/*designware*
PCI DRIVER FOR TI DRA7XX
M: Kishon Vijay Abraham I <kishon@ti.com>
@@ -10959,14 +10960,14 @@ L: linux-omap@vger.kernel.org
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/ti-pci.txt
-F: drivers/pci/dwc/pci-dra7xx.c
+F: drivers/pci/controller/dwc/pci-dra7xx.c
PCI DRIVER FOR TI KEYSTONE
M: Murali Karicheri <m-karicheri2@ti.com>
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: drivers/pci/dwc/*keystone*
+F: drivers/pci/controller/dwc/*keystone*
PCI ENDPOINT SUBSYSTEM
M: Kishon Vijay Abraham I <kishon@ti.com>
@@ -10999,7 +11000,7 @@ L: rfi@lists.rocketboards.org (moderated for non-subscribers)
L: linux-pci@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/pci/altera-pcie-msi.txt
-F: drivers/pci/host/pcie-altera-msi.c
+F: drivers/pci/controller/pcie-altera-msi.c
PCI MSI DRIVER FOR APPLIEDMICRO XGENE
M: Duc Dang <dhdang@apm.com>
@@ -11007,7 +11008,7 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org
S: Maintained
F: Documentation/devicetree/bindings/pci/xgene-pci-msi.txt
-F: drivers/pci/host/pci-xgene-msi.c
+F: drivers/pci/controller/pci-xgene-msi.c
PCI SUBSYSTEM
M: Bjorn Helgaas <bhelgaas@google.com>
@@ -11033,9 +11034,7 @@ L: linux-pci@vger.kernel.org
Q: http://patchwork.ozlabs.org/project/linux-pci/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/lpieralisi/pci.git/
S: Supported
-F: drivers/pci/cadence/
-F: drivers/pci/host/
-F: drivers/pci/dwc/
+F: drivers/pci/controller/
PCIE DRIVER FOR AXIS ARTPEC
M: Jesper Nilsson <jesper.nilsson@axis.com>
@@ -11043,7 +11042,7 @@ L: linux-arm-kernel@axis.com
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/axis,artpec*
-F: drivers/pci/dwc/*artpec*
+F: drivers/pci/controller/dwc/*artpec*
PCIE DRIVER FOR CAVIUM THUNDERX
M: David Daney <david.daney@cavium.com>
@@ -11051,22 +11050,22 @@ L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Supported
F: Documentation/devicetree/bindings/pci/pci-thunder-*
-F: drivers/pci/host/pci-thunder-*
+F: drivers/pci/controller/pci-thunder-*
PCIE DRIVER FOR HISILICON
M: Zhou Wang <wangzhou1@hisilicon.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
-F: drivers/pci/dwc/pcie-hisi.c
+F: drivers/pci/controller/dwc/pcie-hisi.c
PCIE DRIVER FOR HISILICON KIRIN
M: Xiaowei Song <songxiaowei@hisilicon.com>
M: Binghui Wang <wangbinghui@hisilicon.com>
L: linux-pci@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/pci/pcie-kirin.txt
-F: drivers/pci/dwc/pcie-kirin.c
+F: Documentation/devicetree/bindings/pci/kirin-pcie.txt
+F: drivers/pci/controller/dwc/pcie-kirin.c
PCIE DRIVER FOR HISILICON STB
M: Jianguo Sun <sunjianguo1@huawei.com>
@@ -11074,7 +11073,7 @@ M: Shawn Guo <shawn.guo@linaro.org>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt
-F: drivers/pci/dwc/pcie-histb.c
+F: drivers/pci/controller/dwc/pcie-histb.c
PCIE DRIVER FOR MEDIATEK
M: Ryder Lee <ryder.lee@mediatek.com>
@@ -11082,14 +11081,14 @@ L: linux-pci@vger.kernel.org
L: linux-mediatek@lists.infradead.org
S: Supported
F: Documentation/devicetree/bindings/pci/mediatek*
-F: drivers/pci/host/*mediatek*
+F: drivers/pci/controller/*mediatek*
PCIE DRIVER FOR QUALCOMM MSM
M: Stanimir Varbanov <svarbanov@mm-sol.com>
L: linux-pci@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Maintained
-F: drivers/pci/dwc/*qcom*
+F: drivers/pci/controller/dwc/*qcom*
PCIE DRIVER FOR ROCKCHIP
M: Shawn Lin <shawn.lin@rock-chips.com>
@@ -11097,20 +11096,20 @@ L: linux-pci@vger.kernel.org
L: linux-rockchip@lists.infradead.org
S: Maintained
F: Documentation/devicetree/bindings/pci/rockchip-pcie*
-F: drivers/pci/host/pcie-rockchip*
+F: drivers/pci/controller/pcie-rockchip*
PCI DRIVER FOR V3 SEMICONDUCTOR V360EPC
M: Linus Walleij <linus.walleij@linaro.org>
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/v3-v360epc-pci.txt
-F: drivers/pci/host/pci-v3-semi.c
+F: drivers/pci/controller/pci-v3-semi.c
PCIE DRIVER FOR ST SPEAR13XX
M: Pratyush Anand <pratyush.anand@gmail.com>
L: linux-pci@vger.kernel.org
S: Maintained
-F: drivers/pci/dwc/*spear*
+F: drivers/pci/controller/dwc/*spear*
PCMCIA SUBSYSTEM
M: Dominik Brodowski <linux@dominikbrodowski.net>
@@ -12178,7 +12177,7 @@ F: drivers/mtd/nand/raw/r852.h
RISC-V ARCHITECTURE
M: Palmer Dabbelt <palmer@sifive.com>
-M: Albert Ou <albert@sifive.com>
+M: Albert Ou <aou@eecs.berkeley.edu>
L: linux-riscv@lists.infradead.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux.git
S: Supported
@@ -12456,7 +12455,7 @@ L: linux-crypto@vger.kernel.org
L: linux-samsung-soc@vger.kernel.org
S: Maintained
F: drivers/crypto/exynos-rng.c
-F: Documentation/devicetree/bindings/crypto/samsung,exynos-rng4.txt
+F: Documentation/devicetree/bindings/rng/samsung,exynos4-rng.txt
SAMSUNG EXYNOS TRUE RANDOM NUMBER GENERATOR (TRNG) DRIVER
M: Łukasz Stelmach <l.stelmach@samsung.com>
@@ -12938,6 +12937,14 @@ F: drivers/media/usb/siano/
F: drivers/media/usb/siano/
F: drivers/media/mmc/siano/
+SIFIVE DRIVERS
+M: Palmer Dabbelt <palmer@sifive.com>
+L: linux-riscv@lists.infradead.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux.git
+S: Supported
+K: sifive
+N: sifive
+
SILEAD TOUCHSCREEN DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: linux-input@vger.kernel.org
@@ -13290,7 +13297,7 @@ M: Vinod Koul <vkoul@kernel.org>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound.git
S: Supported
-F: Documentation/sound/alsa/compress_offload.txt
+F: Documentation/sound/designs/compress-offload.rst
F: include/sound/compress_driver.h
F: include/uapi/sound/compress_*
F: sound/core/compress_offload.c
@@ -13311,7 +13318,7 @@ L: alsa-devel@alsa-project.org (moderated for non-subscribers)
W: http://alsa-project.org/main/index.php/ASoC
S: Supported
F: Documentation/devicetree/bindings/sound/
-F: Documentation/sound/alsa/soc/
+F: Documentation/sound/soc/
F: sound/soc/
F: include/sound/soc*
@@ -13563,6 +13570,16 @@ T: git git://linuxtv.org/media_tree.git
S: Maintained
F: drivers/media/usb/stk1160/
+STM32 TIMER/LPTIMER DRIVERS
+M: Fabrice Gasnier <fabrice.gasnier@st.com>
+S: Maintained
+F: drivers/*/stm32-*timer*
+F: drivers/pwm/pwm-stm32*
+F: include/linux/*/stm32-*tim*
+F: Documentation/ABI/testing/*timer-stm32
+F: Documentation/devicetree/bindings/*/stm32-*timer*
+F: Documentation/devicetree/bindings/pwm/pwm-stm32*
+
STMMAC ETHERNET DRIVER
M: Giuseppe Cavallaro <peppe.cavallaro@st.com>
M: Alexandre Torgue <alexandre.torgue@st.com>
@@ -13631,7 +13648,7 @@ M: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
L: iommu@lists.linux-foundation.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/konrad/swiotlb.git
S: Supported
-F: lib/swiotlb.c
+F: kernel/dma/swiotlb.c
F: arch/*/kernel/pci-swiotlb.c
F: include/linux/swiotlb.h
@@ -13783,7 +13800,7 @@ SYSTEM TRACE MODULE CLASS
M: Alexander Shishkin <alexander.shishkin@linux.intel.com>
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ash/stm.git
-F: Documentation/trace/stm.txt
+F: Documentation/trace/stm.rst
F: drivers/hwtracing/stm/
F: include/linux/stm.h
F: include/uapi/linux/stm.h
@@ -14460,7 +14477,7 @@ M: Steven Rostedt <rostedt@goodmis.org>
M: Ingo Molnar <mingo@redhat.com>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git perf/core
S: Maintained
-F: Documentation/trace/ftrace.txt
+F: Documentation/trace/ftrace.rst
F: arch/*/*/*/ftrace.h
F: arch/*/kernel/ftrace.c
F: include/*/ftrace.h
@@ -14929,7 +14946,7 @@ M: Heikki Krogerus <heikki.krogerus@linux.intel.com>
L: linux-usb@vger.kernel.org
S: Maintained
F: Documentation/ABI/testing/sysfs-class-typec
-F: Documentation/usb/typec.rst
+F: Documentation/driver-api/usb/typec.rst
F: drivers/usb/typec/
F: include/linux/usb/typec.h
@@ -14996,8 +15013,7 @@ F: drivers/media/usb/zr364xx/
USER-MODE LINUX (UML)
M: Jeff Dike <jdike@addtoit.com>
M: Richard Weinberger <richard@nod.at>
-L: user-mode-linux-devel@lists.sourceforge.net
-L: user-mode-linux-user@lists.sourceforge.net
+L: linux-um@lists.infradead.org
W: http://user-mode-linux.sourceforge.net
T: git git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml.git
S: Maintained
@@ -15556,9 +15572,17 @@ M: x86@kernel.org
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
S: Maintained
+F: Documentation/devicetree/bindings/x86/
F: Documentation/x86/
F: arch/x86/
+X86 ENTRY CODE
+M: Andy Lutomirski <luto@kernel.org>
+L: linux-kernel@vger.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/asm
+S: Maintained
+F: arch/x86/entry/
+
X86 MCE INFRASTRUCTURE
M: Tony Luck <tony.luck@intel.com>
M: Borislav Petkov <bp@alien8.de>
@@ -15581,7 +15605,7 @@ F: drivers/platform/x86/
F: drivers/platform/olpc/
X86 VDSO
-M: Andy Lutomirski <luto@amacapital.net>
+M: Andy Lutomirski <luto@kernel.org>
L: linux-kernel@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/vdso
S: Maintained
@@ -15759,7 +15783,7 @@ YEALINK PHONE DRIVER
M: Henk Vergonet <Henk.Vergonet@gmail.com>
L: usbb2k-api-dev@nongnu.org
S: Maintained
-F: Documentation/input/yealink.rst
+F: Documentation/input/devices/yealink.rst
F: drivers/input/misc/yealink.*
Z8530 DRIVER FOR AX.25
diff --git a/Makefile b/Makefile
index 019a5a0..ca2af1a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 4
-PATCHLEVEL = 17
+PATCHLEVEL = 18
SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc1
NAME = Merciless Moray
# *DOCUMENTATION*
@@ -442,8 +442,6 @@ export KBUILD_AFLAGS_MODULE KBUILD_CFLAGS_MODULE KBUILD_LDFLAGS_MODULE
export KBUILD_AFLAGS_KERNEL KBUILD_CFLAGS_KERNEL
export KBUILD_ARFLAGS
-export CC_VERSION_TEXT := $(shell $(CC) --version | head -n 1)
-
# When compiling out-of-tree modules, put MODVERDIR in the module
# tree rather than in the kernel tree. The kernel tree might
# even be read-only.
@@ -514,6 +512,12 @@ ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/cc-can-link.sh $(CC)), y)
export CC_CAN_LINK
endif
+# The expansion should be delayed until arch/$(SRCARCH)/Makefile is included.
+# Some architectures define CROSS_COMPILE in arch/$(SRCARCH)/Makefile.
+# CC_VERSION_TEXT is referenced from Kconfig (so it needs export),
+# and from include/config/auto.conf.cmd to detect the compiler upgrade.
+CC_VERSION_TEXT = $(shell $(CC) --version | head -n 1)
+
ifeq ($(config-targets),1)
# ===========================================================================
# *config targets only - make sure prerequisites are updated, and descend
@@ -523,7 +527,7 @@ ifeq ($(config-targets),1)
# KBUILD_DEFCONFIG may point out an alternative default configuration
# used for 'make defconfig'
include arch/$(SRCARCH)/Makefile
-export KBUILD_DEFCONFIG KBUILD_KCONFIG
+export KBUILD_DEFCONFIG KBUILD_KCONFIG CC_VERSION_TEXT
config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
@@ -585,12 +589,32 @@ virt-y := virt/
endif # KBUILD_EXTMOD
ifeq ($(dot-config),1)
-# Read in config
-include include/config/auto.conf
+endif
+
+# The all: target is the default when no target is given on the
+# command line.
+# This allow a user to issue only 'make' to build a kernel including modules
+# Defaults to vmlinux, but the arch makefile usually adds further targets
+all: vmlinux
+
+CFLAGS_GCOV := -fprofile-arcs -ftest-coverage \
+ $(call cc-option,-fno-tree-loop-im) \
+ $(call cc-disable-warning,maybe-uninitialized,)
+export CFLAGS_GCOV
+# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
+# values of the respective KBUILD_* variables
+ARCH_CPPFLAGS :=
+ARCH_AFLAGS :=
+ARCH_CFLAGS :=
+include arch/$(SRCARCH)/Makefile
+
+ifeq ($(dot-config),1)
ifeq ($(KBUILD_EXTMOD),)
-# Read in dependencies to all Kconfig* files, make sure to run
-# oldconfig if changes are detected.
+# Read in dependencies to all Kconfig* files, make sure to run syncconfig if
+# changes are detected. This should be included after arch/$(SRCARCH)/Makefile
+# because some architectures define CROSS_COMPILE there.
-include include/config/auto.conf.cmd
# To avoid any implicit rule to kick in, define an empty command
@@ -622,24 +646,6 @@ else
include/config/auto.conf: ;
endif # $(dot-config)
-# The all: target is the default when no target is given on the
-# command line.
-# This allow a user to issue only 'make' to build a kernel including modules
-# Defaults to vmlinux, but the arch makefile usually adds further targets
-all: vmlinux
-
-CFLAGS_GCOV := -fprofile-arcs -ftest-coverage \
- $(call cc-option,-fno-tree-loop-im) \
- $(call cc-disable-warning,maybe-uninitialized,)
-export CFLAGS_GCOV CFLAGS_KCOV
-
-# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
-# values of the respective KBUILD_* variables
-ARCH_CPPFLAGS :=
-ARCH_AFLAGS :=
-ARCH_CFLAGS :=
-include arch/$(SRCARCH)/Makefile
-
KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,)
KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,)
KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation)
@@ -680,55 +686,11 @@ ifneq ($(CONFIG_FRAME_WARN),0)
KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN})
endif
-# This selects the stack protector compiler flag. Testing it is delayed
-# until after .config has been reprocessed, in the prepare-compiler-check
-# target.
-ifdef CONFIG_CC_STACKPROTECTOR_AUTO
- stackp-flag := $(call cc-option,-fstack-protector-strong,$(call cc-option,-fstack-protector))
- stackp-name := AUTO
-else
-ifdef CONFIG_CC_STACKPROTECTOR_REGULAR
- stackp-flag := -fstack-protector
- stackp-name := REGULAR
-else
-ifdef CONFIG_CC_STACKPROTECTOR_STRONG
- stackp-flag := -fstack-protector-strong
- stackp-name := STRONG
-else
- # If either there is no stack protector for this architecture or
- # CONFIG_CC_STACKPROTECTOR_NONE is selected, we're done, and $(stackp-name)
- # is empty, skipping all remaining stack protector tests.
- #
- # Force off for distro compilers that enable stack protector by default.
- KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
-endif
-endif
-endif
-# Find arch-specific stack protector compiler sanity-checking script.
-ifdef stackp-name
-ifneq ($(stackp-flag),)
- stackp-path := $(srctree)/scripts/gcc-$(SRCARCH)_$(BITS)-has-stack-protector.sh
- stackp-check := $(wildcard $(stackp-path))
- # If the wildcard test matches a test script, run it to check functionality.
- ifdef stackp-check
- ifneq ($(shell $(CONFIG_SHELL) $(stackp-check) $(CC) $(KBUILD_CPPFLAGS) $(biarch)),y)
- stackp-broken := y
- endif
- endif
- ifndef stackp-broken
- # If the stack protector is functional, enable code that depends on it.
- KBUILD_CPPFLAGS += -DCONFIG_CC_STACKPROTECTOR
- # Either we've already detected the flag (for AUTO) or we'll fail the
- # build in the prepare-compiler-check rule (for specific flag).
- KBUILD_CFLAGS += $(stackp-flag)
- else
- # We have to make sure stack protector is unconditionally disabled if
- # the compiler is broken (in case we're going to continue the build in
- # AUTO mode).
- KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector)
- endif
-endif
-endif
+stackp-flags-$(CONFIG_CC_HAS_STACKPROTECTOR_NONE) := -fno-stack-protector
+stackp-flags-$(CONFIG_STACKPROTECTOR) := -fstack-protector
+stackp-flags-$(CONFIG_STACKPROTECTOR_STRONG) := -fstack-protector-strong
+
+KBUILD_CFLAGS += $(stackp-flags-y)
ifeq ($(cc-name),clang)
KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,)
@@ -1112,7 +1074,7 @@ endif
# prepare2 creates a makefile if using a separate output directory.
# From this point forward, .config has been reprocessed, so any rules
# that need to depend on updated CONFIG_* values can be checked here.
-prepare2: prepare3 prepare-compiler-check outputmakefile asm-generic
+prepare2: prepare3 outputmakefile asm-generic
prepare1: prepare2 $(version_h) $(autoksyms_h) include/generated/utsrelease.h \
include/config/auto.conf
@@ -1138,43 +1100,6 @@ uapi-asm-generic:
PHONY += prepare-objtool
prepare-objtool: $(objtool_target)
-# Check for CONFIG flags that require compiler support. Abort the build
-# after .config has been processed, but before the kernel build starts.
-#
-# For security-sensitive CONFIG options, we don't want to fallback and/or
-# silently change which compiler flags will be used, since that leads to
-# producing kernels with different security feature characteristics
-# depending on the compiler used. (For example, "But I selected
-# CC_STACKPROTECTOR_STRONG! Why did it build with _REGULAR?!")
-PHONY += prepare-compiler-check
-prepare-compiler-check: FORCE
-# Make sure compiler supports requested stack protector flag.
-ifdef stackp-name
- # Warn about CONFIG_CC_STACKPROTECTOR_AUTO having found no option.
- ifeq ($(stackp-flag),)
- @echo CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
- Compiler does not support any known stack-protector >&2
- else
- # Fail if specifically requested stack protector is missing.
- ifeq ($(call cc-option, $(stackp-flag)),)
- @echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
- $(stackp-flag) not supported by compiler >&2 && exit 1
- endif
- endif
-endif
-# Make sure compiler does not have buggy stack-protector support. If a
-# specific stack-protector was requested, fail the build, otherwise warn.
-ifdef stackp-broken
- ifeq ($(stackp-name),AUTO)
- @echo CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
- $(stackp-flag) available but compiler is broken: disabling >&2
- else
- @echo Cannot use CONFIG_CC_STACKPROTECTOR_$(stackp-name): \
- $(stackp-flag) available but compiler is broken >&2 && exit 1
- endif
-endif
- @:
-
# Generate some files
# ---------------------------------------------------------------------------
diff --git a/arch/Kconfig b/arch/Kconfig
index 86ae4c4..1aa5906 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -403,7 +403,16 @@ config SECCOMP_FILTER
in terms of Berkeley Packet Filter programs which implement
task-defined system call filtering polices.
- See Documentation/prctl/seccomp_filter.txt for details.
+ See Documentation/userspace-api/seccomp_filter.rst for details.
+
+preferred-plugin-hostcc := $(if-success,[ $(gcc-version) -ge 40800 ],$(HOSTCXX),$(HOSTCC))
+
+config PLUGIN_HOSTCC
+ string
+ default "$(shell,$(srctree)/scripts/gcc-plugin.sh "$(preferred-plugin-hostcc)" "$(HOSTCXX)" "$(CC)")"
+ help
+ Host compiler used to build GCC plugins. This can be $(HOSTCXX),
+ $(HOSTCC), or a null string if GCC plugin is unsupported.
config HAVE_GCC_PLUGINS
bool
@@ -414,7 +423,7 @@ config HAVE_GCC_PLUGINS
menuconfig GCC_PLUGINS
bool "GCC plugins"
depends on HAVE_GCC_PLUGINS
- depends on !COMPILE_TEST
+ depends on PLUGIN_HOSTCC != ""
help
GCC plugins are loadable modules that provide extra features to the
compiler. They are useful for runtime instrumentation and static analysis.
@@ -424,7 +433,7 @@ menuconfig GCC_PLUGINS
config GCC_PLUGIN_CYC_COMPLEXITY
bool "Compute the cyclomatic complexity of a function" if EXPERT
depends on GCC_PLUGINS
- depends on !COMPILE_TEST
+ depends on !COMPILE_TEST # too noisy
help
The complexity M of a function's control flow graph is defined as:
M = E - N + 2P
@@ -484,6 +493,7 @@ config GCC_PLUGIN_STRUCTLEAK
config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL
bool "Force initialize all struct type variables passed by reference"
depends on GCC_PLUGIN_STRUCTLEAK
+ depends on !COMPILE_TEST
help
Zero initialize any struct type local variable that may be passed by
reference without having been initialized.
@@ -491,7 +501,7 @@ config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL
config GCC_PLUGIN_STRUCTLEAK_VERBOSE
bool "Report forcefully initialized variables"
depends on GCC_PLUGIN_STRUCTLEAK
- depends on !COMPILE_TEST
+ depends on !COMPILE_TEST # too noisy
help
This option will cause a warning to be printed each time the
structleak plugin finds a variable it thinks needs to be
@@ -531,7 +541,7 @@ config GCC_PLUGIN_RANDSTRUCT
config GCC_PLUGIN_RANDSTRUCT_PERFORMANCE
bool "Use cacheline-aware structure randomization"
depends on GCC_PLUGIN_RANDSTRUCT
- depends on !COMPILE_TEST
+ depends on !COMPILE_TEST # do not reduce test coverage
help
If you say Y here, the RANDSTRUCT randomization will make a
best effort at restricting randomization to cacheline-sized
@@ -539,17 +549,20 @@ config GCC_PLUGIN_RANDSTRUCT_PERFORMANCE
in structures. This reduces the performance hit of RANDSTRUCT
at the cost of weakened randomization.
-config HAVE_CC_STACKPROTECTOR
+config HAVE_STACKPROTECTOR
bool
help
An arch should select this symbol if:
- - its compiler supports the -fstack-protector option
- it has implemented a stack canary (e.g. __stack_chk_guard)
-choice
- prompt "Stack Protector buffer overflow detection"
- depends on HAVE_CC_STACKPROTECTOR
- default CC_STACKPROTECTOR_AUTO
+config CC_HAS_STACKPROTECTOR_NONE
+ def_bool $(cc-option,-fno-stack-protector)
+
+config STACKPROTECTOR
+ bool "Stack Protector buffer overflow detection"
+ depends on HAVE_STACKPROTECTOR
+ depends on $(cc-option,-fstack-protector)
+ default y
help
This option turns on the "stack-protector" GCC feature. This
feature puts, at the beginning of functions, a canary value on
@@ -559,14 +572,6 @@ choice
overwrite the canary, which gets detected and the attack is then
neutralized via a kernel panic.
-config CC_STACKPROTECTOR_NONE
- bool "None"
- help
- Disable "stack-protector" GCC feature.
-
-config CC_STACKPROTECTOR_REGULAR
- bool "Regular"
- help
Functions will have the stack-protector canary logic added if they
have an 8-byte or larger character array on the stack.
@@ -577,8 +582,11 @@ config CC_STACKPROTECTOR_REGULAR
about 3% of all kernel functions, which increases kernel code size
by about 0.3%.
-config CC_STACKPROTECTOR_STRONG
- bool "Strong"
+config STACKPROTECTOR_STRONG
+ bool "Strong Stack Protector"
+ depends on STACKPROTECTOR
+ depends on $(cc-option,-fstack-protector-strong)
+ default y
help
Functions will have the stack-protector canary logic added in any
of the following conditions:
@@ -596,14 +604,6 @@ config CC_STACKPROTECTOR_STRONG
about 20% of all kernel functions, which increases the kernel code
size by about 2%.
-config CC_STACKPROTECTOR_AUTO
- bool "Automatic"
- help
- If the compiler supports it, the best available stack-protector
- option will be chosen.
-
-endchoice
-
config HAVE_ARCH_WITHIN_STACK_FRAMES
bool
help
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index 0c4805a..04a4a13 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -555,11 +555,6 @@ config SMP
If you don't know what to do here, say N.
-config HAVE_DEC_LOCK
- bool
- depends on SMP
- default y
-
config NR_CPUS
int "Maximum number of CPUs (2-32)"
range 2 32
diff --git a/arch/alpha/lib/Makefile b/arch/alpha/lib/Makefile
index 04f9729..854d5e7 100644
--- a/arch/alpha/lib/Makefile
+++ b/arch/alpha/lib/Makefile
@@ -35,8 +35,6 @@ lib-y = __divqu.o __remqu.o __divlu.o __remlu.o \
callback_srm.o srm_puts.o srm_printk.o \
fls.o
-lib-$(CONFIG_SMP) += dec_and_lock.o
-
# The division routines are built from single source, with different defines.
AFLAGS___divqu.o = -DDIV
AFLAGS___remqu.o = -DREM
diff --git a/arch/alpha/lib/dec_and_lock.c b/arch/alpha/lib/dec_and_lock.c
deleted file mode 100644
index a117707..0000000
--- a/arch/alpha/lib/dec_and_lock.c
+++ /dev/null
@@ -1,44 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * arch/alpha/lib/dec_and_lock.c
- *
- * ll/sc version of atomic_dec_and_lock()
- *
- */
-
-#include <linux/spinlock.h>
-#include <linux/atomic.h>
-#include <linux/export.h>
-
- asm (".text \n\
- .global _atomic_dec_and_lock \n\
- .ent _atomic_dec_and_lock \n\
- .align 4 \n\
-_atomic_dec_and_lock: \n\
- .prologue 0 \n\
-1: ldl_l $1, 0($16) \n\
- subl $1, 1, $1 \n\
- beq $1, 2f \n\
- stl_c $1, 0($16) \n\
- beq $1, 4f \n\
- mb \n\
- clr $0 \n\
- ret \n\
-2: br $29, 3f \n\
-3: ldgp $29, 0($29) \n\
- br $atomic_dec_and_lock_1..ng \n\
- .subsection 2 \n\
-4: br 1b \n\
- .previous \n\
- .end _atomic_dec_and_lock");
-
-static int __used atomic_dec_and_lock_1(atomic_t *atomic, spinlock_t *lock)
-{
- /* Slow path */
- spin_lock(lock);
- if (atomic_dec_and_test(atomic))
- return 1;
- spin_unlock(lock);
- return 0;
-}
-EXPORT_SYMBOL(_atomic_dec_and_lock);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 94d2225..54eeb8d 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -8,9 +8,10 @@ config ARM
select ARCH_HAS_DEVMEM_IS_ALLOWED
select ARCH_HAS_ELF_RANDOMIZE
select ARCH_HAS_FORTIFY_SOURCE
+ select ARCH_HAS_KCOV
select ARCH_HAS_PTE_SPECIAL if ARM_LPAE
- select ARCH_HAS_SET_MEMORY
select ARCH_HAS_PHYS_TO_DMA
+ select ARCH_HAS_SET_MEMORY
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
select ARCH_HAS_STRICT_MODULE_RWX if MMU
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
@@ -57,7 +58,6 @@ config ARM
select HAVE_ARCH_TRACEHOOK
select HAVE_ARM_SMCCC if CPU_V7
select HAVE_EBPF_JIT if !CPU_ENDIAN_BE32
- select HAVE_CC_STACKPROTECTOR
select HAVE_CONTEXT_TRACKING
select HAVE_C_RECORDMCOUNT
select HAVE_DEBUG_KMEMLEAK
@@ -92,6 +92,7 @@ config ARM
select HAVE_RCU_TABLE_FREE if (SMP && ARM_LPAE)
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RSEQ
+ select HAVE_STACKPROTECTOR
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_UID16
select HAVE_VIRT_CPU_ACCOUNTING_GEN
@@ -1301,7 +1302,7 @@ config SMP
will run faster if you say N here.
See also <file:Documentation/x86/i386/IO-APIC.txt>,
- <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
+ <file:Documentation/lockup-watchdogs.txt> and the SMP-HOWTO available at
<http://tldp.org/HOWTO/SMP-HOWTO.html>.
If you don't know what to do here, say N.
@@ -1463,7 +1464,7 @@ config ARM_PSCI
config ARCH_NR_GPIO
int
default 2048 if ARCH_SOCFPGA
- default 1024 if ARCH_BRCMSTB || ARCH_SHMOBILE || ARCH_TEGRA || \
+ default 1024 if ARCH_BRCMSTB || ARCH_RENESAS || ARCH_TEGRA || \
ARCH_ZYNQ
default 512 if ARCH_EXYNOS || ARCH_KEYSTONE || SOC_OMAP5 || \
SOC_DRA7XX || ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PV210
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 199ebc1..693f843 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -942,6 +942,13 @@ choice
via SCIF0 on Renesas RZ/G1M (R8A7743), R-Car H2 (R8A7790),
M2-W (R8A7791), V2H (R8A7792), or M2-N (R8A7793).
+ config DEBUG_RCAR_GEN2_SCIF1
+ bool "Kernel low-level debugging messages via SCIF1 on R8A77470"
+ depends on ARCH_R8A77470
+ help
+ Say Y here if you want kernel low-level debugging support
+ via SCIF1 on Renesas RZ/G1C (R8A77470).
+
config DEBUG_RCAR_GEN2_SCIF2
bool "Kernel low-level debugging messages via SCIF2 on R8A7794"
depends on ARCH_R8A7794
@@ -1495,6 +1502,7 @@ config DEBUG_LL_INCLUDE
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF0
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN1_SCIF2
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF0
+ default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF1
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF2
default "debug/renesas-scif.S" if DEBUG_RCAR_GEN2_SCIF4
default "debug/renesas-scif.S" if DEBUG_RMOBILE_SCIFA0
@@ -1617,6 +1625,7 @@ config DEBUG_UART_PHYS
default 0xe6c80000 if DEBUG_RMOBILE_SCIFA4
default 0xe6e58000 if DEBUG_RCAR_GEN2_SCIF2
default 0xe6e60000 if DEBUG_RCAR_GEN2_SCIF0
+ default 0xe6e68000 if DEBUG_RCAR_GEN2_SCIF1
default 0xe6ee0000 if DEBUG_RCAR_GEN2_SCIF4
default 0xe8008000 if DEBUG_R7S72100_SCIF2
default 0xf0000be0 if ARCH_EBSA110
@@ -1651,8 +1660,8 @@ config DEBUG_UART_PHYS
DEBUG_NETX_UART || \
DEBUG_QCOM_UARTDM || DEBUG_R7S72100_SCIF2 || \
DEBUG_RCAR_GEN1_SCIF0 || DEBUG_RCAR_GEN1_SCIF2 || \
- DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF2 || \
- DEBUG_RCAR_GEN2_SCIF4 || \
+ DEBUG_RCAR_GEN2_SCIF0 || DEBUG_RCAR_GEN2_SCIF1 || \
+ DEBUG_RCAR_GEN2_SCIF2 || DEBUG_RCAR_GEN2_SCIF4 || \
DEBUG_RMOBILE_SCIFA0 || DEBUG_RMOBILE_SCIFA1 || \
DEBUG_RMOBILE_SCIFA4 || DEBUG_S3C24XX_UART || \
DEBUG_S3C64XX_UART || \
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 1dc4045..fc26c3d 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -212,7 +212,7 @@ machine-$(CONFIG_ARCH_S3C24XX) += s3c24xx
machine-$(CONFIG_ARCH_S3C64XX) += s3c64xx
machine-$(CONFIG_ARCH_S5PV210) += s5pv210
machine-$(CONFIG_ARCH_SA1100) += sa1100
-machine-$(CONFIG_ARCH_SHMOBILE) += shmobile
+machine-$(CONFIG_ARCH_RENESAS) += shmobile
machine-$(CONFIG_ARCH_SIRF) += prima2
machine-$(CONFIG_ARCH_SOCFPGA) += socfpga
machine-$(CONFIG_ARCH_STI) += sti
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index a3c5fbc..1f5a5ff 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -25,6 +25,9 @@ endif
GCOV_PROFILE := n
+# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
+KCOV_INSTRUMENT := n
+
#
# Architecture dependencies
#
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 7e24249..37a3de7 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -75,6 +75,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += \
bcm2835-rpi-a-plus.dtb \
bcm2836-rpi-2-b.dtb \
bcm2837-rpi-3-b.dtb \
+ bcm2837-rpi-3-b-plus.dtb \
bcm2835-rpi-zero.dtb \
bcm2835-rpi-zero-w.dtb
dtb-$(CONFIG_ARCH_BCM_5301X) += \
@@ -102,8 +103,10 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
bcm47094-dlink-dir-885l.dtb \
bcm47094-linksys-panamera.dtb \
bcm47094-luxul-abr-4500.dtb \
+ bcm47094-luxul-xap-1610.dtb \
bcm47094-luxul-xbr-4500.dtb \
bcm47094-luxul-xwr-3100.dtb \
+ bcm47094-luxul-xwr-3150-v1.dtb \
bcm47094-netgear-r8500.dtb \
bcm94708.dtb \
bcm94709.dtb \
@@ -140,6 +143,7 @@ dtb-$(CONFIG_ARCH_BCM_NSP) += \
dtb-$(CONFIG_ARCH_BERLIN) += \
berlin2-sony-nsz-gs7.dtb \
berlin2cd-google-chromecast.dtb \
+ berlin2cd-valve-steamlink.dtb \
berlin2q-marvell-dmp.dtb
dtb-$(CONFIG_ARCH_BRCMSTB) += \
bcm7445-bcm97445svmb.dtb
@@ -190,8 +194,6 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
exynos5422-odroidxu3.dtb \
exynos5422-odroidxu3-lite.dtb \
exynos5422-odroidxu4.dtb \
- exynos5440-sd5v1.dtb \
- exynos5440-ssdk5440.dtb \
exynos5800-peach-pi.dtb
dtb-$(CONFIG_ARCH_GEMINI) += \
gemini-dlink-dir-685.dtb \
@@ -312,14 +314,14 @@ dtb-$(CONFIG_ARCH_NPCM7XX) += \
dtb-$(CONFIG_MACH_MESON6) += \
meson6-atv1200.dtb
dtb-$(CONFIG_MACH_MESON8) += \
- meson8-minix-neo-x8.dtb
+ meson8-minix-neo-x8.dtb \
+ meson8b-mxq.dtb \
+ meson8b-odroidc1.dtb \
+ meson8m2-mxiii-plus.dtb
dtb-$(CONFIG_ARCH_MMP) += \
pxa168-aspenite.dtb \
pxa910-dkb.dtb \
mmp2-brownstone.dtb
-dtb-$(CONFIG_MACH_MESON8B) += \
- meson8b-mxq.dtb \
- meson8b-odroidc1.dtb
dtb-$(CONFIG_ARCH_MPS2) += \
mps2-an385.dtb \
mps2-an399.dtb
@@ -399,6 +401,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6dl-hummingboard2-som-v15.dtb \
imx6dl-icore.dtb \
imx6dl-icore-rqs.dtb \
+ imx6dl-mamoj.dtb \
imx6dl-nit6xlite.dtb \
imx6dl-nitrogen6x.dtb \
imx6dl-phytec-mira-rdk-nand.dtb \
@@ -439,6 +442,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-cubox-i-emmc-som-v15.dtb \
imx6q-cubox-i-som-v15.dtb \
imx6q-dfi-fs700-m60.dtb \
+ imx6q-dhcom-pdk2.dtb \
imx6q-display5-tianma-tm070-1280x768.dtb \
imx6q-dmo-edmqmx6.dtb \
imx6q-dms-ba16.dtb \
@@ -463,9 +467,11 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6q-hummingboard2-emmc-som-v15.dtb \
imx6q-hummingboard2-som-v15.dtb \
imx6q-icore.dtb \
+ imx6q-icore-mipi.dtb \
imx6q-icore-ofcap10.dtb \
imx6q-icore-ofcap12.dtb \
imx6q-icore-rqs.dtb \
+ imx6q-kp-tpc.dtb \
imx6q-marsboard.dtb \
imx6q-mccmon6.dtb \
imx6q-nitrogen6x.dtb \
@@ -688,6 +694,7 @@ dtb-$(CONFIG_SOC_AM33XX) += \
am335x-pdu001.dtb \
am335x-pepper.dtb \
am335x-phycore-rdk.dtb \
+ am335x-pocketbeagle.dtb \
am335x-shc.dtb \
am335x-sbc-t335.dtb \
am335x-sl50.dtb \
@@ -760,12 +767,17 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-apq8084-ifc6540.dtb \
qcom-apq8084-mtp.dtb \
qcom-ipq4019-ap.dk01.1-c1.dtb \
+ qcom-ipq4019-ap.dk04.1-c1.dtb \
+ qcom-ipq4019-ap.dk04.1-c3.dtb \
+ qcom-ipq4019-ap.dk07.1-c1.dtb \
+ qcom-ipq4019-ap.dk07.1-c2.dtb \
qcom-ipq8064-ap148.dtb \
qcom-msm8660-surf.dtb \
qcom-msm8960-cdp.dtb \
qcom-msm8974-fairphone-fp2.dtb \
qcom-msm8974-lge-nexus5-hammerhead.dtb \
qcom-msm8974-samsung-klte.dtb \
+ qcom-msm8974-sony-xperia-amami.dtb \
qcom-msm8974-sony-xperia-castor.dtb \
qcom-msm8974-sony-xperia-honami.dtb \
qcom-mdm9615-wp8548-mangoh-green.dtb
@@ -795,6 +807,7 @@ dtb-$(CONFIG_ARCH_RENESAS) += \
r8a7745-iwg22d-sodimm.dtb \
r8a7745-iwg22d-sodimm-dbhd-ca.dtb \
r8a7745-sk-rzg1e.dtb \
+ r8a77470-iwg23s-sbc.dtb \
r8a7778-bockw.dtb \
r8a7779-marzen.dtb \
r8a7790-lager.dtb \
@@ -959,6 +972,7 @@ dtb-$(CONFIG_MACH_SUN7I) += \
sun7i-a20-m3.dtb \
sun7i-a20-mk808c.dtb \
sun7i-a20-olimex-som-evb.dtb \
+ sun7i-a20-olimex-som-evb-emmc.dtb \
sun7i-a20-olimex-som204-evb.dtb \
sun7i-a20-olimex-som204-evb-emmc.dtb \
sun7i-a20-olinuxino-lime.dtb \
@@ -992,8 +1006,9 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-a83t-bananapi-m3.dtb \
sun8i-a83t-cubietruck-plus.dtb \
sun8i-a83t-tbs-a711.dtb \
- sun8i-h2-plus-orangepi-r1.dtb \
sun8i-h2-plus-bananapi-m2-zero.dtb \
+ sun8i-h2-plus-libretech-all-h3-cc.dtb \
+ sun8i-h2-plus-orangepi-r1.dtb \
sun8i-h2-plus-orangepi-zero.dtb \
sun8i-h3-bananapi-m2-plus.dtb \
sun8i-h3-beelink-x2.dtb \
@@ -1010,6 +1025,8 @@ dtb-$(CONFIG_MACH_SUN8I) += \
sun8i-h3-orangepi-plus.dtb \
sun8i-h3-orangepi-plus2e.dtb \
sun8i-r16-bananapi-m2m.dtb \
+ sun8i-r16-nintendo-nes-classic.dtb \
+ sun8i-r16-nintendo-super-nes-classic.dtb \
sun8i-r16-parrot.dtb \
sun8i-r40-bananapi-m2-ultra.dtb \
sun8i-v3s-licheepi-zero.dtb \
@@ -1054,9 +1071,7 @@ dtb-$(CONFIG_ARCH_U8500) += \
ste-hrefprev60-stuib.dtb \
ste-hrefprev60-tvk.dtb \
ste-hrefv60plus-stuib.dtb \
- ste-hrefv60plus-tvk.dtb \
- ste-ccu8540.dtb \
- ste-ccu9540.dtb
+ ste-hrefv60plus-tvk.dtb
dtb-$(CONFIG_ARCH_UNIPHIER) += \
uniphier-ld4-ref.dtb \
uniphier-ld6b-ref.dtb \
@@ -1150,6 +1165,9 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += \
mt6580-evbp1.dtb \
mt6589-aquaris5.dtb \
mt6592-evb.dtb \
+ mt7623a-rfb-emmc.dtb \
+ mt7623a-rfb-nand.dtb \
+ mt7623n-rfb-emmc.dtb \
mt7623n-rfb-nand.dtb \
mt7623n-bananapi-bpi-r2.dtb \
mt8127-moose.dtb \
@@ -1158,8 +1176,11 @@ dtb-$(CONFIG_ARCH_ZX) += zx296702-ad1.dtb
dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-ast2500-evb.dtb \
aspeed-bmc-arm-centriq2400-rep.dtb \
+ aspeed-bmc-intel-s2600wf.dtb \
+ aspeed-bmc-opp-lanyang.dtb \
aspeed-bmc-opp-palmetto.dtb \
aspeed-bmc-opp-romulus.dtb \
aspeed-bmc-opp-witherspoon.dtb \
aspeed-bmc-opp-zaius.dtb \
+ aspeed-bmc-portwell-neptune.dtb \
aspeed-bmc-quanta-q71l.dtb
diff --git a/arch/arm/boot/dts/am335x-baltos-ir3220.dts b/arch/arm/boot/dts/am335x-baltos-ir3220.dts
index 46df1b2..1b215c4 100644
--- a/arch/arm/boot/dts/am335x-baltos-ir3220.dts
+++ b/arch/arm/boot/dts/am335x-baltos-ir3220.dts
@@ -85,7 +85,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&gpio0>;
- interrupts = <20 GPIO_ACTIVE_LOW>;
+ interrupts = <20 IRQ_TYPE_EDGE_RISING>;
pinctrl-names = "default";
pinctrl-0 = <&tca6416_pins>;
};
diff --git a/arch/arm/boot/dts/am335x-baltos-ir5221.dts b/arch/arm/boot/dts/am335x-baltos-ir5221.dts
index 5d56355..832ead8 100644
--- a/arch/arm/boot/dts/am335x-baltos-ir5221.dts
+++ b/arch/arm/boot/dts/am335x-baltos-ir5221.dts
@@ -94,7 +94,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&gpio0>;
- interrupts = <20 GPIO_ACTIVE_LOW>;
+ interrupts = <20 IRQ_TYPE_EDGE_RISING>;
pinctrl-names = "default";
pinctrl-0 = <&tca6416_pins>;
};
diff --git a/arch/arm/boot/dts/am335x-baltos.dtsi b/arch/arm/boot/dts/am335x-baltos.dtsi
index ec6052c..ed7a5a3 100644
--- a/arch/arm/boot/dts/am335x-baltos.dtsi
+++ b/arch/arm/boot/dts/am335x-baltos.dtsi
@@ -249,7 +249,7 @@
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&gpio1>;
- interrupts = <28 GPIO_ACTIVE_LOW>;
+ interrupts = <28 IRQ_TYPE_EDGE_RISING>;
pinctrl-names = "default";
pinctrl-0 = <&tps65910_pins>;
};
diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi
index e67b4d6..f9e8667 100644
--- a/arch/arm/boot/dts/am335x-bone-common.dtsi
+++ b/arch/arm/boot/dts/am335x-bone-common.dtsi
@@ -161,7 +161,14 @@
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
- AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* GPIO0_6 */
+ AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spio0_cs1.gpio0_6 */
+ AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+ AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+ AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+ AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+ AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+ AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+ AM33XX_IOPAD(0x9a0, PIN_INPUT | MUX_MODE4) /* mcasp0_aclkr.mmc0_sdwp */
>;
};
diff --git a/arch/arm/boot/dts/am335x-boneblue.dts b/arch/arm/boot/dts/am335x-boneblue.dts
index 58baee1..7bcd726 100644
--- a/arch/arm/boot/dts/am335x-boneblue.dts
+++ b/arch/arm/boot/dts/am335x-boneblue.dts
@@ -364,7 +364,7 @@
compatible = "invensense,mpu9250";
reg = <0x68>;
interrupt-parent = <&gpio3>;
- interrupts = <21 GPIO_ACTIVE_LOW>;
+ interrupts = <21 IRQ_TYPE_EDGE_RISING>;
i2c-gate {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index fee6b3e..1356fd6 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -303,7 +303,14 @@
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
- AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+ AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+ AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+ AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+ AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+ AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+ AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+ AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+ AM33XX_IOPAD(0x9a0, PIN_INPUT | MUX_MODE4) /* mcasp0_aclkr.mmc0_sdwp */
>;
};
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index fa608cd..0c096a7 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -137,7 +137,7 @@
};
};
- backlight {
+ lcd_bl: backlight {
compatible = "pwm-backlight";
pwms = <&ecap2 0 50000 PWM_POLARITY_INVERTED>;
brightness-levels = <0 58 61 66 75 90 125 170 255>;
@@ -172,6 +172,7 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&lcd_pins_default>;
pinctrl-1 = <&lcd_pins_sleep>;
+ backlight = <&lcd_bl>;
status = "okay";
panel-info {
ac-bias = <255>;
@@ -399,7 +400,14 @@
mmc1_pins: pinmux_mmc1_pins {
pinctrl-single,pins = <
- AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+ AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* spi0_cs1.gpio0_6 */
+ AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat0.mmc0_dat0 */
+ AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat1.mmc0_dat1 */
+ AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat2.mmc0_dat2 */
+ AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_dat3.mmc0_dat3 */
+ AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_cmd.mmc0_cmd */
+ AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc0_clk.mmc0_clk */
+ AM33XX_IOPAD(0x9a0, PIN_INPUT | MUX_MODE4) /* mcasp0_aclkr.mmc0_sdwp */
>;
};
diff --git a/arch/arm/boot/dts/am335x-osd335x-common.dtsi b/arch/arm/boot/dts/am335x-osd335x-common.dtsi
new file mode 100644
index 0000000..f8ff473
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-osd335x-common.dtsi
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author: Robert Nelson <robertcnelson@gmail.com>
+ */
+
+/ {
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&dcdc2_reg>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x20000000>; /* 512 MB */
+ };
+};
+
+&cpu0_opp_table {
+ /*
+ * Octavo Systems:
+ * The EFUSE_SMA register is not programmed for any of the AM335x wafers
+ * we get and we are not programming them during our production test.
+ * Therefore, from a DEVICE_ID revision point of view, the silicon looks
+ * like it is Revision 2.1. However, from an EFUSE_SMA point of view for
+ * the HW OPP table, the silicon looks like it is Revision 1.0 (ie the
+ * EFUSE_SMA register reads as all zeros).
+ */
+ oppnitro-1000000000 {
+ opp-supported-hw = <0x06 0x0100>;
+ };
+};
+
+&am33xx_pinmux {
+ i2c0_pins: pinmux-i2c0-pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x988, PIN_INPUT_PULLUP | MUX_MODE0) /* (C17) I2C0_SDA.I2C0_SDA */
+ AM33XX_IOPAD(0x98c, PIN_INPUT_PULLUP | MUX_MODE0) /* (C16) I2C0_SCL.I2C0_SCL */
+ >;
+ };
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+
+ status = "okay";
+ clock-frequency = <400000>;
+
+ tps: tps@24 {
+ reg = <0x24>;
+ };
+};
+
+/include/ "tps65217.dtsi"
+
+&tps {
+ interrupts = <7>; /* NMI */
+ interrupt-parent = <&intc>;
+
+ ti,pmic-shutdown-controller;
+
+ pwrbutton {
+ interrupts = <2>;
+ status = "okay";
+ };
+
+ regulators {
+ dcdc1_reg: regulator@0 {
+ regulator-name = "vdds_dpr";
+ regulator-always-on;
+ };
+
+ dcdc2_reg: regulator@1 {
+ /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */
+ regulator-name = "vdd_mpu";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1351500>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ dcdc3_reg: regulator@2 {
+ /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */
+ regulator-name = "vdd_core";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1_reg: regulator@3 {
+ regulator-name = "vio,vrtc,vdds";
+ regulator-always-on;
+ };
+
+ ldo2_reg: regulator@4 {
+ regulator-name = "vdd_3v3aux";
+ regulator-always-on;
+ };
+
+ ldo3_reg: regulator@5 {
+ regulator-name = "vdd_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ ldo4_reg: regulator@6 {
+ regulator-name = "vdd_3v3a";
+ regulator-always-on;
+ };
+ };
+};
+
+&aes {
+ status = "okay";
+};
+
+&sham {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/am335x-pocketbeagle.dts b/arch/arm/boot/dts/am335x-pocketbeagle.dts
new file mode 100644
index 0000000..62fe5ca
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-pocketbeagle.dts
@@ -0,0 +1,237 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Author: Robert Nelson <robertcnelson@gmail.com>
+ */
+/dts-v1/;
+
+#include "am33xx.dtsi"
+#include "am335x-osd335x-common.dtsi"
+
+/ {
+ model = "TI AM335x PocketBeagle";
+ compatible = "ti,am335x-pocketbeagle", "ti,am335x-bone", "ti,am33xx";
+
+ chosen {
+ stdout-path = &uart0;
+ };
+
+ leds {
+ pinctrl-names = "default";
+ pinctrl-0 = <&usr_leds_pins>;
+
+ compatible = "gpio-leds";
+
+ usr0 {
+ label = "beaglebone:green:usr0";
+ gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ default-state = "off";
+ };
+
+ usr1 {
+ label = "beaglebone:green:usr1";
+ gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "mmc0";
+ default-state = "off";
+ };
+
+ usr2 {
+ label = "beaglebone:green:usr2";
+ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "cpu0";
+ default-state = "off";
+ };
+
+ usr3 {
+ label = "beaglebone:green:usr3";
+ gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
+ vmmcsd_fixed: fixedregulator0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vmmcsd_fixed";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&am33xx_pinmux {
+ i2c2_pins: pinmux-i2c2-pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x97c, PIN_INPUT_PULLUP | MUX_MODE3) /* (D17) uart1_rtsn.I2C2_SCL */
+ AM33XX_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE3) /* (D18) uart1_ctsn.I2C2_SDA */
+ >;
+ };
+
+ ehrpwm0_pins: pinmux-ehrpwm0-pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x990, PIN_OUTPUT_PULLDOWN | MUX_MODE1) /* (A13) mcasp0_aclkx.ehrpwm0A */
+ >;
+ };
+
+ ehrpwm1_pins: pinmux-ehrpwm1-pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x848, PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* (U14) gpmc_a2.ehrpwm1A */
+ >;
+ };
+
+ mmc0_pins: pinmux-mmc0-pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x960, PIN_INPUT | MUX_MODE7) /* (C15) spi0_cs1.gpio0[6] */
+ AM33XX_IOPAD(0x8fc, PIN_INPUT_PULLUP | MUX_MODE0) /* (G16) mmc0_dat0.mmc0_dat0 */
+ AM33XX_IOPAD(0x8f8, PIN_INPUT_PULLUP | MUX_MODE0) /* (G15) mmc0_dat1.mmc0_dat1 */
+ AM33XX_IOPAD(0x8f4, PIN_INPUT_PULLUP | MUX_MODE0) /* (F18) mmc0_dat2.mmc0_dat2 */
+ AM33XX_IOPAD(0x8f0, PIN_INPUT_PULLUP | MUX_MODE0) /* (F17) mmc0_dat3.mmc0_dat3 */
+ AM33XX_IOPAD(0x904, PIN_INPUT_PULLUP | MUX_MODE0) /* (G18) mmc0_cmd.mmc0_cmd */
+ AM33XX_IOPAD(0x900, PIN_INPUT_PULLUP | MUX_MODE0) /* (G17) mmc0_clk.mmc0_clk */
+ AM33XX_IOPAD(0x9a0, PIN_INPUT | MUX_MODE4) /* (B12) mcasp0_aclkr.mmc0_sdwp */
+ >;
+ };
+
+ spi0_pins: pinmux-spi0-pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x950, PIN_INPUT_PULLUP | MUX_MODE0) /* (A17) spi0_sclk.spi0_sclk */
+ AM33XX_IOPAD(0x954, PIN_INPUT_PULLUP | MUX_MODE0) /* (B17) spi0_d0.spi0_d0 */
+ AM33XX_IOPAD(0x958, PIN_INPUT_PULLUP | MUX_MODE0) /* (B16) spi0_d1.spi0_d1 */
+ AM33XX_IOPAD(0x95c, PIN_INPUT_PULLUP | MUX_MODE0) /* (A16) spi0_cs0.spi0_cs0 */
+ >;
+ };
+
+ spi1_pins: pinmux-spi1-pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x964, PIN_INPUT_PULLUP | MUX_MODE4) /* (C18) eCAP0_in_PWM0_out.spi1_sclk */
+ AM33XX_IOPAD(0x968, PIN_INPUT_PULLUP | MUX_MODE4) /* (E18) uart0_ctsn.spi1_d0 */
+ AM33XX_IOPAD(0x96c, PIN_INPUT_PULLUP | MUX_MODE4) /* (E17) uart0_rtsn.spi1_d1 */
+ AM33XX_IOPAD(0x9b0, PIN_INPUT_PULLUP | MUX_MODE4) /* (A15) xdma_event_intr0.spi1_cs1 */
+ >;
+ };
+
+ usr_leds_pins: pinmux-usr-leds-pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x854, PIN_OUTPUT | MUX_MODE7) /* (V15) gpmc_a5.gpio1[21] - USR_LED_0 */
+ AM33XX_IOPAD(0x858, PIN_OUTPUT | MUX_MODE7) /* (U15) gpmc_a6.gpio1[22] - USR_LED_1 */
+ AM33XX_IOPAD(0x85c, PIN_OUTPUT | MUX_MODE7) /* (T15) gpmc_a7.gpio1[23] - USR_LED_2 */
+ AM33XX_IOPAD(0x860, PIN_OUTPUT | MUX_MODE7) /* (V16) gpmc_a8.gpio1[24] - USR_LED_3 */
+ >;
+ };
+
+ uart0_pins: pinmux-uart0-pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0) /* (E15) uart0_rxd.uart0_rxd */
+ AM33XX_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* (E16) uart0_txd.uart0_txd */
+ >;
+ };
+
+ uart4_pins: pinmux-uart4-pins {
+ pinctrl-single,pins = <
+ AM33XX_IOPAD(0x870, PIN_INPUT_PULLUP | MUX_MODE6) /* (T17) gpmc_wait0.uart4_rxd */
+ AM33XX_IOPAD(0x874, PIN_OUTPUT_PULLDOWN | MUX_MODE6) /* (U17) gpmc_wpn.uart4_txd */
+ >;
+ };
+};
+
+&epwmss0 {
+ status = "okay";
+};
+
+&ehrpwm0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&ehrpwm0_pins>;
+};
+
+&epwmss1 {
+ status = "okay";
+};
+
+&ehrpwm1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&ehrpwm1_pins>;
+};
+
+&i2c0 {
+ eeprom: eeprom@50 {
+ compatible = "atmel,24c256";
+ reg = <0x50>;
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins>;
+
+ status = "okay";
+ clock-frequency = <400000>;
+};
+
+&mmc1 {
+ status = "okay";
+ vmmc-supply = <&vmmcsd_fixed>;
+ bus-width = <4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>;
+ cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
+};
+
+&rtc {
+ system-power-controller;
+};
+
+&tscadc {
+ status = "okay";
+ adc {
+ ti,adc-channels = <0 1 2 3 4 5 6 7>;
+ ti,chan-step-avg = <16 16 16 16 16 16 16 16>;
+ ti,chan-step-opendelay = <0x98 0x98 0x98 0x98 0x98 0x98 0x98 0x98>;
+ ti,chan-step-sampledelay = <0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0>;
+ };
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
+
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart4_pins>;
+
+ status = "okay";
+};
+
+&usb {
+ status = "okay";
+};
+
+&usb_ctrl_mod {
+ status = "okay";
+};
+
+&usb0_phy {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+ dr_mode = "otg";
+};
+
+&usb1_phy {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+ dr_mode = "host";
+};
+
+&cppi41dma {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/am3517-evm.dts b/arch/arm/boot/dts/am3517-evm.dts
index 0e4a125..98aadb0 100644
--- a/arch/arm/boot/dts/am3517-evm.dts
+++ b/arch/arm/boot/dts/am3517-evm.dts
@@ -8,11 +8,17 @@
/dts-v1/;
#include "am3517.dtsi"
+#include "am3517-som.dtsi"
+#include <dt-bindings/input/input.h>
/ {
model = "TI AM3517 EVM (AM3517/05 TMDSEVM3517)";
compatible = "ti,am3517-evm", "ti,am3517", "ti,omap3";
+ aliases {
+ display0 = &lcd0;
+ };
+
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 256 MB */
@@ -24,6 +30,144 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
+
+ gpio-keys {
+ compatible = "gpio-keys-polled";
+ poll-interval = <100>;
+
+ user_pb {
+ label = "User Push Button";
+ linux,code = <BTN_0>;
+ gpios = <&tca6416 5 GPIO_ACTIVE_LOW>;
+ };
+
+ user_sw_1 {
+ label = "User Switch 1";
+ linux,code = <BTN_1>;
+ gpios = <&tca6416 8 GPIO_ACTIVE_LOW>;
+ };
+
+ user_sw_2 {
+ label = "User Switch 2";
+ linux,code = <BTN_2>;
+ gpios = <&tca6416 9 GPIO_ACTIVE_LOW>;
+ };
+
+ user_sw_3 {
+ label = "User Switch 3";
+ linux,code = <BTN_3>;
+ gpios = <&tca6416 10 GPIO_ACTIVE_LOW>;
+ };
+
+ user_sw_4 {
+ label = "User Switch 4";
+ linux,code = <BTN_4>;
+ gpios = <&tca6416 11 GPIO_ACTIVE_LOW>;
+ };
+
+ user_sw_5 {
+ label = "User Switch 5";
+ linux,code = <BTN_5>;
+ gpios = <&tca6416 12 GPIO_ACTIVE_LOW>;
+ };
+
+ user_sw_6 {
+ label = "User Switch 6";
+ linux,code = <BTN_6>;
+ gpios = <&tca6416 13 GPIO_ACTIVE_LOW>;
+ };
+
+ user_sw_7 {
+ label = "User Switch 7";
+ linux,code = <BTN_7>;
+ gpios = <&tca6416 14 GPIO_ACTIVE_LOW>;
+ };
+
+ user_sw_8 {
+ label = "User Switch 8";
+ linux,code = <BTN_8>;
+ gpios = <&tca6416 15 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ gpio-leds {
+ compatible = "gpio-leds";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&leds_pins>;
+
+ user_led_1 {
+ label = "am3517evm:green:user_led_1";
+ gpios = <&tca6416 7 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ };
+
+ user_led_2 {
+ label = "am3517evm:green:user_led_2";
+ gpios = <&tca6416 6 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ };
+
+ user_led_3 {
+ label = "am3517evm:green:user_led_3";
+ gpios = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "mmc0"; /* SD/MMC card activity */
+ };
+
+ user_led_4 {
+ label = "am3517evm:green:user_led_4";
+ gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ lcd0: display@0 {
+ compatible = "panel-dpi";
+ label = "15";
+ status = "okay";
+ pinctrl-names = "default";
+ enable-gpios = <&gpio6 16 GPIO_ACTIVE_HIGH>; /* gpio176, lcd INI */
+
+ port {
+ lcd_in: endpoint {
+ remote-endpoint = <&dpi_out>;
+ };
+ };
+
+ panel-timing {
+ clock-frequency = <9000000>;
+ hactive = <480>;
+ vactive = <272>;
+ hfront-porch = <3>;
+ hback-porch = <2>;
+ hsync-len = <42>;
+ vback-porch = <3>;
+ vfront-porch = <4>;
+ vsync-len = <11>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+ };
+
+ bl: backlight {
+ compatible = "pwm-backlight";
+ pinctrl-names = "default";
+ pinctrl-0 = <&backlight_pins>;
+ pwms = <&pwm11 0 5000000 0>;
+ brightness-levels = <0 10 20 30 40 50 60 70 80 90 100>;
+ default-brightness-level = <7>;
+ enable-gpios = <&gpio6 22 GPIO_ACTIVE_HIGH>; /* gpio_182 */
+ };
+
+ pwm11: dmtimer-pwm@11 {
+ compatible = "ti,omap-dmtimer-pwm";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_pins>;
+ ti,timers = <&timer11>;
+ #pwm-cells = <3>;
+ };
};
&davinci_emac {
@@ -34,12 +178,32 @@
status = "okay";
};
-&i2c1 {
- clock-frequency = <400000>;
+&dss {
+ status = "ok";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&dss_dpi_pins>;
+
+ vdds_dsi-supply = <&vdd_io_reg>;
+ vdda_video-supply = <&vdd_io_reg>;
+
+ port {
+ dpi_out: endpoint {
+ remote-endpoint = <&lcd_in>;
+ data-lines = <16>;
+ };
+ };
};
&i2c2 {
clock-frequency = <400000>;
+ /* User DIP swithes [1:8] / User LEDS [1:2] */
+ tca6416: gpio@21 {
+ compatible = "ti,tca6416";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
};
&i2c3 {
@@ -47,8 +211,13 @@
};
&mmc1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pins>;
vmmc-supply = <&vmmc_fixed>;
bus-width = <4>;
+ wp-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>; /* gpio_126 */
+ cd-gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>; /* gpio_127 */
};
&mmc2 {
@@ -59,3 +228,63 @@
status = "disabled";
};
+&omap3_pmx_core {
+
+ leds_pins: pinmux_leds_pins {
+ pinctrl-single,pins = <
+ OMAP3_WKUP_IOPAD(0x2a24, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu0.gpio_11 */
+ OMAP3_WKUP_IOPAD(0x2a26, PIN_OUTPUT_PULLUP | MUX_MODE4) /* jtag_emu1.gpio_31 */
+ >;
+ };
+
+ mmc1_pins: pinmux_mmc1_pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x2144, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_clk.sdmmc1_clk */
+ OMAP3_CORE1_IOPAD(0x2146, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_cmd.sdmmc1_cmd */
+ OMAP3_CORE1_IOPAD(0x2148, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat0.sdmmc1_dat0 */
+ OMAP3_CORE1_IOPAD(0x214a, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat1.sdmmc1_dat1 */
+ OMAP3_CORE1_IOPAD(0x214c, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat2.sdmmc1_dat2 */
+ OMAP3_CORE1_IOPAD(0x214e, PIN_INPUT_PULLUP | MUX_MODE0) /* sdmmc1_dat3.sdmmc1_dat3 */
+ OMAP3_CORE1_IOPAD(0x2150, PIN_INPUT_PULLUP | MUX_MODE4) /* sdmmc1_dat4.gpio_126 */
+ OMAP3_CORE1_IOPAD(0x2152, PIN_INPUT_PULLUP | MUX_MODE4) /* sdmmc1_dat5.gpio_127 */
+ >;
+ };
+
+ pwm_pins: pinmux_pwm_pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x21dc, PIN_OUTPUT | MUX_MODE1) /* mcspi2_cs0.gpt11_pwm */
+ >;
+ };
+
+ backlight_pins: pinmux_backlight_pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x21de, PIN_OUTPUT | MUX_MODE4) /* mcspi2_cs1.gpio_182 */
+ >;
+ };
+
+ dss_dpi_pins: pinmux_dss_dpi_pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x21d2, PIN_OUTPUT | MUX_MODE4) /* mcspi1_cs2.gpio_176 */
+ OMAP3_CORE1_IOPAD(0x20d4, PIN_OUTPUT | MUX_MODE0) /* dss_pclk.dss_pclk */
+ OMAP3_CORE1_IOPAD(0x20d6, PIN_OUTPUT | MUX_MODE0) /* dss_hsync.dss_hsync */
+ OMAP3_CORE1_IOPAD(0x20d8, PIN_OUTPUT | MUX_MODE0) /* dss_vsync.dss_vsync */
+ OMAP3_CORE1_IOPAD(0x20da, PIN_OUTPUT | MUX_MODE0) /* dss_acbias.dss_acbias */
+ OMAP3_CORE1_IOPAD(0x20dc, PIN_OUTPUT | MUX_MODE0) /* dss_data0.dss_data0 */
+ OMAP3_CORE1_IOPAD(0x20de, PIN_OUTPUT | MUX_MODE0) /* dss_data1.dss_data1 */
+ OMAP3_CORE1_IOPAD(0x20e0, PIN_OUTPUT | MUX_MODE0) /* dss_data2.dss_data2 */
+ OMAP3_CORE1_IOPAD(0x20e2, PIN_OUTPUT | MUX_MODE0) /* dss_data3.dss_data3 */
+ OMAP3_CORE1_IOPAD(0x20e4, PIN_OUTPUT | MUX_MODE0) /* dss_data4.dss_data4 */
+ OMAP3_CORE1_IOPAD(0x20e6, PIN_OUTPUT | MUX_MODE0) /* dss_data5.dss_data5 */
+ OMAP3_CORE1_IOPAD(0x20e8, PIN_OUTPUT | MUX_MODE0) /* dss_data6.dss_data6 */
+ OMAP3_CORE1_IOPAD(0x20ea, PIN_OUTPUT | MUX_MODE0) /* dss_data7.dss_data7 */
+ OMAP3_CORE1_IOPAD(0x20ec, PIN_OUTPUT | MUX_MODE0) /* dss_data8.dss_data8 */
+ OMAP3_CORE1_IOPAD(0x20ee, PIN_OUTPUT | MUX_MODE0) /* dss_data9.dss_data9 */
+ OMAP3_CORE1_IOPAD(0x20f0, PIN_OUTPUT | MUX_MODE0) /* dss_data10.dss_data10 */
+ OMAP3_CORE1_IOPAD(0x20f2, PIN_OUTPUT | MUX_MODE0) /* dss_data11.dss_data11 */
+ OMAP3_CORE1_IOPAD(0x20f4, PIN_OUTPUT | MUX_MODE0) /* dss_data12.dss_data12 */
+ OMAP3_CORE1_IOPAD(0x20f6, PIN_OUTPUT | MUX_MODE0) /* dss_data13.dss_data13 */
+ OMAP3_CORE1_IOPAD(0x20f8, PIN_OUTPUT | MUX_MODE0) /* dss_data14.dss_data14 */
+ OMAP3_CORE1_IOPAD(0x20fa, PIN_OUTPUT | MUX_MODE0) /* dss_data15.dss_data15 */
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/am3517-som.dtsi b/arch/arm/boot/dts/am3517-som.dtsi
new file mode 100644
index 0000000..a6d5ff7
--- /dev/null
+++ b/arch/arm/boot/dts/am3517-som.dtsi
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 Derald D. Woods <woods.technical@gmail.com>
+ *
+ * Based on am3517-evm.dts
+ *
+ * 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.
+ */
+
+/ {
+ cpus {
+ cpu@0 {
+ cpu0-supply = <&vdd_core_reg>;
+ };
+ };
+};
+
+&gpmc {
+ ranges = <0 0 0x30000000 0x1000000>; /* CS0: 16MB for NAND */
+
+ nand@0,0 {
+ compatible = "ti,omap2-nand";
+ linux,mtd-name = "micron,mt29f4g16abchch";
+ reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
+ nand-bus-width = <16>;
+ ti,nand-ecc-opt = "bch8";
+ gpmc,sync-clk-ps = <0>;
+ gpmc,cs-on-ns = <0>;
+ gpmc,cs-rd-off-ns = <44>;
+ gpmc,cs-wr-off-ns = <44>;
+ gpmc,adv-on-ns = <6>;
+ gpmc,adv-rd-off-ns = <34>;
+ gpmc,adv-wr-off-ns = <44>;
+ gpmc,we-off-ns = <40>;
+ gpmc,oe-off-ns = <54>;
+ gpmc,access-ns = <64>;
+ gpmc,rd-cycle-ns = <82>;
+ gpmc,wr-cycle-ns = <82>;
+ gpmc,wr-access-ns = <40>;
+ gpmc,wr-data-mux-bus-ns = <0>;
+ gpmc,device-width = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+
+ s35390a: s35390a@30 {
+ compatible = "sii,s35390a";
+ reg = <0x30>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&rtc_pins>;
+ interrupts-extended = <&gpio2 23 IRQ_TYPE_EDGE_FALLING>; /* gpio_55 */
+ };
+
+ tps: tps65023@48 {
+ compatible = "ti,tps65023";
+ reg = <0x48>;
+
+ regulators {
+ vdd_core_reg: VDCDC1 {
+ regulator-name = "vdd_core";
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vdd_io_reg: VDCDC2 {
+ regulator-name = "vdd_io";
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vdd_1v8_reg: VDCDC3 {
+ regulator-name = "vdd_1v8";
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vdd_usb18_reg: LDO1 {
+ regulator-name = "vdd_usb18";
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vdd_usb33_reg: LDO2 {
+ regulator-name = "vdd_usb33";
+ compatible = "regulator-fixed";
+ regulator-always-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
+
+ touchscreen: tsc2004@4b {
+ compatible = "ti,tsc2004";
+ reg = <0x4b>;
+
+ vio-supply = <&vdd_io_reg>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsc2004_pins>;
+ interrupts-extended = <&gpio3 1 IRQ_TYPE_EDGE_RISING>; /* gpio_65 */
+
+ touchscreen-fuzz-x = <4>;
+ touchscreen-fuzz-y = <7>;
+ touchscreen-fuzz-pressure = <2>;
+ touchscreen-size-x = <480>;
+ touchscreen-size-y = <272>;
+ touchscreen-max-pressure = <2048>;
+
+ ti,x-plate-ohms = <280>;
+ ti,esd-recovery-timeout-ms = <8000>;
+ };
+};
+
+&omap3_pmx_core {
+
+ rtc_pins: pinmux_rtc_pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x20b6, PIN_INPUT_PULLUP | MUX_MODE4) /* gpmc_ncs4.gpio_55 */
+ >;
+ };
+
+ tsc2004_pins: pinmux_tsc2004_pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x20d2, PIN_INPUT | MUX_MODE4) /* gpmc_wait3.gpio_65 */
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/am437x-cm-t43.dts b/arch/arm/boot/dts/am437x-cm-t43.dts
index 3b9a94c..bff5abe 100644
--- a/arch/arm/boot/dts/am437x-cm-t43.dts
+++ b/arch/arm/boot/dts/am437x-cm-t43.dts
@@ -203,7 +203,7 @@
tps65218: tps65218@24 {
compatible = "ti,tps65218";
reg = <0x24>;
- interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* NMIn */
interrupt-parent = <&gic>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts
index 8fe95cd..60414b1 100644
--- a/arch/arm/boot/dts/am437x-gp-evm.dts
+++ b/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -543,7 +543,7 @@
tps65218: tps65218@24 {
reg = <0x24>;
compatible = "ti,tps65218";
- interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* NMIn */
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts
index 4118802..440351a 100644
--- a/arch/arm/boot/dts/am437x-sk-evm.dts
+++ b/arch/arm/boot/dts/am437x-sk-evm.dts
@@ -15,6 +15,7 @@
#include <dt-bindings/pwm/pwm.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
+#include <dt-bindings/interrupt-controller/irq.h>
/ {
model = "TI AM437x SK EVM";
@@ -158,6 +159,22 @@
};
};
};
+
+ vmmcwl_fixed: fixedregulator-mmcwl {
+ /*
+ * WL_EN is not SDIO standard compliant. It is an out of band
+ * signal and hard to be dealt with in a standard way by the
+ * SDIO core driver.
+ * So modelling the WL_EN line as a regulator was a natural
+ * choice as the MMC core already deals with MMC supplies.
+ */
+ compatible = "regulator-fixed";
+ regulator-name = "vmmcwl_fixed";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&gpio4 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
};
&am43xx_pinmux {
@@ -418,6 +435,62 @@
AM4372_IOPAD(0xac4, PIN_OUTPUT | MUX_MODE0) /* usb0_drvvbus.usb0_drvvbus */
>;
};
+
+ mmc3_pins_default: pinmux_mmc3_pins_default {
+ pinctrl-single,pins = <
+ AM4372_IOPAD(0x9f0, PIN_INPUT_PULLUP | MUX_MODE3) /* (AD21) cam1_data2.mmc2_clk */
+ AM4372_IOPAD(0x9f4, PIN_INPUT_PULLUP | MUX_MODE3) /* (AE22) cam1_data3.mmc2_cmd */
+ AM4372_IOPAD(0x9f8, PIN_INPUT_PULLUP | MUX_MODE3) /* (AD22) cam1_data4.mmc2_dat0 */
+ AM4372_IOPAD(0x9fc, PIN_INPUT_PULLUP | MUX_MODE3) /* (AE23) cam1_data5.mmc2_dat1 */
+ AM4372_IOPAD(0xa00, PIN_INPUT_PULLUP | MUX_MODE3) /* (AD23) cam1_data6.mmc2_dat2 */
+ AM4372_IOPAD(0xa04, PIN_INPUT_PULLUP | MUX_MODE3) /* (AE24) cam1_data7.mmc2_dat3 */
+ >;
+ };
+
+ mmc3_pins_sleep: pinmux_mmc3_pins_sleep {
+ pinctrl-single,pins = <
+ AM4372_IOPAD(0x9f0, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (AD21) cam1_data2.mmc2_clk */
+ AM4372_IOPAD(0x9f4, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (AE22) cam1_data3.mmc2_cmd */
+ AM4372_IOPAD(0x9f8, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (AD22) cam1_data4.mmc2_dat0 */
+ AM4372_IOPAD(0x9fc, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (AE23) cam1_data5.mmc2_dat1 */
+ AM4372_IOPAD(0xa00, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (AD23) cam1_data6.mmc2_dat2 */
+ AM4372_IOPAD(0xa04, PIN_INPUT_PULLDOWN | MUX_MODE7) /* (AE24) cam1_data7.mmc2_dat3 */
+ >;
+ };
+
+ wlan_pins_default: pinmux_wlan_pins_default {
+ pinctrl-single,pins = <
+ AM4372_IOPAD(0x9d0, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* cam1_data8.gpio4_8 WL_EN */
+ AM4372_IOPAD(0x9e4, PIN_INPUT | WAKEUP_ENABLE | MUX_MODE7) /* cam1_wen.gpio4_13 WL_IRQ */
+ >;
+ };
+
+ wlan_pins_sleep: pinmux_wlan_pins_sleep {
+ pinctrl-single,pins = <
+ AM4372_IOPAD(0x9d0, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* cam1_data8.gpio4_8 WL_EN */
+ AM4372_IOPAD(0x9e4, PIN_INPUT | WAKEUP_ENABLE | MUX_MODE7) /* cam1_wen.gpio4_13 WL_IRQ */
+ >;
+ };
+
+ uart1_bt_pins_default: pinmux_uart1_bt_pins_default {
+ pinctrl-single,pins = <
+ AM4372_IOPAD(0x980, PIN_INPUT | MUX_MODE0) /* uart1_rxd.uart1_rxd */
+ AM4372_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_txd.uart1_txd */
+ AM4372_IOPAD(0x978, PIN_INPUT_PULLUP | MUX_MODE0) /* uart1_ctsn.uart1_ctsn */
+ AM4372_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart1_rtsn.uart1_rtsn */
+ AM4372_IOPAD(0x9cc, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* cam1_data9.gpio4_7 BT_EN */
+ >;
+ };
+
+ uart1_bt_pins_sleep: pinmux_uart1_bt_pins_sleep {
+ pinctrl-single,pins = <
+ AM4372_IOPAD(0x980, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart1_rxd.uart1_rxd */
+ AM4372_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart1_txd.uart1_txd */
+ AM4372_IOPAD(0x978, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart1_ctsn.uart1_ctsn */
+ AM4372_IOPAD(0x97c, PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* uart1_rtsn.uart1_rtsn */
+ AM4372_IOPAD(0x9cc, PIN_OUTPUT_PULLUP | MUX_MODE7) /* cam1_data9.gpio4_7 BT_EN */
+ >;
+ };
};
&i2c0 {
@@ -581,6 +654,10 @@
status = "okay";
};
+&gpio4 {
+ status = "okay";
+};
+
&gpio5 {
status = "okay";
};
@@ -595,6 +672,44 @@
cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
};
+&uart1 {
+ status = "okay";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&uart1_bt_pins_default>;
+ pinctrl-1 = <&uart1_bt_pins_sleep>;
+};
+
+&mmc3 {
+ status = "okay";
+ /*
+ * these are on the crossbar and are outlined in the
+ * xbar-event-map element
+ */
+ dmas = <&edma_xbar 30 0 1>,
+ <&edma_xbar 31 0 2>;
+ dma-names = "tx", "rx";
+ vmmc-supply = <&vmmcwl_fixed>;
+ bus-width = <4>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&mmc3_pins_default>;
+ pinctrl-1 = <&mmc3_pins_sleep>;
+ cap-power-off-card;
+ keep-power-in-suspend;
+ ti,non-removable;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ wlcore: wlcore@2 {
+ compatible = "ti,wl1835";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&wlan_pins_default>;
+ pinctrl-1 = <&wlan_pins_sleep>;
+ reg = <2>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
+ };
+};
+
&usb2_phy1 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index a669418..6502d33 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -595,7 +595,7 @@
tps65218: tps65218@24 {
reg = <0x24>;
compatible = "ti,tps65218";
- interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* NMIn */
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; /* NMIn */
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arm/boot/dts/am571x-idk.dts b/arch/arm/boot/dts/am571x-idk.dts
index a255514..5bb9d68 100644
--- a/arch/arm/boot/dts/am571x-idk.dts
+++ b/arch/arm/boot/dts/am571x-idk.dts
@@ -10,6 +10,7 @@
#include "dra72x.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include "dra7-mmc-iodelay.dtsi"
#include "dra72x-mmc-iodelay.dtsi"
#include "am57xx-idk-common.dtsi"
@@ -102,7 +103,7 @@
&mmc1 {
pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
- pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-0 = <&mmc1_pins_default_no_clk_pu>;
pinctrl-1 = <&mmc1_pins_hs>;
pinctrl-2 = <&mmc1_pins_sdr12>;
pinctrl-3 = <&mmc1_pins_sdr25>;
@@ -112,7 +113,7 @@
};
&mmc2 {
- pinctrl-names = "default", "hs", "ddr_1_8v";
+ pinctrl-names = "default", "hs", "ddr_3_3v";
pinctrl-0 = <&mmc2_pins_default>;
pinctrl-1 = <&mmc2_pins_hs>;
pinctrl-2 = <&mmc2_pins_ddr_rev20 &mmc2_iodelay_ddr_conf>;
diff --git a/arch/arm/boot/dts/am572x-idk.dts b/arch/arm/boot/dts/am572x-idk.dts
index 3a02ed7..3ef9111 100644
--- a/arch/arm/boot/dts/am572x-idk.dts
+++ b/arch/arm/boot/dts/am572x-idk.dts
@@ -9,6 +9,7 @@
/dts-v1/;
#include "dra74x.dtsi"
+#include "dra7-mmc-iodelay.dtsi"
#include "dra74x-mmc-iodelay.dtsi"
#include "am572x-idk-common.dtsi"
@@ -20,7 +21,7 @@
&mmc1 {
pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
- pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-0 = <&mmc1_pins_default_no_clk_pu>;
pinctrl-1 = <&mmc1_pins_hs>;
pinctrl-2 = <&mmc1_pins_sdr12>;
pinctrl-3 = <&mmc1_pins_sdr25>;
@@ -30,7 +31,7 @@
};
&mmc2 {
- pinctrl-names = "default", "hs", "ddr_1_8v";
+ pinctrl-names = "default", "hs", "ddr_3_3v";
pinctrl-0 = <&mmc2_pins_default>;
pinctrl-1 = <&mmc2_pins_hs>;
pinctrl-2 = <&mmc2_pins_ddr_rev20>;
diff --git a/arch/arm/boot/dts/am574x-idk.dts b/arch/arm/boot/dts/am574x-idk.dts
index 41e12a3..378dfa7 100644
--- a/arch/arm/boot/dts/am574x-idk.dts
+++ b/arch/arm/boot/dts/am574x-idk.dts
@@ -7,6 +7,8 @@
/dts-v1/;
#include "dra76x.dtsi"
+#include "dra7-mmc-iodelay.dtsi"
+#include "dra76x-mmc-iodelay.dtsi"
#include "am572x-idk-common.dtsi"
/ {
@@ -20,3 +22,21 @@
spi-max-frequency = <96000000>;
};
};
+
+&mmc1 {
+ pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
+ pinctrl-0 = <&mmc1_pins_default_no_clk_pu>;
+ pinctrl-1 = <&mmc1_pins_hs>;
+ pinctrl-2 = <&mmc1_pins_default>;
+ pinctrl-3 = <&mmc1_pins_hs>;
+ pinctrl-4 = <&mmc1_pins_sdr50>;
+ pinctrl-5 = <&mmc1_pins_ddr50 &mmc1_iodelay_ddr_conf>;
+ pinctrl-6 = <&mmc1_pins_ddr50 &mmc1_iodelay_sdr104_conf>;
+};
+
+&mmc2 {
+ pinctrl-names = "default", "hs", "ddr_3_3v";
+ pinctrl-0 = <&mmc2_pins_default>;
+ pinctrl-1 = <&mmc2_pins_default>;
+ pinctrl-2 = <&mmc2_pins_default>;
+};
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
index 6204a26..ad95311 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
+++ b/arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
@@ -444,8 +444,8 @@
vmmc-supply = <&vdd_3v3>;
vqmmc-supply = <&vdd_3v3>;
bus-width = <8>;
- ti,non-removable;
- cap-mmc-dual-data-rate;
+ non-removable;
+ no-1-8-v;
};
&sata {
diff --git a/arch/arm/boot/dts/am57xx-beagle-x15.dts b/arch/arm/boot/dts/am57xx-beagle-x15.dts
index d668910..70a71c6 100644
--- a/arch/arm/boot/dts/am57xx-beagle-x15.dts
+++ b/arch/arm/boot/dts/am57xx-beagle-x15.dts
@@ -25,10 +25,11 @@
pinctrl-1 = <&mmc1_pins_hs>;
vmmc-supply = <&ldo1_reg>;
+ no-1-8-v;
};
&mmc2 {
- pinctrl-names = "default", "hs", "ddr_1_8v";
+ pinctrl-names = "default", "hs", "ddr_3_3v";
pinctrl-0 = <&mmc2_pins_default>;
pinctrl-1 = <&mmc2_pins_hs>;
pinctrl-2 = <&mmc2_pins_ddr_3_3v_rev11 &mmc2_iodelay_ddr_3_3v_rev11_conf>;
diff --git a/arch/arm/boot/dts/am57xx-idk-common.dtsi b/arch/arm/boot/dts/am57xx-idk-common.dtsi
index 43cdf52..ad87f1a 100644
--- a/arch/arm/boot/dts/am57xx-idk-common.dtsi
+++ b/arch/arm/boot/dts/am57xx-idk-common.dtsi
@@ -115,17 +115,6 @@
DRA7XX_CORE_IOPAD(0x37d4, MUX_MODE15 | PULL_UP) /* dcan1_rx.off */
>;
};
-
- mmc1_pins_default: mmc1_pins_default {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mmc1_clk.clk */
- DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
- DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
- DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
- DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
- DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
- >;
- };
};
&i2c1 {
@@ -423,8 +412,9 @@
vmmc-supply = <&v3_3d>;
vqmmc-supply = <&v3_3d>;
bus-width = <8>;
- ti,non-removable;
+ non-removable;
max-frequency = <96000000>;
+ no-1-8-v;
};
&dcan1 {
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts
index afe4609..77261a2 100644
--- a/arch/arm/boot/dts/armada-370-db.dts
+++ b/arch/arm/boot/dts/armada-370-db.dts
@@ -105,33 +105,6 @@
usb@51000 {
status = "okay";
};
-
- nand@d0000 {
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "U-Boot";
- reg = <0 0x800000>;
- };
- partition@800000 {
- label = "Linux";
- reg = <0x800000 0x800000>;
- };
- partition@1000000 {
- label = "Filesystem";
- reg = <0x1000000 0x3f000000>;
- };
- };
- };
};
};
@@ -239,3 +212,33 @@
};
};
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0 0x800000>;
+ };
+ partition@800000 {
+ label = "Linux";
+ reg = <0x800000 0x800000>;
+ };
+ partition@1000000 {
+ label = "Filesystem";
+ reg = <0x1000000 0x3f000000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-370-dlink-dns327l.dts b/arch/arm/boot/dts/armada-370-dlink-dns327l.dts
index 8e46f63..baa459d 100644
--- a/arch/arm/boot/dts/armada-370-dlink-dns327l.dts
+++ b/arch/arm/boot/dts/armada-370-dlink-dns327l.dts
@@ -44,61 +44,6 @@
usb@50000 {
status = "okay";
};
-
- nand@d0000 {
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
-
- partition@0 {
- label = "u-boot";
- /* 1.0 MiB */
- reg = <0x0000000 0x100000>;
- read-only;
- };
-
- partition@100000 {
- label = "u-boot-env";
- /* 128 KiB */
- reg = <0x100000 0x20000>;
- read-only;
- };
-
- partition@120000 {
- label = "uImage";
- /* 7 MiB */
- reg = <0x120000 0x700000>;
- };
-
- partition@820000 {
- label = "ubifs";
- /* ~ 84 MiB */
- reg = <0x820000 0x54e0000>;
- };
-
- /* Hardcoded into stock bootloader */
- partition@5d00000 {
- label = "failsafe-uImage";
- /* 5 MiB */
- reg = <0x5d00000 0x500000>;
- };
-
- partition@6200000 {
- label = "failsafe-fs";
- /* 29 MiB */
- reg = <0x6200000 0x1d00000>;
- };
-
- partition@7f00000 {
- label = "bbt";
- /* 1 MiB for BBT */
- reg = <0x7f00000 0x100000>;
- };
- };
};
};
@@ -319,3 +264,68 @@
clock-frequency = <100000>;
status = "okay";
};
+
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ /* 1.0 MiB */
+ reg = <0x0000000 0x100000>;
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u-boot-env";
+ /* 128 KiB */
+ reg = <0x100000 0x20000>;
+ read-only;
+ };
+
+ partition@120000 {
+ label = "uImage";
+ /* 7 MiB */
+ reg = <0x120000 0x700000>;
+ };
+
+ partition@820000 {
+ label = "ubifs";
+ /* ~ 84 MiB */
+ reg = <0x820000 0x54e0000>;
+ };
+
+ /* Hardcoded into stock bootloader */
+ partition@5d00000 {
+ label = "failsafe-uImage";
+ /* 5 MiB */
+ reg = <0x5d00000 0x500000>;
+ };
+
+ partition@6200000 {
+ label = "failsafe-fs";
+ /* 29 MiB */
+ reg = <0x6200000 0x1d00000>;
+ };
+
+ partition@7f00000 {
+ label = "bbt";
+ /* 1 MiB for BBT */
+ reg = <0x7f00000 0x100000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-370-mirabox.dts b/arch/arm/boot/dts/armada-370-mirabox.dts
index 996f31b..7c2f5a7 100644
--- a/arch/arm/boot/dts/armada-370-mirabox.dts
+++ b/arch/arm/boot/dts/armada-370-mirabox.dts
@@ -108,27 +108,6 @@
reg = <0x25>;
};
};
-
- nand@d0000 {
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
-
- partition@0 {
- label = "U-Boot";
- reg = <0 0x400000>;
- };
- partition@400000 {
- label = "Linux";
- reg = <0x400000 0x400000>;
- };
- partition@800000 {
- label = "Filesystem";
- reg = <0x800000 0x3f800000>;
- };
- };
};
};
};
@@ -173,3 +152,33 @@
};
};
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0 0x400000>;
+ };
+ partition@400000 {
+ label = "Linux";
+ reg = <0x400000 0x400000>;
+ };
+ partition@800000 {
+ label = "Filesystem";
+ reg = <0x800000 0x3f800000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-370-netgear-rn102.dts b/arch/arm/boot/dts/armada-370-netgear-rn102.dts
index 5663480..b0b640b 100644
--- a/arch/arm/boot/dts/armada-370-netgear-rn102.dts
+++ b/arch/arm/boot/dts/armada-370-netgear-rn102.dts
@@ -81,46 +81,6 @@
pwm_polarity = <0>;
};
};
-
- nand@d0000 {
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
-
- /* Use Hardware BCH ECC */
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
-
- partition@0 {
- label = "u-boot";
- reg = <0x0000000 0x180000>; /* 1.5MB */
- read-only;
- };
-
- partition@180000 {
- label = "u-boot-env";
- reg = <0x180000 0x20000>; /* 128KB */
- read-only;
- };
-
- partition@200000 {
- label = "uImage";
- reg = <0x0200000 0x600000>; /* 6MB */
- };
-
- partition@800000 {
- label = "minirootfs";
- reg = <0x0800000 0x400000>; /* 4MB */
- };
-
- /* Last MB is for the BBT, i.e. not writable */
- partition@c00000 {
- label = "ubifs";
- reg = <0x0c00000 0x7400000>; /* 116MB */
- };
- };
};
};
@@ -264,3 +224,53 @@
marvell,function = "gpio";
};
};
+
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+
+ /* Use Hardware BCH ECC */
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x180000>; /* 1.5MB */
+ read-only;
+ };
+
+ partition@180000 {
+ label = "u-boot-env";
+ reg = <0x180000 0x20000>; /* 128KB */
+ read-only;
+ };
+
+ partition@200000 {
+ label = "uImage";
+ reg = <0x0200000 0x600000>; /* 6MB */
+ };
+
+ partition@800000 {
+ label = "minirootfs";
+ reg = <0x0800000 0x400000>; /* 4MB */
+ };
+
+ /* Last MB is for the BBT, i.e. not writable */
+ partition@c00000 {
+ label = "ubifs";
+ reg = <0x0c00000 0x7400000>; /* 116MB */
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-370-netgear-rn104.dts b/arch/arm/boot/dts/armada-370-netgear-rn104.dts
index 16d0307..9fd1cb9 100644
--- a/arch/arm/boot/dts/armada-370-netgear-rn104.dts
+++ b/arch/arm/boot/dts/armada-370-netgear-rn104.dts
@@ -90,46 +90,6 @@
reg = <0x23>;
};
};
-
- nand@d0000 {
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
-
- /* Use Hardware BCH ECC */
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
-
- partition@0 {
- label = "u-boot";
- reg = <0x0000000 0x180000>; /* 1.5MB */
- read-only;
- };
-
- partition@180000 {
- label = "u-boot-env";
- reg = <0x180000 0x20000>; /* 128KB */
- read-only;
- };
-
- partition@200000 {
- label = "uImage";
- reg = <0x0200000 0x600000>; /* 6MB */
- };
-
- partition@800000 {
- label = "minirootfs";
- reg = <0x0800000 0x400000>; /* 4MB */
- };
-
- /* Last MB is for the BBT, i.e. not writable */
- partition@c00000 {
- label = "ubifs";
- reg = <0x0c00000 0x7400000>; /* 116MB */
- };
- };
};
};
@@ -276,3 +236,53 @@
marvell,function = "gpio";
};
};
+
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+
+ /* Use Hardware BCH ECC */
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x180000>; /* 1.5MB */
+ read-only;
+ };
+
+ partition@180000 {
+ label = "u-boot-env";
+ reg = <0x180000 0x20000>; /* 128KB */
+ read-only;
+ };
+
+ partition@200000 {
+ label = "uImage";
+ reg = <0x0200000 0x600000>; /* 6MB */
+ };
+
+ partition@800000 {
+ label = "minirootfs";
+ reg = <0x0800000 0x400000>; /* 4MB */
+ };
+
+ /* Last MB is for the BBT, i.e. not writable */
+ partition@c00000 {
+ label = "ubifs";
+ reg = <0x0c00000 0x7400000>; /* 116MB */
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/armada-370-rd.dts
index cc2f774..2bfb310 100644
--- a/arch/arm/boot/dts/armada-370-rd.dts
+++ b/arch/arm/boot/dts/armada-370-rd.dts
@@ -112,27 +112,6 @@
default-state = "keep";
};
};
-
- nand@d0000 {
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
-
- partition@0 {
- label = "U-Boot";
- reg = <0 0x800000>;
- };
- partition@800000 {
- label = "Linux";
- reg = <0x800000 0x800000>;
- };
- partition@1000000 {
- label = "Filesystem";
- reg = <0x1000000 0x3f000000>;
- };
- };
};
};
@@ -288,3 +267,34 @@
marvell,function = "gpio";
};
};
+
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0 0x800000>;
+ };
+ partition@800000 {
+ label = "Linux";
+ reg = <0x800000 0x800000>;
+ };
+ partition@1000000 {
+ label = "Filesystem";
+ reg = <0x1000000 0x3f000000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi b/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi
index a5206db..b52634e 100644
--- a/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi
+++ b/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi
@@ -66,33 +66,6 @@
interrupts = <110>;
};
};
-
- nand@d0000 {
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
-
- partition@0 {
- label = "u-boot";
- reg = <0x0 0x300000>;
- };
- partition@300000 {
- label = "device-tree";
- reg = <0x300000 0x20000>;
- };
- partition@320000 {
- label = "linux";
- reg = <0x320000 0x2000000>;
- };
- partition@2320000 {
- label = "rootfs";
- reg = <0x2320000 0xdce0000>;
- };
- };
};
};
@@ -227,3 +200,40 @@
marvell,function = "gpio";
};
};
+
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0 0x300000>;
+ };
+ partition@300000 {
+ label = "device-tree";
+ reg = <0x300000 0x20000>;
+ };
+ partition@320000 {
+ label = "linux";
+ reg = <0x320000 0x2000000>;
+ };
+ partition@2320000 {
+ label = "rootfs";
+ reg = <0x2320000 0xdce0000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
index 11fc327..c15f5e9 100644
--- a/arch/arm/boot/dts/armada-370-xp.dtsi
+++ b/arch/arm/boot/dts/armada-370-xp.dtsi
@@ -244,11 +244,11 @@
status = "disabled";
};
- nand: nand@d0000 {
- compatible = "marvell,armada370-nand";
+ nand_controller: nand-controller@d0000 {
+ compatible = "marvell,armada370-nand-controller";
reg = <0xd0000 0x54>;
#address-cells = <1>;
- #size-cells = <1>;
+ #size-cells = <0>;
interrupts = <113>;
clocks = <&coredivclk 0>;
status = "disabled";
diff --git a/arch/arm/boot/dts/armada-375-db.dts b/arch/arm/boot/dts/armada-375-db.dts
index e4ecd7e..0e67946 100644
--- a/arch/arm/boot/dts/armada-375-db.dts
+++ b/arch/arm/boot/dts/armada-375-db.dts
@@ -103,28 +103,38 @@
nr-ports = <2>;
};
-&nand {
+&nand_controller {
+ status = "okay";
pinctrl-0 = <&nand_pins>;
pinctrl-names = "default";
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
-
- partition@0 {
- label = "U-Boot";
- reg = <0 0x800000>;
- };
- partition@800000 {
- label = "Linux";
- reg = <0x800000 0x800000>;
- };
- partition@1000000 {
- label = "Filesystem";
- reg = <0x1000000 0x3f000000>;
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0 0x800000>;
+ };
+ partition@800000 {
+ label = "Linux";
+ reg = <0x800000 0x800000>;
+ };
+ partition@1000000 {
+ label = "Filesystem";
+ reg = <0x1000000 0x3f000000>;
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi
index 53ead6f..2932a29 100644
--- a/arch/arm/boot/dts/armada-375.dtsi
+++ b/arch/arm/boot/dts/armada-375.dtsi
@@ -502,11 +502,11 @@
status = "disabled";
};
- nand: nand@d0000 {
- compatible = "marvell,armada370-nand";
+ nand_controller: nand-controller@d0000 {
+ compatible = "marvell,armada370-nand-controller";
reg = <0xd0000 0x54>;
#address-cells = <1>;
- #size-cells = <1>;
+ #size-cells = <0>;
interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gateclk 11>;
status = "disabled";
diff --git a/arch/arm/boot/dts/armada-385-db-ap.dts b/arch/arm/boot/dts/armada-385-db-ap.dts
index d294f24..0e4613b 100644
--- a/arch/arm/boot/dts/armada-385-db-ap.dts
+++ b/arch/arm/boot/dts/armada-385-db-ap.dts
@@ -135,39 +135,6 @@
status = "okay";
};
- nfc: flash@d0000 {
- status = "okay";
- num-cs = <1>;
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "U-Boot";
- reg = <0x00000000 0x00800000>;
- read-only;
- };
-
- partition@800000 {
- label = "uImage";
- reg = <0x00800000 0x00400000>;
- read-only;
- };
-
- partition@c00000 {
- label = "Root";
- reg = <0x00c00000 0x3f400000>;
- };
- };
- };
-
usb3@f0000 {
status = "okay";
usb-phy = <&usb3_phy>;
@@ -233,3 +200,39 @@
spi-max-frequency = <54000000>;
};
};
+
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0x00000000 0x00800000>;
+ read-only;
+ };
+
+ partition@800000 {
+ label = "uImage";
+ reg = <0x00800000 0x00400000>;
+ read-only;
+ };
+
+ partition@c00000 {
+ label = "Root";
+ reg = <0x00c00000 0x3f400000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-385-linksys-caiman.dts b/arch/arm/boot/dts/armada-385-linksys-caiman.dts
index 1f30993..a03050c 100644
--- a/arch/arm/boot/dts/armada-385-linksys-caiman.dts
+++ b/arch/arm/boot/dts/armada-385-linksys-caiman.dts
@@ -73,67 +73,72 @@
&nand {
/* 128MiB */
-
- partition@0 {
- label = "u-boot";
- reg = <0x0000000 0x200000>; /* 2MiB */
- read-only;
- };
-
- partition@100000 {
- label = "u_env";
- reg = <0x200000 0x40000>; /* 256KiB */
- };
-
- partition@140000 {
- label = "s_env";
- reg = <0x240000 0x40000>; /* 256KiB */
- };
-
- partition@900000 {
- label = "devinfo";
- reg = <0x900000 0x100000>; /* 1MiB */
- read-only;
- };
-
- /* kernel1 overlaps with rootfs1 by design */
- partition@a00000 {
- label = "kernel1";
- reg = <0xa00000 0x2800000>; /* 40MiB */
- };
-
- partition@1000000 {
- label = "rootfs1";
- reg = <0x1000000 0x2200000>; /* 34MiB */
- };
-
- /* kernel2 overlaps with rootfs2 by design */
- partition@3200000 {
- label = "kernel2";
- reg = <0x3200000 0x2800000>; /* 40MiB */
- };
-
- partition@3800000 {
- label = "rootfs2";
- reg = <0x3800000 0x2200000>; /* 34MiB */
- };
-
- /*
- * 38MiB, last MiB is for the BBT, not writable
- */
- partition@5a00000 {
- label = "syscfg";
- reg = <0x5a00000 0x2600000>;
- };
-
- /*
- * Unused area between "s_env" and "devinfo".
- * Moved here because otherwise the renumbered
- * partitions would break the bootloader
- * supplied bootargs
- */
- partition@180000 {
- label = "unused_area";
- reg = <0x280000 0x680000>; /* 6.5MiB */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x200000>; /* 2MiB */
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u_env";
+ reg = <0x200000 0x40000>; /* 256KiB */
+ };
+
+ partition@140000 {
+ label = "s_env";
+ reg = <0x240000 0x40000>; /* 256KiB */
+ };
+
+ partition@900000 {
+ label = "devinfo";
+ reg = <0x900000 0x100000>; /* 1MiB */
+ read-only;
+ };
+
+ /* kernel1 overlaps with rootfs1 by design */
+ partition@a00000 {
+ label = "kernel1";
+ reg = <0xa00000 0x2800000>; /* 40MiB */
+ };
+
+ partition@1000000 {
+ label = "rootfs1";
+ reg = <0x1000000 0x2200000>; /* 34MiB */
+ };
+
+ /* kernel2 overlaps with rootfs2 by design */
+ partition@3200000 {
+ label = "kernel2";
+ reg = <0x3200000 0x2800000>; /* 40MiB */
+ };
+
+ partition@3800000 {
+ label = "rootfs2";
+ reg = <0x3800000 0x2200000>; /* 34MiB */
+ };
+
+ /*
+ * 38MiB, last MiB is for the BBT, not writable
+ */
+ partition@5a00000 {
+ label = "syscfg";
+ reg = <0x5a00000 0x2600000>;
+ };
+
+ /*
+ * Unused area between "s_env" and "devinfo".
+ * Moved here because otherwise the renumbered
+ * partitions would break the bootloader
+ * supplied bootargs
+ */
+ partition@180000 {
+ label = "unused_area";
+ reg = <0x280000 0x680000>; /* 6.5MiB */
+ };
};
};
diff --git a/arch/arm/boot/dts/armada-385-linksys-cobra.dts b/arch/arm/boot/dts/armada-385-linksys-cobra.dts
index bc34802..e3e4877 100644
--- a/arch/arm/boot/dts/armada-385-linksys-cobra.dts
+++ b/arch/arm/boot/dts/armada-385-linksys-cobra.dts
@@ -73,67 +73,72 @@
&nand {
/* 128MiB */
-
- partition@0 {
- label = "u-boot";
- reg = <0x0000000 0x200000>; /* 2MiB */
- read-only;
- };
-
- partition@100000 {
- label = "u_env";
- reg = <0x200000 0x40000>; /* 256KiB */
- };
-
- partition@140000 {
- label = "s_env";
- reg = <0x240000 0x40000>; /* 256KiB */
- };
-
- partition@900000 {
- label = "devinfo";
- reg = <0x900000 0x100000>; /* 1MiB */
- read-only;
- };
-
- /* kernel1 overlaps with rootfs1 by design */
- partition@a00000 {
- label = "kernel1";
- reg = <0xa00000 0x2800000>; /* 40MiB */
- };
-
- partition@1000000 {
- label = "rootfs1";
- reg = <0x1000000 0x2200000>; /* 34MiB */
- };
-
- /* kernel2 overlaps with rootfs2 by design */
- partition@3200000 {
- label = "kernel2";
- reg = <0x3200000 0x2800000>; /* 40MiB */
- };
-
- partition@3800000 {
- label = "rootfs2";
- reg = <0x3800000 0x2200000>; /* 34MiB */
- };
-
- /*
- * 38MiB, last MiB is for the BBT, not writable
- */
- partition@5a00000 {
- label = "syscfg";
- reg = <0x5a00000 0x2600000>;
- };
-
- /*
- * Unused area between "s_env" and "devinfo".
- * Moved here because otherwise the renumbered
- * partitions would break the bootloader
- * supplied bootargs
- */
- partition@180000 {
- label = "unused_area";
- reg = <0x280000 0x680000>; /* 6.5MiB */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x200000>; /* 2MiB */
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u_env";
+ reg = <0x200000 0x40000>; /* 256KiB */
+ };
+
+ partition@140000 {
+ label = "s_env";
+ reg = <0x240000 0x40000>; /* 256KiB */
+ };
+
+ partition@900000 {
+ label = "devinfo";
+ reg = <0x900000 0x100000>; /* 1MiB */
+ read-only;
+ };
+
+ /* kernel1 overlaps with rootfs1 by design */
+ partition@a00000 {
+ label = "kernel1";
+ reg = <0xa00000 0x2800000>; /* 40MiB */
+ };
+
+ partition@1000000 {
+ label = "rootfs1";
+ reg = <0x1000000 0x2200000>; /* 34MiB */
+ };
+
+ /* kernel2 overlaps with rootfs2 by design */
+ partition@3200000 {
+ label = "kernel2";
+ reg = <0x3200000 0x2800000>; /* 40MiB */
+ };
+
+ partition@3800000 {
+ label = "rootfs2";
+ reg = <0x3800000 0x2200000>; /* 34MiB */
+ };
+
+ /*
+ * 38MiB, last MiB is for the BBT, not writable
+ */
+ partition@5a00000 {
+ label = "syscfg";
+ reg = <0x5a00000 0x2600000>;
+ };
+
+ /*
+ * Unused area between "s_env" and "devinfo".
+ * Moved here because otherwise the renumbered
+ * partitions would break the bootloader
+ * supplied bootargs
+ */
+ partition@180000 {
+ label = "unused_area";
+ reg = <0x280000 0x680000>; /* 6.5MiB */
+ };
};
};
diff --git a/arch/arm/boot/dts/armada-385-linksys-rango.dts b/arch/arm/boot/dts/armada-385-linksys-rango.dts
index 5b745a0..3c4af57 100644
--- a/arch/arm/boot/dts/armada-385-linksys-rango.dts
+++ b/arch/arm/boot/dts/armada-385-linksys-rango.dts
@@ -81,74 +81,79 @@
&nand {
/* AMD/Spansion S34ML02G2 256MiB, OEM Layout */
-
- partition@0 {
- label = "u-boot";
- reg = <0x0000000 0x200000>; /* 2MiB */
- read-only;
- };
-
- partition@200000 {
- label = "u_env";
- reg = <0x200000 0x20000>; /* 128KiB */
- };
-
- partition@220000 {
- label = "s_env";
- reg = <0x220000 0x40000>; /* 256KiB */
- };
-
- partition@7e0000 {
- label = "devinfo";
- reg = <0x7e0000 0x40000>; /* 256KiB */
- read-only;
- };
-
- partition@820000 {
- label = "sysdiag";
- reg = <0x820000 0x1e0000>; /* 1920KiB */
- read-only;
- };
-
- /* kernel1 overlaps with rootfs1 by design */
- partition@a00000 {
- label = "kernel1";
- reg = <0xa00000 0x5000000>; /* 80MiB */
- };
-
- partition@1000000 {
- label = "rootfs1";
- reg = <0x1000000 0x4a00000>; /* 74MiB */
- };
-
- /* kernel2 overlaps with rootfs2 by design */
- partition@5a00000 {
- label = "kernel2";
- reg = <0x5a00000 0x5000000>; /* 80MiB */
- };
-
- partition@6000000 {
- label = "rootfs2";
- reg = <0x6000000 0x4a00000>; /* 74MiB */
- };
-
- /*
- * 86MiB, last MiB is for the BBT, not writable
- */
- partition@aa00000 {
- label = "syscfg";
- reg = <0xaa00000 0x5600000>;
- };
-
- /*
- * Unused area between "s_env" and "devinfo".
- * Moved here because otherwise the renumbered
- * partitions would break the bootloader
- * supplied bootargs
- */
- partition@180000 {
- label = "unused_area";
- reg = <0x260000 0x5c0000>; /* 5.75MiB */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x200000>; /* 2MiB */
+ read-only;
+ };
+
+ partition@200000 {
+ label = "u_env";
+ reg = <0x200000 0x20000>; /* 128KiB */
+ };
+
+ partition@220000 {
+ label = "s_env";
+ reg = <0x220000 0x40000>; /* 256KiB */
+ };
+
+ partition@7e0000 {
+ label = "devinfo";
+ reg = <0x7e0000 0x40000>; /* 256KiB */
+ read-only;
+ };
+
+ partition@820000 {
+ label = "sysdiag";
+ reg = <0x820000 0x1e0000>; /* 1920KiB */
+ read-only;
+ };
+
+ /* kernel1 overlaps with rootfs1 by design */
+ partition@a00000 {
+ label = "kernel1";
+ reg = <0xa00000 0x5000000>; /* 80MiB */
+ };
+
+ partition@1000000 {
+ label = "rootfs1";
+ reg = <0x1000000 0x4a00000>; /* 74MiB */
+ };
+
+ /* kernel2 overlaps with rootfs2 by design */
+ partition@5a00000 {
+ label = "kernel2";
+ reg = <0x5a00000 0x5000000>; /* 80MiB */
+ };
+
+ partition@6000000 {
+ label = "rootfs2";
+ reg = <0x6000000 0x4a00000>; /* 74MiB */
+ };
+
+ /*
+ * 86MiB, last MiB is for the BBT, not writable
+ */
+ partition@aa00000 {
+ label = "syscfg";
+ reg = <0xaa00000 0x5600000>;
+ };
+
+ /*
+ * Unused area between "s_env" and "devinfo".
+ * Moved here because otherwise the renumbered
+ * partitions would break the bootloader
+ * supplied bootargs
+ */
+ partition@180000 {
+ label = "unused_area";
+ reg = <0x260000 0x5c0000>; /* 5.75MiB */
+ };
};
};
diff --git a/arch/arm/boot/dts/armada-385-linksys-shelby.dts b/arch/arm/boot/dts/armada-385-linksys-shelby.dts
index 44f5aeb..3451cd3 100644
--- a/arch/arm/boot/dts/armada-385-linksys-shelby.dts
+++ b/arch/arm/boot/dts/armada-385-linksys-shelby.dts
@@ -73,67 +73,72 @@
&nand {
/* 128MiB */
-
- partition@0 {
- label = "u-boot";
- reg = <0x0000000 0x200000>; /* 2MiB */
- read-only;
- };
-
- partition@100000 {
- label = "u_env";
- reg = <0x200000 0x40000>; /* 256KiB */
- };
-
- partition@140000 {
- label = "s_env";
- reg = <0x240000 0x40000>; /* 256KiB */
- };
-
- partition@900000 {
- label = "devinfo";
- reg = <0x900000 0x100000>; /* 1MiB */
- read-only;
- };
-
- /* kernel1 overlaps with rootfs1 by design */
- partition@a00000 {
- label = "kernel1";
- reg = <0xa00000 0x2800000>; /* 40MiB */
- };
-
- partition@1000000 {
- label = "rootfs1";
- reg = <0x1000000 0x2200000>; /* 34MiB */
- };
-
- /* kernel2 overlaps with rootfs2 by design */
- partition@3200000 {
- label = "kernel2";
- reg = <0x3200000 0x2800000>; /* 40MiB */
- };
-
- partition@3800000 {
- label = "rootfs2";
- reg = <0x3800000 0x2200000>; /* 34MiB */
- };
-
- /*
- * 38MiB, last MiB is for the BBT, not writable
- */
- partition@5a00000 {
- label = "syscfg";
- reg = <0x5a00000 0x2600000>;
- };
-
- /*
- * Unused area between "s_env" and "devinfo".
- * Moved here because otherwise the renumbered
- * partitions would break the bootloader
- * supplied bootargs
- */
- partition@180000 {
- label = "unused_area";
- reg = <0x280000 0x680000>; /* 6.5MiB */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x200000>; /* 2MiB */
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u_env";
+ reg = <0x200000 0x40000>; /* 256KiB */
+ };
+
+ partition@140000 {
+ label = "s_env";
+ reg = <0x240000 0x40000>; /* 256KiB */
+ };
+
+ partition@900000 {
+ label = "devinfo";
+ reg = <0x900000 0x100000>; /* 1MiB */
+ read-only;
+ };
+
+ /* kernel1 overlaps with rootfs1 by design */
+ partition@a00000 {
+ label = "kernel1";
+ reg = <0xa00000 0x2800000>; /* 40MiB */
+ };
+
+ partition@1000000 {
+ label = "rootfs1";
+ reg = <0x1000000 0x2200000>; /* 34MiB */
+ };
+
+ /* kernel2 overlaps with rootfs2 by design */
+ partition@3200000 {
+ label = "kernel2";
+ reg = <0x3200000 0x2800000>; /* 40MiB */
+ };
+
+ partition@3800000 {
+ label = "rootfs2";
+ reg = <0x3800000 0x2200000>; /* 34MiB */
+ };
+
+ /*
+ * 38MiB, last MiB is for the BBT, not writable
+ */
+ partition@5a00000 {
+ label = "syscfg";
+ reg = <0x5a00000 0x2600000>;
+ };
+
+ /*
+ * Unused area between "s_env" and "devinfo".
+ * Moved here because otherwise the renumbered
+ * partitions would break the bootloader
+ * supplied bootargs
+ */
+ partition@180000 {
+ label = "unused_area";
+ reg = <0x280000 0x680000>; /* 6.5MiB */
+ };
};
};
diff --git a/arch/arm/boot/dts/armada-385-linksys.dtsi b/arch/arm/boot/dts/armada-385-linksys.dtsi
index 4a0d736..827e82b 100644
--- a/arch/arm/boot/dts/armada-385-linksys.dtsi
+++ b/arch/arm/boot/dts/armada-385-linksys.dtsi
@@ -138,13 +138,19 @@
};
};
-&nand {
+&nand_controller {
/* 128MiB or 256MiB */
status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand: nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+ };
};
&mdio {
diff --git a/arch/arm/boot/dts/armada-388-db.dts b/arch/arm/boot/dts/armada-388-db.dts
index 05250d4..a2bec07b 100644
--- a/arch/arm/boot/dts/armada-388-db.dts
+++ b/arch/arm/boot/dts/armada-388-db.dts
@@ -91,29 +91,6 @@
status = "okay";
};
- flash@d0000 {
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
-
- partition@0 {
- label = "U-Boot";
- reg = <0 0x800000>;
- };
- partition@800000 {
- label = "Linux";
- reg = <0x800000 0x800000>;
- };
- partition@1000000 {
- label = "Filesystem";
- reg = <0x1000000 0x3f000000>;
- };
- };
-
sdhci@d8000 {
broken-cd;
wp-inverted;
@@ -165,3 +142,35 @@
};
};
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0 0x800000>;
+ };
+ partition@800000 {
+ label = "Linux";
+ reg = <0x800000 0x800000>;
+ };
+ partition@1000000 {
+ label = "Filesystem";
+ reg = <0x1000000 0x3f000000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
index 6916d75..18edc9b 100644
--- a/arch/arm/boot/dts/armada-38x.dtsi
+++ b/arch/arm/boot/dts/armada-38x.dtsi
@@ -551,11 +551,11 @@
status = "okay";
};
- nand: flash@d0000 {
- compatible = "marvell,armada370-nand";
+ nand_controller: nand-controller@d0000 {
+ compatible = "marvell,armada370-nand-controller";
reg = <0xd0000 0x54>;
#address-cells = <1>;
- #size-cells = <1>;
+ #size-cells = <0>;
interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&coredivclk 0>;
status = "disabled";
diff --git a/arch/arm/boot/dts/armada-390-db.dts b/arch/arm/boot/dts/armada-390-db.dts
index 1b2362e..0e29474 100644
--- a/arch/arm/boot/dts/armada-390-db.dts
+++ b/arch/arm/boot/dts/armada-390-db.dts
@@ -49,37 +49,6 @@
status = "okay";
};
- flash@d0000 {
- status = "okay";
- pinctrl-0 = <&nand_pins>;
- pinctrl-names = "default";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
- nand-ecc-strength = <8>;
- nand-ecc-step-size = <512>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "U-Boot";
- reg = <0 0x800000>;
- };
- partition@800000 {
- label = "Linux";
- reg = <0x800000 0x800000>;
- };
- partition@1000000 {
- label = "Filesystem";
- reg = <0x1000000 0x3f000000>;
- };
- };
- };
-
/* CON98 */
usb3@f8000 {
status = "okay";
@@ -136,3 +105,38 @@
};
};
};
+
+&nand_controller {
+ status = "okay";
+ pinctrl-0 = <&nand_pins>;
+ pinctrl-names = "default";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <8>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0 0x800000>;
+ };
+ partition@800000 {
+ label = "Linux";
+ reg = <0x800000 0x800000>;
+ };
+ partition@1000000 {
+ label = "Filesystem";
+ reg = <0x1000000 0x3f000000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-395-gp.dts b/arch/arm/boot/dts/armada-395-gp.dts
index 2a9de19..6dd9e90 100644
--- a/arch/arm/boot/dts/armada-395-gp.dts
+++ b/arch/arm/boot/dts/armada-395-gp.dts
@@ -57,41 +57,6 @@
status = "okay";
};
- flash@d0000 {
- status = "okay";
- pinctrl-0 = <&nand_pins>;
- pinctrl-names = "default";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "U-Boot";
- reg = <0x00000000 0x00600000>;
- read-only;
- };
-
- partition@800000 {
- label = "uImage";
- reg = <0x00600000 0x00400000>;
- read-only;
- };
-
- partition@1000000 {
- label = "Root";
- reg = <0x00a00000 0x3f600000>;
- };
- };
- };
-
/* CON18 */
sdhci@d8000 {
clock-frequency = <200000000>;
@@ -130,3 +95,42 @@
};
};
};
+
+&nand_controller {
+ status = "okay";
+ pinctrl-0 = <&nand_pins>;
+ pinctrl-names = "default";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0x00000000 0x00600000>;
+ read-only;
+ };
+
+ partition@800000 {
+ label = "uImage";
+ reg = <0x00600000 0x00400000>;
+ read-only;
+ };
+
+ partition@1000000 {
+ label = "Root";
+ reg = <0x00a00000 0x3f600000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-398-db.dts b/arch/arm/boot/dts/armada-398-db.dts
index 2337f24..fc28308 100644
--- a/arch/arm/boot/dts/armada-398-db.dts
+++ b/arch/arm/boot/dts/armada-398-db.dts
@@ -51,31 +51,6 @@
status = "okay";
};
- flash@d0000 {
- status = "okay";
- pinctrl-0 = <&nand_pins>;
- pinctrl-names = "default";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
- nand-ecc-strength = <8>;
- nand-ecc-step-size = <512>;
-
- partition@0 {
- label = "U-Boot";
- reg = <0 0x800000>;
- };
- partition@800000 {
- label = "Linux";
- reg = <0x800000 0x800000>;
- };
- partition@1000000 {
- label = "Filesystem";
- reg = <0x1000000 0x3f000000>;
- };
- };
-
usb3@f8000 {
status = "okay";
};
@@ -122,3 +97,38 @@
};
};
};
+
+&nand_controller {
+ status = "okay";
+ pinctrl-0 = <&nand_pins>;
+ pinctrl-names = "default";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <8>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "U-Boot";
+ reg = <0 0x800000>;
+ };
+ partition@800000 {
+ label = "Linux";
+ reg = <0x800000 0x800000>;
+ };
+ partition@1000000 {
+ label = "Filesystem";
+ reg = <0x1000000 0x3f000000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-39x.dtsi b/arch/arm/boot/dts/armada-39x.dtsi
index c1737c0..f0c9498 100644
--- a/arch/arm/boot/dts/armada-39x.dtsi
+++ b/arch/arm/boot/dts/armada-39x.dtsi
@@ -367,11 +367,11 @@
interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
};
- flash@d0000 {
- compatible = "marvell,armada370-nand";
+ nand_controller: nand-controller@d0000 {
+ compatible = "marvell,armada370-nand-controller";
reg = <0xd0000 0x54>;
#address-cells = <1>;
- #size-cells = <1>;
+ #size-cells = <0>;
interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&coredivclk 0>;
status = "disabled";
diff --git a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi b/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
index a5da44f..8d708cc 100644
--- a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
+++ b/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
@@ -306,6 +306,19 @@
&pinctrl {
compatible = "marvell,98dx3236-pinctrl";
+ nand_pins: nand-pins {
+ marvell,pins = "mpp20", "mpp21", "mpp22",
+ "mpp23", "mpp24", "mpp25",
+ "mpp26", "mpp27", "mpp28",
+ "mpp29", "mpp30";
+ marvell,function = "dev";
+ };
+
+ nand_rb: nand-rb {
+ marvell,pins = "mpp19";
+ marvell,function = "nand";
+ };
+
spi0_pins: spi0-pins {
marvell,pins = "mpp0", "mpp1",
"mpp2", "mpp3";
diff --git a/arch/arm/boot/dts/armada-xp-db-dxbc2.dts b/arch/arm/boot/dts/armada-xp-db-dxbc2.dts
index 4c64923f..f42fc61 100644
--- a/arch/arm/boot/dts/armada-xp-db-dxbc2.dts
+++ b/arch/arm/boot/dts/armada-xp-db-dxbc2.dts
@@ -70,9 +70,9 @@
&nand {
status = "okay";
+ label = "pxa3xx_nand-0";
num-cs = <1>;
marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
nand-on-flash-bbt;
nand-ecc-strength = <4>;
nand-ecc-step-size = <512>;
diff --git a/arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts b/arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts
index a0ebb52..8432f51 100644
--- a/arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts
+++ b/arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts
@@ -69,9 +69,9 @@
&nand {
status = "okay";
+ label = "pxa3xx_nand-0";
num-cs = <1>;
marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
nand-on-flash-bbt;
nand-ecc-strength = <4>;
nand-ecc-step-size = <512>;
diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts
index 73d3f5c..f3ac748 100644
--- a/arch/arm/boot/dts/armada-xp-db.dts
+++ b/arch/arm/boot/dts/armada-xp-db.dts
@@ -146,9 +146,9 @@
nand@d0000 {
status = "okay";
+ label = "pxa3xx_nand-0";
num-cs = <1>;
marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
nand-on-flash-bbt;
partitions {
diff --git a/arch/arm/boot/dts/armada-xp-gp.dts b/arch/arm/boot/dts/armada-xp-gp.dts
index c143556..1139e94 100644
--- a/arch/arm/boot/dts/armada-xp-gp.dts
+++ b/arch/arm/boot/dts/armada-xp-gp.dts
@@ -162,9 +162,9 @@
nand@d0000 {
status = "okay";
+ label = "pxa3xx_nand-0";
num-cs = <1>;
marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
nand-on-flash-bbt;
};
};
diff --git a/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts b/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts
index def62e9..bbbb388 100644
--- a/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts
+++ b/arch/arm/boot/dts/armada-xp-lenovo-ix4-300d.dts
@@ -83,9 +83,9 @@
nand@d0000 {
status = "okay";
+ label = "pxa3xx_nand-0";
num-cs = <1>;
marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
nand-on-flash-bbt;
partitions {
diff --git a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
index f8b60d9..7a2606c 100644
--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
+++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
@@ -165,79 +165,6 @@
bm@c8000 {
status = "okay";
};
-
- nand@d0000 {
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
-
- partition@0 {
- label = "u-boot";
- reg = <0x0000000 0x100000>; /* 1MB */
- read-only;
- };
-
- partition@100000 {
- label = "u_env";
- reg = <0x100000 0x40000>; /* 256KB */
- };
-
- partition@140000 {
- label = "s_env";
- reg = <0x140000 0x40000>; /* 256KB */
- };
-
- partition@900000 {
- label = "devinfo";
- reg = <0x900000 0x100000>; /* 1MB */
- read-only;
- };
-
- /* kernel1 overlaps with rootfs1 by design */
- partition@a00000 {
- label = "kernel1";
- reg = <0xa00000 0x2800000>; /* 40MB */
- };
-
- partition@d00000 {
- label = "rootfs1";
- reg = <0xd00000 0x2500000>; /* 37MB */
- };
-
- /* kernel2 overlaps with rootfs2 by design */
- partition@3200000 {
- label = "kernel2";
- reg = <0x3200000 0x2800000>; /* 40MB */
- };
-
- partition@3500000 {
- label = "rootfs2";
- reg = <0x3500000 0x2500000>; /* 37MB */
- };
-
- /*
- * 38MB, last MB is for the BBT, not writable
- */
- partition@5a00000 {
- label = "syscfg";
- reg = <0x5a00000 0x2600000>;
- };
-
- /*
- * Unused area between "s_env" and "devinfo".
- * Moved here because otherwise the renumbered
- * partitions would break the bootloader
- * supplied bootargs
- */
- partition@180000 {
- label = "unused_area";
- reg = <0x180000 0x780000>; /* 7.5MB */
- };
- };
};
bm-bppi {
@@ -434,3 +361,86 @@
};
};
};
+
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x100000>; /* 1MB */
+ read-only;
+ };
+
+ partition@100000 {
+ label = "u_env";
+ reg = <0x100000 0x40000>; /* 256KB */
+ };
+
+ partition@140000 {
+ label = "s_env";
+ reg = <0x140000 0x40000>; /* 256KB */
+ };
+
+ partition@900000 {
+ label = "devinfo";
+ reg = <0x900000 0x100000>; /* 1MB */
+ read-only;
+ };
+
+ /* kernel1 overlaps with rootfs1 by design */
+ partition@a00000 {
+ label = "kernel1";
+ reg = <0xa00000 0x2800000>; /* 40MB */
+ };
+
+ partition@d00000 {
+ label = "rootfs1";
+ reg = <0xd00000 0x2500000>; /* 37MB */
+ };
+
+ /* kernel2 overlaps with rootfs2 by design */
+ partition@3200000 {
+ label = "kernel2";
+ reg = <0x3200000 0x2800000>; /* 40MB */
+ };
+
+ partition@3500000 {
+ label = "rootfs2";
+ reg = <0x3500000 0x2500000>; /* 37MB */
+ };
+
+ /*
+ * 38MB, last MB is for the BBT, not writable
+ */
+ partition@5a00000 {
+ label = "syscfg";
+ reg = <0x5a00000 0x2600000>;
+ };
+
+ /*
+ * Unused area between "s_env" and "devinfo".
+ * Moved here because otherwise the renumbered
+ * partitions would break the bootloader
+ * supplied bootargs
+ */
+ partition@180000 {
+ label = "unused_area";
+ reg = <0x180000 0x780000>; /* 7.5MB */
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
index c350b1c..8ea7358 100644
--- a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
+++ b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
@@ -117,46 +117,6 @@
nr-ports = <2>;
status = "okay";
};
-
- nand@d0000 {
- status = "okay";
- num-cs = <1>;
- marvell,nand-keep-config;
- marvell,nand-enable-arbiter;
- nand-on-flash-bbt;
-
- /* Use Hardware BCH ECC */
- nand-ecc-strength = <4>;
- nand-ecc-step-size = <512>;
-
- partition@0 {
- label = "u-boot";
- reg = <0x0000000 0x180000>; /* 1.5MB */
- read-only;
- };
-
- partition@180000 {
- label = "u-boot-env";
- reg = <0x180000 0x20000>; /* 128KB */
- read-only;
- };
-
- partition@200000 {
- label = "uImage";
- reg = <0x0200000 0x600000>; /* 6MB */
- };
-
- partition@800000 {
- label = "minirootfs";
- reg = <0x0800000 0x400000>; /* 4MB */
- };
-
- /* Last MB is for the BBT, i.e. not writable */
- partition@c00000 {
- label = "ubifs";
- reg = <0x0c00000 0x7400000>; /* 116MB */
- };
- };
};
};
@@ -345,3 +305,53 @@
marvell,function = "gpio";
};
};
+
+&nand_controller {
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ label = "pxa3xx_nand-0";
+ nand-rb = <0>;
+ marvell,nand-keep-config;
+ nand-on-flash-bbt;
+
+ /* Use Hardware BCH ECC */
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "u-boot";
+ reg = <0x0000000 0x180000>; /* 1.5MB */
+ read-only;
+ };
+
+ partition@180000 {
+ label = "u-boot-env";
+ reg = <0x180000 0x20000>; /* 128KB */
+ read-only;
+ };
+
+ partition@200000 {
+ label = "uImage";
+ reg = <0x0200000 0x600000>; /* 6MB */
+ };
+
+ partition@800000 {
+ label = "minirootfs";
+ reg = <0x0800000 0x400000>; /* 4MB */
+ };
+
+ /* Last MB is for the BBT, i.e. not writable */
+ partition@c00000 {
+ label = "ubifs";
+ reg = <0x0c00000 0x7400000>; /* 116MB */
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/aspeed-ast2500-evb.dts b/arch/arm/boot/dts/aspeed-ast2500-evb.dts
index 91a36c1..ede11c5 100644
--- a/arch/arm/boot/dts/aspeed-ast2500-evb.dts
+++ b/arch/arm/boot/dts/aspeed-ast2500-evb.dts
@@ -79,3 +79,21 @@
reg = <0x4d>;
};
};
+
+&ehci0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2ah_default>;
+};
+
+&ehci1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb2bh_default>;
+};
+
+&uhci {
+ status = "okay";
+
+ /* No pinctrl, this follows the above EHCI settings */
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts b/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts
new file mode 100644
index 0000000..7a291de
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-intel-s2600wf.dts
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017 Intel Corporation
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
+
+/ {
+ model = "S2600WF BMC";
+ compatible = "intel,s2600wf-bmc", "aspeed,ast2500";
+
+ chosen {
+ stdout-path = &uart5;
+ bootargs = "earlyprintk";
+ };
+
+ memory {
+ reg = <0x80000000 0x20000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ vga_memory: framebuffer@7f000000 {
+ no-map;
+ reg = <0x7f000000 0x01000000>;
+ };
+ };
+
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>,
+ <&adc 4>, <&adc 5>, <&adc 6>, <&adc 7>,
+ <&adc 8>, <&adc 9>, <&adc 10>, <&adc 11>,
+ <&adc 12>, <&adc 13>, <&adc 14>, <&adc 15>;
+ };
+
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "bmc";
+#include "openbmc-flash-layout.dtsi"
+ };
+};
+
+&spi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1_default>;
+
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "pnor";
+ };
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&mac0 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii1_default>;
+ use-ncsi;
+};
+
+&mac1 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+};
+
+&i2c5 {
+ status = "okay";
+};
+
+&i2c6 {
+ status = "okay";
+};
+
+&i2c7 {
+ status = "okay";
+};
+
+&i2c13 {
+ status = "okay";
+};
+
+&gfx {
+ status = "okay";
+};
+
+&pinctrl {
+ aspeed,external-nodes = <&gfx &lhc>;
+};
+
+&pwm_tacho {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default
+ &pinctrl_pwm2_default &pinctrl_pwm3_default
+ &pinctrl_pwm4_default &pinctrl_pwm5_default
+ &pinctrl_pwm6_default &pinctrl_pwm7_default>;
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-lanyang.dts b/arch/arm/boot/dts/aspeed-bmc-opp-lanyang.dts
new file mode 100644
index 0000000..d598b63
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-lanyang.dts
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2018 Inventec Corporation
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+
+/ {
+ model = "Lanyang BMC";
+ compatible = "inventec,lanyang-bmc", "aspeed,ast2500";
+
+ chosen {
+ stdout-path = &uart5;
+ bootargs = "console=ttyS4,115200 earlyprintk";
+ };
+
+ memory {
+ reg = <0x80000000 0x40000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ flash_memory: region@98000000 {
+ no-map;
+ reg = <0x98000000 0x04000000>; /* 64M */
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ sys_boot_status {
+ label = "System_boot_status";
+ gpios = <&gpio ASPEED_GPIO(B, 6) GPIO_ACTIVE_LOW>;
+ };
+
+ attention {
+ label = "Attention_locator";
+ gpios = <&gpio ASPEED_GPIO(B, 7) GPIO_ACTIVE_HIGH>;
+ };
+
+ plt_fault {
+ label = "Platform_fault";
+ gpios = <&gpio ASPEED_GPIO(B, 1) GPIO_ACTIVE_HIGH>;
+ };
+
+ hdd_fault {
+ label = "Onboard_drive_fault";
+ gpios = <&gpio ASPEED_GPIO(B, 3) GPIO_ACTIVE_HIGH>;
+ };
+ bmc_err {
+ lable = "BMC_fault";
+ gpios = <&gpio ASPEED_GPIO(H, 6) GPIO_ACTIVE_HIGH>;
+ };
+
+ sys_err {
+ lable = "Sys_fault";
+ gpios = <&gpio ASPEED_GPIO(H, 7) GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ fsi: gpio-fsi {
+ compatible = "fsi-master-gpio", "fsi-master";
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ clock-gpios = <&gpio ASPEED_GPIO(J, 0) GPIO_ACTIVE_HIGH>;
+ data-gpios = <&gpio ASPEED_GPIO(J, 1) GPIO_ACTIVE_HIGH>;
+ trans-gpios = <&gpio ASPEED_GPIO(D, 5) GPIO_ACTIVE_HIGH>;
+ enable-gpios = <&gpio ASPEED_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
+ mux-gpios = <&gpio ASPEED_GPIO(H, 2) GPIO_ACTIVE_HIGH>;
+ };
+
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>,
+ <&adc 4>, <&adc 5>, <&adc 6>, <&adc 7>,
+ <&adc 8>, <&adc 9>, <&adc 10>, <&adc 11>,
+ <&adc 13>, <&adc 14>, <&adc 15>;
+ };
+
+ iio-hwmon-battery {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 12>;
+ };
+};
+
+&pwm_tacho {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default
+ &pinctrl_pwm2_default &pinctrl_pwm3_default>;
+
+ fan@0 {
+ reg = <0x00>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x00>;
+ };
+
+ fan@1 {
+ reg = <0x01>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x01>;
+ };
+
+ fan@2 {
+ reg = <0x02>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x02>;
+ };
+
+ fan@3 {
+ reg = <0x03>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x03>;
+ };
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "bmc";
+#include "openbmc-flash-layout.dtsi"
+ };
+};
+
+&spi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1_default>;
+
+ flash@0 {
+ status = "okay";
+ label = "pnor";
+ m25p,fast-read;
+ };
+};
+
+&spi2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi2ck_default
+ &pinctrl_spi2cs0_default
+ &pinctrl_spi2cs1_default
+ &pinctrl_spi2miso_default
+ &pinctrl_spi2mosi_default>;
+
+ flash@0 {
+ status = "okay";
+ };
+};
+
+&uart1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd1_default
+ &pinctrl_rxd1_default>;
+};
+
+&lpc_ctrl {
+ status = "okay";
+ memory-region = <&flash_memory>;
+ flash = <&spi1>;
+};
+
+&lpc_snoop {
+ status = "okay";
+ snoop-ports = <0x80>;
+};
+
+&uart5 {
+ status = "okay";
+};
+
+&mac0 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii1_default>;
+ use-ncsi;
+};
+
+&mac1 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
+};
+
+&i2c0 {
+ status = "okay";
+
+ eeprom@55 {
+ compatible = "atmel,24c64";
+ reg = <0x55>;
+ pagesize = <32>;
+ };
+
+ rtc@68 {
+ compatible = "nxp,pcf8523";
+ reg = <0x68>;
+ };
+
+ tmp75@48 {
+ compatible = "ti,tmp75";
+ reg = <0x48>;
+ };
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&i2c4 {
+ status = "okay";
+};
+
+&i2c5 {
+ status = "okay";
+};
+
+&i2c6 {
+ status = "okay";
+};
+
+&i2c7 {
+ status = "okay";
+};
+
+&i2c8 {
+ status = "okay";
+};
+
+&i2c9 {
+ status = "okay";
+};
+
+&i2c10 {
+ status = "okay";
+};
+
+&i2c11 {
+ status = "okay";
+};
+
+&vuart {
+ status = "okay";
+};
+
+&gfx {
+ status = "okay";
+};
+
+&pinctrl {
+ aspeed,external-nodes = <&gfx &lhc>;
+};
+
+&gpio {
+ pin_gpio_b0 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(B, 0) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "BMC_HDD1_PWR_EN";
+ };
+
+ pin_gpio_b5 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(B, 5) GPIO_ACTIVE_HIGH>;
+ input;
+ line-name = "BMC_USB1_OCI2";
+ };
+
+ pin_gpio_h5 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(H, 5) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "BMC_CP0_PERST_ENABLE_R";
+ };
+
+ pin_gpio_z2 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(Z, 2) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "RST_PCA9546_U177_N";
+ };
+
+ pin_gpio_aa6 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(AA, 6) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "BMC_CP0_RESET_N";
+ };
+
+ pin_gpio_aa7 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(AA, 7) GPIO_ACTIVE_HIGH>;
+ output-high;
+ line-name = "BMC_TPM_RESET_N";
+ };
+
+ pin_gpio_ab0 {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(AB, 0) GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "BMC_USB_PWRON_N";
+ };
+};
+
+&ibt {
+ status = "okay";
+};
+
+&adc {
+ status = "okay";
+};
+
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts b/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
index 51bc6a2..389f5f83 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
@@ -68,6 +68,12 @@
gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_LOW>;
linux,code = <ASPEED_GPIO(J, 2)>;
};
+
+ id-button {
+ label = "id-button";
+ gpios = <&gpio ASPEED_GPIO(Q, 7) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(Q, 7)>;
+ };
};
};
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts b/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts
index 7056231..78a511e 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-witherspoon.dts
@@ -28,6 +28,34 @@
};
};
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ air-water {
+ label = "air-water";
+ gpios = <&gpio ASPEED_GPIO(B, 5) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(B, 5)>;
+ };
+
+ checkstop {
+ label = "checkstop";
+ gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(J, 2)>;
+ };
+
+ ps0-presence {
+ label = "ps0-presence";
+ gpios = <&gpio ASPEED_GPIO(P, 7) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(P, 7)>;
+ };
+
+ ps1-presence {
+ label = "ps1-presence";
+ gpios = <&gpio ASPEED_GPIO(N, 0) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(N, 0)>;
+ };
+ };
+
gpio-keys-polled {
compatible = "gpio-keys-polled";
#address-cells = <1>;
@@ -547,6 +575,10 @@
pinctrl-0 = <&pinctrl_wdtrst1_default>;
};
+&wdt2 {
+ aspeed,alt-boot;
+};
+
&ibt {
status = "okay";
};
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts b/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts
index ebe726a..ccbf645 100644
--- a/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-opp-zaius.dts
@@ -55,6 +55,12 @@
gpios = <&gpio ASPEED_GPIO(F, 7) GPIO_ACTIVE_LOW>;
linux,code = <ASPEED_GPIO(F, 7)>;
};
+
+ pcie-e2b-present{
+ label = "pcie-e2b-present";
+ gpios = <&gpio ASPEED_GPIO(E, 7) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(E, 7)>;
+ };
};
leds {
diff --git a/arch/arm/boot/dts/aspeed-bmc-portwell-neptune.dts b/arch/arm/boot/dts/aspeed-bmc-portwell-neptune.dts
new file mode 100644
index 0000000..43ed139
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-portwell-neptune.dts
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017 Facebook Inc.
+/dts-v1/;
+
+#include "aspeed-g5.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+
+/ {
+ model = "Portwell Neptune BMC";
+ compatible = "portwell,neptune-bmc", "aspeed,ast2500";
+ aliases {
+ serial0 = &uart1;
+ serial4 = &uart5;
+ };
+ chosen {
+ stdout-path = &uart5;
+ bootargs = "console=ttyS4,115200 earlyprintk";
+ };
+
+ memory {
+ reg = <0x80000000 0x20000000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ postcode0 {
+ label="BMC_UP";
+ gpios = <&gpio ASPEED_GPIO(H, 0) GPIO_ACTIVE_HIGH>;
+ default-state = "on";
+ };
+ postcode1 {
+ label="BMC_HB";
+ gpios = <&gpio ASPEED_GPIO(H, 1) GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ postcode2 {
+ label="FAULT";
+ gpios = <&gpio ASPEED_GPIO(H, 2) GPIO_ACTIVE_HIGH>;
+ };
+ // postcode3-7 are GPIOH3-H7
+ };
+};
+
+&fmc {
+ status = "okay";
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+#include "openbmc-flash-layout.dtsi"
+ };
+};
+
+&spi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_spi1_default>;
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "pnor";
+ };
+};
+
+&uart1 {
+ // Host Console
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_txd1_default
+ &pinctrl_rxd1_default>;
+};
+
+&uart5 {
+ // BMC Console
+ status = "okay";
+};
+
+&mac0 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii1_default
+ &pinctrl_mdio1_default>;
+};
+
+&mac1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii2_default>;
+ use-ncsi;
+};
+
+&i2c1 {
+ status = "okay";
+ // To PCIe slot SMBUS
+};
+
+&i2c2 {
+ status = "okay";
+ // To LAN I210
+};
+
+&i2c3 {
+ status = "okay";
+ // SMBus to COMe AB
+};
+
+&i2c4 {
+ status = "okay";
+ // I2C to COMe AB
+};
+
+&i2c5 {
+ status = "okay";
+// USB Debug card
+ pca9555@27 {
+ compatible = "nxp,pca9555";
+ reg = <0x27>;
+ };
+};
+
+&i2c6 {
+ status = "okay";
+ tpm@20 {
+ compatible = "infineon,slb9645tt";
+ reg = <0x20>;
+ };
+ tmp421@4e {
+ compatible = "ti,tmp421";
+ reg = <0x4e>;
+ };
+ tmp421@4f {
+ compatible = "ti,tmp421";
+ reg = <0x4f>;
+ };
+};
+
+&i2c8 {
+ status = "okay";
+ eeprom@51 {
+ compatible = "atmel,24c128";
+ reg = <0x51>;
+ pagesize = <32>;
+ };
+};
+
+&pwm_tacho {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default>;
+ fan@0 {
+ reg = <0x00>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x00>;
+ };
+
+ fan@1 {
+ reg = <0x00>;
+ aspeed,fan-tach-ch = /bits/ 8 <0x01>;
+ };
+};
diff --git a/arch/arm/boot/dts/aspeed-g4.dtsi b/arch/arm/boot/dts/aspeed-g4.dtsi
index 518d2bc..75df157 100644
--- a/arch/arm/boot/dts/aspeed-g4.dtsi
+++ b/arch/arm/boot/dts/aspeed-g4.dtsi
@@ -108,6 +108,23 @@
status = "disabled";
};
+ ehci0: usb@1e6a1000 {
+ compatible = "aspeed,ast2400-ehci", "generic-ehci";
+ reg = <0x1e6a1000 0x100>;
+ interrupts = <5>;
+ clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
+ status = "disabled";
+ };
+
+ uhci: usb@1e6b0000 {
+ compatible = "aspeed,ast2400-uhci", "generic-uhci";
+ reg = <0x1e6b0000 0x100>;
+ interrupts = <14>;
+ #ports = <3>;
+ clocks = <&syscon ASPEED_CLK_GATE_USBUHCICLK>;
+ status = "disabled";
+ };
+
apb {
compatible = "simple-bus";
#address-cells = <1>;
@@ -125,6 +142,14 @@
pinctrl: pinctrl {
compatible = "aspeed,g4-pinctrl";
};
+
+ };
+
+ rng: hwrng@1e6e2078 {
+ compatible = "timeriomem_rng";
+ reg = <0x1e6e2078 0x4>;
+ period = <1>;
+ quality = <100>;
};
adc: adc@1e6e9000 {
@@ -1250,6 +1275,16 @@
groups = "USBCKI";
};
+ pinctrl_usb2h_default: usb2h_default {
+ function = "USB2H1";
+ groups = "USB2H1";
+ };
+
+ pinctrl_usb2d_default: usb2d_default {
+ function = "USB2D1";
+ groups = "USB2D1";
+ };
+
pinctrl_vgabios_rom_default: vgabios_rom_default {
function = "VGABIOS_ROM";
groups = "VGABIOS_ROM";
diff --git a/arch/arm/boot/dts/aspeed-g5.dtsi b/arch/arm/boot/dts/aspeed-g5.dtsi
index f991771..17f2714 100644
--- a/arch/arm/boot/dts/aspeed-g5.dtsi
+++ b/arch/arm/boot/dts/aspeed-g5.dtsi
@@ -143,6 +143,31 @@
status = "disabled";
};
+ ehci0: usb@1e6a1000 {
+ compatible = "aspeed,ast2500-ehci", "generic-ehci";
+ reg = <0x1e6a1000 0x100>;
+ interrupts = <5>;
+ clocks = <&syscon ASPEED_CLK_GATE_USBPORT1CLK>;
+ status = "disabled";
+ };
+
+ ehci1: usb@1e6a3000 {
+ compatible = "aspeed,ast2500-ehci", "generic-ehci";
+ reg = <0x1e6a3000 0x100>;
+ interrupts = <13>;
+ clocks = <&syscon ASPEED_CLK_GATE_USBPORT2CLK>;
+ status = "disabled";
+ };
+
+ uhci: usb@1e6b0000 {
+ compatible = "aspeed,ast2500-uhci", "generic-uhci";
+ reg = <0x1e6b0000 0x100>;
+ interrupts = <14>;
+ #ports = <2>;
+ clocks = <&syscon ASPEED_CLK_GATE_USBUHCICLK>;
+ status = "disabled";
+ };
+
apb {
compatible = "simple-bus";
#address-cells = <1>;
@@ -164,6 +189,13 @@
};
};
+ rng: hwrng@1e6e2078 {
+ compatible = "timeriomem_rng";
+ reg = <0x1e6e2078 0x4>;
+ period = <1>;
+ quality = <100>;
+ };
+
gfx: display@1e6e6000 {
compatible = "aspeed,ast2500-gfx", "syscon";
reg = <0x1e6e6000 0x1000>;
@@ -1380,6 +1412,21 @@
groups = "USBCKI";
};
+ pinctrl_usb2ah_default: usb2ah_default {
+ function = "USB2AH";
+ groups = "USB2AH";
+ };
+
+ pinctrl_usb11bhid_default: usb11bhid_default {
+ function = "USB11BHID";
+ groups = "USB11BHID";
+ };
+
+ pinctrl_usb2bh_default: usb2bh_default {
+ function = "USB2BH";
+ groups = "USB2BH";
+ };
+
pinctrl_vgabiosrom_default: vgabiosrom_default {
function = "VGABIOSROM";
groups = "VGABIOSROM";
diff --git a/arch/arm/boot/dts/at91-sama5d2_xplained.dts b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
index e4bbb7e..fcc85d7 100644
--- a/arch/arm/boot/dts/at91-sama5d2_xplained.dts
+++ b/arch/arm/boot/dts/at91-sama5d2_xplained.dts
@@ -232,7 +232,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_charger_chglev &pinctrl_charger_lbo &pinctrl_charger_irq>;
interrupt-parent = <&pioA>;
- interrupts = <PIN_PB13 GPIO_ACTIVE_LOW>;
+ interrupts = <PIN_PB13 IRQ_TYPE_EDGE_RISING>;
active-semi,chglev-gpios = <&pioA PIN_PA12 GPIO_ACTIVE_HIGH>;
active-semi,lbo-gpios = <&pioA PIN_PC8 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/at91-sama5d4ek.dts b/arch/arm/boot/dts/at91-sama5d4ek.dts
index 7887a71..0702a2f 100644
--- a/arch/arm/boot/dts/at91-sama5d4ek.dts
+++ b/arch/arm/boot/dts/at91-sama5d4ek.dts
@@ -129,8 +129,8 @@
wakeup-source;
};
- atmel_mxt_ts@4c {
- compatible = "atmel,atmel_mxt_ts";
+ touchscreen@4c {
+ compatible = "atmel,maxtouch";
reg = <0x4c>;
interrupt-parent = <&pioE>;
interrupts = <24 0x0>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
index aa1fc7b..2cd9c5e 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
@@ -101,6 +101,12 @@
hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
};
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts
index 425f6b0..067d1f0 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-a.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts
@@ -96,6 +96,12 @@
hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
};
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
index effa195..cfbdaac 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
@@ -103,6 +103,12 @@
hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
};
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
index 772ec3b..5641d16 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
@@ -96,6 +96,12 @@
hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
};
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts
index 434483d..31ff602 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -91,6 +91,12 @@
hpd-gpios = <&gpio 46 GPIO_ACTIVE_HIGH>;
};
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi
index 6c3cfaa..cb2d6d7 100644
--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
@@ -83,12 +83,6 @@
bus-width = <4>;
};
-&pwm {
- pinctrl-names = "default";
- pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
- status = "okay";
-};
-
&usb {
power-domains = <&power RPI_POWER_DOMAIN_USB>;
};
diff --git a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
index 5c339ad..2fef70a 100644
--- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
+++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
@@ -41,6 +41,12 @@
hpd-gpios = <&gpio 46 GPIO_ACTIVE_LOW>;
};
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
+ status = "okay";
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_gpio14>;
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
new file mode 100644
index 0000000..4adb85e
--- /dev/null
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+#include "bcm2837.dtsi"
+#include "bcm2835-rpi.dtsi"
+#include "bcm283x-rpi-lan7515.dtsi"
+#include "bcm283x-rpi-usb-host.dtsi"
+
+/ {
+ compatible = "raspberrypi,3-model-b-plus", "brcm,bcm2837";
+ model = "Raspberry Pi 3 Model B+";
+
+ chosen {
+ /* 8250 auxiliary UART instead of pl011 */
+ stdout-path = "serial1:115200n8";
+ };
+
+ memory {
+ reg = <0 0x40000000>;
+ };
+
+ leds {
+ act {
+ gpios = <&gpio 29 GPIO_ACTIVE_HIGH>;
+ };
+
+ pwr {
+ label = "PWR";
+ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&expgpio 1 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&firmware {
+ expgpio: gpio {
+ compatible = "raspberrypi,firmware-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-line-names = "BT_ON",
+ "WL_ON",
+ "STATUS_LED",
+ "LAN_RUN",
+ "",
+ "CAM_GPIO0",
+ "CAM_GPIO1",
+ "";
+ status = "okay";
+ };
+};
+
+&hdmi {
+ hpd-gpios = <&gpio 28 GPIO_ACTIVE_LOW>;
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio41>;
+ status = "okay";
+};
+
+/* SDHCI is used to control the SDIO for wireless */
+&sdhci {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_gpio34>;
+ status = "okay";
+ bus-width = <4>;
+ non-removable;
+ mmc-pwrseq = <&wifi_pwrseq>;
+
+ brcmf: wifi@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
+
+/* SDHOST is used to drive the SD card */
+&sdhost {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhost_gpio48>;
+ status = "okay";
+ bus-width = <4>;
+};
+
+/* uart0 communicates with the BT module */
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_ctsrts_gpio30 &uart0_gpio32 &gpclk2_gpio43>;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ max-speed = <2000000>;
+ shutdown-gpios = <&expgpio 0 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+/* uart1 is mapped to the pin header */
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_gpio14>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
index 0b31d99..c318bcb 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
@@ -20,9 +20,14 @@
leds {
act {
- gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
+ gpios = <&expgpio 2 GPIO_ACTIVE_HIGH>;
};
};
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&expgpio 1 GPIO_ACTIVE_HIGH>;
+ };
};
&firmware {
@@ -42,6 +47,16 @@
};
};
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio41>;
+ status = "okay";
+};
+
+&hdmi {
+ hpd-gpios = <&expgpio 4 GPIO_ACTIVE_LOW>;
+};
+
/* uart0 communicates with the BT module */
&uart0 {
pinctrl-names = "default";
@@ -51,6 +66,7 @@
bluetooth {
compatible = "brcm,bcm43438-bt";
max-speed = <2000000>;
+ shutdown-gpios = <&expgpio 0 GPIO_ACTIVE_HIGH>;
};
};
@@ -63,11 +79,19 @@
/* SDHCI is used to control the SDIO for wireless */
&sdhci {
+ #address-cells = <1>;
+ #size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&emmc_gpio34>;
status = "okay";
bus-width = <4>;
non-removable;
+ mmc-pwrseq = <&wifi_pwrseq>;
+
+ brcmf: wifi@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
};
/* SDHOST is used to drive the SD card */
diff --git a/arch/arm/boot/dts/bcm283x-rpi-lan7515.dtsi b/arch/arm/boot/dts/bcm283x-rpi-lan7515.dtsi
new file mode 100644
index 0000000..9403da0
--- /dev/null
+++ b/arch/arm/boot/dts/bcm283x-rpi-lan7515.dtsi
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+/ {
+ aliases {
+ ethernet0 = &ethernet;
+ };
+};
+
+&usb {
+ usb-port@1 {
+ compatible = "usb424,2514";
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb-port@1 {
+ compatible = "usb424,2514";
+ reg = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet: ethernet@1 {
+ compatible = "usb424,7800";
+ reg = <1>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index ac00e73..61315cf 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -136,6 +136,7 @@
rng@7e104000 {
compatible = "brcm,bcm2835-rng";
reg = <0x7e104000 0x10>;
+ interrupts = <2 29>;
};
mailbox: mailbox@7e00b880 {
diff --git a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
index 4175174..ff2e551 100644
--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
+++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Asus RT-AC56U
*
* Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
- *
- * 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/bcm4708-asus-rt-ac68u.dts b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
index 8fa033f..3bcc037 100644
--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
+++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Asus RT-AC68U
*
* Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
- *
- * 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/bcm4708-buffalo-wzr-1750dhp.dts b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
index 8b64caa..a587384 100644
--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
@@ -1,10 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Buffalo WZR-1750DHP
*
* Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
- *
- * Licensed under the GNU/GPL. See COPYING for details.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts b/arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts
index 126ab58..6c8f0ad 100644
--- a/arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts
+++ b/arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
index f591b0f..ebda45f 100644
--- a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
+++ b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright 2016 Luxul Inc.
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
index 50d65d8..9dd0e22 100644
--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
+++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
@@ -1,10 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Luxul XWC-1000
*
* Copyright 2014 Luxul Inc.
- *
- * Licensed under the GNU/GPL. See COPYING for details.
*/
/dts-v1/;
@@ -26,9 +25,15 @@
nand: nand@18028000 {
nandcs@0 {
- partition@0 {
- label = "ubi";
- reg = <0x00000000 0x08000000>;
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "ubi";
+ reg = <0x00000000 0x08000000>;
+ };
};
};
};
diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
index bb66ceb..2642494 100644
--- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
+++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Netgear R6300 V2
*
* Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
- *
- * 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/bcm4708-smartrg-sr400ac.dts b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
index 83a4c60..e7b09b7 100644
--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
+++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
@@ -1,10 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X arm platform code.
* DTS for SmartRG SR400ac
*
* Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
- *
- * Licensed under the GNU/GPL. See COPYING for details.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
index 0800a96..16314fc 100644
--- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
+++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Asus RT-N18U
*
* Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
- *
- * 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-buffalo-wzr-600dhp2.dts b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
index c2af33e..328aa90 100644
--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Buffalo WZR-600DHP2
*
* Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
- *
- * 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-buffalo-wzr-900dhp.dts b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
index 87ea6ba..8ea46ee 100644
--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Buffalo WZR-900DHP
*
* Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
- *
- * 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-luxul-xap-1410.dts b/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts
index 9b57598..5eeac73 100644
--- a/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts
+++ b/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright 2017 Luxul Inc.
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts b/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts
index ba1c19b..da4d9ec 100644
--- a/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts
+++ b/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright 2017 Luxul Inc.
- *
- * Licensed under the ISC license.
*/
/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
index 3ed8de4..c94c732 100644
--- a/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts
+++ b/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
index df473cc..2227181 100644
--- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
+++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Asus RT-AC87U
*
* Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
- *
- * 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/bcm4709-buffalo-wxr-1900dhp.dts b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
index 92058c7..79a9633 100644
--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
+++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
@@ -1,10 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Buffalo WXR-1900DHP
*
* Copyright (C) 2015 Felix Fietkau <nbd@openwrt.org>
- *
- * Licensed under the GNU/GPL. See COPYING for details.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts b/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts
index 3d1d9c2..db744a5 100644
--- a/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts
+++ b/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts
index f43ab47..9e267d3 100644
--- a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts
+++ b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for Netgear R7000
*
* Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
- *
- * 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/bcm4709-tplink-archer-c9-v1.dts b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
index ec4a50e..f5bf658 100644
--- a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
+++ b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts b/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
index 7cc7d34..d173bcd 100644
--- a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
+++ b/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
@@ -1,20 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X ARM platform code.
* DTS for D-Link DIR-885L
*
* Copyright (C) 2016 Rafał Miłecki <zajec5@gmail.com>
- *
- * 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,9 +26,15 @@
nand: nand@18028000 {
nandcs@0 {
- partition@0 {
- label = "firmware";
- reg = <0x00000000 0x08000000>;
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "firmware";
+ reg = <0x00000000 0x08000000>;
+ };
};
};
};
diff --git a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
index b6750f7..f47afe3 100644
--- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
+++ b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts b/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts
index ecd22a2..a5cef51 100644
--- a/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts
+++ b/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright (C) 2017 Luxul Inc.
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts b/arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts
new file mode 100644
index 0000000..7fd8547
--- /dev/null
+++ b/arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2018 Luxul Inc.
+ */
+
+/dts-v1/;
+
+#include "bcm47094.dtsi"
+
+/ {
+ compatible = "luxul,xap-1610-v1", "brcm,bcm47094", "brcm,bcm4708";
+ model = "Luxul XAP-1610 V1";
+
+ chosen {
+ bootargs = "earlycon";
+ };
+
+ memory {
+ reg = <0x00000000 0x08000000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ status {
+ label = "bcm53xx:green:status";
+ gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "timer";
+ };
+
+ 2ghz {
+ label = "bcm53xx:blue:2ghz";
+ gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+ };
+
+ 5ghz {
+ label = "bcm53xx:blue:5ghz";
+ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ restart {
+ label = "Reset";
+ linux,code = <KEY_RESTART>;
+ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&spi_nor {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts b/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts
index 15ffb1a..7496aab 100644
--- a/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts
+++ b/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright (C) 2017 Luxul Inc.
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts b/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
index bc1d1e1..53aaa52 100644
--- a/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
+++ b/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright 2016 Luxul Inc.
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts b/arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts
new file mode 100644
index 0000000..bdad726
--- /dev/null
+++ b/arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Copyright 2018 Luxul Inc.
+ */
+
+/dts-v1/;
+
+#include "bcm47094.dtsi"
+#include "bcm5301x-nand-cs0-bch8.dtsi"
+
+/ {
+ compatible = "luxul,xwr-3150-v1", "brcm,bcm47094", "brcm,bcm4708";
+ model = "Luxul XWR-3150 V1";
+
+ chosen {
+ bootargs = "earlycon";
+ };
+
+ memory {
+ reg = <0x00000000 0x08000000
+ 0x88000000 0x18000000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ power {
+ label = "bcm53xx:green:power";
+ gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "default-on";
+ };
+
+ usb3 {
+ label = "bcm53xx:green:usb3";
+ gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
+ trigger-sources = <&ohci_port1>, <&ehci_port1>,
+ <&xhci_port1>;
+ linux,default-trigger = "usbport";
+ };
+
+ status {
+ label = "bcm53xx:green:status";
+ gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "timer";
+ };
+
+ 2ghz {
+ label = "bcm53xx:green:2ghz";
+ gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+ };
+
+ 5ghz {
+ label = "bcm53xx:green:5ghz";
+ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ restart {
+ label = "Reset";
+ linux,code = <KEY_RESTART>;
+ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
+ };
+ };
+};
+
+&usb3 {
+ vcc-gpio = <&chipcommon 18 GPIO_ACTIVE_HIGH>;
+};
+
+&spi_nor {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/bcm47094-netgear-r8500.dts b/arch/arm/boot/dts/bcm47094-netgear-r8500.dts
index 8599299..0e718ed 100644
--- a/arch/arm/boot/dts/bcm47094-netgear-r8500.dts
+++ b/arch/arm/boot/dts/bcm47094-netgear-r8500.dts
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright (C) 2016 Rafał Miłecki <rafal@milecki.pl>
- *
- * Licensed under the ISC license.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/bcm5301x-nand-cs0-bch1.dtsi b/arch/arm/boot/dts/bcm5301x-nand-cs0-bch1.dtsi
index 24b099c..c349e8f0 100644
--- a/arch/arm/boot/dts/bcm5301x-nand-cs0-bch1.dtsi
+++ b/arch/arm/boot/dts/bcm5301x-nand-cs0-bch1.dtsi
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom Northstar NAND.
*
* Copyright (C) 2016 Rafał Miłecki <rafal.milecki@gmail.com>
- *
- * Licensed under the ISC license.
*/
#include "bcm5301x-nand-cs0.dtsi"
diff --git a/arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi b/arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi
index b4e875d..18e25e3 100644
--- a/arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi
+++ b/arch/arm/boot/dts/bcm5301x-nand-cs0-bch4.dtsi
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Copyright 2016 Luxul Inc.
- *
- * Licensed under the ISC license.
*/
#include "bcm5301x-nand-cs0.dtsi"
diff --git a/arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi b/arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi
index 9a9630d..c8e56d3 100644
--- a/arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi
+++ b/arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom BCM470X / BCM5301X Nand chip defaults.
*
@@ -5,8 +6,6 @@
* and uses 8 bit ECC.
*
* Copyright (C) 2015 Hauke Mehrtens <hauke@hauke-m.de>
- *
- * Licensed under the GNU/GPL. See COPYING for details.
*/
#include "bcm5301x-nand-cs0.dtsi"
diff --git a/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi b/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi
index 1684951..e5a2d62 100644
--- a/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi
+++ b/arch/arm/boot/dts/bcm5301x-nand-cs0.dtsi
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
/*
* Broadcom Northstar NAND.
*
* Copyright (C) 2015 Hauke Mehrtens <hauke@hauke-m.de>
- *
- * Licensed under the GNU/GPL. See COPYING for details.
*/
/ {
diff --git a/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts b/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts
index 1c47579..64a2977 100644
--- a/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts
+++ b/arch/arm/boot/dts/berlin2-sony-nsz-gs7.dts
@@ -1,39 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Device Tree file for Sony NSZ-GS7
*
* Sebastian Hesselbarth <sebastian.hesselbarth@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 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/;
diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi
index d575823..db67377 100644
--- a/arch/arm/boot/dts/berlin2.dtsi
+++ b/arch/arm/boot/dts/berlin2.dtsi
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Device Tree Include file for Marvell Armada 1500 (Berlin BG2) SoC
*
@@ -5,38 +6,6 @@
*
* based on GPL'ed 2.6 kernel sources
* (c) Marvell International 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 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.
*/
#include <dt-bindings/clock/berlin2.h>
@@ -149,7 +118,7 @@
local-timer@ad0600 {
compatible = "arm,cortex-a9-twd-timer";
reg = <0xad0600 0x20>;
- interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
clocks = <&chip_clk CLKID_TWD>;
};
diff --git a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
index ca24def..56fa951 100644
--- a/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
+++ b/arch/arm/boot/dts/berlin2cd-google-chromecast.dts
@@ -1,39 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Device Tree file for Google Chromecast
*
* Sebastian Hesselbarth <sebastian.hesselbarth@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 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/;
@@ -52,22 +21,35 @@
memory@0 {
device_type = "memory";
- reg = <0x00000000 0x20000000>; /* 512 MB */
+
+ /*
+ * We're using "linux,usable-memory" instead of "reg" here
+ * because the (signed and encrypted) bootloader that shipped
+ * with this device provides an incorrect memory range in
+ * ATAG_MEM. Linux helpfully overrides the "reg" property with
+ * data from the ATAG, so we can't specify the proper range
+ * normally. Fortunately, this alternate property is checked
+ * first by the OF driver, so we can (ab)use it instead.
+ */
+ linux,usable-memory = <0x00000000 0x20000000>; /* 512 MB */
};
leds {
- compatible = "gpio-leds";
+ compatible = "pwm-leds";
+ pinctrl-0 = <&ledpwm_pmux>;
+ pinctrl-names = "default";
white {
label = "white";
- gpios = <&portc 1 GPIO_ACTIVE_HIGH>;
- default-state = "keep";
+ pwms = <&pwm 0 600000 0>;
+ max-brightness = <255>;
+ linux,default-trigger = "default-on";
};
red {
label = "red";
- gpios = <&portc 2 GPIO_ACTIVE_HIGH>;
- default-state = "keep";
+ pwms = <&pwm 1 600000 0>;
+ max-brightness = <255>;
};
};
};
@@ -86,3 +68,10 @@
&usb_phy1 { status = "okay"; };
&usb1 { status = "okay"; };
+
+&soc_pinctrl {
+ ledpwm_pmux: ledpwm-pmux {
+ groups = "G0";
+ function = "pwm";
+ };
+};
diff --git a/arch/arm/boot/dts/berlin2cd-valve-steamlink.dts b/arch/arm/boot/dts/berlin2cd-valve-steamlink.dts
new file mode 100644
index 0000000..79ac842
--- /dev/null
+++ b/arch/arm/boot/dts/berlin2cd-valve-steamlink.dts
@@ -0,0 +1,79 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright 2018 Alexander Monakov <amonakov@gmail.com>
+ */
+/dts-v1/;
+
+#include "berlin2cd.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "Valve Steam Link";
+ compatible = "valve,steamlink", "marvell,berlin2cd", "marvell,berlin";
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x20000000>; /* 512 MB */
+ };
+
+ gpio-restart {
+ compatible = "gpio-restart";
+ gpios = <&porta 6 GPIO_ACTIVE_HIGH>;
+ active-delay = <100>;
+ inactive-delay = <10>;
+ wait-delay = <100>;
+ priority = <200>;
+ };
+};
+
+&cpu {
+ cpu-supply = <&vcpu>;
+ operating-points = <
+ /* kHz uV */
+ 1000000 1325000
+ >;
+};
+
+&i2c0 {
+ status = "okay";
+
+ /* There are two regulators on the board. One is accessible via I2C,
+ * with buck1 providing SoC power (set up by bootloader to 1.325V or
+ * less depending on leakage value in OTP), and buck2 likely used for
+ * DRAM (providing 1.35V). The other regulator on the opposite side
+ * of the board is probably supplying SDIO and NAND fixed voltages. */
+ regulator@19 {
+ compatible = "marvell,88pg868";
+ reg = <0x19>;
+
+ vcpu: buck1 {
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1325000>;
+ };
+ };
+};
+
+/* Fixed interface to on-board Marvell 8897 Wi-Fi/Bluetooth/NFC chip. */
+&sdhci0 {
+ keep-power-in-suspend;
+ non-removable;
+ status = "okay";
+};
+
+&uart0 {
+ /* RX/TX are routed to TP50/TP51 on the board. */
+ status = "okay";
+};
+
+/* The SoC is connected to on-board USB hub that in turn has one downstream
+ * port wired to the on-board Steam Controller wireless receiver chip. */
+&usb_phy1 { status = "okay"; };
+
+&usb1 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&eth1 { status = "okay"; };
diff --git a/arch/arm/boot/dts/berlin2cd.dtsi b/arch/arm/boot/dts/berlin2cd.dtsi
index 501c59d..e5c1f42 100644
--- a/arch/arm/boot/dts/berlin2cd.dtsi
+++ b/arch/arm/boot/dts/berlin2cd.dtsi
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Device Tree Include file for Marvell Armada 1500-mini (Berlin BG2CD) SoC
*
@@ -5,38 +6,6 @@
*
* based on GPL'ed 2.6 kernel sources
* (c) Marvell International 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 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.
*/
#include <dt-bindings/clock/berlin2.h>
@@ -57,7 +26,7 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu: cpu@0 {
compatible = "arm,cortex-a9";
device_type = "cpu";
next-level-cache = <&l2>;
@@ -73,6 +42,12 @@
};
};
+ pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
refclk: oscillator {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -87,11 +62,6 @@
ranges = <0 0xf7000000 0x1000000>;
- pmu {
- compatible = "arm,cortex-a9-pmu";
- interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
- };
-
sdhci0: sdhci@ab0000 {
compatible = "mrvl,pxav3-mmc";
reg = <0xab0000 0x200>;
@@ -108,6 +78,11 @@
cache-level = <2>;
};
+ snoop-control-unit@ad0000 {
+ compatible = "arm,cortex-a9-scu";
+ reg = <0xad0000 0x100>;
+ };
+
gic: interrupt-controller@ad1000 {
compatible = "arm,cortex-a9-gic";
reg = <0xad1000 0x1000>, <0xad0100 0x0100>;
@@ -115,10 +90,24 @@
#interrupt-cells = <3>;
};
+ global-timer@ad0200 {
+ compatible = "arm,cortex-a9-global-timer";
+ reg = <0xad0200 0x20>;
+ interrupts = <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_EDGE_RISING)>;
+ clocks = <&chip_clk CLKID_TWD>;
+ };
+
local-timer@ad0600 {
compatible = "arm,cortex-a9-twd-timer";
reg = <0xad0600 0x20>;
- interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_EDGE_RISING)>;
+ clocks = <&chip_clk CLKID_TWD>;
+ };
+
+ local-wdt@ad0620 {
+ compatible = "arm,cortex-a9-twd-wdt";
+ reg = <0xad0620 0x20>;
+ interrupts = <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_EDGE_RISING)>;
clocks = <&chip_clk CLKID_TWD>;
};
@@ -254,6 +243,60 @@
};
};
+ i2c0: i2c@1400 {
+ compatible = "snps,designware-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1400 0x100>;
+ interrupts = <16>;
+ clocks = <&chip_clk CLKID_CFG>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@1800 {
+ compatible = "snps,designware-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1800 0x100>;
+ interrupts = <17>;
+ clocks = <&chip_clk CLKID_CFG>;
+ status = "disabled";
+ };
+
+ spi0: spi@1c00 {
+ compatible = "snps,dw-apb-ssi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x1c00 0x100>;
+ interrupts = <4>;
+ clocks = <&chip_clk CLKID_CFG>;
+ status = "disabled";
+ };
+
+ wdt4: watchdog@2000 {
+ compatible = "snps,dw-wdt";
+ reg = <0x2000 0x100>;
+ clocks = <&chip_clk CLKID_CFG>;
+ interrupts = <5>;
+ status = "disabled";
+ };
+
+ wdt5: watchdog@2400 {
+ compatible = "snps,dw-wdt";
+ reg = <0x2400 0x100>;
+ clocks = <&chip_clk CLKID_CFG>;
+ interrupts = <6>;
+ status = "disabled";
+ };
+
+ wdt6: watchdog@2800 {
+ compatible = "snps,dw-wdt";
+ reg = <0x2800 0x100>;
+ clocks = <&chip_clk CLKID_CFG>;
+ interrupts = <7>;
+ status = "disabled";
+ };
+
timer0: timer@2c00 {
compatible = "snps,dw-apb-timer";
reg = <0x2c00 0x14>;
@@ -435,6 +478,36 @@
};
};
+ spi1: spi@6000 {
+ compatible = "snps,dw-apb-ssi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x6000 0x100>;
+ clocks = <&refclk>;
+ interrupts = <5>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@7000 {
+ compatible = "snps,designware-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x7000 0x100>;
+ interrupts = <6>;
+ clocks = <&refclk>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@8000 {
+ compatible = "snps,designware-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x8000 0x100>;
+ interrupts = <7>;
+ clocks = <&refclk>;
+ status = "disabled";
+ };
+
sm_gpio0: gpio@c000 {
compatible = "snps,dw-apb-gpio";
reg = <0xc000 0x400>;
@@ -472,6 +545,16 @@
status = "disabled";
};
+ uart2: serial@b000 {
+ compatible = "snps,dw-apb-uart";
+ reg = <0xb000 0x100>;
+ reg-shift = <2>;
+ reg-io-width = <1>;
+ interrupts = <10>;
+ clocks = <&refclk>;
+ status = "disabled";
+ };
+
sysctrl: system-controller@d000 {
compatible = "simple-mfd", "syscon";
reg = <0xd000 0x100>;
@@ -479,6 +562,12 @@
sys_pinctrl: pin-controller {
compatible = "marvell,berlin2cd-system-pinctrl";
};
+
+ adc: adc {
+ compatible = "marvell,berlin2-adc";
+ interrupts = <12>, <14>;
+ interrupt-names = "adc", "tsen";
+ };
};
sic: interrupt-controller@e000 {
diff --git a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
index 57aa5f8..c162f98 100644
--- a/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
+++ b/arch/arm/boot/dts/berlin2q-marvell-dmp.dts
@@ -1,37 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (C) 2014 Antoine Ténart <antoine.tenart@free-electrons.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 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/;
diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi
index bf3a6c9..516a7ce 100644
--- a/arch/arm/boot/dts/berlin2q.dtsi
+++ b/arch/arm/boot/dts/berlin2q.dtsi
@@ -1,37 +1,6 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (C) 2014 Antoine Ténart <antoine.tenart@free-electrons.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 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.
*/
#include <dt-bindings/clock/berlin2q.h>
@@ -53,7 +22,7 @@
#size-cells = <0>;
enable-method = "marvell,berlin-smp";
- cpu@0 {
+ cpu0: cpu@0 {
compatible = "arm,cortex-a9";
device_type = "cpu";
next-level-cache = <&l2>;
@@ -71,21 +40,21 @@
>;
};
- cpu@1 {
+ cpu1: cpu@1 {
compatible = "arm,cortex-a9";
device_type = "cpu";
next-level-cache = <&l2>;
reg = <1>;
};
- cpu@2 {
+ cpu2: cpu@2 {
compatible = "arm,cortex-a9";
device_type = "cpu";
next-level-cache = <&l2>;
reg = <2>;
};
- cpu@3 {
+ cpu3: cpu@3 {
compatible = "arm,cortex-a9";
device_type = "cpu";
next-level-cache = <&l2>;
@@ -93,6 +62,19 @@
};
};
+ pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>,
+ <&cpu1>,
+ <&cpu2>,
+ <&cpu3>;
+ };
+
refclk: oscillator {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -107,14 +89,6 @@
ranges = <0 0xf7000000 0x1000000>;
interrupt-parent = <&gic>;
- pmu {
- compatible = "arm,cortex-a9-pmu";
- interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
- };
-
sdhci0: sdhci@ab0000 {
compatible = "mrvl,pxav3-mmc";
reg = <0xab0000 0x200>;
@@ -145,6 +119,7 @@
l2: l2-cache-controller@ac0000 {
compatible = "arm,pl310-cache";
reg = <0xac0000 0x1000>;
+ cache-unified;
cache-level = <2>;
arm,data-latency = <2 2 2>;
arm,tag-latency = <2 2 2>;
@@ -159,7 +134,7 @@
compatible = "arm,cortex-a9-twd-timer";
reg = <0xad0600 0x20>;
clocks = <&chip_clk CLKID_TWD>;
- interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
};
gic: interrupt-controller@ad1000 {
diff --git a/arch/arm/boot/dts/da850-evm.dts b/arch/arm/boot/dts/da850-evm.dts
index 3962fa4..0e82bb9 100644
--- a/arch/arm/boot/dts/da850-evm.dts
+++ b/arch/arm/boot/dts/da850-evm.dts
@@ -27,143 +27,6 @@
spi0 = &spi1;
};
- soc@1c00000 {
- pmx_core: pinmux@14120 {
- status = "okay";
-
- mcasp0_pins: pinmux_mcasp0_pins {
- pinctrl-single,bits = <
- /*
- * AHCLKX, ACLKX, AFSX, AHCLKR, ACLKR,
- * AFSR, AMUTE
- */
- 0x00 0x11111111 0xffffffff
- /* AXR11, AXR12 */
- 0x04 0x00011000 0x000ff000
- >;
- };
- nand_pins: nand_pins {
- pinctrl-single,bits = <
- /* EMA_WAIT[0], EMA_OE, EMA_WE, EMA_CS[4], EMA_CS[3] */
- 0x1c 0x10110110 0xf0ff0ff0
- /*
- * EMA_D[0], EMA_D[1], EMA_D[2],
- * EMA_D[3], EMA_D[4], EMA_D[5],
- * EMA_D[6], EMA_D[7]
- */
- 0x24 0x11111111 0xffffffff
- /* EMA_A[1], EMA_A[2] */
- 0x30 0x01100000 0x0ff00000
- >;
- };
- };
- serial0: serial@42000 {
- status = "okay";
- };
- serial1: serial@10c000 {
- status = "okay";
- };
- serial2: serial@10d000 {
- status = "okay";
- };
- rtc0: rtc@23000 {
- status = "okay";
- };
- i2c0: i2c@22000 {
- status = "okay";
- clock-frequency = <100000>;
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0_pins>;
-
- tps: tps@48 {
- reg = <0x48>;
- };
- tlv320aic3106: tlv320aic3106@18 {
- #sound-dai-cells = <0>;
- compatible = "ti,tlv320aic3106";
- reg = <0x18>;
- status = "okay";
-
- /* Regulators */
- IOVDD-supply = <&vdcdc2_reg>;
- /* Derived from VBAT: Baseboard 3.3V / 1.8V */
- AVDD-supply = <&vbat>;
- DRVDD-supply = <&vbat>;
- DVDD-supply = <&vbat>;
- };
- tca6416: gpio@20 {
- compatible = "ti,tca6416";
- reg = <0x20>;
- gpio-controller;
- #gpio-cells = <2>;
- };
- };
- wdt: wdt@21000 {
- status = "okay";
- };
- mmc0: mmc@40000 {
- max-frequency = <50000000>;
- bus-width = <4>;
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mmc0_pins>;
- };
- spi1: spi@30e000 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&spi1_pins &spi1_cs0_pin>;
- flash: m25p80@0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "m25p64";
- spi-max-frequency = <30000000>;
- m25p,fast-read;
- reg = <0>;
- partition@0 {
- label = "U-Boot-SPL";
- reg = <0x00000000 0x00010000>;
- read-only;
- };
- partition@1 {
- label = "U-Boot";
- reg = <0x00010000 0x00080000>;
- read-only;
- };
- partition@2 {
- label = "U-Boot-Env";
- reg = <0x00090000 0x00010000>;
- read-only;
- };
- partition@3 {
- label = "Kernel";
- reg = <0x000a0000 0x00280000>;
- };
- partition@4 {
- label = "Filesystem";
- reg = <0x00320000 0x00400000>;
- };
- partition@5 {
- label = "MAC-Address";
- reg = <0x007f0000 0x00010000>;
- read-only;
- };
- };
- };
- mdio: mdio@224000 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mdio_pins>;
- bus_freq = <2200000>;
- };
- eth0: ethernet@220000 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&mii_pins>;
- };
- gpio: gpio@226000 {
- status = "okay";
- };
- };
vbat: fixedregulator0 {
compatible = "regulator-fixed";
regulator-name = "vbat";
@@ -200,6 +63,155 @@
};
};
+&pmx_core {
+ status = "okay";
+
+ mcasp0_pins: pinmux_mcasp0_pins {
+ pinctrl-single,bits = <
+ /*
+ * AHCLKX, ACLKX, AFSX, AHCLKR, ACLKR,
+ * AFSR, AMUTE
+ */
+ 0x00 0x11111111 0xffffffff
+ /* AXR11, AXR12 */
+ 0x04 0x00011000 0x000ff000
+ >;
+ };
+ nand_pins: nand_pins {
+ pinctrl-single,bits = <
+ /* EMA_WAIT[0], EMA_OE, EMA_WE, EMA_CS[4], EMA_CS[3] */
+ 0x1c 0x10110110 0xf0ff0ff0
+ /*
+ * EMA_D[0], EMA_D[1], EMA_D[2],
+ * EMA_D[3], EMA_D[4], EMA_D[5],
+ * EMA_D[6], EMA_D[7]
+ */
+ 0x24 0x11111111 0xffffffff
+ /* EMA_A[1], EMA_A[2] */
+ 0x30 0x01100000 0x0ff00000
+ >;
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
+
+&serial1 {
+ status = "okay";
+};
+
+&serial2 {
+ status = "okay";
+};
+
+&rtc0 {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+
+ tps: tps@48 {
+ reg = <0x48>;
+ };
+ tlv320aic3106: tlv320aic3106@18 {
+ #sound-dai-cells = <0>;
+ compatible = "ti,tlv320aic3106";
+ reg = <0x18>;
+ status = "okay";
+
+ /* Regulators */
+ IOVDD-supply = <&vdcdc2_reg>;
+ /* Derived from VBAT: Baseboard 3.3V / 1.8V */
+ AVDD-supply = <&vbat>;
+ DRVDD-supply = <&vbat>;
+ DVDD-supply = <&vbat>;
+ };
+ tca6416: gpio@20 {
+ compatible = "ti,tca6416";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+};
+
+&wdt {
+ status = "okay";
+};
+
+&mmc0 {
+ max-frequency = <50000000>;
+ bus-width = <4>;
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc0_pins>;
+ cd-gpios = <&gpio 64 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio 65 GPIO_ACTIVE_HIGH>;
+};
+
+&spi1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins &spi1_cs0_pin>;
+ flash: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "m25p64";
+ spi-max-frequency = <30000000>;
+ m25p,fast-read;
+ reg = <0>;
+ partition@0 {
+ label = "U-Boot-SPL";
+ reg = <0x00000000 0x00010000>;
+ read-only;
+ };
+ partition@1 {
+ label = "U-Boot";
+ reg = <0x00010000 0x00080000>;
+ read-only;
+ };
+ partition@2 {
+ label = "U-Boot-Env";
+ reg = <0x00090000 0x00010000>;
+ read-only;
+ };
+ partition@3 {
+ label = "Kernel";
+ reg = <0x000a0000 0x00280000>;
+ };
+ partition@4 {
+ label = "Filesystem";
+ reg = <0x00320000 0x00400000>;
+ };
+ partition@5 {
+ label = "MAC-Address";
+ reg = <0x007f0000 0x00010000>;
+ read-only;
+ };
+ };
+};
+
+&mdio {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mdio_pins>;
+ bus_freq = <2200000>;
+};
+
+&eth0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mii_pins>;
+};
+
+&gpio {
+ status = "okay";
+};
+
/include/ "tps6507x.dtsi"
&tps {
@@ -309,6 +321,18 @@
};
};
+&usb_phy {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
&vpif {
pinctrl-names = "default";
pinctrl-0 = <&vpif_capture_pins>, <&vpif_display_pins>;
diff --git a/arch/arm/boot/dts/da850-lego-ev3.dts b/arch/arm/boot/dts/da850-lego-ev3.dts
index 1ffd877..ee39324 100644
--- a/arch/arm/boot/dts/da850-lego-ev3.dts
+++ b/arch/arm/boot/dts/da850-lego-ev3.dts
@@ -33,11 +33,9 @@
*/
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
label = "EV3 Brick Buttons";
pinctrl-names = "default";
- pinctrl-0 = <&button_pins>, <&button_bias>;
+ pinctrl-0 = <&button_bias>;
center {
label = "Center";
@@ -81,8 +79,6 @@
*/
leds {
compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&led_pins>;
left_green {
label = "led0:green:brick-status";
@@ -119,8 +115,6 @@
gpio-poweroff {
compatible = "gpio-poweroff";
gpios = <&gpio 107 GPIO_ACTIVE_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&system_power_pin>;
};
sound {
@@ -136,8 +130,6 @@
* the sensor (input) ports, the motor (output) ports and the A/DC.
*/
vcc5v: regulator1 {
- pinctrl-names = "default";
- pinctrl-0 = <&vcc5v_pins>;
compatible = "regulator-fixed";
regulator-name = "vcc5v";
regulator-min-microvolt = <5000000>;
@@ -165,8 +157,6 @@
* 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>;
@@ -177,8 +167,6 @@
* The EV3 can use 6-AA batteries or a rechargeable Li-ion battery pack.
*/
battery {
- pinctrl-names = "default";
- pinctrl-0 = <&battery_pins>;
compatible = "lego,ev3-battery";
io-channels = <&adc 4>, <&adc 3>;
io-channel-names = "voltage", "current";
@@ -206,73 +194,10 @@
&pmx_core {
status = "okay";
- mmc0_cd_pin: pinmux_mmc0_cd {
- pinctrl-single,bits = <
- /* GP5[14] */
- 0x2C 0x00000080 0x000000f0
- >;
- };
-
- button_pins: pinmux_button_pins {
- pinctrl-single,bits = <
- /* GP1[13] */
- 0x8 0x00000800 0x00000f00
- /* GP6[10] */
- 0x34 0x00800000 0x00f00000
- /* GP6[6] */
- 0x38 0x00000080 0x000000f0
- /* GP7[12], GP7[14], GP7[15] */
- 0x40 0x00808800 0x00f0ff00
- >;
- };
-
- led_pins: pinmux_led_pins {
- pinctrl-single,bits = <
- /* GP6[12], GP6[13], GP6[14] */
- 0x34 0x00008880 0x0000fff0
- /* GP6[7] */
- 0x38 0x00000008 0x0000000f
- >;
- };
-
- system_power_pin: pinmux_system_power {
- pinctrl-single,bits = <
- /* GP6[11] */
- 0x34 0x00080000 0x000f0000
- >;
- };
-
- vcc5v_pins: pinmux_vcc5v {
- pinctrl-single,bits = <
- /* GP6[5] */
- 0x40 0x00000080 0x000000f0
- /* GP6[3] */
- 0x4c 0x00008000 0x0000f000
- >;
- };
-
- amp_pins: pinmux_amp_pins {
- pinctrl-single,bits = <
- /* GP6[15] */
- 0x34 0x00000008 0x0000000f
- >;
- };
-
- battery_pins: pinmux_battery_pins {
- pinctrl-single,bits = <
- /* GP0[6] */
- 0x04 0x00000080 0x000000f0
- /* GP8[8] */
- 0x4c 0x00000080 0x000000f0
- >;
- };
-
ev3_lcd_pins: pinmux_lcd {
pinctrl-single,bits = <
- /* SIMO, GP2[11], GP2[12], CLK */
- 0x14 0x00188100 0x00ffff00
- /* GP5[0] */
- 0x30 0x80000000 0xf0000000
+ /* SIMO, CLK */
+ 0x14 0x00100100 0x00f00f00
>;
};
};
@@ -327,7 +252,7 @@
bus-width = <4>;
cd-gpios = <&gpio 94 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
- pinctrl-0 = <&mmc0_pins>, <&mmc0_cd_pin>;
+ pinctrl-0 = <&mmc0_pins>;
};
&spi0 {
diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi
index 1201000..f6f1597 100644
--- a/arch/arm/boot/dts/da850.dtsi
+++ b/arch/arm/boot/dts/da850.dtsi
@@ -59,8 +59,18 @@
pinctrl-single,bit-per-mux;
pinctrl-single,register-width = <32>;
pinctrl-single,function-mask = <0xf>;
+ /* pin base, nr pins & gpio function */
+ pinctrl-single,gpio-range = <&range 0 17 0x8>,
+ <&range 17 8 0x4>,
+ <&range 26 8 0x4>,
+ <&range 34 80 0x8>,
+ <&range 129 31 0x8>;
status = "disabled";
+ range: gpio-range {
+ #pinctrl-single,gpio-range-cells = <3>;
+ };
+
serial0_rtscts_pins: pinmux_serial0_rtscts_pins {
pinctrl-single,bits = <
/* UART0_RTS UART0_CTS */
@@ -549,6 +559,150 @@
status = "disabled";
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx_core 0 15 1>,
+ <&pmx_core 1 14 1>,
+ <&pmx_core 2 13 1>,
+ <&pmx_core 3 12 1>,
+ <&pmx_core 4 11 1>,
+ <&pmx_core 5 10 1>,
+ <&pmx_core 6 9 1>,
+ <&pmx_core 7 8 1>,
+ <&pmx_core 8 7 1>,
+ <&pmx_core 9 6 1>,
+ <&pmx_core 10 5 1>,
+ <&pmx_core 11 4 1>,
+ <&pmx_core 12 3 1>,
+ <&pmx_core 13 2 1>,
+ <&pmx_core 14 1 1>,
+ <&pmx_core 15 0 1>,
+ <&pmx_core 16 39 1>,
+ <&pmx_core 17 38 1>,
+ <&pmx_core 18 37 1>,
+ <&pmx_core 19 36 1>,
+ <&pmx_core 20 35 1>,
+ <&pmx_core 21 34 1>,
+ <&pmx_core 22 33 1>,
+ <&pmx_core 23 32 1>,
+ <&pmx_core 24 24 1>,
+ <&pmx_core 25 22 1>,
+ <&pmx_core 26 21 1>,
+ <&pmx_core 27 20 1>,
+ <&pmx_core 28 19 1>,
+ <&pmx_core 29 18 1>,
+ <&pmx_core 30 17 1>,
+ <&pmx_core 31 16 1>,
+ <&pmx_core 32 55 1>,
+ <&pmx_core 33 54 1>,
+ <&pmx_core 34 53 1>,
+ <&pmx_core 35 52 1>,
+ <&pmx_core 36 51 1>,
+ <&pmx_core 37 50 1>,
+ <&pmx_core 38 49 1>,
+ <&pmx_core 39 48 1>,
+ <&pmx_core 40 47 1>,
+ <&pmx_core 41 46 1>,
+ <&pmx_core 42 45 1>,
+ <&pmx_core 43 44 1>,
+ <&pmx_core 44 43 1>,
+ <&pmx_core 45 42 1>,
+ <&pmx_core 46 41 1>,
+ <&pmx_core 47 40 1>,
+ <&pmx_core 48 71 1>,
+ <&pmx_core 49 70 1>,
+ <&pmx_core 50 69 1>,
+ <&pmx_core 51 68 1>,
+ <&pmx_core 52 67 1>,
+ <&pmx_core 53 66 1>,
+ <&pmx_core 54 65 1>,
+ <&pmx_core 55 64 1>,
+ <&pmx_core 56 63 1>,
+ <&pmx_core 57 62 1>,
+ <&pmx_core 58 61 1>,
+ <&pmx_core 59 60 1>,
+ <&pmx_core 60 59 1>,
+ <&pmx_core 61 58 1>,
+ <&pmx_core 62 57 1>,
+ <&pmx_core 63 56 1>,
+ <&pmx_core 64 87 1>,
+ <&pmx_core 65 86 1>,
+ <&pmx_core 66 85 1>,
+ <&pmx_core 67 84 1>,
+ <&pmx_core 68 83 1>,
+ <&pmx_core 69 82 1>,
+ <&pmx_core 70 81 1>,
+ <&pmx_core 71 80 1>,
+ <&pmx_core 72 70 1>,
+ <&pmx_core 73 78 1>,
+ <&pmx_core 74 77 1>,
+ <&pmx_core 75 76 1>,
+ <&pmx_core 76 75 1>,
+ <&pmx_core 77 74 1>,
+ <&pmx_core 78 73 1>,
+ <&pmx_core 79 72 1>,
+ <&pmx_core 80 103 1>,
+ <&pmx_core 81 102 1>,
+ <&pmx_core 82 101 1>,
+ <&pmx_core 83 100 1>,
+ <&pmx_core 84 99 1>,
+ <&pmx_core 85 98 1>,
+ <&pmx_core 86 97 1>,
+ <&pmx_core 87 96 1>,
+ <&pmx_core 88 95 1>,
+ <&pmx_core 89 94 1>,
+ <&pmx_core 90 93 1>,
+ <&pmx_core 91 92 1>,
+ <&pmx_core 92 91 1>,
+ <&pmx_core 93 90 1>,
+ <&pmx_core 94 89 1>,
+ <&pmx_core 95 88 1>,
+ <&pmx_core 96 158 1>,
+ <&pmx_core 97 157 1>,
+ <&pmx_core 98 156 1>,
+ <&pmx_core 99 155 1>,
+ <&pmx_core 100 154 1>,
+ <&pmx_core 101 129 1>,
+ <&pmx_core 102 113 1>,
+ <&pmx_core 103 112 1>,
+ <&pmx_core 104 111 1>,
+ <&pmx_core 105 110 1>,
+ <&pmx_core 106 109 1>,
+ <&pmx_core 107 108 1>,
+ <&pmx_core 108 107 1>,
+ <&pmx_core 109 106 1>,
+ <&pmx_core 110 105 1>,
+ <&pmx_core 111 104 1>,
+ <&pmx_core 112 145 1>,
+ <&pmx_core 113 144 1>,
+ <&pmx_core 114 143 1>,
+ <&pmx_core 115 142 1>,
+ <&pmx_core 116 141 1>,
+ <&pmx_core 117 140 1>,
+ <&pmx_core 118 139 1>,
+ <&pmx_core 119 138 1>,
+ <&pmx_core 120 137 1>,
+ <&pmx_core 121 136 1>,
+ <&pmx_core 122 135 1>,
+ <&pmx_core 123 134 1>,
+ <&pmx_core 124 133 1>,
+ <&pmx_core 125 132 1>,
+ <&pmx_core 126 131 1>,
+ <&pmx_core 127 130 1>,
+ <&pmx_core 128 159 1>,
+ <&pmx_core 129 31 1>,
+ <&pmx_core 130 30 1>,
+ <&pmx_core 131 20 1>,
+ <&pmx_core 132 28 1>,
+ <&pmx_core 133 27 1>,
+ <&pmx_core 134 26 1>,
+ <&pmx_core 135 23 1>,
+ <&pmx_core 136 153 1>,
+ <&pmx_core 137 152 1>,
+ <&pmx_core 138 151 1>,
+ <&pmx_core 139 150 1>,
+ <&pmx_core 140 149 1>,
+ <&pmx_core 141 148 1>,
+ <&pmx_core 142 147 1>,
+ <&pmx_core 143 146 1>;
};
pinconf: pin-controller@22c00c {
compatible = "ti,da850-pupd";
diff --git a/arch/arm/boot/dts/dm8148-t410.dts b/arch/arm/boot/dts/dm8148-t410.dts
index 6418f9c..c46a227 100644
--- a/arch/arm/boot/dts/dm8148-t410.dts
+++ b/arch/arm/boot/dts/dm8148-t410.dts
@@ -77,7 +77,7 @@
DM814X_IOPAD(0x09dc, PIN_INPUT_PULLUP | 0x1) /* SD2_DAT[0] */
DM814X_IOPAD(0x09e0, PIN_INPUT | 0x1) /* SD2_CLK */
DM814X_IOPAD(0x09f4, PIN_INPUT_PULLUP | 0x2) /* SD2_CMD */
- DM814X_IOPAD(0x0920, PIN_INPUT | 40) /* SD2_SDCD */
+ DM814X_IOPAD(0x0920, PIN_INPUT | 0x40) /* SD2_SDCD */
>;
};
diff --git a/arch/arm/boot/dts/dra7-evm-common.dtsi b/arch/arm/boot/dts/dra7-evm-common.dtsi
index 05a7b1a..33230c8 100644
--- a/arch/arm/boot/dts/dra7-evm-common.dtsi
+++ b/arch/arm/boot/dts/dra7-evm-common.dtsi
@@ -260,3 +260,18 @@
&pcie1_rc {
status = "okay";
};
+
+&mmc4 {
+ bus-width = <4>;
+ cap-power-off-card;
+ keep-power-in-suspend;
+ non-removable;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ wifi@2 {
+ compatible = "ti,wl1835";
+ reg = <2>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <7 IRQ_TYPE_EDGE_RISING>;
+ };
+};
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index f1425b0..0894593 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -20,6 +20,16 @@
reg = <0x0 0x80000000 0x0 0x60000000>; /* 1536 MB */
};
+ evm_12v0: fixedregulator-evm_12v0 {
+ /* main supply */
+ compatible = "regulator-fixed";
+ regulator-name = "evm_12v0";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
evm_1v8_sw: fixedregulator-evm_1v8 {
compatible = "regulator-fixed";
regulator-name = "evm_1v8";
@@ -54,6 +64,48 @@
regulator-max-microvolt = <1800000>;
};
+ evm_3v3: fixedregulator-evm3v3 {
+ /* Output of Cntlr A of TPS43351-Q1 on dra7-evm */
+ compatible = "regulator-fixed";
+ regulator-name = "evm_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&evm_12v0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ evm_5v0: fixedregulator-evm_5v0 {
+ /* Output of Cntlr B of TPS43351-Q1 on dra7-evm */
+ compatible = "regulator-fixed";
+ regulator-name = "evm_5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&evm_12v0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ evm_3v6: fixedregulator-evm_3v6 {
+ compatible = "regulator-fixed";
+ regulator-name = "evm_3v6";
+ regulator-min-microvolt = <3600000>;
+ regulator-max-microvolt = <3600000>;
+ vin-supply = <&evm_5v0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vmmcwl_fixed: fixedregulator-mmcwl {
+ compatible = "regulator-fixed";
+ regulator-name = "vmmcwl_fixed";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&gpio5 8 0>;
+ startup-delay-us = <70000>;
+ enable-active-high;
+ };
+
extcon_usb2: extcon_usb2 {
compatible = "linux,extcon-usb-gpio";
id-gpio = <&pcf_gpio_21 2 GPIO_ACTIVE_HIGH>;
@@ -325,6 +377,7 @@
vmmc-supply = <&evm_1v8_sw>;
vqmmc-supply = <&evm_1v8_sw>;
bus-width = <8>;
+ non-removable;
pinctrl-names = "default", "hs", "ddr_1_8v-rev11", "ddr_1_8v", "hs200_1_8v-rev11", "hs200_1_8v";
pinctrl-0 = <&mmc2_pins_default>;
pinctrl-1 = <&mmc2_pins_hs>;
@@ -334,6 +387,21 @@
pinctrl-5 = <&mmc2_pins_hs200 &mmc2_iodelay_hs200_rev20_conf>;
};
+&mmc4 {
+ status = "okay";
+ vmmc-supply = <&evm_3v6>;
+ vqmmc-supply = <&vmmcwl_fixed>;
+ pinctrl-names = "default-rev11", "default", "hs-rev11", "hs", "sdr12-rev11", "sdr12", "sdr25-rev11", "sdr25";
+ pinctrl-0 = <&mmc4_pins_default &mmc4_iodelay_ds_rev11_conf>;
+ pinctrl-1 = <&mmc4_pins_default &mmc4_iodelay_ds_rev20_conf>;
+ pinctrl-2 = <&mmc4_pins_hs &mmc4_iodelay_sdr12_hs_sdr25_rev11_conf>;
+ pinctrl-3 = <&mmc4_pins_hs &mmc4_iodelay_sdr12_hs_sdr25_rev20_conf>;
+ pinctrl-4 = <&mmc4_pins_sdr12 &mmc4_iodelay_sdr12_hs_sdr25_rev11_conf>;
+ pinctrl-5 = <&mmc4_pins_sdr12 &mmc4_iodelay_sdr12_hs_sdr25_rev20_conf>;
+ pinctrl-6 = <&mmc4_pins_sdr25 &mmc4_iodelay_sdr12_hs_sdr25_rev11_conf>;
+ pinctrl-7 = <&mmc4_pins_sdr25 &mmc4_iodelay_sdr12_hs_sdr25_rev20_conf>;
+};
+
&cpu0 {
vdd-supply = <&smps123_reg>;
};
diff --git a/arch/arm/boot/dts/dra7-mmc-iodelay.dtsi b/arch/arm/boot/dts/dra7-mmc-iodelay.dtsi
new file mode 100644
index 0000000..aa09472
--- /dev/null
+++ b/arch/arm/boot/dts/dra7-mmc-iodelay.dtsi
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MMC IOdelay values for TI's DRA7xx SoCs.
+ * Copyright (C) 2018 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ */
+
+&dra7_pmx_core {
+ mmc1_pins_default_no_clk_pu: mmc1_pins_default_no_clk_pu {
+ pinctrl-single,pins = <
+ DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mmc1_clk.clk */
+ DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
+ DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
+ DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
+ DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
+ DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index f4ddd86..9dcd14e 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -1079,17 +1079,15 @@
};
mmc1: mmc@4809c000 {
- compatible = "ti,omap4-hsmmc";
+ compatible = "ti,dra7-sdhci";
reg = <0x4809c000 0x400>;
interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc1";
- ti,dual-volt;
- ti,needs-special-reset;
- dmas = <&sdma_xbar 61>, <&sdma_xbar 62>;
- dma-names = "tx", "rx";
status = "disabled";
pbias-supply = <&pbias_mmc_reg>;
max-frequency = <192000000>;
+ mmc-ddr-1_8v;
+ mmc-ddr-3_3v;
};
hdqw1w: 1w@480b2000 {
@@ -1100,40 +1098,40 @@
};
mmc2: mmc@480b4000 {
- compatible = "ti,omap4-hsmmc";
+ compatible = "ti,dra7-sdhci";
reg = <0x480b4000 0x400>;
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc2";
- ti,needs-special-reset;
- dmas = <&sdma_xbar 47>, <&sdma_xbar 48>;
- dma-names = "tx", "rx";
status = "disabled";
max-frequency = <192000000>;
+ /* SDR104/DDR50/SDR50 bits in CAPA2 is not supported */
+ sdhci-caps-mask = <0x7 0x0>;
+ mmc-hs200-1_8v;
+ mmc-ddr-1_8v;
+ mmc-ddr-3_3v;
};
mmc3: mmc@480ad000 {
- compatible = "ti,omap4-hsmmc";
+ compatible = "ti,dra7-sdhci";
reg = <0x480ad000 0x400>;
interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc3";
- ti,needs-special-reset;
- dmas = <&sdma_xbar 77>, <&sdma_xbar 78>;
- dma-names = "tx", "rx";
status = "disabled";
/* Errata i887 limits max-frequency of MMC3 to 64 MHz */
max-frequency = <64000000>;
+ /* SDMA is not supported */
+ sdhci-caps-mask = <0x0 0x400000>;
};
mmc4: mmc@480d1000 {
- compatible = "ti,omap4-hsmmc";
+ compatible = "ti,dra7-sdhci";
reg = <0x480d1000 0x400>;
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mmc4";
- ti,needs-special-reset;
- dmas = <&sdma_xbar 57>, <&sdma_xbar 58>;
- dma-names = "tx", "rx";
status = "disabled";
max-frequency = <192000000>;
+ /* SDMA is not supported */
+ sdhci-caps-mask = <0x0 0x400000>;
};
mmu0_dsp1: mmu@40d01000 {
diff --git a/arch/arm/boot/dts/dra71-evm.dts b/arch/arm/boot/dts/dra71-evm.dts
index ebc4bba..b7aeaee 100644
--- a/arch/arm/boot/dts/dra71-evm.dts
+++ b/arch/arm/boot/dts/dra71-evm.dts
@@ -7,6 +7,7 @@
*/
#include "dra72-evm-common.dtsi"
+#include "dra7-mmc-iodelay.dtsi"
#include "dra72x-mmc-iodelay.dtsi"
#include <dt-bindings/net/ti-dp83867.h>
@@ -50,19 +51,6 @@
};
};
-&dra7_pmx_core {
- mmc1_pins_default: mmc1_pins_default {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLDOWN | MUX_MODE0) /* mmc1_clk.clk */
- DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
- DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
- DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
- DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
- DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
- >;
- };
-};
-
&i2c1 {
status = "okay";
clock-frequency = <400000>;
@@ -187,7 +175,7 @@
&mmc1 {
pinctrl-names = "default", "hs", "sdr12", "sdr25", "sdr50", "ddr50", "sdr104";
- pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-0 = <&mmc1_pins_default_no_clk_pu>;
pinctrl-1 = <&mmc1_pins_hs>;
pinctrl-2 = <&mmc1_pins_sdr12>;
pinctrl-3 = <&mmc1_pins_sdr25>;
@@ -204,6 +192,7 @@
pinctrl-2 = <&mmc2_pins_ddr_rev20 &mmc2_iodelay_ddr_conf>;
pinctrl-3 = <&mmc2_pins_hs200 &mmc2_iodelay_hs200_rev20_conf>;
vmmc-supply = <&evm_1v8_sw>;
+ vqmmc-supply = <&evm_1v8_sw>;
};
&mac {
diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi
index e85f560..df174f5 100644
--- a/arch/arm/boot/dts/dra72-evm-common.dtsi
+++ b/arch/arm/boot/dts/dra72-evm-common.dtsi
@@ -44,6 +44,16 @@
regulator-boot-on;
};
+ evm_3v6: fixedregulator-evm_3v6 {
+ compatible = "regulator-fixed";
+ regulator-name = "evm_3v6";
+ regulator-min-microvolt = <3600000>;
+ regulator-max-microvolt = <3600000>;
+ vin-supply = <&evm_5v0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
vsys_3v3: fixedregulator-vsys3v3 {
/* Output 2 of TPS43351QDAPRQ1 on dra72-evm */
/* Output 2 of LM5140QRWGTQ1 on dra71-evm */
@@ -171,36 +181,18 @@
clocks = <&atl_clkin2_ck>;
};
};
-};
-
-&dra7_pmx_core {
- mmc1_pins_default: mmc1_pins_default {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x376c, PIN_INPUT | MUX_MODE14) /* mmc1sdcd.gpio219 */
- DRA7XX_CORE_IOPAD(0x3754, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_clk.clk */
- DRA7XX_CORE_IOPAD(0x3758, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_cmd.cmd */
- DRA7XX_CORE_IOPAD(0x375c, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat0.dat0 */
- DRA7XX_CORE_IOPAD(0x3760, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat1.dat1 */
- DRA7XX_CORE_IOPAD(0x3764, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat2.dat2 */
- DRA7XX_CORE_IOPAD(0x3768, PIN_INPUT_PULLUP | MUX_MODE0) /* mmc1_dat3.dat3 */
- >;
- };
- mmc2_pins_default: mmc2_pins_default {
- pinctrl-single,pins = <
- DRA7XX_CORE_IOPAD(0x349c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a23.mmc2_clk */
- DRA7XX_CORE_IOPAD(0x34b0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_cs1.mmc2_cmd */
- DRA7XX_CORE_IOPAD(0x34a0, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a24.mmc2_dat0 */
- DRA7XX_CORE_IOPAD(0x34a4, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a25.mmc2_dat1 */
- DRA7XX_CORE_IOPAD(0x34a8, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a26.mmc2_dat2 */
- DRA7XX_CORE_IOPAD(0x34ac, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a27.mmc2_dat3 */
- DRA7XX_CORE_IOPAD(0x348c, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a19.mmc2_dat4 */
- DRA7XX_CORE_IOPAD(0x3490, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a20.mmc2_dat5 */
- DRA7XX_CORE_IOPAD(0x3494, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a21.mmc2_dat6 */
- DRA7XX_CORE_IOPAD(0x3498, PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
- >;
+ vmmcwl_fixed: fixedregulator-mmcwl {
+ compatible = "regulator-fixed";
+ regulator-name = "vmmcwl_fixed";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&gpio5 8 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
};
+};
+&dra7_pmx_core {
dcan1_pins_default: dcan1_pins_default {
pinctrl-single,pins = <
DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0) /* dcan1_tx */
@@ -421,10 +413,33 @@
pinctrl-names = "default";
pinctrl-0 = <&mmc2_pins_default>;
bus-width = <8>;
- ti,non-removable;
+ non-removable;
max-frequency = <192000000>;
};
+&mmc4 {
+ status = "okay";
+ vmmc-supply = <&evm_3v6>;
+ vqmmc-supply = <&vmmcwl_fixed>;
+ bus-width = <4>;
+ cap-power-off-card;
+ keep-power-in-suspend;
+ non-removable;
+ pinctrl-names = "default", "hs", "sdr12", "sdr25";
+ pinctrl-0 = <&mmc4_pins_default>;
+ pinctrl-1 = <&mmc4_pins_default>;
+ pinctrl-2 = <&mmc4_pins_default>;
+ pinctrl-3 = <&mmc4_pins_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ wifi@2 {
+ compatible = "ti,wl1835";
+ reg = <2>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <7 IRQ_TYPE_EDGE_RISING>;
+ };
+};
+
&mac {
status = "okay";
};
diff --git a/arch/arm/boot/dts/dra72x-mmc-iodelay.dtsi b/arch/arm/boot/dts/dra72x-mmc-iodelay.dtsi
index 088013c..edad87c 100644
--- a/arch/arm/boot/dts/dra72x-mmc-iodelay.dtsi
+++ b/arch/arm/boot/dts/dra72x-mmc-iodelay.dtsi
@@ -202,6 +202,17 @@
DRA7XX_CORE_IOPAD(0x3498, PIN_INPUT_PULLUP | MODE_SELECT | MUX_MODE1) /* gpmc_a22.mmc2_dat7 */
>;
};
+
+ mmc4_pins_default: mmc4_pins_default {
+ pinctrl-single,pins = <
+ DRA7XX_CORE_IOPAD(0x37e8, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_ctsn.mmc4_clk */
+ DRA7XX_CORE_IOPAD(0x37ec, PIN_INPUT_PULLUP | MUX_MODE3) /* uart1_rtsn.mmc4_cmd */
+ DRA7XX_CORE_IOPAD(0x37f0, PIN_INPUT_PULLUP | MUX_MODE3) /* uart2_rxd.mmc4_dat0 */
+ DRA7XX_CORE_IOPAD(0x37f4, PIN_INPUT_PULLUP | MUX_MODE3) /* uart2_txd.mmc4_dat1 */
+ DRA7XX_CORE_IOPAD(0x37f8, PIN_INPUT_PULLUP | MUX_MODE3) /* uart2_ctsn.mmc4_dat2 */
+ DRA7XX_CORE_IOPAD(0x37fc, PIN_INPUT_PULLUP | MUX_MODE3) /* uart2_rtsn.mmc4_dat3 */
+ >;
+ };
};
&dra7_iodelay_core {
diff --git a/arch/arm/boot/dts/dra76-evm.dts b/arch/arm/boot/dts/dra76-evm.dts
index 2deb964..c07f005 100644
--- a/arch/arm/boot/dts/dra76-evm.dts
+++ b/arch/arm/boot/dts/dra76-evm.dts
@@ -42,6 +42,16 @@
regulator-boot-on;
};
+ vio_3v6: fixedregulator-vio_3v6 {
+ compatible = "regulator-fixed";
+ regulator-name = "vio_3v6";
+ regulator-min-microvolt = <3600000>;
+ regulator-max-microvolt = <3600000>;
+ vin-supply = <&vsys_5v0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
vsys_3v3: fixedregulator-vsys3v3 {
/* Output of Cntlr A of TPS43351-Q1 on dra76-evm */
compatible = "regulator-fixed";
@@ -81,6 +91,16 @@
vin-supply = <&smps5_reg>;
};
+ vmmcwl_fixed: fixedregulator-mmcwl {
+ compatible = "regulator-fixed";
+ regulator-name = "vmmcwl_fixed";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&gpio5 8 0>; /* gpio5_8 */
+ startup-delay-us = <70000>;
+ enable-active-high;
+ };
+
vtt_fixed: fixedregulator-vtt {
compatible = "regulator-fixed";
regulator-name = "vtt_fixed";
@@ -307,7 +327,7 @@
&mmc1 {
status = "okay";
vmmc-supply = <&vio_3v3_sd>;
- vmmc_aux-supply = <&ldo4_reg>;
+ vqmmc-supply = <&ldo4_reg>;
bus-width = <4>;
/*
* SDCD signal is not being used here - using the fact that GPIO mode
@@ -324,6 +344,7 @@
vmmc-supply = <&vio_1v8>;
vqmmc-supply = <&vio_1v8>;
bus-width = <8>;
+ non-removable;
pinctrl-names = "default", "hs", "ddr_1_8v", "hs200_1_8v";
pinctrl-0 = <&mmc2_pins_default>;
pinctrl-1 = <&mmc2_pins_default>;
@@ -331,6 +352,17 @@
pinctrl-3 = <&mmc2_pins_hs200 &mmc2_iodelay_hs200_conf>;
};
+&mmc4 {
+ status = "okay";
+ vmmc-supply = <&vio_3v6>;
+ vqmmc-supply = <&vmmcwl_fixed>;
+ pinctrl-names = "default", "hs", "sdr12", "sdr25";
+ pinctrl-0 = <&mmc4_pins_hs &mmc4_iodelay_default_conf>;
+ pinctrl-1 = <&mmc4_pins_hs &mmc4_iodelay_manual1_conf>;
+ pinctrl-2 = <&mmc4_pins_hs &mmc4_iodelay_manual1_conf>;
+ pinctrl-3 = <&mmc4_pins_hs &mmc4_iodelay_manual1_conf>;
+};
+
/* No RTC on this device */
&rtc {
status = "disabled";
diff --git a/arch/arm/boot/dts/emev2-kzm9d.dts b/arch/arm/boot/dts/emev2-kzm9d.dts
index c238407..0af44b7 100644
--- a/arch/arm/boot/dts/emev2-kzm9d.dts
+++ b/arch/arm/boot/dts/emev2-kzm9d.dts
@@ -34,9 +34,6 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
-
one {
debounce-interval = <50>;
wakeup-source;
diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/emev2.dtsi
index 42ea246..fec1241 100644
--- a/arch/arm/boot/dts/emev2.dtsi
+++ b/arch/arm/boot/dts/emev2.dtsi
@@ -31,13 +31,13 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
clock-frequency = <533000000>;
};
- cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <1>;
@@ -57,6 +57,7 @@
compatible = "arm,cortex-a9-pmu";
interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
};
clocks@e0110000 {
diff --git a/arch/arm/boot/dts/exynos-syscon-restart.dtsi b/arch/arm/boot/dts/exynos-syscon-restart.dtsi
index 4b3dd05..ecf4166 100644
--- a/arch/arm/boot/dts/exynos-syscon-restart.dtsi
+++ b/arch/arm/boot/dts/exynos-syscon-restart.dtsi
@@ -3,22 +3,18 @@
* Samsung's Exynos SoC syscon reboot/poweroff nodes common definition.
*/
-/ {
- soc {
- compatible = "simple-bus";
-
- poweroff: syscon-poweroff {
- compatible = "syscon-poweroff";
- regmap = <&pmu_system_controller>;
- offset = <0x330C>; /* PS_HOLD_CONTROL */
- mask = <0x5200>; /* reset value */
- };
+&pmu_system_controller {
+ poweroff: syscon-poweroff {
+ compatible = "syscon-poweroff";
+ regmap = <&pmu_system_controller>;
+ offset = <0x330C>; /* PS_HOLD_CONTROL */
+ mask = <0x5200>; /* reset value */
+ };
- reboot: syscon-reboot {
- compatible = "syscon-reboot";
- regmap = <&pmu_system_controller>;
- offset = <0x0400>; /* SWRESET */
- mask = <0x1>;
- };
+ reboot: syscon-reboot {
+ compatible = "syscon-reboot";
+ regmap = <&pmu_system_controller>;
+ offset = <0x0400>; /* SWRESET */
+ mask = <0x1>;
};
};
diff --git a/arch/arm/boot/dts/exynos3250-rinato.dts b/arch/arm/boot/dts/exynos3250-rinato.dts
index 2c34607..2a6b828 100644
--- a/arch/arm/boot/dts/exynos3250-rinato.dts
+++ b/arch/arm/boot/dts/exynos3250-rinato.dts
@@ -24,6 +24,10 @@
i2c7 = &i2c_max77836;
};
+ chosen {
+ stdout-path = &serial_1;
+ };
+
memory@40000000 {
device_type = "memory";
reg = <0x40000000 0x1ff00000>;
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index 0a5f989..962af97 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -15,7 +15,6 @@
*/
#include "exynos4-cpu-thermal.dtsi"
-#include "exynos-syscon-restart.dtsi"
#include <dt-bindings/clock/exynos3250.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
@@ -919,3 +918,4 @@
};
#include "exynos3250-pinctrl.dtsi"
+#include "exynos-syscon-restart.dtsi"
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index 909a9f2..dfe41b6 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -20,7 +20,6 @@
#include <dt-bindings/clock/exynos-audss-clk.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
-#include "exynos-syscon-restart.dtsi"
/ {
interrupt-parent = <&gic>;
@@ -1025,3 +1024,5 @@
};
};
};
+
+#include "exynos-syscon-restart.dtsi"
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index 9a310e8..2ab99f9 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -34,26 +34,17 @@
stdout-path = &serial_2;
};
- regulators {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <0>;
-
- mmc_reg: regulator@0 {
- compatible = "regulator-fixed";
- reg = <0>;
- regulator-name = "VMEM_VDD_2.8V";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- gpio = <&gpx1 1 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- };
+ mmc_reg: voltage-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "VMEM_VDD_2.8V";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ gpio = <&gpx1 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
};
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
up {
label = "Up";
@@ -131,12 +122,23 @@
cpu0-supply = <&buck1_reg>;
};
+&exynos_usbphy {
+ status = "okay";
+};
+
&fimd {
pinctrl-0 = <&lcd_en &lcd_clk &lcd_data24 &pwm0_out>;
pinctrl-names = "default";
status = "okay";
};
+&hsotg {
+ vusb_d-supply = <&ldo3_reg>;
+ vusb_a-supply = <&ldo8_reg>;
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
&i2c_0 {
status = "okay";
samsung,i2c-sda-delay = <100>;
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index eaeeb4f..6f1d76c 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -259,8 +259,8 @@
reg = <0x48>;
interrupt-parent = <&gpx0>;
interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
- x-size = <720>;
- y-size = <1280>;
+ touchscreen-size-x = <720>;
+ touchscreen-size-y = <1280>;
avdd-supply = <&tsp_reg>;
vdd-supply = <&tsp_reg>;
};
diff --git a/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi b/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi
index ee8e1f4..30eee59 100644
--- a/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi
+++ b/arch/arm/boot/dts/exynos4412-galaxy-s3.dtsi
@@ -15,24 +15,22 @@
i2c10 = &i2c_cm36651;
};
- regulators {
- lcd_vdd3_reg: voltage-regulator-2 {
- compatible = "regulator-fixed";
- regulator-name = "LCD_VDD_2.2V";
- regulator-min-microvolt = <2200000>;
- regulator-max-microvolt = <2200000>;
- gpio = <&gpc0 1 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- };
+ lcd_vdd3_reg: voltage-regulator-6 {
+ compatible = "regulator-fixed";
+ regulator-name = "LCD_VDD_2.2V";
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ gpio = <&gpc0 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
- ps_als_reg: voltage-regulator-5 {
- compatible = "regulator-fixed";
- regulator-name = "LED_A_3.0V";
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- gpio = <&gpj0 5 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- };
+ ps_als_reg: voltage-regulator-7 {
+ compatible = "regulator-fixed";
+ regulator-name = "LED_A_3.0V";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpj0 5 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
};
i2c_ak8975: i2c-gpio-0 {
@@ -120,8 +118,8 @@
reg = <0x48>;
interrupt-parent = <&gpm2>;
interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
- x-size = <720>;
- y-size = <1280>;
+ touchscreen-size-x = <720>;
+ touchscreen-size-y = <1280>;
avdd-supply = <&ldo23_reg>;
vdd-supply = <&ldo24_reg>;
};
diff --git a/arch/arm/boot/dts/exynos4412-midas.dtsi b/arch/arm/boot/dts/exynos4412-midas.dtsi
index 76f2b30..dc11ca1 100644
--- a/arch/arm/boot/dts/exynos4412-midas.dtsi
+++ b/arch/arm/boot/dts/exynos4412-midas.dtsi
@@ -46,56 +46,50 @@
};
};
- regulators {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <0>;
-
- cam_io_reg: voltage-regulator-1 {
- compatible = "regulator-fixed";
- regulator-name = "CAM_SENSOR_A";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- enable-active-high;
- status = "disabled";
- };
+ cam_io_reg: voltage-regulator-1 {
+ compatible = "regulator-fixed";
+ regulator-name = "CAM_SENSOR_A";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ enable-active-high;
+ status = "disabled";
+ };
- cam_af_reg: voltage-regulator-3 {
- compatible = "regulator-fixed";
- regulator-name = "CAM_AF";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- enable-active-high;
- status = "disabled";
- };
+ cam_af_reg: voltage-regulator-2 {
+ compatible = "regulator-fixed";
+ regulator-name = "CAM_AF";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ enable-active-high;
+ status = "disabled";
+ };
- vsil12: voltage-regulator-6 {
- compatible = "regulator-fixed";
- regulator-name = "VSIL_1.2V";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- gpio = <&gpl0 4 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- vin-supply = <&buck7_reg>;
- };
+ vsil12: voltage-regulator-3 {
+ compatible = "regulator-fixed";
+ regulator-name = "VSIL_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ gpio = <&gpl0 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&buck7_reg>;
+ };
- vcc33mhl: voltage-regulator-7 {
- compatible = "regulator-fixed";
- regulator-name = "VCC_3.3_MHL";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- gpio = <&gpl0 4 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- };
+ vcc33mhl: voltage-regulator-4 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_3.3_MHL";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpl0 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
- vcc18mhl: voltage-regulator-8 {
- compatible = "regulator-fixed";
- regulator-name = "VCC_1.8_MHL";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- gpio = <&gpl0 4 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- };
+ vcc18mhl: voltage-regulator-5 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_1.8_MHL";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ gpio = <&gpl0 4 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
};
gpio-keys {
diff --git a/arch/arm/boot/dts/exynos4412-n710x.dts b/arch/arm/boot/dts/exynos4412-n710x.dts
index eb402a0..fe2bfd7 100644
--- a/arch/arm/boot/dts/exynos4412-n710x.dts
+++ b/arch/arm/boot/dts/exynos4412-n710x.dts
@@ -13,15 +13,13 @@
/* bootargs are passed in by bootloader */
- regulators {
- cam_vdda_reg: voltage-regulator-9 {
- compatible = "regulator-fixed";
- regulator-name = "CAM_SENSOR_CORE_1.2V";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- gpio = <&gpm4 1 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- };
+ cam_vdda_reg: voltage-regulator-6 {
+ compatible = "regulator-fixed";
+ regulator-name = "CAM_SENSOR_CORE_1.2V";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ gpio = <&gpm4 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
};
};
diff --git a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
index d7ad07f..a09e46c 100644
--- a/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
+++ b/arch/arm/boot/dts/exynos4412-odroid-common.dtsi
@@ -37,20 +37,14 @@
};
sound: sound {
- compatible = "simple-audio-card";
+ compatible = "hardkernel,odroid-xu4-audio";
- simple-audio-card,format = "i2s";
- simple-audio-card,bitclock-master = <&link0_codec>;
- simple-audio-card,frame-master = <&link0_codec>;
-
- simple-audio-card,cpu {
+ cpu {
sound-dai = <&i2s0 0>;
- system-clock-frequency = <19200000>;
};
- link0_codec: simple-audio-card,codec {
- sound-dai = <&max98090>;
- clocks = <&i2s0 CLK_I2S_CDCLK>;
+ codec {
+ sound-dai = <&hdmi>, <&max98090>;
};
};
@@ -142,14 +136,25 @@
pinctrl-0 = <>;
};
+&clock {
+ assigned-clocks = <&clock CLK_FOUT_EPLL>;
+ assigned-clock-rates = <45158401>;
+};
+
&clock_audss {
assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>,
<&clock_audss EXYNOS_MOUT_I2S>,
<&clock_audss EXYNOS_DOUT_SRP>,
- <&clock_audss EXYNOS_DOUT_AUD_BUS>;
+ <&clock_audss EXYNOS_DOUT_AUD_BUS>,
+ <&clock_audss EXYNOS_DOUT_I2S>;
+
assigned-clock-parents = <&clock CLK_FOUT_EPLL>,
- <&clock_audss EXYNOS_MOUT_AUDSS>;
- assigned-clock-rates = <0>, <0>, <192000000>, <19200000>;
+ <&clock_audss EXYNOS_MOUT_AUDSS>;
+
+ assigned-clock-rates = <0>, <0>,
+ <196608001>,
+ <(196608001 / 2)>,
+ <(196608001 / 8)>;
};
&cpu0 {
@@ -498,6 +503,8 @@
pinctrl-0 = <&i2s0_bus>;
pinctrl-names = "default";
status = "okay";
+ assigned-clocks = <&i2s0 CLK_I2S_RCLK_SRC>;
+ assigned-clock-parents = <&clock_audss EXYNOS_SCLK_I2S>;
};
&mixer {
diff --git a/arch/arm/boot/dts/exynos4412-odroidu3.dts b/arch/arm/boot/dts/exynos4412-odroidu3.dts
index bdcd452..459919b 100644
--- a/arch/arm/boot/dts/exynos4412-odroidu3.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidu3.dts
@@ -113,11 +113,11 @@
};
&sound {
- simple-audio-card,name = "Odroid-U3";
- simple-audio-card,widgets =
+ model = "Odroid-U3";
+ samsung,audio-widgets =
"Headphone", "Headphone Jack",
"Speakers", "Speakers";
- simple-audio-card,routing =
+ samsung,audio-routing =
"Headphone Jack", "HPL",
"Headphone Jack", "HPR",
"Headphone Jack", "MICBIAS",
diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts
index 2dff129..348556f 100644
--- a/arch/arm/boot/dts/exynos4412-odroidx.dts
+++ b/arch/arm/boot/dts/exynos4412-odroidx.dts
@@ -97,12 +97,12 @@
};
&sound {
- simple-audio-card,name = "Odroid-X";
- simple-audio-card,widgets =
+ model = "Odroid-X";
+ samsung,audio-widgets =
"Headphone", "Headphone Jack",
"Microphone", "Mic Jack",
"Microphone", "DMIC";
- simple-audio-card,routing =
+ samsung,audio-routing =
"Headphone Jack", "HPL",
"Headphone Jack", "HPR",
"IN1", "Mic Jack",
diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
index 1514f0d..346f719 100644
--- a/arch/arm/boot/dts/exynos4412-origen.dts
+++ b/arch/arm/boot/dts/exynos4412-origen.dts
@@ -90,7 +90,7 @@
samsung,vbus-gpio = <&gpx3 5 1>;
status = "okay";
- port@1{
+ port@1 {
status = "okay";
};
port@2 {
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi
index 2ae1ab6..7b43c10 100644
--- a/arch/arm/boot/dts/exynos4412.dtsi
+++ b/arch/arm/boot/dts/exynos4412.dtsi
@@ -298,7 +298,7 @@
status = "disabled";
};
- sysmmu_g2d: sysmmu@10A40000{
+ sysmmu_g2d: sysmmu@10a40000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x10A40000 0x1000>;
interrupt-parent = <&combiner>;
diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index f8d7de1..5d2f0a0 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -12,7 +12,6 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/interrupt-controller/irq.h>
-#include "exynos-syscon-restart.dtsi"
/ {
interrupt-parent = <&gic>;
@@ -197,8 +196,6 @@
reg = <0x145B0000 0x1000>;
interrupts = <10 3>;
interrupt-parent = <&combiner>;
- #address-cells = <1>;
- #size-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index 45283a6..2daf505 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -132,10 +132,6 @@
reg = <0x100440A0 0x20>;
#power-domain-cells = <0>;
label = "DISP1";
- clocks = <&clock CLK_FIN_PLL>,
- <&clock CLK_MOUT_ACLK200_DISP1_SUB>,
- <&clock CLK_MOUT_ACLK300_DISP1_SUB>;
- clock-names = "oscclk", "clk0", "clk1";
};
pd_mau: power-domain@100440c0 {
@@ -882,7 +878,7 @@
#iommu-cells = <0>;
};
- sysmmu_fimc_dis1: sysmmu@132E0000{
+ sysmmu_fimc_dis1: sysmmu@132e0000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x132E0000 0x1000>;
interrupt-parent = <&combiner>;
@@ -1117,3 +1113,4 @@
};
#include "exynos5250-pinctrl.dtsi"
+#include "exynos-syscon-restart.dtsi"
diff --git a/arch/arm/boot/dts/exynos5410.dtsi b/arch/arm/boot/dts/exynos5410.dtsi
index 55509c6..20e789e 100644
--- a/arch/arm/boot/dts/exynos5410.dtsi
+++ b/arch/arm/boot/dts/exynos5410.dtsi
@@ -439,3 +439,4 @@
};
#include "exynos5410-pinctrl.dtsi"
+#include "exynos-syscon-restart.dtsi"
diff --git a/arch/arm/boot/dts/exynos5420-peach-pit.dts b/arch/arm/boot/dts/exynos5420-peach-pit.dts
index 244f009..57c2332 100644
--- a/arch/arm/boot/dts/exynos5420-peach-pit.dts
+++ b/arch/arm/boot/dts/exynos5420-peach-pit.dts
@@ -29,7 +29,7 @@
aliases {
/* Assign 20 so we don't get confused w/ builtin ones */
- i2c20 = "/spi@12d40000/cros-ec@0/i2c-tunnel";
+ i2c20 = &i2c_tunnel;
};
backlight: backlight {
@@ -970,7 +970,7 @@
samsung,spi-feedback-delay = <1>;
};
- i2c-tunnel {
+ i2c_tunnel: i2c-tunnel {
compatible = "google,cros-ec-i2c-tunnel";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index 2f3cb2a..f4e8c58 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -276,10 +276,6 @@
reg = <0x10044000 0x20>;
#power-domain-cells = <0>;
label = "GSC";
- clocks = <&clock CLK_FIN_PLL>,
- <&clock CLK_MOUT_USER_ACLK300_GSCL>,
- <&clock CLK_GSCL0>, <&clock CLK_GSCL1>;
- clock-names = "oscclk", "clk0", "asb0", "asb1";
};
isp_pd: power-domain@10044020 {
@@ -292,10 +288,6 @@
mfc_pd: power-domain@10044060 {
compatible = "samsung,exynos4210-pd";
reg = <0x10044060 0x20>;
- clocks = <&clock CLK_FIN_PLL>,
- <&clock CLK_MOUT_USER_ACLK333>,
- <&clock CLK_ACLK333>;
- clock-names = "oscclk", "clk0","asb0";
#power-domain-cells = <0>;
label = "MFC";
};
@@ -312,12 +304,6 @@
reg = <0x100440C0 0x20>;
#power-domain-cells = <0>;
label = "DISP";
- clocks = <&clock CLK_FIN_PLL>,
- <&clock CLK_MOUT_USER_ACLK200_DISP1>,
- <&clock CLK_MOUT_USER_ACLK300_DISP1>,
- <&clock CLK_MOUT_USER_ACLK400_DISP1>,
- <&clock CLK_FIMD1>, <&clock CLK_MIXER>;
- clock-names = "oscclk", "clk0", "clk1", "clk2", "asb0", "asb1";
};
mau_pd: power-domain@100440e0 {
@@ -687,6 +673,36 @@
iommus = <&sysmmu_gscl1>;
};
+ scaler_0: scaler@12800000 {
+ compatible = "samsung,exynos5420-scaler";
+ reg = <0x12800000 0x1294>;
+ interrupts = <0 220 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clock CLK_MSCL0>;
+ clock-names = "mscl";
+ power-domains = <&msc_pd>;
+ iommus = <&sysmmu_scaler0r>, <&sysmmu_scaler0w>;
+ };
+
+ scaler_1: scaler@12810000 {
+ compatible = "samsung,exynos5420-scaler";
+ reg = <0x12810000 0x1294>;
+ interrupts = <0 221 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clock CLK_MSCL1>;
+ clock-names = "mscl";
+ power-domains = <&msc_pd>;
+ iommus = <&sysmmu_scaler1r>, <&sysmmu_scaler1w>;
+ };
+
+ scaler_2: scaler@12820000 {
+ compatible = "samsung,exynos5420-scaler";
+ reg = <0x12820000 0x1294>;
+ interrupts = <0 222 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clock CLK_MSCL2>;
+ clock-names = "mscl";
+ power-domains = <&msc_pd>;
+ iommus = <&sysmmu_scaler2r>, <&sysmmu_scaler2w>;
+ };
+
jpeg_0: jpeg@11f50000 {
compatible = "samsung,exynos5420-jpeg";
reg = <0x11F50000 0x1000>;
@@ -761,7 +777,7 @@
#include "exynos5420-tmu-sensor-conf.dtsi"
};
- sysmmu_g2dr: sysmmu@0x10A60000 {
+ sysmmu_g2dr: sysmmu@10a60000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x10A60000 0x1000>;
interrupt-parent = <&combiner>;
@@ -771,7 +787,7 @@
#iommu-cells = <0>;
};
- sysmmu_g2dw: sysmmu@0x10A70000 {
+ sysmmu_g2dw: sysmmu@10a70000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x10A70000 0x1000>;
interrupt-parent = <&combiner>;
@@ -781,7 +797,7 @@
#iommu-cells = <0>;
};
- sysmmu_tv: sysmmu@0x14650000 {
+ sysmmu_tv: sysmmu@14650000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x14650000 0x1000>;
interrupt-parent = <&combiner>;
@@ -792,7 +808,7 @@
#iommu-cells = <0>;
};
- sysmmu_gscl0: sysmmu@0x13E80000 {
+ sysmmu_gscl0: sysmmu@13e80000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x13E80000 0x1000>;
interrupt-parent = <&combiner>;
@@ -803,7 +819,7 @@
#iommu-cells = <0>;
};
- sysmmu_gscl1: sysmmu@0x13E90000 {
+ sysmmu_gscl1: sysmmu@13e90000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x13E90000 0x1000>;
interrupt-parent = <&combiner>;
@@ -814,65 +830,71 @@
#iommu-cells = <0>;
};
- sysmmu_scaler0r: sysmmu@0x12880000 {
+ sysmmu_scaler0r: sysmmu@12880000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x12880000 0x1000>;
interrupt-parent = <&combiner>;
interrupts = <22 4>;
clock-names = "sysmmu", "master";
clocks = <&clock CLK_SMMU_MSCL0>, <&clock CLK_MSCL0>;
+ power-domains = <&msc_pd>;
#iommu-cells = <0>;
};
- sysmmu_scaler1r: sysmmu@0x12890000 {
+ sysmmu_scaler1r: sysmmu@12890000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x12890000 0x1000>;
interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "sysmmu", "master";
clocks = <&clock CLK_SMMU_MSCL1>, <&clock CLK_MSCL1>;
+ power-domains = <&msc_pd>;
#iommu-cells = <0>;
};
- sysmmu_scaler2r: sysmmu@0x128A0000 {
+ sysmmu_scaler2r: sysmmu@128a0000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x128A0000 0x1000>;
interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "sysmmu", "master";
clocks = <&clock CLK_SMMU_MSCL2>, <&clock CLK_MSCL2>;
+ power-domains = <&msc_pd>;
#iommu-cells = <0>;
};
- sysmmu_scaler0w: sysmmu@0x128C0000 {
+ sysmmu_scaler0w: sysmmu@128c0000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x128C0000 0x1000>;
interrupt-parent = <&combiner>;
interrupts = <27 2>;
clock-names = "sysmmu", "master";
clocks = <&clock CLK_SMMU_MSCL0>, <&clock CLK_MSCL0>;
+ power-domains = <&msc_pd>;
#iommu-cells = <0>;
};
- sysmmu_scaler1w: sysmmu@0x128D0000 {
+ sysmmu_scaler1w: sysmmu@128d0000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x128D0000 0x1000>;
interrupt-parent = <&combiner>;
interrupts = <22 6>;
clock-names = "sysmmu", "master";
clocks = <&clock CLK_SMMU_MSCL1>, <&clock CLK_MSCL1>;
+ power-domains = <&msc_pd>;
#iommu-cells = <0>;
};
- sysmmu_scaler2w: sysmmu@0x128E0000 {
+ sysmmu_scaler2w: sysmmu@128e0000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x128E0000 0x1000>;
interrupt-parent = <&combiner>;
interrupts = <19 6>;
clock-names = "sysmmu", "master";
clocks = <&clock CLK_SMMU_MSCL2>, <&clock CLK_MSCL2>;
+ power-domains = <&msc_pd>;
#iommu-cells = <0>;
};
- sysmmu_rotator: sysmmu@0x11D40000 {
+ sysmmu_rotator: sysmmu@11d40000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x11D40000 0x1000>;
interrupt-parent = <&combiner>;
@@ -882,7 +904,7 @@
#iommu-cells = <0>;
};
- sysmmu_jpeg0: sysmmu@0x11F10000 {
+ sysmmu_jpeg0: sysmmu@11f10000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x11F10000 0x1000>;
interrupt-parent = <&combiner>;
@@ -892,7 +914,7 @@
#iommu-cells = <0>;
};
- sysmmu_jpeg1: sysmmu@0x11F20000 {
+ sysmmu_jpeg1: sysmmu@11f20000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x11F20000 0x1000>;
interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
@@ -901,7 +923,7 @@
#iommu-cells = <0>;
};
- sysmmu_mfc_l: sysmmu@0x11200000 {
+ sysmmu_mfc_l: sysmmu@11200000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x11200000 0x1000>;
interrupt-parent = <&combiner>;
@@ -912,7 +934,7 @@
#iommu-cells = <0>;
};
- sysmmu_mfc_r: sysmmu@0x11210000 {
+ sysmmu_mfc_r: sysmmu@11210000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x11210000 0x1000>;
interrupt-parent = <&combiner>;
@@ -923,7 +945,7 @@
#iommu-cells = <0>;
};
- sysmmu_fimd1_0: sysmmu@0x14640000 {
+ sysmmu_fimd1_0: sysmmu@14640000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x14640000 0x1000>;
interrupt-parent = <&combiner>;
@@ -934,7 +956,7 @@
#iommu-cells = <0>;
};
- sysmmu_fimd1_1: sysmmu@0x14680000 {
+ sysmmu_fimd1_1: sysmmu@14680000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x14680000 0x1000>;
interrupt-parent = <&combiner>;
@@ -1531,3 +1553,4 @@
};
#include "exynos5420-pinctrl.dtsi"
+#include "exynos-syscon-restart.dtsi"
diff --git a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
index d31249f..2f4f408 100644
--- a/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
+++ b/arch/arm/boot/dts/exynos5422-odroid-core.dtsi
@@ -23,7 +23,7 @@
stdout-path = "serial2:115200n8";
};
- firmware@02073000 {
+ firmware@2073000 {
compatible = "samsung,secure-firmware";
reg = <0x02073000 0x1000>;
};
diff --git a/arch/arm/boot/dts/exynos5440-sd5v1.dts b/arch/arm/boot/dts/exynos5440-sd5v1.dts
deleted file mode 100644
index c4b8392..0000000
--- a/arch/arm/boot/dts/exynos5440-sd5v1.dts
+++ /dev/null
@@ -1,42 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * SAMSUNG SD5v1 board device tree source
- *
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- */
-
-/dts-v1/;
-#include "exynos5440.dtsi"
-
-/ {
- model = "SAMSUNG SD5v1 board based on EXYNOS5440";
- compatible = "samsung,sd5v1", "samsung,exynos5440", "samsung,exynos5";
-
- chosen {
- bootargs = "root=/dev/sda2 rw rootwait ignore_loglevel earlyprintk no_console_suspend mem=2048M@0x80000000 mem=6144M@0x100000000 console=ttySAC0,115200";
- };
-
- /* FIXME: set reg property with correct start address and size */
- memory@0 {
- device_type = "memory";
- reg = <0 0>;
- };
-
- fixed-rate-clocks {
- xtal {
- compatible = "samsung,clock-xtal";
- clock-frequency = <50000000>;
- };
- };
-
- spi {
- status = "disabled";
- };
-
-};
-
-&gmac {
- fixed_phy;
- phy_addr = <1>;
-};
diff --git a/arch/arm/boot/dts/exynos5440-ssdk5440.dts b/arch/arm/boot/dts/exynos5440-ssdk5440.dts
deleted file mode 100644
index a33c4fc..0000000
--- a/arch/arm/boot/dts/exynos5440-ssdk5440.dts
+++ /dev/null
@@ -1,81 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * SAMSUNG SSDK5440 board device tree source
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- */
-
-/dts-v1/;
-#include "exynos5440.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-
-/ {
- model = "SAMSUNG SSDK5440 board based on EXYNOS5440";
- compatible = "samsung,ssdk5440", "samsung,exynos5440", "samsung,exynos5";
-
- chosen {
- bootargs = "root=/dev/sda2 rw rootwait ignore_loglevel earlyprintk no_console_suspend mem=2048M@0x80000000 mem=6144M@0x100000000 console=ttySAC0,115200";
- };
-
- /* FIXME: set reg property with correct start address and size */
- memory@0 {
- device_type = "memory";
- reg = <0 0>;
- };
-
- fixed-rate-clocks {
- xtal {
- compatible = "samsung,clock-xtal";
- clock-frequency = <50000000>;
- };
- };
-};
-
-&pcie_0 {
- reset-gpio = <&pin_ctrl 5 GPIO_ACTIVE_HIGH>;
- status = "okay";
-};
-
-&pcie_1 {
- reset-gpio = <&pin_ctrl 22 GPIO_ACTIVE_HIGH>;
- status = "okay";
-};
-
-&spi_0 {
- flash: w25q128@0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "winbond,w25q128";
- spi-max-frequency = <15625000>;
- reg = <0>;
- controller-data {
- samsung,spi-feedback-delay = <0>;
- };
-
- partition@0 {
- label = "BootLoader";
- reg = <0x60000 0x80000>;
- read-only;
- };
-
- partition@e0000 {
- label = "Recovery-Kernel";
- reg = <0xe0000 0x300000>;
- read-only;
- };
-
- partition@3e0000 {
- label = "CRAM-FS";
- reg = <0x3e0000 0x700000>;
- read-only;
- };
-
- partition@ae0000 {
- label = "User-Data";
- reg = <0xae0000 0x520000>;
- };
-
- };
-
-};
diff --git a/arch/arm/boot/dts/exynos5440-tmu-sensor-conf.dtsi b/arch/arm/boot/dts/exynos5440-tmu-sensor-conf.dtsi
deleted file mode 100644
index 0421c3d..0000000
--- a/arch/arm/boot/dts/exynos5440-tmu-sensor-conf.dtsi
+++ /dev/null
@@ -1,20 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Device tree sources for Exynos5440 TMU sensor configuration
- *
- * Copyright (c) 2014 Lukasz Majewski <l.majewski@samsung.com>
- */
-
-#include <dt-bindings/thermal/thermal_exynos.h>
-
-#thermal-sensor-cells = <0>;
-samsung,tmu_gain = <5>;
-samsung,tmu_reference_voltage = <16>;
-samsung,tmu_noise_cancel_mode = <4>;
-samsung,tmu_efuse_value = <0x5d2d>;
-samsung,tmu_min_efuse_value = <16>;
-samsung,tmu_max_efuse_value = <76>;
-samsung,tmu_first_point_trim = <25>;
-samsung,tmu_second_point_trim = <70>;
-samsung,tmu_default_temp_offset = <25>;
-samsung,tmu_cal_type = <TYPE_ONE_POINT_TRIMMING>;
diff --git a/arch/arm/boot/dts/exynos5440-trip-points.dtsi b/arch/arm/boot/dts/exynos5440-trip-points.dtsi
deleted file mode 100644
index a2b04fe..0000000
--- a/arch/arm/boot/dts/exynos5440-trip-points.dtsi
+++ /dev/null
@@ -1,21 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Device tree sources for default Exynos5440 thermal zone definition
- *
- * Copyright (c) 2014 Lukasz Majewski <l.majewski@samsung.com>
- */
-
-polling-delay-passive = <0>;
-polling-delay = <0>;
-trips {
- cpu-alert-0 {
- temperature = <100000>; /* millicelsius */
- hysteresis = <0>; /* millicelsius */
- type = "active";
- };
- cpu-crit-0 {
- temperature = <105000>; /* millicelsius */
- hysteresis = <0>; /* millicelsius */
- type = "critical";
- };
-};
diff --git a/arch/arm/boot/dts/exynos5440.dtsi b/arch/arm/boot/dts/exynos5440.dtsi
deleted file mode 100644
index f3abecc4..0000000
--- a/arch/arm/boot/dts/exynos5440.dtsi
+++ /dev/null
@@ -1,355 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * SAMSUNG EXYNOS5440 SoC device tree source
- *
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- */
-
-#include <dt-bindings/clock/exynos5440.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/interrupt-controller/irq.h>
-
-/ {
- compatible = "samsung,exynos5440", "samsung,exynos5";
-
- interrupt-parent = <&gic>;
- #address-cells = <1>;
- #size-cells = <1>;
-
- aliases {
- serial0 = &serial_0;
- serial1 = &serial_1;
- spi0 = &spi_0;
- tmuctrl0 = &tmuctrl_0;
- tmuctrl1 = &tmuctrl_1;
- tmuctrl2 = &tmuctrl_2;
- };
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpu@0 {
- device_type = "cpu";
- compatible = "arm,cortex-a15";
- reg = <0>;
- };
- cpu@1 {
- device_type = "cpu";
- compatible = "arm,cortex-a15";
- reg = <1>;
- };
- cpu@2 {
- device_type = "cpu";
- compatible = "arm,cortex-a15";
- reg = <2>;
- };
- cpu@3 {
- device_type = "cpu";
- compatible = "arm,cortex-a15";
- reg = <3>;
- };
- };
-
- soc: soc {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- clock: clock-controller@160000 {
- compatible = "samsung,exynos5440-clock";
- reg = <0x160000 0x1000>;
- #clock-cells = <1>;
- };
-
- gic: interrupt-controller@2e0000 {
- compatible = "arm,cortex-a15-gic";
- #interrupt-cells = <3>;
- interrupt-controller;
- reg = <0x2E1000 0x1000>,
- <0x2E2000 0x2000>,
- <0x2E4000 0x2000>,
- <0x2E6000 0x2000>;
- interrupts = <GIC_PPI 9
- (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
- };
-
-
- arm-pmu {
- compatible = "arm,cortex-a15-pmu", "arm,cortex-a9-pmu";
- interrupts = <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>;
- };
-
- timer {
- compatible = "arm,cortex-a15-timer",
- "arm,armv7-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)>;
- clock-frequency = <50000000>;
- };
-
- cpufreq@160000 {
- compatible = "samsung,exynos5440-cpufreq";
- reg = <0x160000 0x1000>;
- interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
- operating-points = <
- /* KHz uV */
- 1500000 1100000
- 1400000 1075000
- 1300000 1050000
- 1200000 1025000
- 1100000 1000000
- 1000000 975000
- 900000 950000
- 800000 925000
- >;
- };
-
- serial_0: serial@b0000 {
- compatible = "samsung,exynos4210-uart";
- reg = <0xB0000 0x1000>;
- interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock CLK_B_125>, <&clock CLK_B_125>;
- clock-names = "uart", "clk_uart_baud0";
- };
-
- serial_1: serial@c0000 {
- compatible = "samsung,exynos4210-uart";
- reg = <0xC0000 0x1000>;
- interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock CLK_B_125>, <&clock CLK_B_125>;
- clock-names = "uart", "clk_uart_baud0";
- };
-
- spi_0: spi@d0000 {
- compatible = "samsung,exynos5440-spi";
- reg = <0xD0000 0x100>;
- interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- samsung,spi-src-clk = <0>;
- num-cs = <1>;
- clocks = <&clock CLK_B_125>, <&clock CLK_SPI_BAUD>;
- clock-names = "spi", "spi_busclk0";
- };
-
- pin_ctrl: pinctrl@e0000 {
- compatible = "samsung,exynos5440-pinctrl";
- reg = <0xE0000 0x1000>;
- interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <2>;
- #gpio-cells = <2>;
-
- fan: fan {
- samsung,exynos5440-pin-function = <1>;
- };
-
- hdd_led0: hdd_led0 {
- samsung,exynos5440-pin-function = <2>;
- };
-
- hdd_led1: hdd_led1 {
- samsung,exynos5440-pin-function = <3>;
- };
-
- uart1: uart1 {
- samsung,exynos5440-pin-function = <4>;
- };
- };
-
- i2c@f0000 {
- compatible = "samsung,exynos5440-i2c";
- reg = <0xF0000 0x1000>;
- interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&clock CLK_B_125>;
- clock-names = "i2c";
- };
-
- i2c@100000 {
- compatible = "samsung,exynos5440-i2c";
- reg = <0x100000 0x1000>;
- interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- clocks = <&clock CLK_B_125>;
- clock-names = "i2c";
- };
-
- watchdog@110000 {
- compatible = "samsung,s3c6410-wdt";
- reg = <0x110000 0x1000>;
- interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock CLK_B_125>;
- clock-names = "watchdog";
- };
-
- gmac: ethernet@230000 {
- compatible = "snps,dwmac-3.70a", "snps,dwmac";
- reg = <0x00230000 0x8000>;
- interrupt-parent = <&gic>;
- interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "macirq";
- phy-mode = "sgmii";
- clocks = <&clock CLK_GMAC0>;
- clock-names = "stmmaceth";
- };
-
- amba {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "simple-bus";
- interrupt-parent = <&gic>;
- ranges;
- };
-
- rtc@130000 {
- compatible = "samsung,s3c6410-rtc";
- reg = <0x130000 0x1000>;
- interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock CLK_B_125>;
- clock-names = "rtc";
- };
-
- tmuctrl_0: tmuctrl@160118 {
- compatible = "samsung,exynos5440-tmu";
- reg = <0x160118 0x230>, <0x160368 0x10>;
- interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock CLK_B_125>;
- clock-names = "tmu_apbif";
- #include "exynos5440-tmu-sensor-conf.dtsi"
- };
-
- tmuctrl_1: tmuctrl@16011c {
- compatible = "samsung,exynos5440-tmu";
- reg = <0x16011C 0x230>, <0x160368 0x10>;
- interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock CLK_B_125>;
- clock-names = "tmu_apbif";
- #include "exynos5440-tmu-sensor-conf.dtsi"
- };
-
- tmuctrl_2: tmuctrl@160120 {
- compatible = "samsung,exynos5440-tmu";
- reg = <0x160120 0x230>, <0x160368 0x10>;
- interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock CLK_B_125>;
- clock-names = "tmu_apbif";
- #include "exynos5440-tmu-sensor-conf.dtsi"
- };
-
- sata@210000 {
- compatible = "snps,exynos5440-ahci";
- reg = <0x210000 0x10000>;
- interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock CLK_SATA>;
- clock-names = "sata";
- };
-
- ohci@220000 {
- compatible = "samsung,exynos5440-ohci";
- reg = <0x220000 0x1000>;
- interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock CLK_USB>;
- clock-names = "usbhost";
- };
-
- ehci@221000 {
- compatible = "samsung,exynos5440-ehci";
- reg = <0x221000 0x1000>;
- interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clock CLK_USB>;
- 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>, <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>;
- clocks = <&clock CLK_PR0_250_O>, <&clock CLK_PB0_250_O>;
- clock-names = "pcie", "pcie_bus";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- phys = <&pcie_phy0>;
- ranges = <0x81000000 0 0 0x40001000 0 0x00010000 /* downstream I/O */
- 0x82000000 0 0x40011000 0x40011000 0 0x1ffef000>; /* non-prefetchable memory */
- bus-range = <0x00 0xff>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 0>;
- interrupt-map = <0x0 0 &gic 53>;
- num-lanes = <4>;
- status = "disabled";
- };
-
- pcie_1: pcie@2a0000 {
- compatible = "samsung,exynos5440-pcie", "snps,dw-pcie";
- 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>;
- clocks = <&clock CLK_PR1_250_O>, <&clock CLK_PB0_250_O>;
- clock-names = "pcie", "pcie_bus";
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- phys = <&pcie_phy1>;
- ranges = <0x81000000 0 0 0x60001000 0 0x00010000 /* downstream I/O */
- 0x82000000 0 0x60011000 0x60011000 0 0x1ffef000>; /* non-prefetchable memory */
- bus-range = <0x00 0xff>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 0>;
- interrupt-map = <0x0 0 &gic 56>;
- num-lanes = <4>;
- status = "disabled";
- };
- };
-
- thermal-zones {
- cpu0_thermal: cpu0-thermal {
- thermal-sensors = <&tmuctrl_0>;
- #include "exynos5440-trip-points.dtsi"
- };
- cpu1_thermal: cpu1-thermal {
- thermal-sensors = <&tmuctrl_1>;
- #include "exynos5440-trip-points.dtsi"
- };
- cpu2_thermal: cpu2-thermal {
- thermal-sensors = <&tmuctrl_2>;
- #include "exynos5440-trip-points.dtsi"
- };
- };
-};
diff --git a/arch/arm/boot/dts/exynos5800-peach-pi.dts b/arch/arm/boot/dts/exynos5800-peach-pi.dts
index 2f8df92..d80ab90 100644
--- a/arch/arm/boot/dts/exynos5800-peach-pi.dts
+++ b/arch/arm/boot/dts/exynos5800-peach-pi.dts
@@ -27,7 +27,7 @@
aliases {
/* Assign 20 so we don't get confused w/ builtin ones */
- i2c20 = "/spi@12d40000/cros-ec@0/i2c-tunnel";
+ i2c20 = &i2c_tunnel;
};
backlight: backlight {
@@ -939,7 +939,7 @@
samsung,spi-feedback-delay = <1>;
};
- i2c-tunnel {
+ i2c_tunnel: i2c-tunnel {
compatible = "google,cros-ec-i2c-tunnel";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/gemini-dlink-dir-685.dts b/arch/arm/boot/dts/gemini-dlink-dir-685.dts
index cadde92..fb5c954 100644
--- a/arch/arm/boot/dts/gemini-dlink-dir-685.dts
+++ b/arch/arm/boot/dts/gemini-dlink-dir-685.dts
@@ -13,22 +13,22 @@
#address-cells = <1>;
#size-cells = <1>;
- memory {
+ memory@0 {
/* 128 MB SDRAM in 2 x Hynix HY5DU121622DTP-D43 */
device_type = "memory";
reg = <0x00000000 0x8000000>;
};
chosen {
- stdout-path = "uart0:115200n8";
+ bootargs = "console=ttyS0,19200n8 root=/dev/sda1 rw rootwait";
+ stdout-path = "uart0:19200n8";
};
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
+
button-esc {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <KEY_ESC>;
label = "reset";
@@ -36,7 +36,7 @@
gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
};
button-eject {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <KEY_EJECTCD>;
label = "unmount";
@@ -98,7 +98,7 @@
/*
* These two LEDs are on the side of the device.
* For electrical reasons, both LEDs cannot be active
- * at the same time so only blue or orange can on at
+ * at the same time so only blue or orange can be on at
* one time. Enabling both makes the LED go dark.
* The LEDs both sit inside the unmount button and the
* label on the case says "unmount".
@@ -108,12 +108,14 @@
/* Collides with LPC_SERIRQ, UART DTR, SSP FSC pins */
gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>;
default-state = "off";
+ linux,default-trigger = "disk-read";
};
led-orange-hd {
label = "dir685:orange:HD";
/* Collides with LPC_LAD[2], UART DSR, SSP ECLK pins */
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
default-state = "off";
+ linux,default-trigger = "disk-write";
};
};
diff --git a/arch/arm/boot/dts/gemini-dlink-dns-313.dts b/arch/arm/boot/dts/gemini-dlink-dns-313.dts
index 403364a..d132932 100644
--- a/arch/arm/boot/dts/gemini-dlink-dns-313.dts
+++ b/arch/arm/boot/dts/gemini-dlink-dns-313.dts
@@ -15,7 +15,7 @@
#address-cells = <1>;
#size-cells = <1>;
- memory {
+ memory@0 {
/* 64 MB SDRAM in a Nanya NT5DS32M16BS-6K package */
device_type = "memory";
reg = <0x00000000 0x4000000>;
@@ -26,15 +26,15 @@
};
chosen {
+ bootargs = "console=ttyS0,19200n8 root=/dev/sda4 rw rootwait";
stdout-path = "uart0:19200n8";
};
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
+
button-esc {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <KEY_ESC>;
label = "reset";
@@ -59,14 +59,13 @@
label = "dns313:green:disk";
gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
default-state = "off";
- linux,default-trigger = "ide-disk";
- /* Ideally should activate while reading */
+ linux,default-trigger = "disk-read";
};
led-disk-red {
label = "dns313:red:disk";
gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
default-state = "off";
- /* Ideally should activate while writing */
+ linux,default-trigger = "disk-write";
};
};
@@ -158,8 +157,12 @@
soc {
flash@30000000 {
+ /*
+ * This is a Eon EN29LV400AB 512 KiB flash with
+ * three partitions.
+ */
+ compatible = "cortina,gemini-flash", "jedec-flash";
status = "okay";
- /* 512KB of flash */
reg = <0x30000000 0x00080000>;
/*
diff --git a/arch/arm/boot/dts/gemini-nas4220b.dts b/arch/arm/boot/dts/gemini-nas4220b.dts
index 4785fbc..963ea89 100644
--- a/arch/arm/boot/dts/gemini-nas4220b.dts
+++ b/arch/arm/boot/dts/gemini-nas4220b.dts
@@ -14,7 +14,7 @@
#address-cells = <1>;
#size-cells = <1>;
- memory { /* 128 MB */
+ memory@0 { /* 128 MB */
device_type = "memory";
reg = <0x00000000 0x8000000>;
};
@@ -26,19 +26,17 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- button@29 {
- debounce_interval = <50>;
+ button-setup {
+ debounce-interval = <50>;
wakeup-source;
linux,code = <KEY_SETUP>;
label = "Backup button";
/* Conflict with TVC */
gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
};
- button@31 {
- debounce_interval = <50>;
+ button-restart {
+ debounce-interval = <50>;
wakeup-source;
linux,code = <KEY_RESTART>;
label = "Softreset button";
@@ -49,13 +47,13 @@
leds {
compatible = "gpio-leds";
- led@28 {
+ led-orange-hdd {
label = "nas4220b:orange:hdd";
/* Conflict with TVC */
gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
default-state = "on";
};
- led@30 {
+ led-green-os {
label = "nas4220b:green:os";
/* Conflict with TVC */
gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
@@ -202,5 +200,9 @@
ata@63000000 {
status = "okay";
};
+
+ ata@63400000 {
+ status = "okay";
+ };
};
};
diff --git a/arch/arm/boot/dts/gemini-rut1xx.dts b/arch/arm/boot/dts/gemini-rut1xx.dts
index 15f2017..eb4f0bf 100644
--- a/arch/arm/boot/dts/gemini-rut1xx.dts
+++ b/arch/arm/boot/dts/gemini-rut1xx.dts
@@ -14,7 +14,7 @@
#address-cells = <1>;
#size-cells = <1>;
- memory { /* 128 MB */
+ memory@0 { /* 128 MB */
device_type = "memory";
reg = <0x00000000 0x8000000>;
};
@@ -26,11 +26,9 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- button@28 {
- debounce_interval = <50>;
+ button-setup {
+ debounce-interval = <50>;
wakeup-source;
linux,code = <KEY_SETUP>;
label = "Reset to defaults";
@@ -41,14 +39,14 @@
leds {
compatible = "gpio-leds";
- led@7 {
+ led-gsm {
/* FIXME: add the LED color */
label = "rut1xx::gsm";
/* Conflict with ICE */
gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
default-state = "on";
};
- led@31 {
+ led-power {
/* FIXME: add the LED color */
label = "rut1xx::power";
/* Conflict with NAND CE0 */
diff --git a/arch/arm/boot/dts/gemini-sq201.dts b/arch/arm/boot/dts/gemini-sq201.dts
index 63c02ca..e5cf9d1 100644
--- a/arch/arm/boot/dts/gemini-sq201.dts
+++ b/arch/arm/boot/dts/gemini-sq201.dts
@@ -14,7 +14,7 @@
#address-cells = <1>;
#size-cells = <1>;
- memory { /* 128 MB */
+ memory@0 { /* 128 MB */
device_type = "memory";
reg = <0x00000000 0x8000000>;
};
@@ -26,11 +26,9 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- button@18 {
- debounce_interval = <50>;
+ button-setup {
+ debounce-interval = <50>;
wakeup-source;
linux,code = <KEY_SETUP>;
label = "factory reset";
@@ -41,14 +39,14 @@
leds {
compatible = "gpio-leds";
- led@20 {
+ led-green-info {
label = "sq201:green:info";
/* Conflict with parallel flash */
gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
default-state = "on";
linux,default-trigger = "heartbeat";
};
- led@31 {
+ led-green-usb {
label = "sq201:green:usb";
/* Conflict with parallel and NAND flash */
gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/gemini-wbd111.dts b/arch/arm/boot/dts/gemini-wbd111.dts
index b4ec9ad..29af86c 100644
--- a/arch/arm/boot/dts/gemini-wbd111.dts
+++ b/arch/arm/boot/dts/gemini-wbd111.dts
@@ -14,7 +14,8 @@
#address-cells = <1>;
#size-cells = <1>;
- memory { /* 128 MB */
+ memory@0 {
+ /* 128 MB */
device_type = "memory";
reg = <0x00000000 0x8000000>;
};
@@ -26,11 +27,9 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- button@5 {
- debounce_interval = <50>;
+ button-setup {
+ debounce-interval = <50>;
wakeup-source;
linux,code = <KEY_SETUP>;
label = "reset";
@@ -42,25 +41,25 @@
leds {
compatible = "gpio-leds";
- led@1 {
+ led-red-l3 {
label = "wbd111:red:L3";
/* Conflict with TVC and extended parallel flash */
gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
- led@2 {
+ led-green-l4 {
label = "wbd111:green:L4";
/* Conflict with TVC and extended parallel flash */
gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
- led@3 {
+ led-red-l4 {
label = "wbd111:red:L4";
/* Conflict with TVC and extended parallel flash */
gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
- led@5 {
+ led-greeb-l3 {
label = "wbd111:green:L3";
/* Conflict with TVC and extended parallel flash */
gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/gemini-wbd222.dts b/arch/arm/boot/dts/gemini-wbd222.dts
index 6d25bcc..24e6ae3 100644
--- a/arch/arm/boot/dts/gemini-wbd222.dts
+++ b/arch/arm/boot/dts/gemini-wbd222.dts
@@ -14,7 +14,7 @@
#address-cells = <1>;
#size-cells = <1>;
- memory { /* 128 MB */
+ memory@0 { /* 128 MB */
device_type = "memory";
reg = <0x00000000 0x8000000>;
};
@@ -26,11 +26,9 @@
gpio_keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
- button@5 {
- debounce_interval = <50>;
+ button-setup {
+ debounce-interval = <50>;
wakeup-source;
linux,code = <KEY_SETUP>;
label = "reset";
@@ -42,25 +40,25 @@
leds {
compatible = "gpio-leds";
- led@1 {
+ led-red-l3 {
label = "wbd111:red:L3";
/* Conflict with TVC and extended parallel flash */
gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
- led@2 {
+ led-green-l4 {
label = "wbd111:green:L4";
/* Conflict with TVC and extended parallel flash */
gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
- led@3 {
+ led-red-l4 {
label = "wbd111:red:L4";
/* Conflict with TVC and extended parallel flash */
gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
- led@5 {
+ led-green-l3 {
label = "wbd111:green:L3";
/* Conflict with TVC and extended parallel flash */
gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/gemini.dtsi b/arch/arm/boot/dts/gemini.dtsi
index 0568bac..eb752e9 100644
--- a/arch/arm/boot/dts/gemini.dtsi
+++ b/arch/arm/boot/dts/gemini.dtsi
@@ -3,8 +3,6 @@
* Device Tree file for Cortina systems Gemini SoC
*/
-/include/ "skeleton.dtsi"
-
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/clock/cortina,gemini-clock.h>
#include <dt-bindings/reset/cortina,gemini-reset.h>
diff --git a/arch/arm/boot/dts/imx1-ads.dts b/arch/arm/boot/dts/imx1-ads.dts
index 6354e4c..a1d81ba 100644
--- a/arch/arm/boot/dts/imx1-ads.dts
+++ b/arch/arm/boot/dts/imx1-ads.dts
@@ -23,17 +23,6 @@
memory@8000000 {
reg = <0x08000000 0x04000000>;
};
-
- clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
- clk32 {
- compatible = "fsl,imx-clk32", "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32000>;
- };
- };
};
&cspi1 {
diff --git a/arch/arm/boot/dts/imx1.dtsi b/arch/arm/boot/dts/imx1.dtsi
index f7b9edf..3edc7b5 100644
--- a/arch/arm/boot/dts/imx1.dtsi
+++ b/arch/arm/boot/dts/imx1.dtsi
@@ -1,13 +1,6 @@
-/*
- * Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (C) 2014 Alexander Shiyan <shc_work@mail.ru>
#include "imx1-pinfunc.h"
@@ -62,6 +55,14 @@
};
};
+ clocks {
+ clk32 {
+ compatible = "fsl,imx-clk32", "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32000>;
+ };
+ };
+
soc {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts
index 9d92ece82..9fb4772 100644
--- a/arch/arm/boot/dts/imx23-evk.dts
+++ b/arch/arm/boot/dts/imx23-evk.dts
@@ -1,13 +1,6 @@
-/*
- * Copyright 2012 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Freescale Semiconductor, Inc.
/dts-v1/;
#include "imx23.dtsi"
diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi
index cb0a3fe..71bfd2b 100644
--- a/arch/arm/boot/dts/imx23.dtsi
+++ b/arch/arm/boot/dts/imx23.dtsi
@@ -1,13 +1,6 @@
-/*
- * Copyright 2012 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Freescale Semiconductor, Inc.
#include "imx23-pinfunc.h"
diff --git a/arch/arm/boot/dts/imx25-pdk.dts b/arch/arm/boot/dts/imx25-pdk.dts
index 7f9bd05..a5626b4 100644
--- a/arch/arm/boot/dts/imx25-pdk.dts
+++ b/arch/arm/boot/dts/imx25-pdk.dts
@@ -1,13 +1,6 @@
-/*
- * Copyright 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2013 Freescale Semiconductor, Inc.
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
@@ -291,7 +284,6 @@
};
&ssi1 {
- codec-handle = <&codec>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx25.dtsi b/arch/arm/boot/dts/imx25.dtsi
index cf70df2..85c15ee 100644
--- a/arch/arm/boot/dts/imx25.dtsi
+++ b/arch/arm/boot/dts/imx25.dtsi
@@ -1,13 +1,6 @@
-/*
- * Copyright 2012 Sascha Hauer, Pengutronix <s.hauer@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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
#include <dt-bindings/gpio/gpio.h>
#include "imx25-pinfunc.h"
@@ -70,9 +63,6 @@
};
clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
osc {
compatible = "fsl,imx-osc", "fixed-clock";
#clock-cells = <0>;
diff --git a/arch/arm/boot/dts/imx27-apf27.dts b/arch/arm/boot/dts/imx27-apf27.dts
index 66941cd..3eddd80 100644
--- a/arch/arm/boot/dts/imx27-apf27.dts
+++ b/arch/arm/boot/dts/imx27-apf27.dts
@@ -22,17 +22,10 @@
memory@a0000000 {
reg = <0xa0000000 0x04000000>;
};
+};
- clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
- osc26m {
- compatible = "fsl,imx-osc26m", "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
- };
+&clk_osc26m {
+ clock-frequency = <0>;
};
&iomuxc {
diff --git a/arch/arm/boot/dts/imx27-pdk.dts b/arch/arm/boot/dts/imx27-pdk.dts
index 924b90c..f9a882d 100644
--- a/arch/arm/boot/dts/imx27-pdk.dts
+++ b/arch/arm/boot/dts/imx27-pdk.dts
@@ -1,13 +1,6 @@
-/*
- * Copyright 2012 Sascha Hauer, Pengutronix
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Sascha Hauer, Pengutronix
/dts-v1/;
#include "imx27.dtsi"
diff --git a/arch/arm/boot/dts/imx27.dtsi b/arch/arm/boot/dts/imx27.dtsi
index 6585b00..753d88d 100644
--- a/arch/arm/boot/dts/imx27.dtsi
+++ b/arch/arm/boot/dts/imx27.dtsi
@@ -1,13 +1,6 @@
-/*
- * Copyright 2012 Sascha Hauer, Pengutronix
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Sascha Hauer, Pengutronix
#include "imx27-pinfunc.h"
@@ -57,10 +50,7 @@
};
clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
- osc26m {
+ clk_osc26m: osc26m {
compatible = "fsl,imx-osc26m", "fixed-clock";
#clock-cells = <0>;
clock-frequency = <26000000>;
diff --git a/arch/arm/boot/dts/imx28-cfa10049.dts b/arch/arm/boot/dts/imx28-cfa10049.dts
index 60e5c7f..f1c8315 100644
--- a/arch/arm/boot/dts/imx28-cfa10049.dts
+++ b/arch/arm/boot/dts/imx28-cfa10049.dts
@@ -398,8 +398,6 @@
compatible = "gpio-keys";
pinctrl-names = "default";
pinctrl-0 = <&rotary_btn_pins_cfa10049>;
- #address-cells = <1>;
- #size-cells = <0>;
rotary_button {
label = "rotary_button";
diff --git a/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts b/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts
index 7f8d40a..2221533 100644
--- a/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts
+++ b/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts
@@ -206,8 +206,6 @@
gpio-keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&enocean_button>;
diff --git a/arch/arm/boot/dts/imx28-evk.dts b/arch/arm/boot/dts/imx28-evk.dts
index b0d3965..6b0ae66 100644
--- a/arch/arm/boot/dts/imx28-evk.dts
+++ b/arch/arm/boot/dts/imx28-evk.dts
@@ -1,13 +1,6 @@
-/*
- * Copyright 2012 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Freescale Semiconductor, Inc.
/dts-v1/;
#include "imx28.dtsi"
diff --git a/arch/arm/boot/dts/imx28-tx28.dts b/arch/arm/boot/dts/imx28-tx28.dts
index 6871863..b8f4643 100644
--- a/arch/arm/boot/dts/imx28-tx28.dts
+++ b/arch/arm/boot/dts/imx28-tx28.dts
@@ -140,15 +140,10 @@
regulator-boot-on;
};
- clocks {
- #address-cells = <1>;
- #size-cells = <0>;
- mclk: clock@0 {
- compatible = "fixed-clock";
- reg = <0>;
- #clock-cells = <0>;
- clock-frequency = <26000000>;
- };
+ mclk: clock-mclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
};
sound {
@@ -345,6 +340,7 @@
interrupts = <5 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
wake-gpios = <&gpio4 9 GPIO_ACTIVE_HIGH>;
+ wakeup-source;
};
touchscreen: tsc2007@48 {
diff --git a/arch/arm/boot/dts/imx28.dtsi b/arch/arm/boot/dts/imx28.dtsi
index 9ad8d35..5107fdc 100644
--- a/arch/arm/boot/dts/imx28.dtsi
+++ b/arch/arm/boot/dts/imx28.dtsi
@@ -1,13 +1,6 @@
-/*
- * Copyright 2012 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Freescale Semiconductor, Inc.
#include <dt-bindings/gpio/gpio.h>
#include "imx28-pinfunc.h"
diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi
index ebc3f2d..4642c81 100644
--- a/arch/arm/boot/dts/imx31.dtsi
+++ b/arch/arm/boot/dts/imx31.dtsi
@@ -1,13 +1,6 @@
-/*
- * Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
/ {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/imx35-pdk.dts b/arch/arm/boot/dts/imx35-pdk.dts
index 646b125..df613e8 100644
--- a/arch/arm/boot/dts/imx35-pdk.dts
+++ b/arch/arm/boot/dts/imx35-pdk.dts
@@ -1,14 +1,7 @@
-/*
- * Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
- * Copyright 2014 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2013 Eukréa Electromatique <denis@eukrea.com>
+// Copyright 2014 Freescale Semiconductor, Inc.
/dts-v1/;
#include "imx35.dtsi"
diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/imx35.dtsi
index 54111ed..1c50b78 100644
--- a/arch/arm/boot/dts/imx35.dtsi
+++ b/arch/arm/boot/dts/imx35.dtsi
@@ -1,12 +1,8 @@
-/*
- * Copyright 2012 Steffen Trumtrar, Pengutronix
- *
- * based on imx27.dtsi
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2012 Steffen Trumtrar, Pengutronix
+//
+// based on imx27.dtsi
#include "imx35-pinfunc.h"
diff --git a/arch/arm/boot/dts/imx50-evk.dts b/arch/arm/boot/dts/imx50-evk.dts
index 23f1833..f0622ec 100644
--- a/arch/arm/boot/dts/imx50-evk.dts
+++ b/arch/arm/boot/dts/imx50-evk.dts
@@ -1,15 +1,8 @@
-/*
- * Copyright 2013 Greg Ungerer <gerg@uclinux.org>
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2013 Greg Ungerer <gerg@uclinux.org>
+// Copyright 2011 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
/dts-v1/;
#include "imx50.dtsi"
diff --git a/arch/arm/boot/dts/imx50.dtsi b/arch/arm/boot/dts/imx50.dtsi
index 7954e79..a9b712d 100644
--- a/arch/arm/boot/dts/imx50.dtsi
+++ b/arch/arm/boot/dts/imx50.dtsi
@@ -60,9 +60,6 @@
};
clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
ckil {
compatible = "fsl,imx-ckil", "fixed-clock";
#clock-cells = <0>;
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index cf7a196..b8ca73d 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -1,14 +1,7 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2011 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
/dts-v1/;
#include "imx51.dtsi"
diff --git a/arch/arm/boot/dts/imx51-zii-rdu1.dts b/arch/arm/boot/dts/imx51-zii-rdu1.dts
index 6464f25..df9eca9 100644
--- a/arch/arm/boot/dts/imx51-zii-rdu1.dts
+++ b/arch/arm/boot/dts/imx51-zii-rdu1.dts
@@ -207,8 +207,6 @@
switch@0 {
compatible = "marvell,mv88e6085";
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0>;
dsa,member = <0 0>;
@@ -462,7 +460,10 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc1>;
bus-width = <4>;
+ no-1-8-v;
non-removable;
+ no-sdio;
+ no-sd;
status = "okay";
};
@@ -591,6 +592,7 @@
phy_type = "ulpi";
fsl,usbphy = <&usbh1phy>;
disable-over-current;
+ maximum-speed = "full-speed";
vbus-supply = <&reg_5p0v_main>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 5d390a6..fe01b89 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -1,14 +1,7 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2011 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
#include "imx51-pinfunc.h"
#include <dt-bindings/clock/imx5-clock.h>
@@ -56,9 +49,6 @@
};
clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
ckil {
compatible = "fsl,imx-ckil", "fixed-clock";
#clock-cells = <0>;
diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts
index 80fc007..117bd00 100644
--- a/arch/arm/boot/dts/imx53-ard.dts
+++ b/arch/arm/boot/dts/imx53-ard.dts
@@ -11,6 +11,7 @@
*/
/dts-v1/;
+#include <dt-bindings/input/input.h>
#include "imx53.dtsi"
/ {
@@ -68,34 +69,34 @@
home {
label = "Home";
gpios = <&gpio5 10 0>;
- linux,code = <102>; /* KEY_HOME */
+ linux,code = <KEY_HOME>;
wakeup-source;
};
back {
label = "Back";
gpios = <&gpio5 11 0>;
- linux,code = <158>; /* KEY_BACK */
+ linux,code = <KEY_BACK>;
wakeup-source;
};
program {
label = "Program";
gpios = <&gpio5 12 0>;
- linux,code = <362>; /* KEY_PROGRAM */
+ linux,code = <KEY_PROGRAM >;
wakeup-source;
};
volume-up {
label = "Volume Up";
gpios = <&gpio5 13 0>;
- linux,code = <115>; /* KEY_VOLUMEUP */
+ linux,code = <KEY_VOLUMEUP>;
};
volume-down {
label = "Volume Down";
gpios = <&gpio4 0 0>;
- linux,code = <114>; /* KEY_VOLUMEDOWN */
+ linux,code = <KEY_VOLUMEDOWN>;
};
};
};
diff --git a/arch/arm/boot/dts/imx53-m53.dtsi b/arch/arm/boot/dts/imx53-m53.dtsi
index 3da6dd5..ce45f08 100644
--- a/arch/arm/boot/dts/imx53-m53.dtsi
+++ b/arch/arm/boot/dts/imx53-m53.dtsi
@@ -53,8 +53,6 @@
stmpe610@41 {
compatible = "st,stmpe610";
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0x41>;
id = <0>;
blocks = <0x5>;
diff --git a/arch/arm/boot/dts/imx53-ppd.dts b/arch/arm/boot/dts/imx53-ppd.dts
index d5628af..3aa6f69 100644
--- a/arch/arm/boot/dts/imx53-ppd.dts
+++ b/arch/arm/boot/dts/imx53-ppd.dts
@@ -180,8 +180,6 @@
power-gpio-keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
power-button {
label = "Power button";
@@ -192,8 +190,6 @@
touch-lock-key {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
touch-lock-button {
label = "Touch lock button";
@@ -300,7 +296,7 @@
compatible = "dlg,da9053-aa";
reg = <0>;
interrupt-parent = <&gpio3>;
- interrupts = <12 0x8>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
spi-max-frequency = <1000000>;
dlg,tsi-as-adc;
tsiref-supply = <&reg_tsiref>;
@@ -473,7 +469,7 @@
compatible = "fsl,mma8453";
reg = <0x1c>;
interrupt-parent = <&gpio1>;
- interrupts = <6 0>;
+ interrupts = <6 IRQ_TYPE_NONE>;
interrupt-names = "INT1";
};
@@ -539,7 +535,7 @@
reset-gpio = <&gpio5 19 GPIO_ACTIVE_HIGH>;
reg = <0x4b>;
interrupt-parent = <&gpio5>;
- interrupts = <4 0x8>;
+ interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
};
};
@@ -559,8 +555,6 @@
status = "okay";
port@2 {
- reg = <2>;
-
lvds0_out: endpoint {
remote-endpoint = <&panel_in_lvds0>;
};
diff --git a/arch/arm/boot/dts/imx53-qsb-common.dtsi b/arch/arm/boot/dts/imx53-qsb-common.dtsi
index 485a69d..ef7658a 100644
--- a/arch/arm/boot/dts/imx53-qsb-common.dtsi
+++ b/arch/arm/boot/dts/imx53-qsb-common.dtsi
@@ -1,14 +1,7 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2011 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
#include "imx53.dtsi"
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
index d3d662e..6831836 100644
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -1,14 +1,7 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2011 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
/dts-v1/;
#include "imx53-qsb-common.dtsi"
@@ -23,7 +16,7 @@
compatible = "dlg,da9053-aa", "dlg,da9052";
reg = <0x48>;
interrupt-parent = <&gpio7>;
- interrupts = <11 0x8>; /* low-level active IRQ at GPIO7_11 */
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>; /* low-level active IRQ at GPIO7_11 */
regulators {
buck1_reg: buck1 {
diff --git a/arch/arm/boot/dts/imx53-qsrb.dts b/arch/arm/boot/dts/imx53-qsrb.dts
index 4e103a9..1bbf24a 100644
--- a/arch/arm/boot/dts/imx53-qsrb.dts
+++ b/arch/arm/boot/dts/imx53-qsrb.dts
@@ -1,14 +1,7 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2011 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
/dts-v1/;
diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts
index fd03012..462071c 100644
--- a/arch/arm/boot/dts/imx53-smd.dts
+++ b/arch/arm/boot/dts/imx53-smd.dts
@@ -1,16 +1,10 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2011 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
/dts-v1/;
+#include <dt-bindings/input/input.h>
#include "imx53.dtsi"
/ {
@@ -27,13 +21,13 @@
volume-up {
label = "Volume Up";
gpios = <&gpio2 14 0>;
- linux,code = <115>; /* KEY_VOLUMEUP */
+ linux,code = <KEY_VOLUMEUP>;
};
volume-down {
label = "Volume Down";
gpios = <&gpio2 15 0>;
- linux,code = <114>; /* KEY_VOLUMEDOWN */
+ linux,code = <KEY_VOLUMEDOWN>;
};
};
};
diff --git a/arch/arm/boot/dts/imx53-tx53-x03x.dts b/arch/arm/boot/dts/imx53-tx53-x03x.dts
index af8ec5e..a7f7752 100644
--- a/arch/arm/boot/dts/imx53-tx53-x03x.dts
+++ b/arch/arm/boot/dts/imx53-tx53-x03x.dts
@@ -245,6 +245,7 @@
interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
reset-gpios = <&gpio2 22 GPIO_ACTIVE_LOW>;
wake-gpios = <&gpio2 21 GPIO_ACTIVE_HIGH>;
+ wakeup-source;
};
touchscreen: tsc2007@48 {
diff --git a/arch/arm/boot/dts/imx53-tx53.dtsi b/arch/arm/boot/dts/imx53-tx53.dtsi
index 69a2af7..54cf3e6 100644
--- a/arch/arm/boot/dts/imx53-tx53.dtsi
+++ b/arch/arm/boot/dts/imx53-tx53.dtsi
@@ -58,7 +58,7 @@
can0 = &can2; /* Make the can interface indices consistent with TX28/TX48 modules */
can1 = &can1;
ipu = &ipu;
- reg_can_xcvr = &reg_can_xcvr;
+ reg-can-xcvr = &reg_can_xcvr;
usbh1 = &usbh1;
usbotg = &usbotg;
};
@@ -67,13 +67,12 @@
ckih1 {
clock-frequency = <0>;
};
+ };
- mclk: clock@0 {
- compatible = "fixed-clock";
- reg = <0>;
- #clock-cells = <0>;
- clock-frequency = <26000000>;
- };
+ mclk: clock-mclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
};
gpio-keys {
@@ -550,7 +549,6 @@
};
&ssi1 {
- codec-handle = <&sgtl5000>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi b/arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi
index df8dafe..f83a8c6 100644
--- a/arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi
+++ b/arch/arm/boot/dts/imx53-voipac-dmm-668.dtsi
@@ -150,7 +150,7 @@
compatible = "dlg,da9053-aa", "dlg,da9052";
reg = <0x48>;
interrupt-parent = <&gpio7>;
- interrupts = <11 0x8>; /* low-level active IRQ at GPIO7_11 */
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>; /* low-level active IRQ at GPIO7_11 */
regulators {
buck1_reg: buck1 {
diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
index 3d65c01..1a7a7bb 100644
--- a/arch/arm/boot/dts/imx53.dtsi
+++ b/arch/arm/boot/dts/imx53.dtsi
@@ -88,9 +88,6 @@
};
clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
ckil {
compatible = "fsl,imx-ckil", "fixed-clock";
#clock-cells = <0>;
@@ -488,6 +485,10 @@
remote-endpoint = <&ipu_di0_lvds0>;
};
};
+
+ port@2 {
+ reg = <2>;
+ };
};
lvds-channel@1 {
@@ -503,6 +504,10 @@
remote-endpoint = <&ipu_di1_lvds1>;
};
};
+
+ port@2 {
+ reg = <2>;
+ };
};
};
diff --git a/arch/arm/boot/dts/imx6dl-aristainetos2_4.dts b/arch/arm/boot/dts/imx6dl-aristainetos2_4.dts
index 7128c76..29940ba 100644
--- a/arch/arm/boot/dts/imx6dl-aristainetos2_4.dts
+++ b/arch/arm/boot/dts/imx6dl-aristainetos2_4.dts
@@ -78,8 +78,6 @@
&ecspi1 {
lcd_panel: display@0 {
- #address-cells = <1>;
- #size-cells = <1>;
compatible = "lg,lg4573";
spi-max-frequency = <10000000>;
reg = <0>;
diff --git a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
index ea184d1..3dee3af 100644
--- a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
@@ -72,15 +72,12 @@
stdout-path = "serial0:115200n8";
};
- clocks {
- /* Fixed crystal dedicated to mcp251x */
- clk16m: clk@1 {
- compatible = "fixed-clock";
- reg = <1>;
- #clock-cells = <0>;
- clock-frequency = <16000000>;
- clock-output-names = "clk16m";
- };
+ /* Fixed crystal dedicated to mcp251x */
+ clk16m: clock-16m {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <16000000>;
+ clock-output-names = "clk16m";
};
gpio-keys {
diff --git a/arch/arm/boot/dts/imx6dl-mamoj.dts b/arch/arm/boot/dts/imx6dl-mamoj.dts
new file mode 100644
index 0000000..6b2d2913
--- /dev/null
+++ b/arch/arm/boot/dts/imx6dl-mamoj.dts
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 BTicino
+ * Copyright (C) 2018 Amarula Solutions B.V.
+ */
+
+/dts-v1/;
+
+#include "imx6dl.dtsi"
+
+/ {
+ model = "BTicino i.MX6DL Mamoj board";
+ compatible = "bticino,imx6dl-mamoj", "fsl,imx6dl";
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "mii";
+ status = "okay";
+};
+
+&i2c3 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ pfuze100: pmic@8 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ /* CPU vdd_arm core */
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ /* SOC vdd_soc */
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ /* I/O power GEN_3V3 */
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* DDR memory */
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* DDR memory */
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ /* not used */
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ /* not used */
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ /* PMIC vsnvs. EX boot mode */
+ 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;
+ };
+
+ /* not used */
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ /* not used */
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ /* not used */
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ /* 1v8 general power */
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ /* 2v8 general power IMX6 */
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ /* 3v3 Ethernet */
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ bus-width = <8>;
+ non-removable;
+ keep-power-in-suspend;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b1
+ MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0
+ MX6QDL_PAD_KEY_ROW2__ENET_TX_DATA2 0x1b0b0
+ MX6QDL_PAD_KEY_ROW0__ENET_TX_DATA3 0x1b0b0
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
+ MX6QDL_PAD_GPIO_19__ENET_TX_ER 0x1b0b0
+ MX6QDL_PAD_GPIO_18__ENET_RX_CLK 0x1b0b1
+ MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0
+ MX6QDL_PAD_KEY_COL2__ENET_RX_DATA2 0x1b0b0
+ MX6QDL_PAD_KEY_COL0__ENET_RX_DATA3 0x1b0b0
+ MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0
+ MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0
+ MX6QDL_PAD_KEY_COL3__ENET_CRS 0x1b0b0
+ MX6QDL_PAD_KEY_ROW1__ENET_COL 0x1b0b0
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__I2C4_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_8__I2C4_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 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
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6dl-sabreauto.dts b/arch/arm/boot/dts/imx6dl-sabreauto.dts
index a6ce7b4..660d52a 100644
--- a/arch/arm/boot/dts/imx6dl-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6dl-sabreauto.dts
@@ -1,10 +1,6 @@
-/*
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2013 Freescale Semiconductor, Inc.
/dts-v1/;
diff --git a/arch/arm/boot/dts/imx6dl-sabresd.dts b/arch/arm/boot/dts/imx6dl-sabresd.dts
index 9607afe..cd6bbf2 100644
--- a/arch/arm/boot/dts/imx6dl-sabresd.dts
+++ b/arch/arm/boot/dts/imx6dl-sabresd.dts
@@ -1,10 +1,6 @@
-/*
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2013 Freescale Semiconductor, Inc.
/dts-v1/;
diff --git a/arch/arm/boot/dts/imx6dl-udoo.dts b/arch/arm/boot/dts/imx6dl-udoo.dts
index e3713f0..d871cac 100644
--- a/arch/arm/boot/dts/imx6dl-udoo.dts
+++ b/arch/arm/boot/dts/imx6dl-udoo.dts
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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.
- *
*/
/dts-v1/;
#include "imx6dl.dtsi"
diff --git a/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts b/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts
index 5727fa4..738db4f 100644
--- a/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts
+++ b/arch/arm/boot/dts/imx6dl-wandboard-revb1.dts
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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.
- *
*/
/dts-v1/;
#include "imx6dl.dtsi"
diff --git a/arch/arm/boot/dts/imx6dl-wandboard-revd1.dts b/arch/arm/boot/dts/imx6dl-wandboard-revd1.dts
index a72c07d..51de6b4 100644
--- a/arch/arm/boot/dts/imx6dl-wandboard-revd1.dts
+++ b/arch/arm/boot/dts/imx6dl-wandboard-revd1.dts
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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.
- *
*/
/dts-v1/;
#include "imx6dl.dtsi"
diff --git a/arch/arm/boot/dts/imx6dl-wandboard.dts b/arch/arm/boot/dts/imx6dl-wandboard.dts
index a09f274..b43454d 100644
--- a/arch/arm/boot/dts/imx6dl-wandboard.dts
+++ b/arch/arm/boot/dts/imx6dl-wandboard.dts
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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.
- *
*/
/dts-v1/;
#include "imx6dl.dtsi"
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 558bce8..b384913 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -1,12 +1,6 @@
-
-/*
- * Copyright 2013 Freescale Semiconductor, Inc.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2013 Freescale Semiconductor, Inc.
#include <dt-bindings/interrupt-controller/irq.h>
#include "imx6dl-pinfunc.h"
diff --git a/arch/arm/boot/dts/imx6q-b850v3.dts b/arch/arm/boot/dts/imx6q-b850v3.dts
index 35edbdc..044a5be 100644
--- a/arch/arm/boot/dts/imx6q-b850v3.dts
+++ b/arch/arm/boot/dts/imx6q-b850v3.dts
@@ -156,8 +156,6 @@
stdp2690@72 {
compatible = "megachips,stdp2690-ge-b850v3-fw";
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0x72>;
ports {
@@ -184,8 +182,6 @@
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>;
diff --git a/arch/arm/boot/dts/imx6q-ba16.dtsi b/arch/arm/boot/dts/imx6q-ba16.dtsi
index bf4bdb3..e903c48 100644
--- a/arch/arm/boot/dts/imx6q-ba16.dtsi
+++ b/arch/arm/boot/dts/imx6q-ba16.dtsi
@@ -157,7 +157,12 @@
partition@d0000 {
label = "spare";
- reg = <0xd0000 0x130000>;
+ reg = <0xd0000 0x320000>;
+ };
+
+ partition@3f0000 {
+ label = "mfg";
+ reg = <0x3f0000 0x10000>;
};
};
};
diff --git a/arch/arm/boot/dts/imx6q-bx50v3.dtsi b/arch/arm/boot/dts/imx6q-bx50v3.dtsi
index 990e411..d3cba09 100644
--- a/arch/arm/boot/dts/imx6q-bx50v3.dtsi
+++ b/arch/arm/boot/dts/imx6q-bx50v3.dtsi
@@ -43,13 +43,10 @@
#include "imx6q-ba16.dtsi"
/ {
- clocks {
- mclk: clock@0 {
- compatible = "fixed-clock";
- reg = <0>;
- #clock-cells = <0>;
- clock-frequency = <22000000>;
- };
+ mclk: clock-mclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <22000000>;
};
gpio-poweroff {
@@ -107,8 +104,6 @@
switch@0 {
compatible = "marvell,mv88e6085"; /* 88e6240*/
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0>;
switch_ports: ports {
diff --git a/arch/arm/boot/dts/imx6q-dhcom-pdk2.dts b/arch/arm/boot/dts/imx6q-dhcom-pdk2.dts
new file mode 100644
index 0000000..9c61e3b
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-dhcom-pdk2.dts
@@ -0,0 +1,151 @@
+// SPDX-License-Identifier: (GPL-2.0+)
+/*
+ * Copyright (C) 2015 DH electronics GmbH
+ * Copyright (C) 2018 Marek Vasut <marex@denx.de>
+ */
+
+/dts-v1/;
+
+#include "imx6q-dhcom-som.dtsi"
+
+/ {
+ model = "Freescale i.MX6 Quad DHCOM Premium Developer Kit (2)";
+ compatible = "dh,imx6q-dhcom-pdk2", "dh,imx6q-dhcom-som", "fsl,imx6q";
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ clk_ext_audio_codec: clock-codec {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ };
+
+ sound {
+ compatible = "fsl,imx-audio-sgtl5000";
+ model = "imx-sgtl5000";
+ ssi-controller = <&ssi1>;
+ audio-codec = <&sgtl5000>;
+ audio-routing =
+ "MIC_IN", "Mic Jack",
+ "Mic Jack", "Mic Bias",
+ "LINE_IN", "Line In Jack",
+ "Headphone Jack", "HP_OUT";
+ mux-int-port = <1>;
+ mux-ext-port = <3>;
+ };
+};
+
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux_ext>;
+ status = "okay";
+};
+
+&hdmi {
+ ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&i2c2 {
+ sgtl5000: codec@a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ #sound-dai-cells = <0>;
+ clocks = <&clk_ext_audio_codec>;
+ VDDA-supply = <&reg_3p3v>;
+ VDDIO-supply = <&reg_3p3v>;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_base &pinctrl_hog>;
+
+ pinctrl_hog: hog-grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x400120b0
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x400120b0
+ MX6QDL_PAD_GPIO_5__GPIO1_IO05 0x400120b0
+ MX6QDL_PAD_CSI0_DAT17__GPIO6_IO03 0x400120b0
+ MX6QDL_PAD_GPIO_19__GPIO4_IO05 0x120b0
+ MX6QDL_PAD_DI0_PIN4__GPIO4_IO20 0x400120b0
+ MX6QDL_PAD_EIM_D27__GPIO3_IO27 0x120b0
+ MX6QDL_PAD_KEY_ROW0__GPIO4_IO07 0x120b0
+ MX6QDL_PAD_KEY_COL1__GPIO4_IO08 0x400120b0
+ MX6QDL_PAD_NANDF_CS1__GPIO6_IO14 0x400120b0
+ MX6QDL_PAD_NANDF_CS2__GPIO6_IO15 0x400120b0
+ MX6QDL_PAD_KEY_ROW1__GPIO4_IO09 0x400120b0
+ MX6QDL_PAD_SD3_DAT5__GPIO7_IO00 0x400120b0
+ MX6QDL_PAD_SD3_DAT4__GPIO7_IO01 0x400120b0
+ MX6QDL_PAD_CSI0_VSYNC__GPIO5_IO21 0x400120b0
+ MX6QDL_PAD_GPIO_18__GPIO7_IO13 0x400120b0
+ MX6QDL_PAD_SD1_CMD__GPIO1_IO18 0x400120b0
+ MX6QDL_PAD_SD1_DAT0__GPIO1_IO16 0x400120b0
+ MX6QDL_PAD_SD1_DAT1__GPIO1_IO17 0x400120b0
+ MX6QDL_PAD_SD1_DAT2__GPIO1_IO19 0x400120b0
+ MX6QDL_PAD_SD1_CLK__GPIO1_IO20 0x400120b0
+ MX6QDL_PAD_CSI0_PIXCLK__GPIO5_IO18 0x400120b0
+ MX6QDL_PAD_CSI0_MCLK__GPIO5_IO19 0x400120b0
+ MX6QDL_PAD_KEY_COL0__GPIO4_IO06 0x400120b0
+ >;
+ };
+
+ pinctrl_audmux_ext: audmux-ext-grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ >;
+ };
+
+ pinctrl_enet_1G: enet-1G-grp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x100b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x100b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x100b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x100b0
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x100b0
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x100b0
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x100b0
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x100b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x100b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+ MX6QDL_PAD_EIM_D29__GPIO3_IO29 0x000b0
+ MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x000b1
+ MX6QDL_PAD_EIM_D26__GPIO3_IO26 0x000b1
+ >;
+ };
+
+ pinctrl_pcie: pcie-grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DATA_EN__GPIO5_IO20 0x1b0b1
+ >;
+ };
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie>;
+ reset-gpio = <&gpio6 14 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&ssi1 {
+ status = "okay";
+};
+
+&sata {
+ status = "okay";
+};
+
+&usdhc3 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-dhcom-som.dtsi b/arch/arm/boot/dts/imx6q-dhcom-som.dtsi
new file mode 100644
index 0000000..bbba067
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-dhcom-som.dtsi
@@ -0,0 +1,476 @@
+// SPDX-License-Identifier: (GPL-2.0+)
+/*
+ * Copyright (C) 2015 DH electronics GmbH
+ * Copyright (C) 2018 Marek Vasut <marex@denx.de>
+ */
+
+#include "imx6q.dtsi"
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/imx6qdl-clock.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ aliases {
+ mmc0 = &usdhc2;
+ mmc1 = &usdhc3;
+ mmc2 = &usdhc4;
+ mmc3 = &usdhc1;
+ };
+
+ memory@10000000 {
+ reg = <0x10000000 0x40000000>;
+ };
+
+ reg_usb_otg_vbus: regulator-usb-otg-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_usb_h1_vbus: regulator-usb-h1-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb_h1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_3p3v: regulator-3P3V {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+ status = "okay";
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+ status = "okay";
+};
+
+&ecspi1 {
+ cs-gpios = <&gpio2 30 GPIO_ACTIVE_HIGH>, <&gpio4 11 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1>;
+ status = "okay";
+
+ flash@0 { /* S25FL116K */
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <50000000>;
+ reg = <0>;
+ m25p,fast-read;
+ };
+};
+
+&ecspi2 {
+ cs-gpios = <&gpio5 29 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi2>;
+ status = "okay";
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet_100M>;
+ phy-mode = "rmii";
+ phy-handle = <&ethphy0>;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 { /* SMSC LAN8710Ai */
+ reg = <0>;
+ max-speed = <100>;
+ reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ reset-post-delay-us = <1000>;
+ };
+ };
+};
+
+&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";
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ ltc3676: pmic@3c {
+ compatible = "lltc,ltc3676";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pmic_hw300>;
+ reg = <0x3c>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+
+ regulators {
+ sw1_reg: sw1 {
+ regulator-min-microvolt = <787500>;
+ regulator-max-microvolt = <1527272>;
+ lltc,fb-voltage-divider = <100000 110000>;
+ regulator-suspend-mem-microvolt = <1040000>;
+ regulator-ramp-delay = <7000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <1885714>;
+ regulator-max-microvolt = <3657142>;
+ lltc,fb-voltage-divider = <100000 28000>;
+ regulator-ramp-delay = <7000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3_reg: sw3 {
+ regulator-min-microvolt = <787500>;
+ regulator-max-microvolt = <1527272>;
+ lltc,fb-voltage-divider = <100000 110000>;
+ regulator-suspend-mem-microvolt = <980000>;
+ regulator-ramp-delay = <7000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <855571>;
+ regulator-max-microvolt = <1659291>;
+ lltc,fb-voltage-divider = <100000 93100>;
+ regulator-ramp-delay = <7000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1_reg: ldo1 {
+ regulator-min-microvolt = <3240306>;
+ regulator-max-microvolt = <3240306>;
+ lltc,fb-voltage-divider = <102000 29400>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2_reg: ldo2 {
+ regulator-min-microvolt = <2484708>;
+ regulator-max-microvolt = <2484708>;
+ lltc,fb-voltage-divider = <100000 41200>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+
+ touchscreen@49 { /* TSC2004 */
+ compatible = "ti,tsc2004";
+ reg = <0x49>;
+ vio-supply = <&reg_3p3v>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_tsc2004_hw300>;
+ interrupts-extended = <&gpio4 14 IRQ_TYPE_EDGE_FALLING>;
+ status = "disabled";
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
+
+ rtc@56 {
+ compatible = "rv3029c2";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rtc_hw300>;
+ reg = <0x56>;
+ interrupt-parent = <&gpio7>;
+ interrupts = <12 2>;
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog_base>;
+
+ pinctrl_hog_base: hog-base-grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A19__GPIO2_IO19 0x120b0
+ MX6QDL_PAD_EIM_A23__GPIO6_IO06 0x120b0
+ MX6QDL_PAD_EIM_A22__GPIO2_IO16 0x120b0
+ MX6QDL_PAD_EIM_A16__GPIO2_IO22 0x120b0
+ MX6QDL_PAD_EIM_A17__GPIO2_IO21 0x120b0
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1-grp {
+ 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 0x1b0b0
+ MX6QDL_PAD_KEY_ROW2__GPIO4_IO11 0x1b0b0
+ >;
+ };
+
+ pinctrl_ecspi2: ecspi2-grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT10__ECSPI2_MISO 0x100b1
+ MX6QDL_PAD_CSI0_DAT9__ECSPI2_MOSI 0x100b1
+ MX6QDL_PAD_CSI0_DAT8__ECSPI2_SCLK 0x100b1
+ MX6QDL_PAD_CSI0_DAT11__GPIO5_IO29 0x1b0b0
+ >;
+ };
+
+ pinctrl_enet_100M: enet-100M-grp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN 0x1b0b0
+ MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER 0x1b0b0
+ MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1 0x1b0b0
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
+ MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0 0x1b0b0
+ MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1 0x1b0b0
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ MX6QDL_PAD_EIM_WAIT__GPIO5_IO00 0x000b0
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x000b1
+ MX6QDL_PAD_GPIO_7__GPIO1_IO07 0x120b0
+ >;
+ };
+
+ pinctrl_flexcan1: flexcan1-grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL2__FLEXCAN1_TX 0x1b0b0
+ MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan2: flexcan2-grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT0__FLEXCAN2_TX 0x1b0b0
+ MX6QDL_PAD_SD3_DAT1__FLEXCAN2_RX 0x1b0b0
+ >;
+ };
+
+ pinctrl_i2c1: i2c1-grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
+ MX6QDL_PAD_EIM_D28__I2C1_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c2: i2c2-grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3-grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_pmic_hw300: pmic-hw300-grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1B0B0
+ >;
+ };
+
+ pinctrl_rtc_hw300: rtc-hw300-grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x120B0
+ >;
+ };
+
+ pinctrl_tsc2004_hw300: tsc2004-hw300-grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x120B0
+ >;
+ };
+
+ pinctrl_uart1: uart1-grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D20__UART1_RTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_D19__UART1_CTS_B 0x4001b0b1
+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x4001b0b1
+ MX6QDL_PAD_EIM_D24__GPIO3_IO24 0x4001b0b1
+ MX6QDL_PAD_EIM_D25__GPIO3_IO25 0x4001b0b1
+ MX6QDL_PAD_EIM_EB3__GPIO2_IO31 0x4001b0b1
+ >;
+ };
+
+ pinctrl_uart4: uart4-grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart5: uart5-grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT14__UART5_TX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT15__UART5_RX_DATA 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT18__UART5_RTS_B 0x1b0b1
+ MX6QDL_PAD_CSI0_DAT19__UART5_CTS_B 0x4001b0b1
+ >;
+ };
+
+ pinctrl_usbh1: usbh1-grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x120B0
+ >;
+ };
+
+ pinctrl_usbotg: usbotg-grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2-grp {
+ 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_CS3__GPIO6_IO16 0x120B0
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3-grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 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_RST__GPIO7_IO08 0x120B0
+ >;
+ };
+
+ pinctrl_usdhc4: usdhc4-grp {
+ 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
+ >;
+ };
+};
+
+&reg_arm {
+ vin-supply = <&sw3_reg>;
+};
+
+&reg_soc {
+ vin-supply = <&sw1_reg>;
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ uart-has-rtscts;
+ dtr-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>;
+ dsr-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+ dcd-gpios = <&gpio3 23 GPIO_ACTIVE_LOW>;
+ rng-gpios = <&gpio2 31 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+&uart5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart5>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
+&usbh1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbh1>;
+ vbus-supply = <&reg_usb_h1_vbus>;
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <&reg_usb_otg_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ disable-over-current;
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ cd-gpios = <&gpio6 16 GPIO_ACTIVE_HIGH>;
+ keep-power-in-suspend;
+ status = "okay";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ cd-gpios = <&gpio7 8 GPIO_ACTIVE_LOW>;
+ fsl,wp-controller;
+ keep-power-in-suspend;
+ status = "disabled";
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ non-removable;
+ bus-width = <8>;
+ no-1-8-v;
+ keep-power-in-suspend;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-gk802.dts b/arch/arm/boot/dts/imx6q-gk802.dts
index 0be3756..84d3540 100644
--- a/arch/arm/boot/dts/imx6q-gk802.dts
+++ b/arch/arm/boot/dts/imx6q-gk802.dts
@@ -8,6 +8,7 @@
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
#include "imx6q.dtsi"
/ {
@@ -43,7 +44,7 @@
recovery-button {
label = "recovery";
gpios = <&gpio3 16 1>;
- linux,code = <0x198>; /* KEY_RESTART */
+ linux,code = <KEY_RESTART>;
wakeup-source;
};
};
diff --git a/arch/arm/boot/dts/imx6q-icore-mipi.dts b/arch/arm/boot/dts/imx6q-icore-mipi.dts
new file mode 100644
index 0000000..acd3d33
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-icore-mipi.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2017 Engicam S.r.l.
+ * Copyright (C) 2017 Amarula Solutions B.V.
+ * Author: Jagan Teki <jagan@amarulasolutions.com>
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-icore.dtsi"
+
+/ {
+ model = "Engicam i.CoreM6 Quad/Dual MIPI Starter Kit";
+ compatible = "engicam,imx6-icore", "fsl,imx6q";
+};
+
+&hdmi {
+ ddc-i2c-bus = <&i2c2>;
+ status = "okay";
+};
+
+&usdhc3 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-icore-ofcap12.dts b/arch/arm/boot/dts/imx6q-icore-ofcap12.dts
index 9e230f5..6e27c81 100644
--- a/arch/arm/boot/dts/imx6q-icore-ofcap12.dts
+++ b/arch/arm/boot/dts/imx6q-icore-ofcap12.dts
@@ -48,28 +48,31 @@
/ {
model = "Engicam i.CoreM6 Quad/Dual OpenFrame Capacitive touch 12 Kit";
compatible = "engicam,imx6-icore", "fsl,imx6q";
+
+ panel {
+ compatible = "koe,tx31d200vm0baa";
+ backlight = <&backlight_lvds>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+ };
};
&ldb {
status = "okay";
lvds-channel@0 {
- fsl,data-mapping = "spwg";
- fsl,data-width = <18>;
+ reg = <0>;
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>;
+ port@4 {
+ reg = <4>;
+
+ lvds0_out: endpoint {
+ remote-endpoint = <&panel_in>;
};
};
};
diff --git a/arch/arm/boot/dts/imx6q-kp-tpc.dts b/arch/arm/boot/dts/imx6q-kp-tpc.dts
new file mode 100644
index 0000000..302d8d0
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-kp-tpc.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018
+ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
+ */
+
+/dts-v1/;
+
+#include "imx6q-kp.dtsi"
+
+/ {
+ model = "Freescale i.MX6 Qwuad K+P TPC Board";
+ compatible = "kiebackpeter,imx6q-tpc", "fsl,imx6q";
+
+ memory@10000000 {
+ reg = <0x10000000 0x40000000>;
+ };
+};
+
+&ipu1_di0_disp0 {
+ remote-endpoint = <&lcd_display_in>;
+};
diff --git a/arch/arm/boot/dts/imx6q-kp.dtsi b/arch/arm/boot/dts/imx6q-kp.dtsi
new file mode 100644
index 0000000..24c8169
--- /dev/null
+++ b/arch/arm/boot/dts/imx6q-kp.dtsi
@@ -0,0 +1,432 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018
+ * Lukasz Majewski, DENX Software Engineering, lukma@denx.de
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pwm/pwm.h>
+#include <dt-bindings/sound/fsl-imx-audmux.h>
+
+/ {
+ backlight_lcd: backlight-lcd {
+ compatible = "pwm-backlight";
+ pwms = <&pwm1 0 5000000>;
+ brightness-levels = <0 255>;
+ num-interpolated-steps = <255>;
+ default-brightness-level = <250>;
+ };
+
+ beeper {
+ compatible = "pwm-beeper";
+ pwms = <&pwm2 0 500000>;
+ };
+
+ lcd_display: display {
+ compatible = "fsl,imx-parallel-display";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interface-pix-fmt = "rgb24";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu1>;
+
+ port@0 {
+ reg = <0>;
+
+ lcd_display_in: endpoint {
+ remote-endpoint = <&ipu1_di0_disp0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+
+ lcd_display_out: endpoint {
+ remote-endpoint = <&lcd_panel_in>;
+ };
+ };
+ };
+
+ lcd_panel: lcd-panel {
+ compatible = "auo,g070vvn01";
+ backlight = <&backlight_lcd>;
+ power-supply = <&reg_display>;
+
+ port {
+ lcd_panel_in: endpoint {
+ remote-endpoint = <&lcd_display_out>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ green {
+ label = "led1";
+ gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "gpio";
+ default-state = "off";
+ };
+
+ red {
+ label = "led0";
+ gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "gpio";
+ default-state = "off";
+ };
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_audio: regulator-audio {
+ compatible = "regulator-fixed";
+ regulator-name = "sgtl5000-supply";
+ gpio = <&gpio6 31 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ reg_display: regulator-display {
+ compatible = "regulator-fixed";
+ regulator-name = "display-supply";
+ 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>;
+ enable-active-high;
+ };
+
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "imx6q-sgtl5000-audio";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&codec_dai>;
+ simple-audio-card,frame-master = <&codec_dai>;
+
+ cpu_dai: simple-audio-card,cpu {
+ sound-dai = <&ssi1>;
+ };
+
+ codec_dai: simple-audio-card,codec {
+ sound-dai = <&sgtl5000>;
+ };
+ };
+};
+
+&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)
+ >;
+ };
+};
+
+&can1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan1>;
+};
+
+&can2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexcan2>;
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rgmii";
+ fsl,magic-packet;
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+ touchscreen@5d {
+ compatible = "goodix,gt911";
+ reg = <0x5d>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ts>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+ irq-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
+ };
+
+ ds1307: rtc@32 {
+ compatible = "dallas,ds1307";
+ reg = <0x32>;
+ };
+};
+
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ sgtl5000: audio-codec@a {
+ compatible = "fsl,sgtl5000";
+ #sound-dai-cells = <0>;
+ reg = <0x0a>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_codec>;
+ clocks = <&clks IMX6QDL_CLK_CKO>;
+ VDDA-supply = <&reg_3p3v>;
+ VDDIO-supply = <&reg_3p3v>;
+ };
+};
+
+&iomuxc {
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ >;
+ };
+
+ pinctrl_codec: codecgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x1b0b0
+ /* sgtl5000 sys_mclk clock routed to CLKO1 */
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x000b0
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ >;
+ };
+
+ pinctrl_flexcan1: can1grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_7__FLEXCAN1_TX 0x1b0b0
+ MX6QDL_PAD_GPIO_8__FLEXCAN1_RX 0x1b0b0
+ >;
+ };
+
+ pinctrl_flexcan2: can2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL4__FLEXCAN2_TX 0x1b0b0
+ MX6QDL_PAD_KEY_ROW4__FLEXCAN2_RX 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_ipu1: ipu1grp {
+ fsl,pins = <
+ MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x10
+ MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15 0x10
+ MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02 0x10
+ MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03 0x10
+ MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00 0x10
+ MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01 0x10
+ MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02 0x10
+ MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03 0x10
+ MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04 0x10
+ MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05 0x10
+ MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06 0x10
+ MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07 0x10
+ MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08 0x10
+ MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09 0x10
+ MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10 0x10
+ MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11 0x10
+ MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12 0x10
+ MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13 0x10
+ MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14 0x10
+ MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15 0x10
+ MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16 0x10
+ MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17 0x10
+ MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18 0x10
+ MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19 0x10
+ MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20 0x10
+ MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21 0x10
+ MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22 0x10
+ MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23 0x10
+ >;
+ };
+
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT3__PWM1_OUT 0x1b0b1
+ >;
+ };
+
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_DAT2__PWM2_OUT 0x1b0b1
+ >;
+ };
+
+ pinctrl_ts: tsgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_9__GPIO1_IO09 0x1b0b0
+ MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1b0b0
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D28__UART2_CTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_D29__UART2_RTS_B 0x1b0b1
+ >;
+ };
+
+ 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
+ >;
+ };
+
+ 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
+ >;
+ };
+};
+
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm2>;
+ status = "okay";
+};
+
+&ssi1 {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ uart-has-rtscts;
+};
+
+&usbh1 {
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ bus-width = <4>;
+ cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ bus-width = <8>;
+ non-removable;
+ no-1-8-v;
+ keep-power-in-suspend;
+ status = "okay";
+};
+
+&wdog1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-novena.dts b/arch/arm/boot/dts/imx6q-novena.dts
index 52f3937..fcd824d 100644
--- a/arch/arm/boot/dts/imx6q-novena.dts
+++ b/arch/arm/boot/dts/imx6q-novena.dts
@@ -268,8 +268,6 @@
touch: stmpe811@44 {
compatible = "st,stmpe811";
reg = <0x44>;
- #address-cells = <1>;
- #size-cells = <0>;
irq-gpio = <&gpio5 13 GPIO_ACTIVE_HIGH>;
id = <0>;
blocks = <0x5>;
diff --git a/arch/arm/boot/dts/imx6q-pistachio.dts b/arch/arm/boot/dts/imx6q-pistachio.dts
index bd57b3b..a31e83c 100644
--- a/arch/arm/boot/dts/imx6q-pistachio.dts
+++ b/arch/arm/boot/dts/imx6q-pistachio.dts
@@ -614,7 +614,7 @@
&uart5 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart5>;
- fsl,uart-has-rtscts;
+ uart-has-rtscts;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-sabreauto.dts b/arch/arm/boot/dts/imx6q-sabreauto.dts
index 334b924..6e981a3 100644
--- a/arch/arm/boot/dts/imx6q-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6q-sabreauto.dts
@@ -1,14 +1,7 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
/dts-v1/;
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
index 527772b..eec9446 100644
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ b/arch/arm/boot/dts/imx6q-sabresd.dts
@@ -1,14 +1,7 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
/dts-v1/;
diff --git a/arch/arm/boot/dts/imx6q-udoo.dts b/arch/arm/boot/dts/imx6q-udoo.dts
index c3e64ff..52e9f4a 100644
--- a/arch/arm/boot/dts/imx6q-udoo.dts
+++ b/arch/arm/boot/dts/imx6q-udoo.dts
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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.
- *
*/
/dts-v1/;
#include "imx6q.dtsi"
diff --git a/arch/arm/boot/dts/imx6q-utilite-pro.dts b/arch/arm/boot/dts/imx6q-utilite-pro.dts
index f5d9c34..d16ff20 100644
--- a/arch/arm/boot/dts/imx6q-utilite-pro.dts
+++ b/arch/arm/boot/dts/imx6q-utilite-pro.dts
@@ -61,8 +61,6 @@
encoder {
compatible = "ti,tfp410";
- #address-cells = <1>;
- #size-cells = <0>;
ports {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/imx6q-var-dt6customboard.dts b/arch/arm/boot/dts/imx6q-var-dt6customboard.dts
index e0728d4..f2368a0 100644
--- a/arch/arm/boot/dts/imx6q-var-dt6customboard.dts
+++ b/arch/arm/boot/dts/imx6q-var-dt6customboard.dts
@@ -26,8 +26,6 @@
gpio-keys {
compatible = "gpio-keys";
- #address-cells = <1>;
- #size-cells = <0>;
autorepeat;
back {
diff --git a/arch/arm/boot/dts/imx6q-wandboard-revb1.dts b/arch/arm/boot/dts/imx6q-wandboard-revb1.dts
index b763352..be85b98 100644
--- a/arch/arm/boot/dts/imx6q-wandboard-revb1.dts
+++ b/arch/arm/boot/dts/imx6q-wandboard-revb1.dts
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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.
- *
*/
/dts-v1/;
#include "imx6q.dtsi"
diff --git a/arch/arm/boot/dts/imx6q-wandboard-revd1.dts b/arch/arm/boot/dts/imx6q-wandboard-revd1.dts
index 8691fab..fcfba28 100644
--- a/arch/arm/boot/dts/imx6q-wandboard-revd1.dts
+++ b/arch/arm/boot/dts/imx6q-wandboard-revd1.dts
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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.
- *
*/
/dts-v1/;
#include "imx6q.dtsi"
diff --git a/arch/arm/boot/dts/imx6q-wandboard.dts b/arch/arm/boot/dts/imx6q-wandboard.dts
index 2a3d98c..fa36fe18 100644
--- a/arch/arm/boot/dts/imx6q-wandboard.dts
+++ b/arch/arm/boot/dts/imx6q-wandboard.dts
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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.
- *
*/
/dts-v1/;
#include "imx6q.dtsi"
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index ae7b3f1..70483ce 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -1,12 +1,6 @@
-
-/*
- * Copyright 2013 Freescale Semiconductor, Inc.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2013 Freescale Semiconductor, Inc.
#include <dt-bindings/interrupt-controller/irq.h>
#include "imx6q-pinfunc.h"
@@ -162,22 +156,27 @@
#size-cells = <0>;
reg = <2>;
- ipu2_di0_disp0: disp0-endpoint {
+ ipu2_di0_disp0: endpoint@0 {
+ reg = <0>;
};
- ipu2_di0_hdmi: hdmi-endpoint {
+ ipu2_di0_hdmi: endpoint@1 {
+ reg = <1>;
remote-endpoint = <&hdmi_mux_2>;
};
- ipu2_di0_mipi: mipi-endpoint {
+ ipu2_di0_mipi: endpoint@2 {
+ reg = <2>;
remote-endpoint = <&mipi_mux_2>;
};
- ipu2_di0_lvds0: lvds0-endpoint {
+ ipu2_di0_lvds0: endpoint@3 {
+ reg = <3>;
remote-endpoint = <&lvds0_mux_2>;
};
- ipu2_di0_lvds1: lvds1-endpoint {
+ ipu2_di0_lvds1: endpoint@4 {
+ reg = <4>;
remote-endpoint = <&lvds1_mux_2>;
};
};
@@ -187,19 +186,23 @@
#size-cells = <0>;
reg = <3>;
- ipu2_di1_hdmi: hdmi-endpoint {
+ ipu2_di1_hdmi: endpoint@1 {
+ reg = <1>;
remote-endpoint = <&hdmi_mux_3>;
};
- ipu2_di1_mipi: mipi-endpoint {
+ ipu2_di1_mipi: endpoint@2 {
+ reg = <2>;
remote-endpoint = <&mipi_mux_3>;
};
- ipu2_di1_lvds0: lvds0-endpoint {
+ ipu2_di1_lvds0: endpoint@3 {
+ reg = <3>;
remote-endpoint = <&lvds0_mux_3>;
};
- ipu2_di1_lvds1: lvds1-endpoint {
+ ipu2_di1_lvds1: endpoint@4 {
+ reg = <4>;
remote-endpoint = <&lvds1_mux_3>;
};
};
diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
index 8206683..64fbee6 100644
--- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
@@ -331,8 +331,6 @@
compatible = "st,stmpe811";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_touch_int>;
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0x41>;
interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
interrupt-parent = <&gpio4>;
diff --git a/arch/arm/boot/dts/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/imx6qdl-colibri.dtsi
index e4eb300..76035db 100644
--- a/arch/arm/boot/dts/imx6qdl-colibri.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-colibri.dtsi
@@ -262,8 +262,6 @@
compatible = "st,stmpe811";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_touch_int>;
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0x41>;
interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
interrupt-parent = <&gpio6>;
diff --git a/arch/arm/boot/dts/imx6qdl-gw5904.dtsi b/arch/arm/boot/dts/imx6qdl-gw5904.dtsi
index 58124ad..3c52bdb 100644
--- a/arch/arm/boot/dts/imx6qdl-gw5904.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw5904.dtsi
@@ -162,8 +162,6 @@
switch@0 {
compatible = "marvell,mv88e6085";
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0>;
ports {
diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
index 7e20b47..0e64016 100644
--- a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
@@ -38,6 +38,7 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <dt-bindings/sound/fsl-imx-audmux.h>
/ {
/* Will be filled by the bootloader */
@@ -110,17 +111,27 @@
vin-supply = <&v_5v0>;
};
- sound-sgtl5000 {
- audio-codec = <&sgtl5000>;
- audio-routing =
- "MIC_IN", "Mic Jack",
- "Mic Jack", "Mic Bias",
+ audio: sound-sgtl5000 {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "On-board Codec";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&sound_codec>;
+ simple-audio-card,frame-master = <&sound_codec>;
+ simple-audio-card,widgets =
+ "Microphone", "Headphone Jack",
+ "Headphone", "Headphone Jack";
+ simple-audio-card,routing =
+ "MIC_IN", "Headphone Jack",
+ "Headphone Jack", "Mic Bias",
"Headphone Jack", "HP_OUT";
- compatible = "fsl,imx-audio-sgtl5000";
- model = "On-board Codec";
- mux-ext-port = <5>;
- mux-int-port = <1>;
- ssi-controller = <&ssi1>;
+
+ sound_cpu: simple-audio-card,cpu {
+ sound-dai = <&ssi1>;
+ };
+
+ sound_codec: simple-audio-card,codec {
+ sound-dai = <&sgtl5000>;
+ };
};
sound-spdif {
@@ -134,6 +145,26 @@
&audmux {
status = "okay";
+
+ ssi1 {
+ fsl,audmux-port = <0>;
+ 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)
+ >;
+ };
+
+ pins5 {
+ fsl,audmux-port = <4>;
+ fsl,port-config = <
+ IMX_AUDMUX_V2_PTCR_SYN
+ IMX_AUDMUX_V2_PDCR_RXDSEL(0)
+ >;
+ };
};
&can1 {
@@ -166,6 +197,7 @@
compatible = "fsl,sgtl5000";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hummingboard_sgtl5000>;
+ #sound-dai-cells = <0>;
reg = <0x0a>;
VDDA-supply = <&v_3v2>;
VDDIO-supply = <&v_3v2>;
diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
index 98241ac..c413f9c 100644
--- a/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-hummingboard2.dtsi
@@ -38,6 +38,7 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <dt-bindings/sound/fsl-imx-audmux.h>
/ {
/* Will be filled by the bootloader */
@@ -150,22 +151,52 @@
vin-supply = <&v_5v0>;
};
- sound-sgtl5000 {
- audio-codec = <&sgtl5000>;
- audio-routing =
+ audio: sound-sgtl5000 {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "On-board Codec";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,bitclock-master = <&sound_codec>;
+ simple-audio-card,frame-master = <&sound_codec>;
+ simple-audio-card,widgets =
+ "Microphone", "Mic Jack",
+ "Headphone", "Headphone Jack";
+ simple-audio-card,routing =
"MIC_IN", "Mic Jack",
"Mic Jack", "Mic Bias",
"Headphone Jack", "HP_OUT";
- compatible = "fsl,imx-audio-sgtl5000";
- model = "On-board Codec";
- mux-ext-port = <5>;
- mux-int-port = <1>;
- ssi-controller = <&ssi1>;
+
+ sound_cpu: simple-audio-card,cpu {
+ sound-dai = <&ssi1>;
+ };
+
+ sound_codec: simple-audio-card,codec {
+ sound-dai = <&sgtl5000>;
+ };
};
};
&audmux {
status = "okay";
+
+ ssi1 {
+ fsl,audmux-port = <0>;
+ 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)
+ >;
+ };
+
+ pins5 {
+ fsl,audmux-port = <4>;
+ fsl,port-config = <
+ IMX_AUDMUX_V2_PTCR_SYN
+ IMX_AUDMUX_V2_PDCR_RXDSEL(0)
+ >;
+ };
};
&ecspi2 {
diff --git a/arch/arm/boot/dts/imx6qdl-icore.dtsi b/arch/arm/boot/dts/imx6qdl-icore.dtsi
index b3a463a..0a15749 100644
--- a/arch/arm/boot/dts/imx6qdl-icore.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-icore.dtsi
@@ -49,7 +49,7 @@
reg = <0x10000000 0x80000000>;
};
- backlight {
+ backlight_lvds: backlight-lvds {
compatible = "pwm-backlight";
pwms = <&pwm3 0 100000>;
brightness-levels = <0 4 8 16 32 64 128 255>;
@@ -265,6 +265,14 @@
status = "okay";
};
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ no-1-8-v;
+ non-removable;
+ status = "disabled";
+};
+
&iomuxc {
pinctrl_audmux: audmux {
fsl,pins = <
@@ -378,4 +386,19 @@
MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17070
>;
};
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 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
+ >;
+ };
};
diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
index c58f344..ed1aafd 100644
--- a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
@@ -115,7 +115,7 @@
compatible = "dlg,da9063";
reg = <0x58>;
interrupt-parent = <&gpio2>;
- interrupts = <9 0x8>; /* active-low GPIO2_9 */
+ interrupts = <9 IRQ_TYPE_LEVEL_LOW>; /* active-low GPIO2_9 */
regulators {
vddcore_reg: bcore1 {
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 54b0139..0e28e36 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -1,14 +1,7 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
#include <dt-bindings/gpio/gpio.h>
diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
index 18b6505..654cf2c 100644
--- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
@@ -379,9 +379,6 @@
powerdown-gpios = <&gpio6 9 GPIO_ACTIVE_HIGH>; /* NANDF_WP_B */
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
ov5640_to_mipi_csi2: endpoint {
remote-endpoint = <&mipi_csi2_in>;
clock-lanes = <0>;
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index f019f99..15744ad 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -1,14 +1,7 @@
-/*
- * Copyright 2012 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2012 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
#include <dt-bindings/clock/imx6qdl-clock.h>
#include <dt-bindings/gpio/gpio.h>
@@ -294,9 +287,6 @@
reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
ov5640_to_mipi_csi2: endpoint {
remote-endpoint = <&mipi_csi2_in>;
clock-lanes = <0>;
diff --git a/arch/arm/boot/dts/imx6qdl-tx6-lcd.dtsi b/arch/arm/boot/dts/imx6qdl-tx6-lcd.dtsi
index 5102fc4..79f2354 100644
--- a/arch/arm/boot/dts/imx6qdl-tx6-lcd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-tx6-lcd.dtsi
@@ -77,7 +77,6 @@
enable-gpios = <&gpio3 29 GPIO_ACTIVE_HIGH>;
power-supply = <&reg_3v3>;
backlight = <&backlight>;
- bus-format-override = "rgb24";
port {
lcd_panel_in: endpoint {
diff --git a/arch/arm/boot/dts/imx6qdl-tx6-mb7.dtsi b/arch/arm/boot/dts/imx6qdl-tx6-mb7.dtsi
index 4c4e2e1..410972e 100644
--- a/arch/arm/boot/dts/imx6qdl-tx6-mb7.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-tx6-mb7.dtsi
@@ -54,19 +54,16 @@
lcd-panel {
compatible = "edt,et057090dhu";
- bus-format-override = "rgb24";
pixelclk-active = <0>;
};
lvds0-panel {
compatible = "edt,etml1010g0dka";
- bus-format-override = "spwg-18";
pixelclk-active = <0>;
};
lvds1-panel {
compatible = "edt,etml1010g0dka";
- bus-format-override = "spwg-18";
pixelclk-active = <0>;
};
};
diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi
index f015e2d..a98fb25 100644
--- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi
@@ -50,11 +50,11 @@
can0 = &can2;
can1 = &can1;
ethernet0 = &fec;
- lcdif_23bit_pins_a = &pinctrl_disp0_1;
- lcdif_24bit_pins_a = &pinctrl_disp0_2;
+ lcdif-23bit-pins-a = &pinctrl_disp0_1;
+ lcdif-24bit-pins-a = &pinctrl_disp0_2;
pwm0 = &pwm1;
pwm1 = &pwm2;
- reg_can_xcvr = &reg_can_xcvr;
+ reg-can-xcvr = &reg_can_xcvr;
stk5led = &user_led;
usbotg = &usbotg;
sdhc0 = &usdhc1;
diff --git a/arch/arm/boot/dts/imx6qdl-udoo.dtsi b/arch/arm/boot/dts/imx6qdl-udoo.dtsi
index 9063879..4f27861 100644
--- a/arch/arm/boot/dts/imx6qdl-udoo.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-udoo.dtsi
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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.
- *
*/
/ {
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi
index a320891..855dc6f 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard-revb1.dtsi
@@ -17,7 +17,6 @@
imx6qdl-wandboard {
pinctrl_hog: hoggrp {
fsl,pins = <
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* GPIO_0_CLKO */
MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* uSDHC1 CD */
MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
MX6QDL_PAD_EIM_EB1__GPIO2_IO29 0x0f0b0 /* WL_REF_ON */
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi
index 8d893a7..49a0a55 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard-revc1.dtsi
@@ -17,7 +17,6 @@
imx6qdl-wandboard {
pinctrl_hog: hoggrp {
fsl,pins = <
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 /* GPIO_0_CLKO */
MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* uSDHC1 CD */
MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
MX6QDL_PAD_CSI0_DAT14__GPIO6_IO00 0x0f0b0 /* WIFI_ON (reset, active low) */
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard-revd1.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard-revd1.dtsi
index 3a8a495..69d9c86 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard-revd1.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard-revd1.dtsi
@@ -147,7 +147,6 @@
imx6qdl-wandboard {
pinctrl_hog: hoggrp {
fsl,pins = <
- MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
MX6QDL_PAD_EIM_D22__USB_OTG_PWR 0x80000000 /* USB Power Enable */
MX6QDL_PAD_GPIO_2__GPIO1_IO02 0x80000000 /* USDHC1 CD */
MX6QDL_PAD_EIM_DA9__GPIO3_IO09 0x80000000 /* uSDHC3 CD */
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index ed96d7b..e1afa54 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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 <dt-bindings/gpio/gpio.h>
@@ -83,6 +79,8 @@
status = "okay";
codec: sgtl5000@a {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_mclk>;
compatible = "fsl,sgtl5000";
reg = <0x0a>;
clocks = <&clks IMX6QDL_CLK_CKO>;
@@ -142,6 +140,12 @@
>;
};
+ pinctrl_mclk: mclkgrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
+ >;
+ };
+
pinctrl_spdif: spdifgrp {
fsl,pins = <
MX6QDL_PAD_ENET_RXD0__SPDIF_OUT 0x1b0b0
diff --git a/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi b/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi
index 911f7f0..19a075a 100644
--- a/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi
@@ -263,6 +263,17 @@
};
};
+&cpu0 {
+ fsl,soc-operating-points = <
+ /* ARM kHz SOC-PU uV */
+ 1200000 1300000
+ 996000 1275000
+ 852000 1275000
+ 792000 1200000
+ 396000 1200000
+ >;
+};
+
&reg_arm {
vin-supply = <&sw1a_reg>;
};
@@ -571,6 +582,17 @@
};
};
+ touchscreen@2a {
+ compatible = "eeti,egalax_ts";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ts>;
+ reg = <0x2a>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
+ status = "disabled";
+ };
+
hpa1: amp@60 {
compatible = "ti,tpa6130a2";
pinctrl-names = "default";
@@ -666,8 +688,6 @@
compatible = "marvell,mv88e6085";
pinctrl-0 = <&pinctrl_switch_irq>;
pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0>;
dsa,member = <0 0>;
eeprom-length = <512>;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index c003e62..911141e 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1,14 +1,7 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2011 Freescale Semiconductor, Inc.
+// Copyright 2011 Linaro Ltd.
#include <dt-bindings/clock/imx6qdl-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -58,9 +51,6 @@
};
clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
ckil {
compatible = "fsl,imx-ckil", "fixed-clock";
#clock-cells = <0>;
@@ -695,11 +685,8 @@
interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>,
<0 54 IRQ_TYPE_LEVEL_HIGH>,
<0 127 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- regulator-1p1@20c8110 {
- reg = <0x20c8110>;
+ regulator-1p1 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd1p1";
regulator-min-microvolt = <1000000>;
@@ -714,8 +701,7 @@
anatop-enable-bit = <0>;
};
- regulator-3p0@20c8120 {
- reg = <0x20c8120>;
+ regulator-3p0 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd3p0";
regulator-min-microvolt = <2800000>;
@@ -730,8 +716,7 @@
anatop-enable-bit = <0>;
};
- regulator-2p5@20c8130 {
- reg = <0x20c8130>;
+ regulator-2p5 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd2p5";
regulator-min-microvolt = <2250000>;
@@ -746,8 +731,7 @@
anatop-enable-bit = <0>;
};
- reg_arm: regulator-vddcore@20c8140 {
- reg = <0x20c8140>;
+ reg_arm: regulator-vddcore {
compatible = "fsl,anatop-regulator";
regulator-name = "vddarm";
regulator-min-microvolt = <725000>;
@@ -764,8 +748,7 @@
anatop-max-voltage = <1450000>;
};
- reg_pu: regulator-vddpu@20c8140 {
- reg = <0x20c8140>;
+ reg_pu: regulator-vddpu {
compatible = "fsl,anatop-regulator";
regulator-name = "vddpu";
regulator-min-microvolt = <725000>;
@@ -782,8 +765,7 @@
anatop-max-voltage = <1450000>;
};
- reg_soc: regulator-vddsoc@20c8140 {
- reg = <0x20c8140>;
+ reg_soc: regulator-vddsoc {
compatible = "fsl,anatop-regulator";
regulator-name = "vddsoc";
regulator-min-microvolt = <725000>;
@@ -1187,8 +1169,6 @@
};
mipi_dsi: mipi@21e0000 {
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0x021e0000 0x4000>;
status = "disabled";
@@ -1300,22 +1280,27 @@
#size-cells = <0>;
reg = <2>;
- ipu1_di0_disp0: disp0-endpoint {
+ ipu1_di0_disp0: endpoint@0 {
+ reg = <0>;
};
- ipu1_di0_hdmi: hdmi-endpoint {
+ ipu1_di0_hdmi: endpoint@1 {
+ reg = <1>;
remote-endpoint = <&hdmi_mux_0>;
};
- ipu1_di0_mipi: mipi-endpoint {
+ ipu1_di0_mipi: endpoint@2 {
+ reg = <2>;
remote-endpoint = <&mipi_mux_0>;
};
- ipu1_di0_lvds0: lvds0-endpoint {
+ ipu1_di0_lvds0: endpoint@3 {
+ reg = <3>;
remote-endpoint = <&lvds0_mux_0>;
};
- ipu1_di0_lvds1: lvds1-endpoint {
+ ipu1_di0_lvds1: endpoint@4 {
+ reg = <4>;
remote-endpoint = <&lvds1_mux_0>;
};
};
@@ -1325,22 +1310,27 @@
#size-cells = <0>;
reg = <3>;
- ipu1_di1_disp1: disp1-endpoint {
+ ipu1_di1_disp1: endpoint@0 {
+ reg = <0>;
};
- ipu1_di1_hdmi: hdmi-endpoint {
+ ipu1_di1_hdmi: endpoint@1 {
+ reg = <1>;
remote-endpoint = <&hdmi_mux_1>;
};
- ipu1_di1_mipi: mipi-endpoint {
+ ipu1_di1_mipi: endpoint@2 {
+ reg = <2>;
remote-endpoint = <&mipi_mux_1>;
};
- ipu1_di1_lvds0: lvds0-endpoint {
+ ipu1_di1_lvds0: endpoint@3 {
+ reg = <3>;
remote-endpoint = <&lvds0_mux_1>;
};
- ipu1_di1_lvds1: lvds1-endpoint {
+ ipu1_di1_lvds1: endpoint@4 {
+ reg = <4>;
remote-endpoint = <&lvds1_mux_1>;
};
};
diff --git a/arch/arm/boot/dts/imx6qp-sabreauto.dts b/arch/arm/boot/dts/imx6qp-sabreauto.dts
index 5ce3840..d4caeeb 100644
--- a/arch/arm/boot/dts/imx6qp-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6qp-sabreauto.dts
@@ -1,44 +1,6 @@
-/*
- * Copyright 2016 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.
- */
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+//
+// Copyright 2016 Freescale Semiconductor, Inc.
/dts-v1/;
diff --git a/arch/arm/boot/dts/imx6qp-sabresd.dts b/arch/arm/boot/dts/imx6qp-sabresd.dts
index a8a5004..f1b9cb1 100644
--- a/arch/arm/boot/dts/imx6qp-sabresd.dts
+++ b/arch/arm/boot/dts/imx6qp-sabresd.dts
@@ -1,44 +1,6 @@
-/*
- * Copyright 2016 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.
- */
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+//
+// Copyright 2016 Freescale Semiconductor, Inc.
/dts-v1/;
diff --git a/arch/arm/boot/dts/imx6qp-wandboard-revd1.dts b/arch/arm/boot/dts/imx6qp-wandboard-revd1.dts
index 907ba0c..bcca5ac 100644
--- a/arch/arm/boot/dts/imx6qp-wandboard-revd1.dts
+++ b/arch/arm/boot/dts/imx6qp-wandboard-revd1.dts
@@ -1,12 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2013 Freescale Semiconductor, Inc.
*
* Author: Fabio Estevam <fabio.estevam@freescale.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.
- *
*/
/dts-v1/;
#include "imx6qp.dtsi"
diff --git a/arch/arm/boot/dts/imx6qp-zii-rdu2.dts b/arch/arm/boot/dts/imx6qp-zii-rdu2.dts
index de5b50d..8c293e9 100644
--- a/arch/arm/boot/dts/imx6qp-zii-rdu2.dts
+++ b/arch/arm/boot/dts/imx6qp-zii-rdu2.dts
@@ -53,3 +53,8 @@
reg = <0x10000000 0>;
};
};
+
+&gpu_3d {
+ assigned-clocks = <&clks IMX6QDL_CLK_GPU3D_SHADER_SEL>;
+ assigned-clock-parents = <&clks IMX6QDL_CLK_PLL2_PFD1_594M>;
+};
diff --git a/arch/arm/boot/dts/imx6qp.dtsi b/arch/arm/boot/dts/imx6qp.dtsi
index 5f4fdce..5f51f8e 100644
--- a/arch/arm/boot/dts/imx6qp.dtsi
+++ b/arch/arm/boot/dts/imx6qp.dtsi
@@ -1,44 +1,6 @@
-/*
- * Copyright 2016 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.
- */
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+//
+// Copyright 2016 Freescale Semiconductor, Inc.
#include "imx6q.dtsi"
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 37e792f..92ad01f 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -1,10 +1,6 @@
-/*
- * Copyright (C) 2013 Freescale Semiconductor, Inc.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+//Copyright (C) 2013 Freescale Semiconductor, Inc.
/dts-v1/;
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index ab6a7e2..994e48d 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -1,11 +1,6 @@
-/*
- * Copyright 2013 Freescale Semiconductor, Inc.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2013 Freescale Semiconductor, Inc.
#include <dt-bindings/interrupt-controller/irq.h>
#include "imx6sl-pinfunc.h"
@@ -86,9 +81,6 @@
};
clocks {
- #address-cells = <1>;
- #size-cells = <0>;
-
ckil {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -527,11 +519,8 @@
interrupts = <0 49 IRQ_TYPE_LEVEL_HIGH>,
<0 54 IRQ_TYPE_LEVEL_HIGH>,
<0 127 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- regulator-1p1@20c8110 {
- reg = <0x20c8110>;
+ regulator-1p1 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd1p1";
regulator-min-microvolt = <800000>;
@@ -546,8 +535,7 @@
anatop-enable-bit = <0>;
};
- regulator-3p0@20c8120 {
- reg = <0x20c8120>;
+ regulator-3p0 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd3p0";
regulator-min-microvolt = <2800000>;
@@ -562,8 +550,7 @@
anatop-enable-bit = <0>;
};
- regulator-2p5@20c8130 {
- reg = <0x20c8130>;
+ regulator-2p5 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd2p5";
regulator-min-microvolt = <2100000>;
@@ -578,8 +565,7 @@
anatop-enable-bit = <0>;
};
- reg_arm: regulator-vddcore@20c8140 {
- reg = <0x20c8140>;
+ reg_arm: regulator-vddcore {
compatible = "fsl,anatop-regulator";
regulator-name = "vddarm";
regulator-min-microvolt = <725000>;
@@ -596,8 +582,7 @@
anatop-max-voltage = <1450000>;
};
- reg_pu: regulator-vddpu@20c8140 {
- reg = <0x20c8140>;
+ reg_pu: regulator-vddpu {
compatible = "fsl,anatop-regulator";
regulator-name = "vddpu";
regulator-min-microvolt = <725000>;
@@ -614,8 +599,7 @@
anatop-max-voltage = <1450000>;
};
- reg_soc: regulator-vddsoc@20c8140 {
- reg = <0x20c8140>;
+ reg_soc: regulator-vddsoc {
compatible = "fsl,anatop-regulator";
regulator-name = "vddsoc";
regulator-min-microvolt = <725000>;
diff --git a/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts b/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts
index b58f770..59e52f5 100644
--- a/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts
+++ b/arch/arm/boot/dts/imx6sx-nitrogen6sx.dts
@@ -48,8 +48,8 @@
compatible = "boundary,imx6sx-nitrogen6sx", "fsl,imx6sx";
aliases {
- fb_lcd = &lcdif1;
- t_lcd = &t_lcd;
+ fb-lcd = &lcdif1;
+ t-lcd = &t_lcd;
};
memory@80000000 {
diff --git a/arch/arm/boot/dts/imx6sx-sabreauto.dts b/arch/arm/boot/dts/imx6sx-sabreauto.dts
index 72da5ac..841a27f 100644
--- a/arch/arm/boot/dts/imx6sx-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6sx-sabreauto.dts
@@ -1,10 +1,6 @@
-/*
- * Copyright (C) 2014 Freescale Semiconductor, Inc.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2014 Freescale Semiconductor, Inc.
/dts-v1/;
@@ -18,25 +14,67 @@
reg = <0x80000000 0x80000000>;
};
- regulators {
- compatible = "simple-bus";
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_led>;
+
+ user {
+ label = "debug";
+ gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ vcc_sd3: regulator-vcc-sd3 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_vcc_sd3>;
+ regulator-name = "VCC_SD3";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&anaclk2 {
+ clock-frequency = <24576000>;
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet1>;
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy1>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
#address-cells = <1>;
#size-cells = <0>;
- vcc_sd3: regulator@0 {
- compatible = "regulator-fixed";
+ ethphy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
reg = <0>;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_vcc_sd3>;
- regulator-name = "VCC_SD3";
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- gpio = <&gpio2 11 GPIO_ACTIVE_HIGH>;
- enable-active-high;
+ };
+
+ ethphy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
};
};
};
+&fec2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet2>;
+ phy-mode = "rgmii";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+};
+
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
@@ -69,78 +107,297 @@
};
&iomuxc {
- imx6x-sabreauto {
- pinctrl_uart1: uart1grp {
- fsl,pins = <
- MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1
- MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1
- >;
- };
+ pinctrl_egalax_int: egalax-intgrp {
+ fsl,pins = <
+ MX6SX_PAD_SD4_RESET_B__GPIO6_IO_22 0x10b0
+ >;
+ };
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <
- MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
- MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059
- MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059
- MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059
- MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059
- MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059
- MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059
- MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059
- MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059
- MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059
- MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */
- MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */
- >;
- };
+ pinctrl_enet1: enet1grp {
+ fsl,pins = <
+ MX6SX_PAD_ENET1_MDIO__ENET1_MDIO 0xa0b1
+ MX6SX_PAD_ENET1_MDC__ENET1_MDC 0xa0b1
+ MX6SX_PAD_RGMII1_TXC__ENET1_RGMII_TXC 0xa0b9
+ MX6SX_PAD_RGMII1_TD0__ENET1_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII1_TD1__ENET1_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII1_TD2__ENET1_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII1_TD3__ENET1_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII1_TX_CTL__ENET1_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII1_RXC__ENET1_RX_CLK 0x3081
+ MX6SX_PAD_RGMII1_RD0__ENET1_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII1_RD1__ENET1_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII1_RD2__ENET1_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII1_RD3__ENET1_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII1_RX_CTL__ENET1_RX_EN 0x3081
+ >;
+ };
- pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
- fsl,pins = <
- MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
- MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
- MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9
- MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9
- MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9
- MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9
- MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9
- MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9
- MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9
- MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9
- >;
- };
+ pinctrl_enet2: enet2grp {
+ fsl,pins = <
+ MX6SX_PAD_RGMII2_TXC__ENET2_RGMII_TXC 0xa0b9
+ MX6SX_PAD_RGMII2_TD0__ENET2_TX_DATA_0 0xa0b1
+ MX6SX_PAD_RGMII2_TD1__ENET2_TX_DATA_1 0xa0b1
+ MX6SX_PAD_RGMII2_TD2__ENET2_TX_DATA_2 0xa0b1
+ MX6SX_PAD_RGMII2_TD3__ENET2_TX_DATA_3 0xa0b1
+ MX6SX_PAD_RGMII2_TX_CTL__ENET2_TX_EN 0xa0b1
+ MX6SX_PAD_RGMII2_RXC__ENET2_RX_CLK 0x3081
+ MX6SX_PAD_RGMII2_RD0__ENET2_RX_DATA_0 0x3081
+ MX6SX_PAD_RGMII2_RD1__ENET2_RX_DATA_1 0x3081
+ MX6SX_PAD_RGMII2_RD2__ENET2_RX_DATA_2 0x3081
+ MX6SX_PAD_RGMII2_RD3__ENET2_RX_DATA_3 0x3081
+ MX6SX_PAD_RGMII2_RX_CTL__ENET2_RX_EN 0x3081
+ >;
+ };
- pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
- fsl,pins = <
- MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
- MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
- MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9
- MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9
- MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9
- MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9
- MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9
- MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9
- MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9
- MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9
- >;
- };
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO03__I2C2_SDA 0x4001b8b1
+ MX6SX_PAD_GPIO1_IO02__I2C2_SCL 0x4001b8b1
+ >;
+ };
- pinctrl_usdhc4: usdhc4grp {
- fsl,pins = <
- MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17059
- MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10059
- MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17059
- MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17059
- MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17059
- MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17059
- MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x17059 /* CD */
- MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x17059 /* WP */
- >;
- };
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_ROW4__I2C3_SDA 0x4001b8b1
+ MX6SX_PAD_KEY_COL4__I2C3_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_led: ledgrp {
+ fsl,pins = <
+ MX6SX_PAD_CSI_PIXCLK__GPIO1_IO_24 0x17059
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO04__UART1_TX 0x1b0b1
+ MX6SX_PAD_GPIO1_IO05__UART1_RX 0x1b0b1
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x17059
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x10059
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x17059
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x17059
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x17059
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x17059
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x17059
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x17059
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x17059
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x17059
+ MX6SX_PAD_KEY_COL0__GPIO2_IO_10 0x17059 /* CD */
+ MX6SX_PAD_KEY_ROW0__GPIO2_IO_15 0x17059 /* WP */
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3grp-100mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170b9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100b9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170b9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170b9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170b9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170b9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170b9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170b9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170b9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3grp-200mhz {
+ fsl,pins = <
+ MX6SX_PAD_SD3_CMD__USDHC3_CMD 0x170f9
+ MX6SX_PAD_SD3_CLK__USDHC3_CLK 0x100f9
+ MX6SX_PAD_SD3_DATA0__USDHC3_DATA0 0x170f9
+ MX6SX_PAD_SD3_DATA1__USDHC3_DATA1 0x170f9
+ MX6SX_PAD_SD3_DATA2__USDHC3_DATA2 0x170f9
+ MX6SX_PAD_SD3_DATA3__USDHC3_DATA3 0x170f9
+ MX6SX_PAD_SD3_DATA4__USDHC3_DATA4 0x170f9
+ MX6SX_PAD_SD3_DATA5__USDHC3_DATA5 0x170f9
+ MX6SX_PAD_SD3_DATA6__USDHC3_DATA6 0x170f9
+ MX6SX_PAD_SD3_DATA7__USDHC3_DATA7 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6SX_PAD_SD4_CMD__USDHC4_CMD 0x17059
+ MX6SX_PAD_SD4_CLK__USDHC4_CLK 0x10059
+ MX6SX_PAD_SD4_DATA0__USDHC4_DATA0 0x17059
+ MX6SX_PAD_SD4_DATA1__USDHC4_DATA1 0x17059
+ MX6SX_PAD_SD4_DATA2__USDHC4_DATA2 0x17059
+ MX6SX_PAD_SD4_DATA3__USDHC4_DATA3 0x17059
+ MX6SX_PAD_SD4_DATA7__GPIO6_IO_21 0x17059 /* CD */
+ MX6SX_PAD_SD4_DATA6__GPIO6_IO_20 0x17059 /* WP */
+ >;
+ };
+
+ pinctrl_vcc_sd3: vccsd3grp {
+ fsl,pins = <
+ MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
+ >;
+ };
+
+ pinctrl_wdog: wdoggrp {
+ fsl,pins = <
+ MX6SX_PAD_GPIO1_IO13__WDOG1_WDOG_ANY 0x30b0
+ >;
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+
+ touchscreen@4 {
+ compatible = "eeti,egalax_ts";
+ reg = <0x04>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_egalax_int>;
+ interrupt-parent = <&gpio6>;
+ interrupts = <22 IRQ_TYPE_EDGE_FALLING>;
+ wakeup-gpios = <&gpio6 22 GPIO_ACTIVE_HIGH>;
+ };
+
+ pfuze100: pmic@8 {
+ compatible = "fsl,pfuze100";
+ reg = <0x08>;
+
+ regulators {
+ sw1a_reg: sw1ab {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw1c_reg: sw1c {
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <6250>;
+ };
+
+ sw2_reg: sw2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3a_reg: sw3a {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw3b_reg: sw3b {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <1975000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sw4_reg: sw4 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ swbst_reg: swbst {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5150000>;
+ };
+
+ snvs_reg: vsnvs {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
- pinctrl_vcc_sd3: vccsd3grp {
- fsl,pins = <
- MX6SX_PAD_KEY_COL1__GPIO2_IO_11 0x17059
- >;
+ vref_reg: vrefddr {
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vgen1_reg: vgen1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ regulator-always-on;
+ };
+
+ vgen2_reg: vgen2 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1550000>;
+ };
+
+ vgen3_reg: vgen3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen4_reg: vgen4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen5_reg: vgen5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vgen6_reg: vgen6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
};
};
+
+ max7322: gpio@68 {
+ compatible = "maxim,max7322";
+ reg = <0x68>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+
+ max7310_a: gpio@30 {
+ compatible = "maxim,max7310";
+ reg = <0x30>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ max7310_b: gpio@32 {
+ compatible = "maxim,max7310";
+ reg = <0x32>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
};
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index 49c7205..d8b94f4 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -1,10 +1,6 @@
-/*
- * Copyright 2014 Freescale Semiconductor, Inc.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2014 Freescale Semiconductor, Inc.
#include <dt-bindings/clock/imx6sx-clock.h>
#include <dt-bindings/gpio/gpio.h>
@@ -104,41 +100,46 @@
interrupt-parent = <&intc>;
};
- clocks {
- #address-cells = <1>;
- #size-cells = <0>;
+ ckil: clock-ckil {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "ckil";
+ };
- ckil: clock@0 {
- compatible = "fixed-clock";
- reg = <0>;
- #clock-cells = <0>;
- clock-frequency = <32768>;
- clock-output-names = "ckil";
- };
+ osc: clock-osc {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "osc";
+ };
- osc: clock@1 {
- compatible = "fixed-clock";
- reg = <1>;
- #clock-cells = <0>;
- clock-frequency = <24000000>;
- clock-output-names = "osc";
- };
+ ipp_di0: clock-ipp-di0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ipp_di0";
+ };
- ipp_di0: clock@2 {
- compatible = "fixed-clock";
- reg = <2>;
- #clock-cells = <0>;
- clock-frequency = <0>;
- clock-output-names = "ipp_di0";
- };
+ ipp_di1: clock-ipp-di1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "ipp_di1";
+ };
- ipp_di1: clock@3 {
- compatible = "fixed-clock";
- reg = <3>;
- #clock-cells = <0>;
- clock-frequency = <0>;
- clock-output-names = "ipp_di1";
- };
+ anaclk1: clock-anaclk1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "anaclk1";
+ };
+
+ anaclk2: clock-anaclk2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ clock-output-names = "anaclk2";
};
tempmon: tempmon {
@@ -575,8 +576,8 @@
interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
#clock-cells = <1>;
- clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>;
- clock-names = "ckil", "osc", "ipp_di0", "ipp_di1";
+ clocks = <&ckil>, <&osc>, <&ipp_di0>, <&ipp_di1>, <&anaclk1>, <&anaclk2>;
+ clock-names = "ckil", "osc", "ipp_di0", "ipp_di1", "anaclk1", "anaclk2";
};
anatop: anatop@20c8000 {
@@ -586,11 +587,8 @@
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- regulator-1p1@20c8110 {
- reg = <0x20c8110>;
+ regulator-1p1 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd1p1";
regulator-min-microvolt = <800000>;
@@ -605,8 +603,7 @@
anatop-enable-bit = <0>;
};
- regulator-3p0@20c8120 {
- reg = <0x20c8120>;
+ regulator-3p0 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd3p0";
regulator-min-microvolt = <2800000>;
@@ -621,8 +618,7 @@
anatop-enable-bit = <0>;
};
- regulator-2p5@20c8130 {
- reg = <0x20c8130>;
+ regulator-2p5 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd2p5";
regulator-min-microvolt = <2100000>;
@@ -637,8 +633,7 @@
anatop-enable-bit = <0>;
};
- reg_arm: regulator-vddcore@20c8140 {
- reg = <0x20c8140>;
+ reg_arm: regulator-vddcore {
compatible = "fsl,anatop-regulator";
regulator-name = "vddarm";
regulator-min-microvolt = <725000>;
@@ -655,8 +650,7 @@
anatop-max-voltage = <1450000>;
};
- reg_pcie: regulator-vddpcie@20c8140 {
- reg = <0x20c8140>;
+ reg_pcie: regulator-vddpcie {
compatible = "fsl,anatop-regulator";
regulator-name = "vddpcie";
regulator-min-microvolt = <725000>;
@@ -672,8 +666,7 @@
anatop-max-voltage = <1450000>;
};
- reg_soc: regulator-vddsoc@20c8140 {
- reg = <0x20c8140>;
+ reg_soc: regulator-vddsoc {
compatible = "fsl,anatop-regulator";
regulator-name = "vddsoc";
regulator-min-microvolt = <725000>;
diff --git a/arch/arm/boot/dts/imx6ul-14x14-evk.dts b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
index 6d720b2..2438669 100644
--- a/arch/arm/boot/dts/imx6ul-14x14-evk.dts
+++ b/arch/arm/boot/dts/imx6ul-14x14-evk.dts
@@ -1,10 +1,6 @@
-/*
- * Copyright (C) 2015 Freescale Semiconductor, Inc.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (C) 2015 Freescale Semiconductor, Inc.
/dts-v1/;
diff --git a/arch/arm/boot/dts/imx6ul-isiot.dtsi b/arch/arm/boot/dts/imx6ul-isiot.dtsi
index 921e12c..cd99285 100644
--- a/arch/arm/boot/dts/imx6ul-isiot.dtsi
+++ b/arch/arm/boot/dts/imx6ul-isiot.dtsi
@@ -153,8 +153,6 @@
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>;
diff --git a/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts b/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts
index 2d80f7b..9768609 100644
--- a/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts
+++ b/arch/arm/boot/dts/imx6ul-tx6ul-mainboard.dts
@@ -48,7 +48,7 @@
compatible = "karo,imx6ul-tx6ul", "fsl,imx6ul";
aliases {
- lcdif_24bit_pins_a = &pinctrl_disp0_3;
+ lcdif-24bit-pins-a = &pinctrl_disp0_3;
mmc0 = &usdhc1;
/delete-property/ mmc1;
serial2 = &uart3;
diff --git a/arch/arm/boot/dts/imx6ul-tx6ul.dtsi b/arch/arm/boot/dts/imx6ul-tx6ul.dtsi
index f678d18..02b5ba4 100644
--- a/arch/arm/boot/dts/imx6ul-tx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul-tx6ul.dtsi
@@ -53,10 +53,10 @@
i2c2 = &i2c1;
i2c3 = &i2c3;
i2c4 = &i2c4;
- lcdif_23bit_pins_a = &pinctrl_disp0_1;
- lcdif_24bit_pins_a = &pinctrl_disp0_2;
+ lcdif-23bit-pins-a = &pinctrl_disp0_1;
+ lcdif-24bit-pins-a = &pinctrl_disp0_2;
pwm0 = &pwm5;
- reg_can_xcvr = &reg_can_xcvr;
+ reg-can-xcvr = &reg_can_xcvr;
serial2 = &uart5;
serial4 = &uart3;
spi0 = &ecspi2;
diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi
index 1241972..47a3453 100644
--- a/arch/arm/boot/dts/imx6ul.dtsi
+++ b/arch/arm/boot/dts/imx6ul.dtsi
@@ -1,10 +1,6 @@
-/*
- * Copyright 2015 Freescale Semiconductor, Inc.
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2015 Freescale Semiconductor, Inc.
#include <dt-bindings/clock/imx6ul-clock.h>
#include <dt-bindings/gpio/gpio.h>
@@ -551,11 +547,8 @@
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- reg_3p0: regulator-3p0@20c8110 {
- reg = <0x20c8110>;
+ reg_3p0: regulator-3p0 {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd3p0";
regulator-min-microvolt = <2625000>;
@@ -569,8 +562,7 @@
anatop-enable-bit = <0>;
};
- reg_arm: regulator-vddcore@20c8140 {
- reg = <0x20c8140>;
+ reg_arm: regulator-vddcore {
compatible = "fsl,anatop-regulator";
regulator-name = "cpu";
regulator-min-microvolt = <725000>;
@@ -587,8 +579,7 @@
anatop-max-voltage = <1450000>;
};
- reg_soc: regulator-vddsoc@20c8140 {
- reg = <0x20c8140>;
+ reg_soc: regulator-vddsoc {
compatible = "fsl,anatop-regulator";
regulator-name = "vddsoc";
regulator-min-microvolt = <725000>;
@@ -769,6 +760,36 @@
reg = <0x02100000 0x100000>;
ranges;
+ crypto: caam@2140000 {
+ compatible = "fsl,imx6ul-caam", "fsl,sec-v4.0";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x2140000 0x3c000>;
+ ranges = <0 0x2140000 0x3c000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clks IMX6UL_CLK_CAAM_IPG>, <&clks IMX6UL_CLK_CAAM_ACLK>,
+ <&clks IMX6UL_CLK_CAAM_MEM>;
+ clock-names = "ipg", "aclk", "mem";
+
+ sec_jr0: jr0@1000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x1000 0x1000>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ sec_jr1: jr1@2000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x2000 0x1000>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ sec_jr2: jr2@3000 {
+ compatible = "fsl,sec-v4.0-job-ring";
+ reg = <0x3000 0x1000>;
+ interrupts = <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
usbotg1: usb@2184000 {
compatible = "fsl,imx6ul-usb", "fsl,imx27-usb";
reg = <0x02184000 0x200>;
diff --git a/arch/arm/boot/dts/imx6ull-pinfunc.h b/arch/arm/boot/dts/imx6ull-pinfunc.h
index 1182023..fdc46bb 100644
--- a/arch/arm/boot/dts/imx6ull-pinfunc.h
+++ b/arch/arm/boot/dts/imx6ull-pinfunc.h
@@ -14,6 +14,14 @@
* The pin function ID is a tuple of
* <mux_reg conf_reg input_reg mux_mode input_val>
*/
+#define MX6ULL_PAD_UART1_TX_DATA__UART5_DTE_RX 0x0084 0x0310 0x0644 0x9 0x4
+#define MX6ULL_PAD_UART1_RX_DATA__UART5_DCE_RX 0x0088 0x0314 0x0644 0x9 0x5
+#define MX6ULL_PAD_UART1_CTS_B__UART5_DCE_RTS 0x008C 0x0318 0x0640 0x9 0x3
+#define MX6ULL_PAD_UART1_RTS_B__UART5_DTE_RTS 0x0090 0x031C 0x0640 0x9 0x4
+#define MX6ULL_PAD_UART5_TX_DATA__UART5_DTE_RX 0x00BC 0x0348 0x0644 0x0 0x6
+#define MX6ULL_PAD_UART5_RX_DATA__UART5_DCE_RX 0x00C0 0x034C 0x0644 0x0 0x7
+#define MX6ULL_PAD_ENET1_RX_EN__UART5_DCE_RTS 0x00CC 0x0358 0x0640 0x1 0x5
+#define MX6ULL_PAD_ENET1_TX_DATA0__UART5_DTE_RTS 0x00D0 0x035C 0x0640 0x1 0x6
#define MX6ULL_PAD_ENET2_RX_DATA0__EPDC_SDDO08 0x00E4 0x0370 0x0000 0x9 0x0
#define MX6ULL_PAD_ENET2_RX_DATA1__EPDC_SDDO09 0x00E8 0x0374 0x0000 0x9 0x0
#define MX6ULL_PAD_ENET2_RX_EN__EPDC_SDDO10 0x00EC 0x0378 0x0000 0x9 0x0
@@ -47,6 +55,7 @@
#define MX6ULL_PAD_CSI_DATA00__ESAI_TX_HF_CLK 0x01E4 0x0470 0x0000 0x9 0x0
#define MX6ULL_PAD_CSI_DATA01__ESAI_RX_HF_CLK 0x01E8 0x0474 0x0000 0x9 0x0
#define MX6ULL_PAD_CSI_DATA02__ESAI_RX_FS 0x01EC 0x0478 0x0000 0x9 0x0
+#define MX6ULL_PAD_CSI_DATA02__UART5_DCE_RTS 0x01EC 0x0478 0x0640 0x8 0x7
#define MX6ULL_PAD_CSI_DATA03__ESAI_RX_CLK 0x01F0 0x047C 0x0000 0x9 0x0
#define MX6ULL_PAD_CSI_DATA04__ESAI_TX_FS 0x01F4 0x0480 0x0000 0x9 0x0
#define MX6ULL_PAD_CSI_DATA05__ESAI_TX_CLK 0x01F8 0x0484 0x0000 0x9 0x0
diff --git a/arch/arm/boot/dts/imx6ull.dtsi b/arch/arm/boot/dts/imx6ull.dtsi
index 571ddd7..ebc25c9 100644
--- a/arch/arm/boot/dts/imx6ull.dtsi
+++ b/arch/arm/boot/dts/imx6ull.dtsi
@@ -45,6 +45,8 @@
/* Delete UART8 in AIPS-1 (i.MX6UL specific) */
/delete-node/ &uart8;
+/* Delete CAAM node in AIPS-2 (i.MX6UL specific) */
+/delete-node/ &crypto;
/ {
soc {
diff --git a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts b/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
index 7f64568..8bf365d 100644
--- a/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
+++ b/arch/arm/boot/dts/imx7d-cl-som-imx7.dts
@@ -33,7 +33,7 @@
};
&cpu0 {
- arm-supply = <&sw1a_reg>;
+ cpu-supply = <&sw1a_reg>;
};
&fec1 {
diff --git a/arch/arm/boot/dts/imx7d-nitrogen7.dts b/arch/arm/boot/dts/imx7d-nitrogen7.dts
index 52167298..70c53e5 100644
--- a/arch/arm/boot/dts/imx7d-nitrogen7.dts
+++ b/arch/arm/boot/dts/imx7d-nitrogen7.dts
@@ -49,8 +49,8 @@
compatible = "boundary,imx7d-nitrogen7", "fsl,imx7d";
aliases {
- fb_lcd = &lcdif;
- t_lcd = &t_lcd;
+ fb-lcd = &lcdif;
+ t-lcd = &t_lcd;
};
memory@80000000 {
@@ -144,7 +144,7 @@
};
&cpu0 {
- arm-supply = <&sw1a_reg>;
+ cpu-supply = <&sw1a_reg>;
};
&fec1 {
diff --git a/arch/arm/boot/dts/imx7d-pinfunc.h b/arch/arm/boot/dts/imx7d-pinfunc.h
index f2493bc..aa9dbea 100644
--- a/arch/arm/boot/dts/imx7d-pinfunc.h
+++ b/arch/arm/boot/dts/imx7d-pinfunc.h
@@ -592,7 +592,7 @@
#define MX7D_PAD_UART2_RX_DATA__UART2_DCE_RX 0x0130 0x03A0 0x06FC 0x0 0x2
#define MX7D_PAD_UART2_RX_DATA__UART2_DTE_TX 0x0130 0x03A0 0x0000 0x0 0x0
#define MX7D_PAD_UART2_RX_DATA__I2C2_SCL 0x0130 0x03A0 0x05DC 0x1 0x0
-#define MX7D_PAD_UART2_RX_DATA__SAI3_RX_BCLK 0x0130 0x03A0 0x0000 0x2 0x0
+#define MX7D_PAD_UART2_RX_DATA__SAI3_RX_BCLK 0x0130 0x03A0 0x06C4 0x2 0x0
#define MX7D_PAD_UART2_RX_DATA__ECSPI1_SS3 0x0130 0x03A0 0x0000 0x3 0x0
#define MX7D_PAD_UART2_RX_DATA__ENET2_1588_EVENT1_IN 0x0130 0x03A0 0x0000 0x4 0x0
#define MX7D_PAD_UART2_RX_DATA__GPIO4_IO2 0x0130 0x03A0 0x0000 0x5 0x0
@@ -1112,13 +1112,13 @@
#define MX7D_PAD_ENET1_RGMII_TD3__GPIO7_IO9 0x0250 0x04C0 0x0000 0x5 0x0
#define MX7D_PAD_ENET1_RGMII_TD3__CAAM_RNG_OSC_OBS 0x0250 0x04C0 0x0000 0x7 0x0
#define MX7D_PAD_ENET1_RGMII_TX_CTL__ENET1_RGMII_TX_CTL 0x0254 0x04C4 0x0000 0x0 0x0
-#define MX7D_PAD_ENET1_RGMII_TX_CTL__SAI1_RX_SYNC 0x0254 0x04C4 0x0000 0x2 0x0
+#define MX7D_PAD_ENET1_RGMII_TX_CTL__SAI1_RX_SYNC 0x0254 0x04C4 0x06A4 0x2 0x1
#define MX7D_PAD_ENET1_RGMII_TX_CTL__GPT2_COMPARE1 0x0254 0x04C4 0x0000 0x3 0x0
#define MX7D_PAD_ENET1_RGMII_TX_CTL__EPDC_PWR_CTRL2 0x0254 0x04C4 0x0000 0x4 0x0
#define MX7D_PAD_ENET1_RGMII_TX_CTL__GPIO7_IO10 0x0254 0x04C4 0x0000 0x5 0x0
#define MX7D_PAD_ENET1_RGMII_TXC__ENET1_RGMII_TXC 0x0258 0x04C8 0x0000 0x0 0x0
#define MX7D_PAD_ENET1_RGMII_TXC__ENET1_TX_ER 0x0258 0x04C8 0x0000 0x1 0x0
-#define MX7D_PAD_ENET1_RGMII_TXC__SAI1_RX_BCLK 0x0258 0x04C8 0x0000 0x2 0x0
+#define MX7D_PAD_ENET1_RGMII_TXC__SAI1_RX_BCLK 0x0258 0x04C8 0x069C 0x2 0x1
#define MX7D_PAD_ENET1_RGMII_TXC__GPT2_COMPARE2 0x0258 0x04C8 0x0000 0x3 0x0
#define MX7D_PAD_ENET1_RGMII_TXC__EPDC_PWR_CTRL3 0x0258 0x04C8 0x0000 0x4 0x0
#define MX7D_PAD_ENET1_RGMII_TXC__GPIO7_IO11 0x0258 0x04C8 0x0000 0x5 0x0
diff --git a/arch/arm/boot/dts/imx7d-sdb-sht11.dts b/arch/arm/boot/dts/imx7d-sdb-sht11.dts
index 64a20ed..9965555 100644
--- a/arch/arm/boot/dts/imx7d-sdb-sht11.dts
+++ b/arch/arm/boot/dts/imx7d-sdb-sht11.dts
@@ -1,44 +1,6 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+//
+// Copyright (C) 2015 Freescale Semiconductor, Inc.
#include "imx7d-sdb.dts"
diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
index 5d6a08b..9408491 100644
--- a/arch/arm/boot/dts/imx7d-sdb.dts
+++ b/arch/arm/boot/dts/imx7d-sdb.dts
@@ -1,44 +1,6 @@
-/*
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+//
+// Copyright (C) 2015 Freescale Semiconductor, Inc.
/dts-v1/;
@@ -52,6 +14,24 @@
reg = <0x80000000 0x80000000>;
};
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio5 10 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+
spi4 {
compatible = "spi-gpio";
pinctrl-names = "default";
@@ -161,7 +141,7 @@
};
&cpu0 {
- arm-supply = <&sw1a_reg>;
+ cpu-supply = <&sw1a_reg>;
};
&ecspi3 {
@@ -519,6 +499,12 @@
>;
};
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX7D_PAD_SD2_RESET_B__GPIO5_IO11 0x59
+ MX7D_PAD_SD2_WP__GPIO5_IO10 0x59
+ >;
+ };
pinctrl_hog: hoggrp {
fsl,pins = <
diff --git a/arch/arm/boot/dts/imx7d.dtsi b/arch/arm/boot/dts/imx7d.dtsi
index d74dd7f..8d3d123 100644
--- a/arch/arm/boot/dts/imx7d.dtsi
+++ b/arch/arm/boot/dts/imx7d.dtsi
@@ -1,45 +1,7 @@
-/*
- * Copyright 2015 Freescale Semiconductor, Inc.
- * Copyright 2016 Toradex AG
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+//
+// Copyright 2015 Freescale Semiconductor, Inc.
+// Copyright 2016 Toradex AG
#include "imx7s.dtsi"
#include <dt-bindings/reset/imx7-reset.h>
@@ -47,12 +9,8 @@
/ {
cpus {
cpu0: cpu@0 {
- operating-points = <
- /* KHz uV */
- 996000 1075000
- 792000 975000
- >;
clock-frequency = <996000000>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
cpu1: cpu@1 {
@@ -60,6 +18,25 @@
device_type = "cpu";
reg = <1>;
clock-frequency = <996000000>;
+ operating-points-v2 = <&cpu0_opp_table>;
+ };
+ };
+
+ cpu0_opp_table: opp-table {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-792000000 {
+ opp-hz = /bits/ 64 <792000000>;
+ opp-microvolt = <975000>;
+ clock-latency-ns = <150000>;
+ };
+
+ opp-996000000 {
+ opp-hz = /bits/ 64 <996000000>;
+ opp-microvolt = <1075000>;
+ clock-latency-ns = <150000>;
+ opp-suspend;
};
};
diff --git a/arch/arm/boot/dts/imx7s-warp.dts b/arch/arm/boot/dts/imx7s-warp.dts
index 8a30b14..fa390da 100644
--- a/arch/arm/boot/dts/imx7s-warp.dts
+++ b/arch/arm/boot/dts/imx7s-warp.dts
@@ -113,10 +113,6 @@
assigned-clock-rates = <884736000>;
};
-&cpu0 {
- arm-supply = <&sw1a_reg>;
-};
-
&i2c1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 69436b9..9ced589 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -1,45 +1,7 @@
-/*
- * Copyright 2015 Freescale Semiconductor, Inc.
- * Copyright 2016 Toradex AG
- *
- * 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.
- */
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+//
+// Copyright 2015 Freescale Semiconductor, Inc.
+// Copyright 2016 Toradex AG
#include <dt-bindings/clock/imx7d-clock.h>
#include <dt-bindings/power/imx7-power.h>
@@ -173,6 +135,17 @@
};
};
+ tempmon: tempmon {
+ compatible = "fsl,imx7d-tempmon";
+ interrupt-parent = <&gpc>;
+ interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,tempmon =<&anatop>;
+ nvmem-cells = <&tempmon_calib>,
+ <&tempmon_temp_grade>;
+ nvmem-cell-names = "calib", "temp_grade";
+ clocks = <&clks IMX7D_PLL_SYS_MAIN_CLK>;
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupt-parent = <&intc>;
@@ -321,7 +294,7 @@
port {
tpiu_in_port: endpoint {
slave-mode;
- remote-endpoint = <&replicator_out_port1>;
+ remote-endpoint = <&replicator_out_port0>;
};
};
};
@@ -540,27 +513,14 @@
};
};
- tempmon: tempmon {
- compatible = "fsl,imx7d-tempmon";
- interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
- fsl,tempmon =<&anatop>;
- nvmem-cells = <&tempmon_calib>,
- <&tempmon_temp_grade>;
- nvmem-cell-names = "calib", "temp_grade";
- clocks = <&clks IMX7D_PLL_SYS_MAIN_CLK>;
- };
-
anatop: anatop@30360000 {
compatible = "fsl,imx7d-anatop", "fsl,imx6q-anatop",
"syscon", "simple-bus";
reg = <0x30360000 0x10000>;
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
- reg_1p0d: regulator-vdd1p0d@30360210 {
- reg = <0x30360210>;
+ reg_1p0d: regulator-vdd1p0d {
compatible = "fsl,anatop-regulator";
regulator-name = "vdd1p0d";
regulator-min-microvolt = <800000>;
@@ -573,6 +533,20 @@
anatop-max-voltage = <1200000>;
anatop-enable-bit = <0>;
};
+
+ reg_1p2: regulator-vdd1p2 {
+ compatible = "fsl,anatop-regulator";
+ regulator-name = "vdd1p2";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ anatop-reg-offset = <0x220>;
+ anatop-vol-bit-shift = <8>;
+ anatop-vol-bit-width = <5>;
+ anatop-min-bit-val = <0x14>;
+ anatop-min-voltage = <1100000>;
+ anatop-max-voltage = <1300000>;
+ anatop-enable-bit = <0>;
+ };
};
snvs: snvs@30370000 {
diff --git a/arch/arm/boot/dts/keystone-k2g-evm.dts b/arch/arm/boot/dts/keystone-k2g-evm.dts
index 6a46577..154fdd7 100644
--- a/arch/arm/boot/dts/keystone-k2g-evm.dts
+++ b/arch/arm/boot/dts/keystone-k2g-evm.dts
@@ -114,6 +114,20 @@
K2G_CORE_IOPAD(0x11f0) (BUFFER_CLASS_B | PIN_PULLDOWN | MUX_MODE0) /* uart2_txd.uart2_txd */
>;
};
+
+ dcan0_pins: pinmux_dcan0_pins {
+ pinctrl-single,pins = <
+ K2G_CORE_IOPAD(0x11fc) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE0) /* dcan0tx.dcan0tx */
+ K2G_CORE_IOPAD(0x1200) (BUFFER_CLASS_B | PIN_PULLDOWN | MUX_MODE0) /* dcan0rx.dcan0rx */
+ >;
+ };
+
+ dcan1_pins: pinmux_dcan1_pins {
+ pinctrl-single,pins = <
+ K2G_CORE_IOPAD(0x1224) (BUFFER_CLASS_B | PULL_DISABLE | MUX_MODE1) /* qspicsn2.dcan1tx */
+ K2G_CORE_IOPAD(0x1228) (BUFFER_CLASS_B | PIN_PULLDOWN | MUX_MODE1) /* qspicsn3.dcan1rx */
+ >;
+ };
};
&uart0 {
@@ -268,3 +282,15 @@
pinctrl-0 = <&uart2_pins>;
status = "okay";
};
+
+&dcan0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dcan0_pins>;
+ status = "okay";
+};
+
+&dcan1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dcan1_pins>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/logicpd-som-lv.dtsi b/arch/arm/boot/dts/logicpd-som-lv.dtsi
index 6fa7bba..3bb28c0 100644
--- a/arch/arm/boot/dts/logicpd-som-lv.dtsi
+++ b/arch/arm/boot/dts/logicpd-som-lv.dtsi
@@ -35,6 +35,13 @@
reset-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; /* gpio_4 */
#phy-cells = <0>;
};
+
+ /* fixed 26MHz oscillator */
+ hfclk_26m: oscillator {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <26000000>;
+ };
};
&gpmc {
@@ -79,6 +86,8 @@
reg = <0x48>;
interrupts = <7>; /* SYS_NIRQ cascaded to intc */
interrupt-parent = <&intc>;
+ clocks = <&hfclk_26m>;
+ clock-names = "fck";
twl_audio: audio {
compatible = "ti,twl4030-audio";
codec {
@@ -98,6 +107,25 @@
pinctrl-names = "default";
pinctrl-0 = <&i2c3_pins>;
clock-frequency = <400000>;
+
+ touchscreen: tsc2004@48 {
+ compatible = "ti,tsc2004";
+ reg = <0x48>;
+ vio-supply = <&vaux1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsc2004_pins>;
+ interrupts-extended = <&gpio5 25 IRQ_TYPE_EDGE_RISING>; /* gpio 153 */
+
+ touchscreen-fuzz-x = <4>;
+ touchscreen-fuzz-y = <7>;
+ touchscreen-fuzz-pressure = <2>;
+ touchscreen-size-x = <4096>;
+ touchscreen-size-y = <4096>;
+ touchscreen-max-pressure = <2048>;
+
+ ti,x-plate-ohms = <280>;
+ ti,esd-recovery-timeout-ms = <8000>;
+ };
};
&mmc3 {
@@ -203,6 +231,12 @@
OMAP3_CORE1_IOPAD(0x20ba, PIN_OUTPUT | MUX_MODE4) /* gpmc_ncs6.gpio_57 */
>;
};
+
+ tsc2004_pins: pinmux_tsc2004_pins {
+ pinctrl-single,pins = <
+ OMAP3_CORE1_IOPAD(0x2186, PIN_INPUT | MUX_MODE4) /* mcbsp4_dr.gpio_153 */
+ >;
+ };
};
&omap3_pmx_wkup {
diff --git a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
index 3e174e4..7d2302e 100644
--- a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
+++ b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
@@ -30,6 +30,13 @@
linux,default-trigger = "none";
};
};
+
+ /* fixed 26MHz oscillator */
+ hfclk_26m: oscillator {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <26000000>;
+ };
};
&gpmc {
@@ -74,6 +81,9 @@
reg = <0x48>;
interrupts = <7>; /* SYS_NIRQ cascaded to intc */
interrupt-parent = <&intc>;
+ clocks = <&hfclk_26m>;
+ clock-names = "fck";
+
twl_audio: audio {
compatible = "ti,twl4030-audio";
codec {
diff --git a/arch/arm/boot/dts/meson8.dtsi b/arch/arm/boot/dts/meson8.dtsi
index dcc9292..d77dcf8 100644
--- a/arch/arm/boot/dts/meson8.dtsi
+++ b/arch/arm/boot/dts/meson8.dtsi
@@ -57,7 +57,7 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@200 {
+ cpu0: cpu@200 {
device_type = "cpu";
compatible = "arm,cortex-a9";
next-level-cache = <&L2>;
@@ -66,7 +66,7 @@
resets = <&clkc CLKC_RESET_CPU0_SOFT_RESET>;
};
- cpu@201 {
+ cpu1: cpu@201 {
device_type = "cpu";
compatible = "arm,cortex-a9";
next-level-cache = <&L2>;
@@ -75,7 +75,7 @@
resets = <&clkc CLKC_RESET_CPU1_SOFT_RESET>;
};
- cpu@202 {
+ cpu2: cpu@202 {
device_type = "cpu";
compatible = "arm,cortex-a9";
next-level-cache = <&L2>;
@@ -84,7 +84,7 @@
resets = <&clkc CLKC_RESET_CPU2_SOFT_RESET>;
};
- cpu@203 {
+ cpu3: cpu@203 {
device_type = "cpu";
compatible = "arm,cortex-a9";
next-level-cache = <&L2>;
@@ -94,6 +94,15 @@
};
};
+ pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
@@ -272,6 +281,22 @@
function = "pwm_e";
};
};
+
+ uart_a1_pins: uart-a1 {
+ mux {
+ groups = "uart_tx_a1",
+ "uart_rx_a1";
+ function = "uart_a";
+ };
+ };
+
+ uart_a1_cts_rts_pins: uart-a1-cts-rts {
+ mux {
+ groups = "uart_cts_a1",
+ "uart_rts_a1";
+ function = "uart_a";
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts
index 3a5603d..ef3177d3 100644
--- a/arch/arm/boot/dts/meson8b-odroidc1.dts
+++ b/arch/arm/boot/dts/meson8b-odroidc1.dts
@@ -103,10 +103,34 @@
};
};
-&uart_AO {
+&ethmac {
status = "okay";
- pinctrl-0 = <&uart_ao_a_pins>;
+
+ snps,reset-gpio = <&gpio GPIOH_4 GPIO_ACTIVE_HIGH>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 10000 30000>;
+
+ pinctrl-0 = <&eth_rgmii_pins>;
pinctrl-names = "default";
+
+ phy-mode = "rgmii";
+ phy-handle = <&eth_phy>;
+ amlogic,tx-delay-ns = <4>;
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Realtek RTL8211F (0x001cc916) */
+ eth_phy: ethernet-phy@0 {
+ reg = <0>;
+ eee-broken-1000t;
+ interrupt-parent = <&gpio_intc>;
+ /* GPIOH_3 */
+ interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
};
&gpio_ao {
@@ -124,12 +148,10 @@
};
};
-&usb1_phy {
- status = "okay";
-};
-
-&usb1 {
+&ir_receiver {
status = "okay";
+ pinctrl-0 = <&ir_recv_pins>;
+ pinctrl-names = "default";
};
&sdio {
@@ -158,32 +180,16 @@
};
};
-&ethmac {
+&uart_AO {
status = "okay";
-
- snps,reset-gpio = <&gpio GPIOH_4 GPIO_ACTIVE_HIGH>;
- snps,reset-active-low;
- snps,reset-delays-us = <0 10000 30000>;
-
- pinctrl-0 = <&eth_rgmii_pins>;
+ pinctrl-0 = <&uart_ao_a_pins>;
pinctrl-names = "default";
+};
- phy-mode = "rgmii";
- phy-handle = <&eth_phy>;
- amlogic,tx-delay-ns = <4>;
-
- mdio {
- compatible = "snps,dwmac-mdio";
- #address-cells = <1>;
- #size-cells = <0>;
+&usb1_phy {
+ status = "okay";
+};
- /* Realtek RTL8211F (0x001cc916) */
- eth_phy: ethernet-phy@0 {
- reg = <0>;
- eee-broken-1000t;
- interrupt-parent = <&gpio_intc>;
- /* GPIOH_3 */
- interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
- };
- };
+&usb1 {
+ status = "okay";
};
diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index 553b821..08f7f6b 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -55,7 +55,7 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@200 {
+ cpu0: cpu@200 {
device_type = "cpu";
compatible = "arm,cortex-a5";
next-level-cache = <&L2>;
@@ -64,7 +64,7 @@
resets = <&clkc CLKC_RESET_CPU0_SOFT_RESET>;
};
- cpu@201 {
+ cpu1: cpu@201 {
device_type = "cpu";
compatible = "arm,cortex-a5";
next-level-cache = <&L2>;
@@ -73,7 +73,7 @@
resets = <&clkc CLKC_RESET_CPU1_SOFT_RESET>;
};
- cpu@202 {
+ cpu2: cpu@202 {
device_type = "cpu";
compatible = "arm,cortex-a5";
next-level-cache = <&L2>;
@@ -82,7 +82,7 @@
resets = <&clkc CLKC_RESET_CPU2_SOFT_RESET>;
};
- cpu@203 {
+ cpu3: cpu@203 {
device_type = "cpu";
compatible = "arm,cortex-a5";
next-level-cache = <&L2>;
@@ -92,6 +92,15 @@
};
};
+ pmu {
+ compatible = "arm,cortex-a5-pmu";
+ interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
@@ -139,6 +148,13 @@
function = "uart_ao";
};
};
+
+ ir_recv_pins: remote {
+ mux {
+ groups = "remote_input";
+ function = "remote";
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/meson8m2-mxiii-plus.dts b/arch/arm/boot/dts/meson8m2-mxiii-plus.dts
new file mode 100644
index 0000000..f585361
--- /dev/null
+++ b/arch/arm/boot/dts/meson8m2-mxiii-plus.dts
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2018 Oleg Ivanov <balbes-150@yandex.ru>
+ * Copyright (c) 2018 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ */
+
+/dts-v1/;
+
+#include "meson8m2.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Tronsmart MXIII Plus";
+ compatible = "tronsmart,mxiii-plus", "amlogic,meson8m2";
+
+ aliases {
+ ethernet0 = &ethmac;
+ i2c0 = &i2c_AO;
+ serial0 = &uart_AO;
+ serial1 = &uart_A;
+ mmc0 = &sd_card_slot;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory {
+ reg = <0x40000000 0x80000000>;
+ };
+
+ 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>;
+ };
+ };
+
+ vcc_3v3: regulator-vcc3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vcck>;
+};
+
+&ethmac {
+ status = "okay";
+
+ pinctrl-0 = <&eth_rgmii_pins>;
+ pinctrl-names = "default";
+
+ phy-handle = <&eth_phy0>;
+ phy-mode = "rgmii";
+
+ amlogic,tx-delay-ns = <4>;
+
+ snps,reset-gpio = <&gpio GPIOH_4 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>;
+ };
+ };
+};
+
+&ir_receiver {
+ status = "okay";
+ pinctrl-0 = <&ir_recv_pins>;
+ pinctrl-names = "default";
+};
+
+&i2c_AO {
+ status = "okay";
+ pinctrl-0 = <&i2c_ao_pins>;
+ pinctrl-names = "default";
+
+ pmic@32 {
+ compatible = "ricoh,rn5t618";
+ reg = <0x32>;
+ system-power-controller;
+
+ regulators {
+ vcck: DCDC1 {
+ regulator-name = "VCCK";
+ regulator-min-microvolt = <825000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ DCDC2 {
+ regulator-name = "VDDAO";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ DCDC3 {
+ regulator-name = "VDD_DDR";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO1 {
+ regulator-name = "VDDIO_AO28";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vddio_ao1v8: LDO2 {
+ regulator-name = "VDDIO_AO18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO3 {
+ regulator-name = "VCC1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO4 {
+ regulator-name = "VCC2V8";
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDO5 {
+ regulator-name = "AVDD1V8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDORTC1 {
+ regulator-name = "VDD_LDO";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ LDORTC2 {
+ regulator-name = "RTC_0V9";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&saradc {
+ status = "okay";
+ vref-supply = <&vddio_ao1v8>;
+};
+
+&sdio {
+ status = "okay";
+
+ pinctrl-0 = <&sd_b_pins>;
+ pinctrl-names = "default";
+
+ /* SD card */
+ sd_card_slot: slot@1 {
+ compatible = "mmc-slot";
+ reg = <1>;
+ status = "okay";
+
+ bus-width = <4>;
+ no-sdio;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ disable-wp;
+
+ cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+ cd-inverted;
+
+ vmmc-supply = <&vcc_3v3>;
+ };
+};
+
+/* connected to the Bluetooth module */
+&uart_A {
+ status = "okay";
+ pinctrl-0 = <&uart_a1_pins>, <&uart_a1_cts_rts_pins>;
+ pinctrl-names = "default";
+ uart-has-rtscts;
+};
+
+&uart_AO {
+ status = "okay";
+ pinctrl-0 = <&uart_ao_a_pins>;
+ pinctrl-names = "default";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&usb0_phy {
+ status = "okay";
+};
+
+&usb1_phy {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/meson8m2.dtsi b/arch/arm/boot/dts/meson8m2.dtsi
new file mode 100644
index 0000000..3e1f922
--- /dev/null
+++ b/arch/arm/boot/dts/meson8m2.dtsi
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>.
+ */
+
+#include "meson8.dtsi"
+
+/ {
+ model = "Amlogic Meson8m2 SoC";
+ compatible = "amlogic,meson8m2";
+}; /* end of / */
+
+&clkc {
+ compatible = "amlogic,meson8m2-clkc", "amlogic,meson8-clkc";
+};
+
+&ethmac {
+ compatible = "amlogic,meson8m2-dwmac", "snps,dwmac";
+ reg = <0xc9410000 0x10000
+ 0xc1108140 0x8>;
+ clocks = <&clkc CLKID_ETH>,
+ <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL2>;
+ clock-names = "stmmaceth", "clkin0", "clkin1";
+ resets = <&reset RESET_ETHERNET>;
+ reset-names = "stmmaceth";
+};
+
+&pinctrl_aobus {
+ compatible = "amlogic,meson8m2-aobus-pinctrl",
+ "amlogic,meson8-aobus-pinctrl";
+};
+
+&pinctrl_cbus {
+ compatible = "amlogic,meson8m2-cbus-pinctrl",
+ "amlogic,meson8-cbus-pinctrl";
+
+ eth_rgmii_pins: ethernet {
+ mux {
+ groups = "eth_tx_clk_50m", "eth_tx_en",
+ "eth_txd3", "eth_txd2",
+ "eth_txd1", "eth_txd0",
+ "eth_rx_clk_in", "eth_rx_dv",
+ "eth_rxd3", "eth_rxd2",
+ "eth_rxd1", "eth_rxd0",
+ "eth_mdio", "eth_mdc";
+ function = "ethernet";
+ };
+ };
+};
+
+&wdt {
+ compatible = "amlogic,meson8m2-wdt", "amlogic,meson8b-wdt";
+};
diff --git a/arch/arm/boot/dts/mt2701-evb.dts b/arch/arm/boot/dts/mt2701-evb.dts
index 63af4b1..be0edb3 100644
--- a/arch/arm/boot/dts/mt2701-evb.dts
+++ b/arch/arm/boot/dts/mt2701-evb.dts
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015 MediaTek Inc.
* Author: Erin Lo <erin.lo@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.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 05557fc..180377e 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015 MediaTek Inc.
* Author: Erin.Lo <erin.lo@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 <dt-bindings/clock/mt2701-clk.h>
@@ -426,104 +419,96 @@
status = "disabled";
};
- afe: audio-controller@11220000 {
- compatible = "mediatek,mt2701-audio";
- reg = <0 0x11220000 0 0x2000>,
- <0 0x112a0000 0 0x20000>;
- interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_LOW>,
- <GIC_SPI 132 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "afe", "asys";
- power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
-
- clocks = <&infracfg CLK_INFRA_AUDIO>,
- <&topckgen CLK_TOP_AUD_MUX1_SEL>,
- <&topckgen CLK_TOP_AUD_MUX2_SEL>,
- <&topckgen CLK_TOP_AUD_MUX1_DIV>,
- <&topckgen CLK_TOP_AUD_MUX2_DIV>,
- <&topckgen CLK_TOP_AUD_48K_TIMING>,
- <&topckgen CLK_TOP_AUD_44K_TIMING>,
- <&topckgen CLK_TOP_AUDPLL_MUX_SEL>,
- <&topckgen CLK_TOP_APLL_SEL>,
- <&topckgen CLK_TOP_AUD1PLL_98M>,
- <&topckgen CLK_TOP_AUD2PLL_90M>,
- <&topckgen CLK_TOP_HADDS2PLL_98M>,
- <&topckgen CLK_TOP_HADDS2PLL_294M>,
- <&topckgen CLK_TOP_AUDPLL>,
- <&topckgen CLK_TOP_AUDPLL_D4>,
- <&topckgen CLK_TOP_AUDPLL_D8>,
- <&topckgen CLK_TOP_AUDPLL_D16>,
- <&topckgen CLK_TOP_AUDPLL_D24>,
- <&topckgen CLK_TOP_AUDINTBUS_SEL>,
- <&clk26m>,
- <&topckgen CLK_TOP_SYSPLL1_D4>,
- <&topckgen CLK_TOP_AUD_K1_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K2_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K3_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K4_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K5_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K6_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K1_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_K2_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_K3_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_K4_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_K5_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_K6_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_I2S1_MCLK>,
- <&topckgen CLK_TOP_AUD_I2S2_MCLK>,
- <&topckgen CLK_TOP_AUD_I2S3_MCLK>,
- <&topckgen CLK_TOP_AUD_I2S4_MCLK>,
- <&topckgen CLK_TOP_AUD_I2S5_MCLK>,
- <&topckgen CLK_TOP_AUD_I2S6_MCLK>,
- <&topckgen CLK_TOP_ASM_M_SEL>,
- <&topckgen CLK_TOP_ASM_H_SEL>,
- <&topckgen CLK_TOP_UNIVPLL2_D4>,
- <&topckgen CLK_TOP_UNIVPLL2_D2>,
- <&topckgen CLK_TOP_SYSPLL_D5>;
-
- clock-names = "infra_sys_audio_clk",
- "top_audio_mux1_sel",
- "top_audio_mux2_sel",
- "top_audio_mux1_div",
- "top_audio_mux2_div",
- "top_audio_48k_timing",
- "top_audio_44k_timing",
- "top_audpll_mux_sel",
- "top_apll_sel",
- "top_aud1_pll_98M",
- "top_aud2_pll_90M",
- "top_hadds2_pll_98M",
- "top_hadds2_pll_294M",
- "top_audpll",
- "top_audpll_d4",
- "top_audpll_d8",
- "top_audpll_d16",
- "top_audpll_d24",
- "top_audintbus_sel",
- "clk_26m",
- "top_syspll1_d4",
- "top_aud_k1_src_sel",
- "top_aud_k2_src_sel",
- "top_aud_k3_src_sel",
- "top_aud_k4_src_sel",
- "top_aud_k5_src_sel",
- "top_aud_k6_src_sel",
- "top_aud_k1_src_div",
- "top_aud_k2_src_div",
- "top_aud_k3_src_div",
- "top_aud_k4_src_div",
- "top_aud_k5_src_div",
- "top_aud_k6_src_div",
- "top_aud_i2s1_mclk",
- "top_aud_i2s2_mclk",
- "top_aud_i2s3_mclk",
- "top_aud_i2s4_mclk",
- "top_aud_i2s5_mclk",
- "top_aud_i2s6_mclk",
- "top_asm_m_sel",
- "top_asm_h_sel",
- "top_univpll2_d4",
- "top_univpll2_d2",
- "top_syspll_d5";
+ audsys: clock-controller@11220000 {
+ compatible = "mediatek,mt2701-audsys", "syscon";
+ reg = <0 0x11220000 0 0x2000>;
+ #clock-cells = <1>;
+
+ afe: audio-controller {
+ compatible = "mediatek,mt2701-audio";
+ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 132 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "afe", "asys";
+ power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+
+ clocks = <&infracfg CLK_INFRA_AUDIO>,
+ <&topckgen CLK_TOP_AUD_MUX1_SEL>,
+ <&topckgen CLK_TOP_AUD_MUX2_SEL>,
+ <&topckgen CLK_TOP_AUD_48K_TIMING>,
+ <&topckgen CLK_TOP_AUD_44K_TIMING>,
+ <&topckgen CLK_TOP_AUD_K1_SRC_SEL>,
+ <&topckgen CLK_TOP_AUD_K2_SRC_SEL>,
+ <&topckgen CLK_TOP_AUD_K3_SRC_SEL>,
+ <&topckgen CLK_TOP_AUD_K4_SRC_SEL>,
+ <&topckgen CLK_TOP_AUD_K1_SRC_DIV>,
+ <&topckgen CLK_TOP_AUD_K2_SRC_DIV>,
+ <&topckgen CLK_TOP_AUD_K3_SRC_DIV>,
+ <&topckgen CLK_TOP_AUD_K4_SRC_DIV>,
+ <&topckgen CLK_TOP_AUD_I2S1_MCLK>,
+ <&topckgen CLK_TOP_AUD_I2S2_MCLK>,
+ <&topckgen CLK_TOP_AUD_I2S3_MCLK>,
+ <&topckgen CLK_TOP_AUD_I2S4_MCLK>,
+ <&audsys CLK_AUD_I2SO1>,
+ <&audsys CLK_AUD_I2SO2>,
+ <&audsys CLK_AUD_I2SO3>,
+ <&audsys CLK_AUD_I2SO4>,
+ <&audsys CLK_AUD_I2SIN1>,
+ <&audsys CLK_AUD_I2SIN2>,
+ <&audsys CLK_AUD_I2SIN3>,
+ <&audsys CLK_AUD_I2SIN4>,
+ <&audsys CLK_AUD_ASRCO1>,
+ <&audsys CLK_AUD_ASRCO2>,
+ <&audsys CLK_AUD_ASRCO3>,
+ <&audsys CLK_AUD_ASRCO4>,
+ <&audsys CLK_AUD_AFE>,
+ <&audsys CLK_AUD_AFE_CONN>,
+ <&audsys CLK_AUD_A1SYS>,
+ <&audsys CLK_AUD_A2SYS>,
+ <&audsys CLK_AUD_AFE_MRGIF>;
+
+ clock-names = "infra_sys_audio_clk",
+ "top_audio_mux1_sel",
+ "top_audio_mux2_sel",
+ "top_audio_a1sys_hp",
+ "top_audio_a2sys_hp",
+ "i2s0_src_sel",
+ "i2s1_src_sel",
+ "i2s2_src_sel",
+ "i2s3_src_sel",
+ "i2s0_src_div",
+ "i2s1_src_div",
+ "i2s2_src_div",
+ "i2s3_src_div",
+ "i2s0_mclk_en",
+ "i2s1_mclk_en",
+ "i2s2_mclk_en",
+ "i2s3_mclk_en",
+ "i2so0_hop_ck",
+ "i2so1_hop_ck",
+ "i2so2_hop_ck",
+ "i2so3_hop_ck",
+ "i2si0_hop_ck",
+ "i2si1_hop_ck",
+ "i2si2_hop_ck",
+ "i2si3_hop_ck",
+ "asrc0_out_ck",
+ "asrc1_out_ck",
+ "asrc2_out_ck",
+ "asrc3_out_ck",
+ "audio_afe_pd",
+ "audio_afe_conn_pd",
+ "audio_a1sys_pd",
+ "audio_a2sys_pd",
+ "audio_mrgif_pd";
+
+ assigned-clocks = <&topckgen CLK_TOP_AUD_MUX1_SEL>,
+ <&topckgen CLK_TOP_AUD_MUX2_SEL>,
+ <&topckgen CLK_TOP_AUD_MUX1_DIV>,
+ <&topckgen CLK_TOP_AUD_MUX2_DIV>;
+ assigned-clock-parents = <&topckgen CLK_TOP_AUD1PLL_98M>,
+ <&topckgen CLK_TOP_AUD2PLL_90M>;
+ assigned-clock-rates = <0>, <0>, <49152000>, <45158400>;
+ };
};
mmsys: syscon@14000000 {
diff --git a/arch/arm/boot/dts/mt6323.dtsi b/arch/arm/boot/dts/mt6323.dtsi
index 7c783d6..ba39740 100644
--- a/arch/arm/boot/dts/mt6323.dtsi
+++ b/arch/arm/boot/dts/mt6323.dtsi
@@ -1,15 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (c) 2017 MediaTek Inc.
+ * Copyright (c) 2017-2018 MediaTek Inc.
* Author: John Crispin <john@phrozen.org>
* Sean Wang <sean.wang@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.
*/
&pwrap {
@@ -20,6 +14,13 @@
interrupt-controller;
#interrupt-cells = <2>;
+ mt6323_leds: leds {
+ compatible = "mediatek,mt6323-led";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
mt6323regulator: mt6323regulator{
compatible = "mediatek,mt6323-regulator";
diff --git a/arch/arm/boot/dts/mt6580-evbp1.dts b/arch/arm/boot/dts/mt6580-evbp1.dts
index 17daeae..ca13789 100644
--- a/arch/arm/boot/dts/mt6580-evbp1.dts
+++ b/arch/arm/boot/dts/mt6580-evbp1.dts
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015 MediaTek Inc.
* Author: Mars.C <mars.cheng@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.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/mt6580.dtsi b/arch/arm/boot/dts/mt6580.dtsi
index a349dba..2bdc5ed 100644
--- a/arch/arm/boot/dts/mt6580.dtsi
+++ b/arch/arm/boot/dts/mt6580.dtsi
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015 MediaTek Inc.
* Author: Mars.C <mars.cheng@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 <dt-bindings/interrupt-controller/irq.h>
diff --git a/arch/arm/boot/dts/mt6589-aquaris5.dts b/arch/arm/boot/dts/mt6589-aquaris5.dts
index 594a6f3..7bbaa12 100644
--- a/arch/arm/boot/dts/mt6589-aquaris5.dts
+++ b/arch/arm/boot/dts/mt6589-aquaris5.dts
@@ -1,16 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2014 MundoReader S.L.
* Author: Matthias Brugger <matthias.bgg@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; 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.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/mt6589.dtsi b/arch/arm/boot/dts/mt6589.dtsi
index 41df742..28df849 100644
--- a/arch/arm/boot/dts/mt6589.dtsi
+++ b/arch/arm/boot/dts/mt6589.dtsi
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2014 MundoReader S.L.
* Author: Matthias Brugger <matthias.bgg@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; 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 <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
diff --git a/arch/arm/boot/dts/mt6592-evb.dts b/arch/arm/boot/dts/mt6592-evb.dts
index b57237e..02849f6 100644
--- a/arch/arm/boot/dts/mt6592-evb.dts
+++ b/arch/arm/boot/dts/mt6592-evb.dts
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 MediaTek Inc.
* Author: Howard Chen <ibanezchen@gmail.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.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/mt6592.dtsi b/arch/arm/boot/dts/mt6592.dtsi
index c69201f..8696ac8 100644
--- a/arch/arm/boot/dts/mt6592.dtsi
+++ b/arch/arm/boot/dts/mt6592.dtsi
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 MediaTek Inc.
* Author: Howard Chen <ibanezchen@gmail.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 <dt-bindings/interrupt-controller/irq.h>
diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi
index e10c034..d1eb123 100644
--- a/arch/arm/boot/dts/mt7623.dtsi
+++ b/arch/arm/boot/dts/mt7623.dtsi
@@ -1,16 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (c) 2017 MediaTek Inc.
+ * Copyright (c) 2017-2018 MediaTek Inc.
* Author: John Crispin <john@phrozen.org>
* Sean Wang <sean.wang@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 <dt-bindings/interrupt-controller/irq.h>
@@ -22,11 +15,12 @@
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/reset/mt2701-resets.h>
#include <dt-bindings/thermal/thermal.h>
-#include "skeleton64.dtsi"
/ {
compatible = "mediatek,mt7623";
interrupt-parent = <&sysirq>;
+ #address-cells = <2>;
+ #size-cells = <2>;
cpu_opp_table: opp-table {
compatible = "operating-points-v2";
@@ -130,14 +124,14 @@
#clock-cells = <0>;
};
- rtc32k: oscillator@1 {
+ rtc32k: oscillator-1 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32000>;
clock-output-names = "rtc32k";
};
- clk26m: oscillator@0 {
+ clk26m: oscillator-0 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <26000000>;
@@ -492,6 +486,18 @@
nvmem-cell-names = "calibration-data";
};
+ btif: serial@1100c000 {
+ compatible = "mediatek,mt7623-btif",
+ "mediatek,mtk-btif";
+ reg = <0 0x1100c000 0 0x1000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_BTIF>;
+ clock-names = "main";
+ reg-shift = <2>;
+ reg-io-width = <4>;
+ status = "disabled";
+ };
+
nandc: nfi@1100d000 {
compatible = "mediatek,mt7623-nfc",
"mediatek,mt2701-nfc";
@@ -517,6 +523,18 @@
status = "disabled";
};
+ nor_flash: spi@11014000 {
+ compatible = "mediatek,mt7623-nor",
+ "mediatek,mt8173-nor";
+ reg = <0 0x11014000 0 0x1000>;
+ clocks = <&pericfg CLK_PERI_FLASH>,
+ <&topckgen CLK_TOP_FLASH_SEL>;
+ clock-names = "spi", "sf";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
spi1: spi@11016000 {
compatible = "mediatek,mt7623-spi",
"mediatek,mt2701-spi";
@@ -545,105 +563,99 @@
status = "disabled";
};
- afe: audio-controller@11220000 {
- compatible = "mediatek,mt7623-audio",
- "mediatek,mt2701-audio";
- reg = <0 0x11220000 0 0x2000>,
- <0 0x112a0000 0 0x20000>;
- interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_LOW>,
- <GIC_SPI 132 IRQ_TYPE_LEVEL_LOW>;
- interrupt-names = "afe", "asys";
- power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+ audsys: clock-controller@11220000 {
+ compatible = "mediatek,mt7623-audsys",
+ "mediatek,mt2701-audsys",
+ "syscon";
+ reg = <0 0x11220000 0 0x2000>;
+ #clock-cells = <1>;
- clocks = <&infracfg CLK_INFRA_AUDIO>,
- <&topckgen CLK_TOP_AUD_MUX1_SEL>,
- <&topckgen CLK_TOP_AUD_MUX2_SEL>,
- <&topckgen CLK_TOP_AUD_MUX1_DIV>,
- <&topckgen CLK_TOP_AUD_MUX2_DIV>,
- <&topckgen CLK_TOP_AUD_48K_TIMING>,
- <&topckgen CLK_TOP_AUD_44K_TIMING>,
- <&topckgen CLK_TOP_AUDPLL_MUX_SEL>,
- <&topckgen CLK_TOP_APLL_SEL>,
- <&topckgen CLK_TOP_AUD1PLL_98M>,
- <&topckgen CLK_TOP_AUD2PLL_90M>,
- <&topckgen CLK_TOP_HADDS2PLL_98M>,
- <&topckgen CLK_TOP_HADDS2PLL_294M>,
- <&topckgen CLK_TOP_AUDPLL>,
- <&topckgen CLK_TOP_AUDPLL_D4>,
- <&topckgen CLK_TOP_AUDPLL_D8>,
- <&topckgen CLK_TOP_AUDPLL_D16>,
- <&topckgen CLK_TOP_AUDPLL_D24>,
- <&topckgen CLK_TOP_AUDINTBUS_SEL>,
- <&clk26m>,
- <&topckgen CLK_TOP_SYSPLL1_D4>,
- <&topckgen CLK_TOP_AUD_K1_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K2_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K3_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K4_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K5_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K6_SRC_SEL>,
- <&topckgen CLK_TOP_AUD_K1_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_K2_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_K3_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_K4_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_K5_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_K6_SRC_DIV>,
- <&topckgen CLK_TOP_AUD_I2S1_MCLK>,
- <&topckgen CLK_TOP_AUD_I2S2_MCLK>,
- <&topckgen CLK_TOP_AUD_I2S3_MCLK>,
- <&topckgen CLK_TOP_AUD_I2S4_MCLK>,
- <&topckgen CLK_TOP_AUD_I2S5_MCLK>,
- <&topckgen CLK_TOP_AUD_I2S6_MCLK>,
- <&topckgen CLK_TOP_ASM_M_SEL>,
- <&topckgen CLK_TOP_ASM_H_SEL>,
- <&topckgen CLK_TOP_UNIVPLL2_D4>,
- <&topckgen CLK_TOP_UNIVPLL2_D2>,
- <&topckgen CLK_TOP_SYSPLL_D5>;
-
- clock-names = "infra_sys_audio_clk",
- "top_audio_mux1_sel",
- "top_audio_mux2_sel",
- "top_audio_mux1_div",
- "top_audio_mux2_div",
- "top_audio_48k_timing",
- "top_audio_44k_timing",
- "top_audpll_mux_sel",
- "top_apll_sel",
- "top_aud1_pll_98M",
- "top_aud2_pll_90M",
- "top_hadds2_pll_98M",
- "top_hadds2_pll_294M",
- "top_audpll",
- "top_audpll_d4",
- "top_audpll_d8",
- "top_audpll_d16",
- "top_audpll_d24",
- "top_audintbus_sel",
- "clk_26m",
- "top_syspll1_d4",
- "top_aud_k1_src_sel",
- "top_aud_k2_src_sel",
- "top_aud_k3_src_sel",
- "top_aud_k4_src_sel",
- "top_aud_k5_src_sel",
- "top_aud_k6_src_sel",
- "top_aud_k1_src_div",
- "top_aud_k2_src_div",
- "top_aud_k3_src_div",
- "top_aud_k4_src_div",
- "top_aud_k5_src_div",
- "top_aud_k6_src_div",
- "top_aud_i2s1_mclk",
- "top_aud_i2s2_mclk",
- "top_aud_i2s3_mclk",
- "top_aud_i2s4_mclk",
- "top_aud_i2s5_mclk",
- "top_aud_i2s6_mclk",
- "top_asm_m_sel",
- "top_asm_h_sel",
- "top_univpll2_d4",
- "top_univpll2_d2",
- "top_syspll_d5";
+ afe: audio-controller {
+ compatible = "mediatek,mt7623-audio",
+ "mediatek,mt2701-audio";
+ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 132 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "afe", "asys";
+ power-domains = <&scpsys MT2701_POWER_DOMAIN_IFR_MSC>;
+
+ clocks = <&infracfg CLK_INFRA_AUDIO>,
+ <&topckgen CLK_TOP_AUD_MUX1_SEL>,
+ <&topckgen CLK_TOP_AUD_MUX2_SEL>,
+ <&topckgen CLK_TOP_AUD_48K_TIMING>,
+ <&topckgen CLK_TOP_AUD_44K_TIMING>,
+ <&topckgen CLK_TOP_AUD_K1_SRC_SEL>,
+ <&topckgen CLK_TOP_AUD_K2_SRC_SEL>,
+ <&topckgen CLK_TOP_AUD_K3_SRC_SEL>,
+ <&topckgen CLK_TOP_AUD_K4_SRC_SEL>,
+ <&topckgen CLK_TOP_AUD_K1_SRC_DIV>,
+ <&topckgen CLK_TOP_AUD_K2_SRC_DIV>,
+ <&topckgen CLK_TOP_AUD_K3_SRC_DIV>,
+ <&topckgen CLK_TOP_AUD_K4_SRC_DIV>,
+ <&topckgen CLK_TOP_AUD_I2S1_MCLK>,
+ <&topckgen CLK_TOP_AUD_I2S2_MCLK>,
+ <&topckgen CLK_TOP_AUD_I2S3_MCLK>,
+ <&topckgen CLK_TOP_AUD_I2S4_MCLK>,
+ <&audsys CLK_AUD_I2SO1>,
+ <&audsys CLK_AUD_I2SO2>,
+ <&audsys CLK_AUD_I2SO3>,
+ <&audsys CLK_AUD_I2SO4>,
+ <&audsys CLK_AUD_I2SIN1>,
+ <&audsys CLK_AUD_I2SIN2>,
+ <&audsys CLK_AUD_I2SIN3>,
+ <&audsys CLK_AUD_I2SIN4>,
+ <&audsys CLK_AUD_ASRCO1>,
+ <&audsys CLK_AUD_ASRCO2>,
+ <&audsys CLK_AUD_ASRCO3>,
+ <&audsys CLK_AUD_ASRCO4>,
+ <&audsys CLK_AUD_AFE>,
+ <&audsys CLK_AUD_AFE_CONN>,
+ <&audsys CLK_AUD_A1SYS>,
+ <&audsys CLK_AUD_A2SYS>,
+ <&audsys CLK_AUD_AFE_MRGIF>;
+
+ clock-names = "infra_sys_audio_clk",
+ "top_audio_mux1_sel",
+ "top_audio_mux2_sel",
+ "top_audio_a1sys_hp",
+ "top_audio_a2sys_hp",
+ "i2s0_src_sel",
+ "i2s1_src_sel",
+ "i2s2_src_sel",
+ "i2s3_src_sel",
+ "i2s0_src_div",
+ "i2s1_src_div",
+ "i2s2_src_div",
+ "i2s3_src_div",
+ "i2s0_mclk_en",
+ "i2s1_mclk_en",
+ "i2s2_mclk_en",
+ "i2s3_mclk_en",
+ "i2so0_hop_ck",
+ "i2so1_hop_ck",
+ "i2so2_hop_ck",
+ "i2so3_hop_ck",
+ "i2si0_hop_ck",
+ "i2si1_hop_ck",
+ "i2si2_hop_ck",
+ "i2si3_hop_ck",
+ "asrc0_out_ck",
+ "asrc1_out_ck",
+ "asrc2_out_ck",
+ "asrc3_out_ck",
+ "audio_afe_pd",
+ "audio_afe_conn_pd",
+ "audio_a1sys_pd",
+ "audio_a2sys_pd",
+ "audio_mrgif_pd";
+
+ assigned-clocks = <&topckgen CLK_TOP_AUD_MUX1_SEL>,
+ <&topckgen CLK_TOP_AUD_MUX2_SEL>,
+ <&topckgen CLK_TOP_AUD_MUX1_DIV>,
+ <&topckgen CLK_TOP_AUD_MUX2_DIV>;
+ assigned-clock-parents = <&topckgen CLK_TOP_AUD1PLL_98M>,
+ <&topckgen CLK_TOP_AUD2PLL_90M>;
+ assigned-clock-rates = <0>, <0>, <49152000>, <45158400>;
+ };
};
mmc0: mmc@11230000 {
@@ -873,6 +885,16 @@
#reset-cells = <1>;
};
+ hsdma: dma-controller@1b007000 {
+ compatible = "mediatek,mt7623-hsdma";
+ reg = <0 0x1b007000 0 0x1000>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&ethsys CLK_ETHSYS_HSDMA>;
+ clock-names = "hsdma";
+ power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>;
+ #dma-cells = <1>;
+ };
+
eth: ethernet@1b100000 {
compatible = "mediatek,mt7623-eth",
"mediatek,mt2701-eth",
@@ -913,3 +935,298 @@
status = "disabled";
};
};
+
+&pio {
+ cir_pins_a:cir-default {
+ pins-cir {
+ pinmux = <MT7623_PIN_46_IR_FUNC_IR>;
+ bias-disable;
+ };
+ };
+
+ i2c0_pins_a: i2c0-default {
+ pins-i2c0 {
+ pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
+ <MT7623_PIN_76_SCL0_FUNC_SCL0>;
+ bias-disable;
+ };
+ };
+
+ i2c1_pins_a: i2c1-default {
+ pin-i2c1 {
+ pinmux = <MT7623_PIN_57_SDA1_FUNC_SDA1>,
+ <MT7623_PIN_58_SCL1_FUNC_SCL1>;
+ bias-disable;
+ };
+ };
+
+ i2c1_pins_b: i2c1-alt {
+ pin-i2c1 {
+ pinmux = <MT7623_PIN_242_URTS2_FUNC_SCL1>,
+ <MT7623_PIN_243_UCTS2_FUNC_SDA1>;
+ bias-disable;
+ };
+ };
+
+ i2c2_pins_a: i2c2-default {
+ pin-i2c2 {
+ pinmux = <MT7623_PIN_77_SDA2_FUNC_SDA2>,
+ <MT7623_PIN_78_SCL2_FUNC_SCL2>;
+ bias-disable;
+ };
+ };
+
+ i2c2_pins_b: i2c2-alt {
+ pin-i2c2 {
+ pinmux = <MT7623_PIN_122_GPIO122_FUNC_SDA2>,
+ <MT7623_PIN_123_HTPLG_FUNC_SCL2>;
+ bias-disable;
+ };
+ };
+
+ i2s0_pins_a: i2s0-default {
+ pin-i2s0 {
+ pinmux = <MT7623_PIN_49_I2S0_DATA_FUNC_I2S0_DATA>,
+ <MT7623_PIN_72_I2S0_DATA_IN_FUNC_I2S0_DATA_IN>,
+ <MT7623_PIN_73_I2S0_LRCK_FUNC_I2S0_LRCK>,
+ <MT7623_PIN_74_I2S0_BCK_FUNC_I2S0_BCK>,
+ <MT7623_PIN_126_I2S0_MCLK_FUNC_I2S0_MCLK>;
+ drive-strength = <MTK_DRIVE_12mA>;
+ bias-pull-down;
+ };
+ };
+
+ i2s1_pins_a: i2s1-default {
+ pin-i2s1 {
+ pinmux = <MT7623_PIN_33_I2S1_DATA_FUNC_I2S1_DATA>,
+ <MT7623_PIN_34_I2S1_DATA_IN_FUNC_I2S1_DATA_IN>,
+ <MT7623_PIN_35_I2S1_BCK_FUNC_I2S1_BCK>,
+ <MT7623_PIN_36_I2S1_LRCK_FUNC_I2S1_LRCK>,
+ <MT7623_PIN_37_I2S1_MCLK_FUNC_I2S1_MCLK>;
+ drive-strength = <MTK_DRIVE_12mA>;
+ bias-pull-down;
+ };
+ };
+
+ key_pins_a: keys-alt {
+ pins-keys {
+ pinmux = <MT7623_PIN_256_GPIO256_FUNC_GPIO256>,
+ <MT7623_PIN_257_GPIO257_FUNC_GPIO257> ;
+ input-enable;
+ };
+ };
+
+ led_pins_a: leds-alt {
+ pins-leds {
+ pinmux = <MT7623_PIN_239_EXT_SDIO0_FUNC_GPIO239>,
+ <MT7623_PIN_240_EXT_XCS_FUNC_GPIO240>,
+ <MT7623_PIN_241_EXT_SCK_FUNC_GPIO241>;
+ };
+ };
+
+ mmc0_pins_default: mmc0default {
+ pins-cmd-dat {
+ pinmux = <MT7623_PIN_111_MSDC0_DAT7_FUNC_MSDC0_DAT7>,
+ <MT7623_PIN_112_MSDC0_DAT6_FUNC_MSDC0_DAT6>,
+ <MT7623_PIN_113_MSDC0_DAT5_FUNC_MSDC0_DAT5>,
+ <MT7623_PIN_114_MSDC0_DAT4_FUNC_MSDC0_DAT4>,
+ <MT7623_PIN_118_MSDC0_DAT3_FUNC_MSDC0_DAT3>,
+ <MT7623_PIN_119_MSDC0_DAT2_FUNC_MSDC0_DAT2>,
+ <MT7623_PIN_120_MSDC0_DAT1_FUNC_MSDC0_DAT1>,
+ <MT7623_PIN_121_MSDC0_DAT0_FUNC_MSDC0_DAT0>,
+ <MT7623_PIN_116_MSDC0_CMD_FUNC_MSDC0_CMD>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins-clk {
+ pinmux = <MT7623_PIN_117_MSDC0_CLK_FUNC_MSDC0_CLK>;
+ bias-pull-down;
+ };
+
+ pins-rst {
+ pinmux = <MT7623_PIN_115_MSDC0_RSTB_FUNC_MSDC0_RSTB>;
+ bias-pull-up;
+ };
+ };
+
+ mmc0_pins_uhs: mmc0 {
+ pins-cmd-dat {
+ pinmux = <MT7623_PIN_111_MSDC0_DAT7_FUNC_MSDC0_DAT7>,
+ <MT7623_PIN_112_MSDC0_DAT6_FUNC_MSDC0_DAT6>,
+ <MT7623_PIN_113_MSDC0_DAT5_FUNC_MSDC0_DAT5>,
+ <MT7623_PIN_114_MSDC0_DAT4_FUNC_MSDC0_DAT4>,
+ <MT7623_PIN_118_MSDC0_DAT3_FUNC_MSDC0_DAT3>,
+ <MT7623_PIN_119_MSDC0_DAT2_FUNC_MSDC0_DAT2>,
+ <MT7623_PIN_120_MSDC0_DAT1_FUNC_MSDC0_DAT1>,
+ <MT7623_PIN_121_MSDC0_DAT0_FUNC_MSDC0_DAT0>,
+ <MT7623_PIN_116_MSDC0_CMD_FUNC_MSDC0_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_2mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-clk {
+ pinmux = <MT7623_PIN_117_MSDC0_CLK_FUNC_MSDC0_CLK>;
+ drive-strength = <MTK_DRIVE_2mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_01>;
+ };
+
+ pins-rst {
+ pinmux = <MT7623_PIN_115_MSDC0_RSTB_FUNC_MSDC0_RSTB>;
+ bias-pull-up;
+ };
+ };
+
+ mmc1_pins_default: mmc1default {
+ pins-cmd-dat {
+ pinmux = <MT7623_PIN_107_MSDC1_DAT0_FUNC_MSDC1_DAT0>,
+ <MT7623_PIN_108_MSDC1_DAT1_FUNC_MSDC1_DAT1>,
+ <MT7623_PIN_109_MSDC1_DAT2_FUNC_MSDC1_DAT2>,
+ <MT7623_PIN_110_MSDC1_DAT3_FUNC_MSDC1_DAT3>,
+ <MT7623_PIN_105_MSDC1_CMD_FUNC_MSDC1_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-clk {
+ pinmux = <MT7623_PIN_106_MSDC1_CLK_FUNC_MSDC1_CLK>;
+ bias-pull-down;
+ drive-strength = <MTK_DRIVE_4mA>;
+ };
+
+ pins-wp {
+ pinmux = <MT7623_PIN_29_EINT7_FUNC_MSDC1_WP>;
+ input-enable;
+ bias-pull-up;
+ };
+
+ pins-insert {
+ pinmux = <MT7623_PIN_261_MSDC1_INS_FUNC_GPIO261>;
+ bias-pull-up;
+ };
+ };
+
+ mmc1_pins_uhs: mmc1 {
+ pins-cmd-dat {
+ pinmux = <MT7623_PIN_107_MSDC1_DAT0_FUNC_MSDC1_DAT0>,
+ <MT7623_PIN_108_MSDC1_DAT1_FUNC_MSDC1_DAT1>,
+ <MT7623_PIN_109_MSDC1_DAT2_FUNC_MSDC1_DAT2>,
+ <MT7623_PIN_110_MSDC1_DAT3_FUNC_MSDC1_DAT3>,
+ <MT7623_PIN_105_MSDC1_CMD_FUNC_MSDC1_CMD>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-clk {
+ pinmux = <MT7623_PIN_106_MSDC1_CLK_FUNC_MSDC1_CLK>;
+ drive-strength = <MTK_DRIVE_4mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ nand_pins_default: nanddefault {
+ pins-ale {
+ pinmux = <MT7623_PIN_116_MSDC0_CMD_FUNC_NALE>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
+ };
+
+ pins-dat {
+ pinmux = <MT7623_PIN_111_MSDC0_DAT7_FUNC_NLD7>,
+ <MT7623_PIN_112_MSDC0_DAT6_FUNC_NLD6>,
+ <MT7623_PIN_114_MSDC0_DAT4_FUNC_NLD4>,
+ <MT7623_PIN_118_MSDC0_DAT3_FUNC_NLD3>,
+ <MT7623_PIN_121_MSDC0_DAT0_FUNC_NLD0>,
+ <MT7623_PIN_120_MSDC0_DAT1_FUNC_NLD1>,
+ <MT7623_PIN_113_MSDC0_DAT5_FUNC_NLD5>,
+ <MT7623_PIN_115_MSDC0_RSTB_FUNC_NLD8>,
+ <MT7623_PIN_119_MSDC0_DAT2_FUNC_NLD2>;
+ input-enable;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up;
+ };
+
+ pins-we {
+ pinmux = <MT7623_PIN_117_MSDC0_CLK_FUNC_NWEB>;
+ drive-strength = <MTK_DRIVE_8mA>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
+ };
+ };
+
+ pcie_default: pcie_pin_default {
+ pins_cmd_dat {
+ pinmux = <MT7623_PIN_208_AUD_EXT_CK1_FUNC_PCIE0_PERST_N>,
+ <MT7623_PIN_209_AUD_EXT_CK2_FUNC_PCIE1_PERST_N>;
+ bias-disable;
+ };
+ };
+
+ pwm_pins_a: pwm-default {
+ pins-pwm {
+ pinmux = <MT7623_PIN_203_PWM0_FUNC_PWM0>,
+ <MT7623_PIN_204_PWM1_FUNC_PWM1>,
+ <MT7623_PIN_205_PWM2_FUNC_PWM2>,
+ <MT7623_PIN_206_PWM3_FUNC_PWM3>,
+ <MT7623_PIN_207_PWM4_FUNC_PWM4>;
+ };
+ };
+
+ spi0_pins_a: spi0-default {
+ pins-spi {
+ pinmux = <MT7623_PIN_53_SPI0_CSN_FUNC_SPI0_CS>,
+ <MT7623_PIN_54_SPI0_CK_FUNC_SPI0_CK>,
+ <MT7623_PIN_55_SPI0_MI_FUNC_SPI0_MI>,
+ <MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MO>;
+ bias-disable;
+ };
+ };
+
+ spi1_pins_a: spi1-default {
+ pins-spi {
+ pinmux = <MT7623_PIN_7_SPI1_CSN_FUNC_SPI1_CS>,
+ <MT7623_PIN_199_SPI1_CK_FUNC_SPI1_CK>,
+ <MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MI>,
+ <MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MO>;
+ };
+ };
+
+ spi2_pins_a: spi2-default {
+ pins-spi {
+ pinmux = <MT7623_PIN_101_SPI2_CSN_FUNC_SPI2_CS>,
+ <MT7623_PIN_104_SPI2_CK_FUNC_SPI2_CK>,
+ <MT7623_PIN_102_SPI2_MI_FUNC_SPI2_MI>,
+ <MT7623_PIN_103_SPI2_MO_FUNC_SPI2_MO>;
+ };
+ };
+
+ uart0_pins_a: uart0-default {
+ pins-dat {
+ pinmux = <MT7623_PIN_79_URXD0_FUNC_URXD0>,
+ <MT7623_PIN_80_UTXD0_FUNC_UTXD0>;
+ };
+ };
+
+ uart1_pins_a: uart1-default {
+ pins-dat {
+ pinmux = <MT7623_PIN_81_URXD1_FUNC_URXD1>,
+ <MT7623_PIN_82_UTXD1_FUNC_UTXD1>;
+ };
+ };
+
+ uart2_pins_a: uart2-default {
+ pins-dat {
+ pinmux = <MT7623_PIN_14_GPIO14_FUNC_URXD2>,
+ <MT7623_PIN_15_GPIO15_FUNC_UTXD2>;
+ };
+ };
+
+ uart2_pins_b: uart2-alt {
+ pins-dat {
+ pinmux = <MT7623_PIN_200_URXD2_FUNC_URXD2>,
+ <MT7623_PIN_201_UTXD2_FUNC_UTXD2>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/mt7623a-rfb-emmc.dts b/arch/arm/boot/dts/mt7623a-rfb-emmc.dts
new file mode 100644
index 0000000..13c8693
--- /dev/null
+++ b/arch/arm/boot/dts/mt7623a-rfb-emmc.dts
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2018 MediaTek Inc.
+ * Author: Sean Wang <sean.wang@mediatek.com>
+ *
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "mt7623a.dtsi"
+#include "mt6323.dtsi"
+
+/ {
+ model = "MediaTek MT7623A with eMMC reference board";
+ compatible = "mediatek,mt7623a-rfb-emmc", "mediatek,mt7623";
+
+ aliases {
+ serial2 = &uart2;
+ };
+
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ cpus {
+ cpu@0 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+
+ cpu@1 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+
+ cpu@2 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+
+ cpu@3 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&key_pins_a>;
+
+ factory {
+ label = "factory";
+ linux,code = <BTN_0>;
+ gpios = <&pio 256 GPIO_ACTIVE_LOW>;
+ };
+
+ wps {
+ label = "wps";
+ linux,code = <KEY_WPS_BUTTON>;
+ gpios = <&pio 257 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0 0x80000000 0 0x20000000>;
+ };
+
+ reg_1p8v: regulator-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_5v: regulator-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sound {
+ compatible = "mediatek,mt2701-wm8960-machine";
+ mediatek,platform = <&afe>;
+ audio-routing =
+ "Headphone", "HP_L",
+ "Headphone", "HP_R",
+ "LINPUT1", "AMIC",
+ "RINPUT1", "AMIC";
+ mediatek,audio-codec = <&wm8960>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_pins_a>;
+ };
+};
+
+&btif {
+ status = "okay";
+};
+
+&crypto {
+ status = "okay";
+};
+
+&eth {
+ status = "okay";
+
+ gmac0: mac@0 {
+ compatible = "mediatek,eth-mac";
+ reg = <0>;
+ phy-mode = "trgmii";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ pause;
+ };
+ };
+
+ mdio-bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ switch@0 {
+ compatible = "mediatek,mt7530";
+ reg = <0>;
+ mediatek,mcm;
+ resets = <&ethsys MT2701_ETHSYS_MCM_RST>;
+ reset-names = "mcm";
+ core-supply = <&mt6323_vpa_reg>;
+ io-supply = <&mt6323_vemc3v3_reg>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "lan0";
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "lan1";
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "lan2";
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan3";
+ };
+
+ port@4 {
+ reg = <4>;
+ label = "wan";
+ };
+
+ port@6 {
+ reg = <6>;
+ label = "cpu";
+ ethernet = <&gmac0>;
+ phy-mode = "trgmii";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+ };
+ };
+ };
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins_b>;
+ status = "okay";
+
+ wm8960: wm8960@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins_b>;
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_pins_default>;
+ pinctrl-1 = <&mmc0_pins_uhs>;
+ status = "okay";
+ bus-width = <8>;
+ max-frequency = <50000000>;
+ cap-mmc-highspeed;
+ vmmc-supply = <&reg_3p3v>;
+ vqmmc-supply = <&reg_1p8v>;
+ non-removable;
+};
+
+&mmc1 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-1 = <&mmc1_pins_uhs>;
+ status = "okay";
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ cap-sd-highspeed;
+ cd-gpios = <&pio 261 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&reg_3p3v>;
+ vqmmc-supply = <&reg_3p3v>;
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_default>;
+ status = "okay";
+
+ pcie@0,0 {
+ status = "okay";
+ };
+
+ pcie@1,0 {
+ status = "okay";
+ };
+};
+
+&pcie0_phy {
+ status = "okay";
+};
+
+&pcie1_phy {
+ status = "okay";
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_pins_a>;
+ status = "okay";
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins_a>;
+ status = "okay";
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins_a>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_pins_b>;
+ status = "okay";
+};
+
+&usb1 {
+ vusb33-supply = <&reg_3p3v>;
+ vbus-supply = <&reg_5v>;
+ status = "okay";
+};
+
+&u3phy1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/mt7623a-rfb-nand.dts b/arch/arm/boot/dts/mt7623a-rfb-nand.dts
new file mode 100644
index 0000000..88d8f0b
--- /dev/null
+++ b/arch/arm/boot/dts/mt7623a-rfb-nand.dts
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2018 MediaTek Inc.
+ * Author: Sean Wang <sean.wang@mediatek.com>
+ *
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "mt7623a.dtsi"
+#include "mt6323.dtsi"
+
+/ {
+ model = "MediaTek MT7623A with NAND reference board";
+ compatible = "mediatek,mt7623a-rfb-nand", "mediatek,mt7623";
+
+ aliases {
+ serial2 = &uart2;
+ };
+
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ cpus {
+ cpu@0 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+
+ cpu@1 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+
+ cpu@2 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+
+ cpu@3 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&key_pins_a>;
+
+ factory {
+ label = "factory";
+ linux,code = <BTN_0>;
+ gpios = <&pio 256 GPIO_ACTIVE_LOW>;
+ };
+
+ wps {
+ label = "wps";
+ linux,code = <KEY_WPS_BUTTON>;
+ gpios = <&pio 257 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0 0x80000000 0 0x20000000>;
+ };
+
+ reg_1p8v: regulator-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_5v: regulator-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sound {
+ compatible = "mediatek,mt2701-wm8960-machine";
+ mediatek,platform = <&afe>;
+ audio-routing =
+ "Headphone", "HP_L",
+ "Headphone", "HP_R",
+ "LINPUT1", "AMIC",
+ "RINPUT1", "AMIC";
+ mediatek,audio-codec = <&wm8960>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_pins_a>;
+ };
+};
+
+&bch {
+ status = "okay";
+};
+
+&btif {
+ status = "okay";
+};
+
+&crypto {
+ status = "okay";
+};
+
+&eth {
+ status = "okay";
+
+ gmac0: mac@0 {
+ compatible = "mediatek,eth-mac";
+ reg = <0>;
+ phy-mode = "trgmii";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ pause;
+ };
+ };
+
+ mdio-bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ switch@0 {
+ compatible = "mediatek,mt7530";
+ reg = <0>;
+ mediatek,mcm;
+ resets = <&ethsys MT2701_ETHSYS_MCM_RST>;
+ reset-names = "mcm";
+ core-supply = <&mt6323_vpa_reg>;
+ io-supply = <&mt6323_vemc3v3_reg>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "lan0";
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "lan1";
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "lan2";
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan3";
+ };
+
+ port@4 {
+ reg = <4>;
+ label = "wan";
+ };
+
+ port@6 {
+ reg = <6>;
+ label = "cpu";
+ ethernet = <&gmac0>;
+ phy-mode = "trgmii";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+ };
+ };
+ };
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins_b>;
+ status = "okay";
+
+ wm8960: wm8960@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins_b>;
+ status = "okay";
+};
+
+&mmc1 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-1 = <&mmc1_pins_uhs>;
+ status = "okay";
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ cap-sd-highspeed;
+ cd-gpios = <&pio 261 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&reg_3p3v>;
+ vqmmc-supply = <&reg_3p3v>;
+};
+
+&nandc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&nand_pins_default>;
+ status = "okay";
+
+ nand@0 {
+ reg = <0>;
+ spare_per_sector = <64>;
+ nand-ecc-mode = "hw";
+ nand-ecc-strength = <12>;
+ nand-ecc-step-size = <1024>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "preloader";
+ reg = <0x0 0x40000>;
+ };
+
+ partition@40000 {
+ label = "uboot";
+ reg = <0x40000 0x80000>;
+ };
+
+ partition@c0000 {
+ label = "uboot-env";
+ reg = <0xC0000 0x40000>;
+ };
+
+ partition@140000 {
+ label = "bootimg";
+ reg = <0x140000 0x2000000>;
+ };
+
+ partition@2140000 {
+ label = "recovery";
+ reg = <0x2140000 0x2000000>;
+ };
+
+ partition@4140000 {
+ label = "rootfs";
+ reg = <0x4140000 0x1000000>;
+ };
+
+ partition@5140000 {
+ label = "usrdata";
+ reg = <0x5140000 0x1000000>;
+ };
+ };
+ };
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_default>;
+ status = "okay";
+
+ pcie@0,0 {
+ status = "okay";
+ };
+
+ pcie@1,0 {
+ status = "okay";
+ };
+};
+
+&pcie0_phy {
+ status = "okay";
+};
+
+&pcie1_phy {
+ status = "okay";
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_pins_a>;
+ status = "okay";
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins_a>;
+ status = "okay";
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins_a>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_pins_b>;
+ status = "okay";
+};
+
+&usb1 {
+ vusb33-supply = <&reg_3p3v>;
+ vbus-supply = <&reg_5v>;
+ status = "okay";
+};
+
+&u3phy1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/mt7623a.dtsi b/arch/arm/boot/dts/mt7623a.dtsi
new file mode 100644
index 0000000..0735a1fb8
--- /dev/null
+++ b/arch/arm/boot/dts/mt7623a.dtsi
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2018 MediaTek Inc.
+ * Author: Sean Wang <sean.wang@mediatek.com>
+ *
+ */
+
+/dts-v1/;
+#include <dt-bindings/power/mt7623a-power.h>
+#include "mt7623.dtsi"
+
+&afe {
+ power-domains = <&scpsys MT7623A_POWER_DOMAIN_IFR_MSC>;
+};
+
+&crypto {
+ power-domains = <&scpsys MT7623A_POWER_DOMAIN_ETH>;
+};
+
+&eth {
+ power-domains = <&scpsys MT7623A_POWER_DOMAIN_ETH>;
+};
+
+&nandc {
+ power-domains = <&scpsys MT7623A_POWER_DOMAIN_IFR_MSC>;
+};
+
+&pcie {
+ power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>;
+};
+
+&scpsys {
+ compatible = "mediatek,mt7623a-scpsys";
+ clocks = <&topckgen CLK_TOP_ETHIF_SEL>;
+ clock-names = "ethif";
+};
+
+&usb1 {
+ power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>;
+};
+
+&usb2 {
+ power-domains = <&scpsys MT7623A_POWER_DOMAIN_HIF>;
+};
diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
index bbf56f8..531d905 100644
--- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
+++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts
@@ -1,5 +1,5 @@
/*
- * Copyright 2017 Sean Wang <sean.wang@mediatek.com>
+ * Copyright 2017-2018 Sean Wang <sean.wang@mediatek.com>
*
* SPDX-License-Identifier: (GPL-2.0+ OR MIT)
*/
@@ -109,10 +109,15 @@
};
memory@80000000 {
- reg = <0 0x80000000 0 0x40000000>;
+ device_type = "memory";
+ reg = <0 0x80000000 0 0x80000000>;
};
};
+&btif {
+ status = "okay";
+};
+
&cir {
pinctrl-names = "default";
pinctrl-0 = <&cir_pins_a>;
@@ -144,8 +149,6 @@
switch@0 {
compatible = "mediatek,mt7530";
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0>;
reset-gpios = <&pio 33 0>;
core-supply = <&mt6323_vpa_reg>;
@@ -154,7 +157,6 @@
ports {
#address-cells = <1>;
#size-cells = <0>;
- reg = <0>;
port@0 {
reg = <0>;
@@ -235,6 +237,28 @@
vqmmc-supply = <&reg_3p3v>;
};
+&mt6323_leds {
+ status = "okay";
+
+ led@0 {
+ reg = <0>;
+ label = "bpi-r2:isink:green";
+ default-state = "off";
+ };
+
+ led@1 {
+ reg = <1>;
+ label = "bpi-r2:isink:red";
+ default-state = "off";
+ };
+
+ led@2 {
+ reg = <2>;
+ label = "bpi-r2:isink:blue";
+ default-state = "off";
+ };
+};
+
&pcie {
pinctrl-names = "default";
pinctrl-0 = <&pcie_default>;
@@ -257,257 +281,12 @@
status = "okay";
};
-&pio {
- cir_pins_a:cir@0 {
- pins-cir {
- pinmux = <MT7623_PIN_46_IR_FUNC_IR>;
- bias-disable;
- };
- };
-
- i2c0_pins_a: i2c@0 {
- pins-i2c0 {
- pinmux = <MT7623_PIN_75_SDA0_FUNC_SDA0>,
- <MT7623_PIN_76_SCL0_FUNC_SCL0>;
- bias-disable;
- };
- };
-
- i2c1_pins_a: i2c@1 {
- pin-i2c1 {
- pinmux = <MT7623_PIN_57_SDA1_FUNC_SDA1>,
- <MT7623_PIN_58_SCL1_FUNC_SCL1>;
- bias-disable;
- };
- };
-
- i2s0_pins_a: i2s@0 {
- pin-i2s0 {
- pinmux = <MT7623_PIN_49_I2S0_DATA_FUNC_I2S0_DATA>,
- <MT7623_PIN_72_I2S0_DATA_IN_FUNC_I2S0_DATA_IN>,
- <MT7623_PIN_73_I2S0_LRCK_FUNC_I2S0_LRCK>,
- <MT7623_PIN_74_I2S0_BCK_FUNC_I2S0_BCK>,
- <MT7623_PIN_126_I2S0_MCLK_FUNC_I2S0_MCLK>;
- drive-strength = <MTK_DRIVE_12mA>;
- bias-pull-down;
- };
- };
-
- i2s1_pins_a: i2s@1 {
- pin-i2s1 {
- pinmux = <MT7623_PIN_33_I2S1_DATA_FUNC_I2S1_DATA>,
- <MT7623_PIN_34_I2S1_DATA_IN_FUNC_I2S1_DATA_IN>,
- <MT7623_PIN_35_I2S1_BCK_FUNC_I2S1_BCK>,
- <MT7623_PIN_36_I2S1_LRCK_FUNC_I2S1_LRCK>,
- <MT7623_PIN_37_I2S1_MCLK_FUNC_I2S1_MCLK>;
- drive-strength = <MTK_DRIVE_12mA>;
- bias-pull-down;
- };
- };
-
- key_pins_a: keys@0 {
- pins-keys {
- pinmux = <MT7623_PIN_256_GPIO256_FUNC_GPIO256>,
- <MT7623_PIN_257_GPIO257_FUNC_GPIO257> ;
- input-enable;
- };
- };
-
- led_pins_a: leds@0 {
- pins-leds {
- pinmux = <MT7623_PIN_239_EXT_SDIO0_FUNC_GPIO239>,
- <MT7623_PIN_240_EXT_XCS_FUNC_GPIO240>,
- <MT7623_PIN_241_EXT_SCK_FUNC_GPIO241>;
- };
- };
-
- mmc0_pins_default: mmc0default {
- pins-cmd-dat {
- pinmux = <MT7623_PIN_111_MSDC0_DAT7_FUNC_MSDC0_DAT7>,
- <MT7623_PIN_112_MSDC0_DAT6_FUNC_MSDC0_DAT6>,
- <MT7623_PIN_113_MSDC0_DAT5_FUNC_MSDC0_DAT5>,
- <MT7623_PIN_114_MSDC0_DAT4_FUNC_MSDC0_DAT4>,
- <MT7623_PIN_118_MSDC0_DAT3_FUNC_MSDC0_DAT3>,
- <MT7623_PIN_119_MSDC0_DAT2_FUNC_MSDC0_DAT2>,
- <MT7623_PIN_120_MSDC0_DAT1_FUNC_MSDC0_DAT1>,
- <MT7623_PIN_121_MSDC0_DAT0_FUNC_MSDC0_DAT0>,
- <MT7623_PIN_116_MSDC0_CMD_FUNC_MSDC0_CMD>;
- input-enable;
- bias-pull-up;
- };
-
- pins-clk {
- pinmux = <MT7623_PIN_117_MSDC0_CLK_FUNC_MSDC0_CLK>;
- bias-pull-down;
- };
-
- pins-rst {
- pinmux = <MT7623_PIN_115_MSDC0_RSTB_FUNC_MSDC0_RSTB>;
- bias-pull-up;
- };
- };
-
- mmc0_pins_uhs: mmc0 {
- pins-cmd-dat {
- pinmux = <MT7623_PIN_111_MSDC0_DAT7_FUNC_MSDC0_DAT7>,
- <MT7623_PIN_112_MSDC0_DAT6_FUNC_MSDC0_DAT6>,
- <MT7623_PIN_113_MSDC0_DAT5_FUNC_MSDC0_DAT5>,
- <MT7623_PIN_114_MSDC0_DAT4_FUNC_MSDC0_DAT4>,
- <MT7623_PIN_118_MSDC0_DAT3_FUNC_MSDC0_DAT3>,
- <MT7623_PIN_119_MSDC0_DAT2_FUNC_MSDC0_DAT2>,
- <MT7623_PIN_120_MSDC0_DAT1_FUNC_MSDC0_DAT1>,
- <MT7623_PIN_121_MSDC0_DAT0_FUNC_MSDC0_DAT0>,
- <MT7623_PIN_116_MSDC0_CMD_FUNC_MSDC0_CMD>;
- input-enable;
- drive-strength = <MTK_DRIVE_2mA>;
- bias-pull-up = <MTK_PUPD_SET_R1R0_01>;
- };
-
- pins-clk {
- pinmux = <MT7623_PIN_117_MSDC0_CLK_FUNC_MSDC0_CLK>;
- drive-strength = <MTK_DRIVE_2mA>;
- bias-pull-down = <MTK_PUPD_SET_R1R0_01>;
- };
-
- pins-rst {
- pinmux = <MT7623_PIN_115_MSDC0_RSTB_FUNC_MSDC0_RSTB>;
- bias-pull-up;
- };
- };
-
- mmc1_pins_default: mmc1default {
- pins-cmd-dat {
- pinmux = <MT7623_PIN_107_MSDC1_DAT0_FUNC_MSDC1_DAT0>,
- <MT7623_PIN_108_MSDC1_DAT1_FUNC_MSDC1_DAT1>,
- <MT7623_PIN_109_MSDC1_DAT2_FUNC_MSDC1_DAT2>,
- <MT7623_PIN_110_MSDC1_DAT3_FUNC_MSDC1_DAT3>,
- <MT7623_PIN_105_MSDC1_CMD_FUNC_MSDC1_CMD>;
- input-enable;
- drive-strength = <MTK_DRIVE_4mA>;
- bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
- };
-
- pins-clk {
- pinmux = <MT7623_PIN_106_MSDC1_CLK_FUNC_MSDC1_CLK>;
- bias-pull-down;
- drive-strength = <MTK_DRIVE_4mA>;
- };
-
- pins-wp {
- pinmux = <MT7623_PIN_29_EINT7_FUNC_MSDC1_WP>;
- input-enable;
- bias-pull-up;
- };
-
- pins-insert {
- pinmux = <MT7623_PIN_261_MSDC1_INS_FUNC_GPIO261>;
- bias-pull-up;
- };
- };
-
- mmc1_pins_uhs: mmc1 {
- pins-cmd-dat {
- pinmux = <MT7623_PIN_107_MSDC1_DAT0_FUNC_MSDC1_DAT0>,
- <MT7623_PIN_108_MSDC1_DAT1_FUNC_MSDC1_DAT1>,
- <MT7623_PIN_109_MSDC1_DAT2_FUNC_MSDC1_DAT2>,
- <MT7623_PIN_110_MSDC1_DAT3_FUNC_MSDC1_DAT3>,
- <MT7623_PIN_105_MSDC1_CMD_FUNC_MSDC1_CMD>;
- input-enable;
- drive-strength = <MTK_DRIVE_4mA>;
- bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
- };
-
- pins-clk {
- pinmux = <MT7623_PIN_106_MSDC1_CLK_FUNC_MSDC1_CLK>;
- drive-strength = <MTK_DRIVE_4mA>;
- bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
- };
- };
-
- pcie_default: pcie_pin_default {
- pins_cmd_dat {
- pinmux = <MT7623_PIN_208_AUD_EXT_CK1_FUNC_PCIE0_PERST_N>,
- <MT7623_PIN_209_AUD_EXT_CK2_FUNC_PCIE1_PERST_N>;
- bias-disable;
- };
- };
-
- pwm_pins_a: pwm@0 {
- pins-pwm {
- pinmux = <MT7623_PIN_203_PWM0_FUNC_PWM0>,
- <MT7623_PIN_204_PWM1_FUNC_PWM1>,
- <MT7623_PIN_205_PWM2_FUNC_PWM2>,
- <MT7623_PIN_206_PWM3_FUNC_PWM3>,
- <MT7623_PIN_207_PWM4_FUNC_PWM4>;
- };
- };
-
- spi0_pins_a: spi@0 {
- pins-spi {
- pinmux = <MT7623_PIN_53_SPI0_CSN_FUNC_SPI0_CS>,
- <MT7623_PIN_54_SPI0_CK_FUNC_SPI0_CK>,
- <MT7623_PIN_55_SPI0_MI_FUNC_SPI0_MI>,
- <MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MO>;
- bias-disable;
- };
- };
-
- uart0_pins_a: uart@0 {
- pins-dat {
- pinmux = <MT7623_PIN_79_URXD0_FUNC_URXD0>,
- <MT7623_PIN_80_UTXD0_FUNC_UTXD0>;
- };
- };
-
- uart1_pins_a: uart@1 {
- pins-dat {
- pinmux = <MT7623_PIN_81_URXD1_FUNC_URXD1>,
- <MT7623_PIN_82_UTXD1_FUNC_UTXD1>;
- };
- };
-
- uart2_pins_a: uart@2 {
- pins-dat {
- pinmux = <MT7623_PIN_14_GPIO14_FUNC_URXD2>,
- <MT7623_PIN_15_GPIO15_FUNC_UTXD2>;
- };
- };
-};
-
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm_pins_a>;
status = "okay";
};
-&pwrap {
- mt6323 {
- mt6323led: led {
- compatible = "mediatek,mt6323-led";
- #address-cells = <1>;
- #size-cells = <0>;
-
- led@0 {
- reg = <0>;
- label = "bpi-r2:isink:green";
- default-state = "off";
- };
-
- led@1 {
- reg = <1>;
- label = "bpi-r2:isink:red";
- default-state = "off";
- };
-
- led@2 {
- reg = <2>;
- label = "bpi-r2:isink:blue";
- default-state = "off";
- };
- };
- };
-};
-
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins_a>;
diff --git a/arch/arm/boot/dts/mt7623n-rfb-emmc.dts b/arch/arm/boot/dts/mt7623n-rfb-emmc.dts
new file mode 100644
index 0000000..b760613
--- /dev/null
+++ b/arch/arm/boot/dts/mt7623n-rfb-emmc.dts
@@ -0,0 +1,326 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017-2018 MediaTek Inc.
+ * Author: Sean Wang <sean.wang@mediatek.com>
+ *
+ */
+
+/dts-v1/;
+#include <dt-bindings/input/input.h>
+#include "mt7623.dtsi"
+#include "mt6323.dtsi"
+
+/ {
+ model = "MediaTek MT7623N with eMMC reference board";
+ compatible = "mediatek,mt7623n-rfb-emmc", "mediatek,mt7623";
+
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ serial2 = &uart2;
+ };
+
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ cpus {
+ cpu@0 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+
+ cpu@1 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+
+ cpu@2 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+
+ cpu@3 {
+ proc-supply = <&mt6323_vproc_reg>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&key_pins_a>;
+
+ factory {
+ label = "factory";
+ linux,code = <BTN_0>;
+ gpios = <&pio 256 GPIO_ACTIVE_LOW>;
+ };
+
+ wps {
+ label = "wps";
+ linux,code = <KEY_WPS_BUTTON>;
+ gpios = <&pio 257 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0 0x80000000 0 0x40000000>;
+ };
+
+ reg_1p8v: regulator-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_5v: regulator-5v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-5V";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ sound {
+ compatible = "mediatek,mt2701-wm8960-machine";
+ mediatek,platform = <&afe>;
+ audio-routing =
+ "Headphone", "HP_L",
+ "Headphone", "HP_R",
+ "LINPUT1", "AMIC",
+ "RINPUT1", "AMIC";
+ mediatek,audio-codec = <&wm8960>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s0_pins_a>;
+ };
+};
+
+&btif {
+ status = "okay";
+};
+
+&cir {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cir_pins_a>;
+ status = "okay";
+};
+
+&crypto {
+ status = "okay";
+};
+
+&eth {
+ status = "okay";
+
+ gmac0: mac@0 {
+ compatible = "mediatek,eth-mac";
+ reg = <0>;
+ phy-mode = "trgmii";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ pause;
+ };
+ };
+
+ mac@1 {
+ compatible = "mediatek,eth-mac";
+ reg = <1>;
+ phy-handle = <&phy5>;
+ };
+
+ mdio-bus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phy5: ethernet-phy@5 {
+ reg = <5>;
+ phy-mode = "rgmii-rxid";
+ };
+
+ switch@0 {
+ compatible = "mediatek,mt7530";
+ reg = <0>;
+ reset-gpios = <&pio 33 0>;
+ core-supply = <&mt6323_vpa_reg>;
+ io-supply = <&mt6323_vemc3v3_reg>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ label = "lan0";
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "lan1";
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "lan2";
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan3";
+ };
+
+ port@4 {
+ reg = <4>;
+ label = "wan";
+ };
+
+ port@6 {
+ reg = <6>;
+ label = "cpu";
+ ethernet = <&gmac0>;
+ phy-mode = "trgmii";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+ };
+ };
+ };
+};
+
+&i2c0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins_a>;
+ status = "okay";
+};
+
+&i2c1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins_b>;
+ status = "okay";
+
+ wm8960: wm8960@1a {
+ compatible = "wlf,wm8960";
+ reg = <0x1a>;
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins_a>;
+ status = "okay";
+};
+
+&mmc0 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_pins_default>;
+ pinctrl-1 = <&mmc0_pins_uhs>;
+ status = "okay";
+ bus-width = <8>;
+ max-frequency = <50000000>;
+ cap-mmc-highspeed;
+ vmmc-supply = <&reg_3p3v>;
+ vqmmc-supply = <&reg_1p8v>;
+ non-removable;
+};
+
+&mmc1 {
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc1_pins_default>;
+ pinctrl-1 = <&mmc1_pins_uhs>;
+ status = "okay";
+ bus-width = <4>;
+ max-frequency = <50000000>;
+ cap-sd-highspeed;
+ cd-gpios = <&pio 261 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&reg_3p3v>;
+ vqmmc-supply = <&reg_3p3v>;
+};
+
+&pcie {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_default>;
+ status = "okay";
+
+ pcie@0,0 {
+ status = "okay";
+ };
+
+ pcie@1,0 {
+ status = "okay";
+ };
+};
+
+&pcie0_phy {
+ status = "okay";
+};
+
+&pcie1_phy {
+ status = "okay";
+};
+
+&pwm {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pwm_pins_a>;
+ status = "okay";
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi0_pins_a>;
+ status = "okay";
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1_pins_a>;
+ status = "okay";
+};
+
+&spi2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi2_pins_a>;
+ status = "okay";
+};
+
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins_a>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_pins_a>;
+ status = "okay";
+};
+
+&usb1 {
+ vusb33-supply = <&reg_3p3v>;
+ vbus-supply = <&reg_5v>;
+ status = "okay";
+};
+
+&u3phy1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/mt7623n-rfb-nand.dts b/arch/arm/boot/dts/mt7623n-rfb-nand.dts
index f729c71..96ff3c9 100644
--- a/arch/arm/boot/dts/mt7623n-rfb-nand.dts
+++ b/arch/arm/boot/dts/mt7623n-rfb-nand.dts
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: John Crispin <john@phrozen.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.
*/
/dts-v1/;
@@ -78,34 +71,3 @@
};
};
};
-
-&pio {
- nand_pins_default: nanddefault {
- pins-ale {
- pinmux = <MT7623_PIN_116_MSDC0_CMD_FUNC_NALE>;
- drive-strength = <MTK_DRIVE_8mA>;
- bias-pull-down = <MTK_PUPD_SET_R1R0_10>;
- };
-
- pins-dat {
- pinmux = <MT7623_PIN_111_MSDC0_DAT7_FUNC_NLD7>,
- <MT7623_PIN_112_MSDC0_DAT6_FUNC_NLD6>,
- <MT7623_PIN_114_MSDC0_DAT4_FUNC_NLD4>,
- <MT7623_PIN_118_MSDC0_DAT3_FUNC_NLD3>,
- <MT7623_PIN_121_MSDC0_DAT0_FUNC_NLD0>,
- <MT7623_PIN_120_MSDC0_DAT1_FUNC_NLD1>,
- <MT7623_PIN_113_MSDC0_DAT5_FUNC_NLD5>,
- <MT7623_PIN_115_MSDC0_RSTB_FUNC_NLD8>,
- <MT7623_PIN_119_MSDC0_DAT2_FUNC_NLD2>;
- input-enable;
- drive-strength = <MTK_DRIVE_8mA>;
- bias-pull-up;
- };
-
- pins-we {
- pinmux = <MT7623_PIN_117_MSDC0_CLK_FUNC_NWEB>;
- drive-strength = <MTK_DRIVE_8mA>;
- bias-pull-up = <MTK_PUPD_SET_R1R0_10>;
- };
- };
-};
diff --git a/arch/arm/boot/dts/mt7623n-rfb.dtsi b/arch/arm/boot/dts/mt7623n-rfb.dtsi
index 256c5fd..5c5cc7d 100644
--- a/arch/arm/boot/dts/mt7623n-rfb.dtsi
+++ b/arch/arm/boot/dts/mt7623n-rfb.dtsi
@@ -1,16 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2017 MediaTek Inc.
* Author: John Crispin <john@phrozen.org>
* Sean Wang <sean.wang@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.
*/
/dts-v1/;
@@ -47,10 +40,11 @@
};
memory@80000000 {
+ device_type = "memory";
reg = <0 0x80000000 0 0x40000000>;
};
- usb_p1_vbus: regulator@0 {
+ usb_p1_vbus: regulator-5v {
compatible = "regulator-fixed";
regulator-name = "usb_vbus";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm/boot/dts/mt8127-moose.dts b/arch/arm/boot/dts/mt8127-moose.dts
index 073e295..308829b 100644
--- a/arch/arm/boot/dts/mt8127-moose.dts
+++ b/arch/arm/boot/dts/mt8127-moose.dts
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 MediaTek Inc.
* Author: Joe.C <yingjoe.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.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/mt8127.dtsi b/arch/arm/boot/dts/mt8127.dtsi
index 916c095..3adfc6f 100644
--- a/arch/arm/boot/dts/mt8127.dtsi
+++ b/arch/arm/boot/dts/mt8127.dtsi
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 MediaTek Inc.
* Author: Joe.C <yingjoe.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 <dt-bindings/interrupt-controller/irq.h>
diff --git a/arch/arm/boot/dts/mt8135-evbp1.dts b/arch/arm/boot/dts/mt8135-evbp1.dts
index 460db6d..0ace7a4 100644
--- a/arch/arm/boot/dts/mt8135-evbp1.dts
+++ b/arch/arm/boot/dts/mt8135-evbp1.dts
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 MediaTek Inc.
* Author: Joe.C <yingjoe.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.
*/
/dts-v1/;
diff --git a/arch/arm/boot/dts/mt8135.dtsi b/arch/arm/boot/dts/mt8135.dtsi
index a97b4ee..688069d 100644
--- a/arch/arm/boot/dts/mt8135.dtsi
+++ b/arch/arm/boot/dts/mt8135.dtsi
@@ -1,15 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 MediaTek Inc.
* Author: Joe.C <yingjoe.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 <dt-bindings/clock/mt8135-clk.h>
diff --git a/arch/arm/boot/dts/omap2420-n810.dts b/arch/arm/boot/dts/omap2420-n810.dts
index 7c485fb..96b9913 100644
--- a/arch/arm/boot/dts/omap2420-n810.dts
+++ b/arch/arm/boot/dts/omap2420-n810.dts
@@ -6,11 +6,70 @@
/ {
model = "Nokia N810";
compatible = "nokia,n810", "nokia,n8x0", "ti,omap2420", "ti,omap2";
+
+ vio_ape: vio_ape {
+ compatible = "regulator-fixed";
+ regulator-name = "vio_ape";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ v28_aic: v28_aic {
+ compatible = "regulator-fixed";
+ regulator-name = "v28_aic";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+};
+
+&omap2420_pmx {
+ mcbsp2_pins: mcbsp2_pins {
+ pinctrl-single,pins = <
+ OMAP2420_CORE_IOPAD(0x0124, PIN_INPUT | MUX_MODE1) /* eac_ac_sclk.mcbsp2_clkx */
+ OMAP2420_CORE_IOPAD(0x0125, PIN_INPUT | MUX_MODE1) /* eac_ac_fs.mcbsp2_fsx */
+ OMAP2420_CORE_IOPAD(0x0126, PIN_INPUT | MUX_MODE1) /* eac_ac_din.mcbsp2_dr */
+ OMAP2420_CORE_IOPAD(0x0127, PIN_OUTPUT | MUX_MODE1) /* eac_ac_dout.mcbsp2_dx */
+ >;
+ };
+
+ aic33_pins: aic33_pins {
+ pinctrl-single,pins = <
+ OMAP2420_CORE_IOPAD(0x0129, PIN_OUTPUT | MUX_MODE3) /* eac_ac_rst.gpio118 */
+ OMAP2420_CORE_IOPAD(0x00e8, PIN_OUTPUT | MUX_MODE2) /* vlynq_tx1.sys_clkout2 */
+ >;
+ };
};
&i2c2 {
- aic3x@18 {
- compatible = "tlv320aic3x";
+ aic33@18 {
+ compatible = "ti,tlv320aic33";
reg = <0x18>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&aic33_pins>;
+
+ gpio-reset = <&gpio4 22 GPIO_ACTIVE_LOW>; /* gpio118 */
+
+ ai3x-gpio-func = <
+ 10 /* AIC3X_GPIO1_FUNC_DIGITAL_MIC_MODCLK */
+ 5 /* AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT */
+ >;
+ ai3x-micbias-vg = <1>; /* 2V */
+
+ AVDD-supply = <&v28_aic>;
+ DRVDD-supply = <&v28_aic>;
+ IOVDD-supply = <&vio_ape>;
+ DVDD-supply = <&vio_ape>;
+
+ assigned-clocks = <&sys_clkout2_src>, <&sys_clkout2>;
+ assigned-clock-parents = <&func_96m_ck>;
+ assigned-clock-rates = <0>, <12000000>;
};
};
+
+&mcbsp2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcbsp2_pins>;
+
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts
index 0349fcc..d80587d 100644
--- a/arch/arm/boot/dts/omap3-beagle-xm.dts
+++ b/arch/arm/boot/dts/omap3-beagle-xm.dts
@@ -30,6 +30,13 @@
ethernet = &ethernet;
};
+ /* fixed 26MHz oscillator */
+ hfclk_26m: oscillator {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <26000000>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -274,6 +281,9 @@
interrupts = <7>; /* SYS_NIRQ cascaded to intc */
interrupt-parent = <&intc>;
+ clocks = <&hfclk_26m>;
+ clock-names = "fck";
+
twl_audio: audio {
compatible = "ti,twl4030-audio";
codec {
diff --git a/arch/arm/boot/dts/omap3-cm-t3x.dtsi b/arch/arm/boot/dts/omap3-cm-t3x.dtsi
index 9dcb18d..cdb632d 100644
--- a/arch/arm/boot/dts/omap3-cm-t3x.dtsi
+++ b/arch/arm/boot/dts/omap3-cm-t3x.dtsi
@@ -60,7 +60,7 @@
regulator-max-microvolt = <3300000>;
};
- tv0: connector {
+ tv0: svideo-connector {
compatible = "svideo-connector";
label = "tv";
diff --git a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
index 0c0bb1b..746a658 100644
--- a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
+++ b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
@@ -349,10 +349,17 @@
vdda_dac-supply = <&vdac>;
port {
- dpi_dvi_out: endpoint {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dpi_dvi_out: endpoint@0 {
+ reg = <0>;
remote-endpoint = <&tfp410_in>;
data-lines = <24>;
};
+
+ endpoint@1 {
+ reg = <1>;
+ };
};
};
diff --git a/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
index 2d64bcf..1093387 100644
--- a/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
+++ b/arch/arm/boot/dts/omap3-devkit8000-lcd-common.dtsi
@@ -30,7 +30,10 @@
&dss {
port {
- dpi_lcd_out: endpoint {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dpi_lcd_out: endpoint@1 {
+ reg = <1>;
remote-endpoint = <&lcd_in>;
data-lines = <24>;
};
diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index 4170be7..ac830b9 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -30,6 +30,13 @@
display0 = &lcd;
};
+ /* fixed 26MHz oscillator */
+ hfclk_26m: oscillator {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <26000000>;
+ };
+
gpio-keys {
compatible = "gpio-keys";
@@ -312,6 +319,9 @@
interrupts = <7>; /* SYS_NIRQ cascaded to intc */
interrupt-parent = <&intc>;
+ clocks = <&hfclk_26m>;
+ clock-names = "fck";
+
twl_audio: audio {
compatible = "ti,twl4030-audio";
ti,enable-vibra = <1>;
diff --git a/arch/arm/boot/dts/omap3-pandora-common.dtsi b/arch/arm/boot/dts/omap3-pandora-common.dtsi
index f83b102..90c98f9 100644
--- a/arch/arm/boot/dts/omap3-pandora-common.dtsi
+++ b/arch/arm/boot/dts/omap3-pandora-common.dtsi
@@ -27,6 +27,13 @@
display0 = &lcd;
};
+ /* fixed 26MHz oscillator */
+ hfclk_26m: oscillator {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ clock-frequency = <26000000>;
+ };
+
tv: connector {
compatible = "connector-analog-tv";
label = "tv";
@@ -357,6 +364,9 @@
interrupts = <7>; /* SYS_NIRQ cascaded to intc */
interrupt-parent = <&intc>;
+ clocks = <&hfclk_26m>;
+ clock-names = "fck";
+
twl_power: power {
compatible = "ti,twl4030-power-reset";
ti,use_poweroff;
@@ -611,7 +621,7 @@
pinctrl-names = "default";
pinctrl-0 = <&penirq_pins>;
interrupt-parent = <&gpio3>;
- interrupts = <30 0>; /* GPIO_94 */
+ interrupts = <30 IRQ_TYPE_NONE>; /* GPIO_94 */
pendown-gpio = <&gpio3 30 GPIO_ACTIVE_HIGH>;
vcc-supply = <&vaux4>;
diff --git a/arch/arm/boot/dts/omap3-sb-t35.dtsi b/arch/arm/boot/dts/omap3-sb-t35.dtsi
index 22b4c8b..fb9842f 100644
--- a/arch/arm/boot/dts/omap3-sb-t35.dtsi
+++ b/arch/arm/boot/dts/omap3-sb-t35.dtsi
@@ -34,7 +34,7 @@
};
};
- dvi0: connector {
+ dvi0: dvi-connector {
compatible = "dvi-connector";
label = "dvi";
diff --git a/arch/arm/boot/dts/pxa3xx.dtsi b/arch/arm/boot/dts/pxa3xx.dtsi
index 982d1a6..132a3b8 100644
--- a/arch/arm/boot/dts/pxa3xx.dtsi
+++ b/arch/arm/boot/dts/pxa3xx.dtsi
@@ -8,6 +8,10 @@
(gpio <= 98) ? (0x0400 + 4 * (gpio - 27)) : \
(gpio <= 127) ? (0x0600 + 4 * (gpio - 99)) : \
0)
+#define MFP_PIN_PXA300_2(gpio) \
+ ((gpio <= 1) ? (0x674 + 4 * gpio) : \
+ (gpio <= 6) ? (0x2dc + 4 * gpio) : \
+ 0)
#define MFP_PIN_PXA310(gpio) \
((gpio <= 2) ? (0x00b4 + 4 * gpio) : \
@@ -18,6 +22,11 @@
(gpio <= 262) ? 0 : \
(gpio <= 268) ? (0x052c + 4 * (gpio - 263)) : \
0)
+#define MFP_PIN_PXA310_2(gpio) \
+ ((gpio <= 1) ? (0x674 + 4 * gpio) : \
+ (gpio <= 6) ? (0x2dc + 4 * gpio) : \
+ (gpio <= 10) ? (0x52c + 4 * gpio) : \
+ 0)
#define MFP_PIN_PXA320(gpio) \
((gpio <= 4) ? (0x0124 + 4 * gpio) : \
@@ -30,6 +39,10 @@
(gpio <= 98) ? (0x04f0 + 4 * (gpio - 74)) : \
(gpio <= 127) ? (0x0600 + 4 * (gpio - 99)) : \
0)
+#define MFP_PIN_PXA320_2(gpio) \
+ ((gpio <= 3) ? (0x674 + 4 * gpio) : \
+ (gpio <= 5) ? (0x284 + 4 * gpio) : \
+ 0)
/*
* MFP Alternate functions for pins having a gpio.
@@ -148,6 +161,7 @@
compatible = "intel,pxa3xx-gpio";
reg = <0x40e00000 0x10000>;
clocks = <&clks CLK_GPIO>;
+ gpio-ranges = <&pinctrl 0 0 128>;
interrupt-names = "gpio0", "gpio1", "gpio_mux";
interrupts = <8 9 10>;
gpio-controller;
@@ -160,7 +174,7 @@
compatible = "marvell,pxa-mmc";
reg = <0x41100000 0x1000>;
interrupts = <23>;
- clocks = <&clks CLK_MMC>;
+ clocks = <&clks CLK_MMC1>;
dmas = <&pdma 21 3
&pdma 22 3>;
dma-names = "rx", "tx";
@@ -171,7 +185,7 @@
compatible = "marvell,pxa-mmc";
reg = <0x42000000 0x1000>;
interrupts = <41>;
- clocks = <&clks CLK_MMC1>;
+ clocks = <&clks CLK_MMC2>;
dmas = <&pdma 93 3
&pdma 94 3>;
dma-names = "rx", "tx";
@@ -182,7 +196,7 @@
compatible = "marvell,pxa-mmc";
reg = <0x42500000 0x1000>;
interrupts = <55>;
- clocks = <&clks CLK_MMC2>;
+ clocks = <&clks CLK_MMC3>;
dmas = <&pdma 46 3
&pdma 47 3>;
dma-names = "rx", "tx";
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 5341a39..4a99c92 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -444,7 +444,7 @@
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
reg = <0x12450000 0x100>,
<0x12400000 0x03>;
- interrupts = <0 193 0x0>;
+ interrupts = <0 193 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GSBI1_UART_CLK>, <&gcc GSBI1_H_CLK>;
clock-names = "core", "iface";
status = "disabled";
@@ -456,11 +456,12 @@
pinctrl-1 = <&i2c1_pins_sleep>;
pinctrl-names = "default", "sleep";
reg = <0x12460000 0x1000>;
- interrupts = <0 194 IRQ_TYPE_NONE>;
+ interrupts = <0 194 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GSBI1_QUP_CLK>, <&gcc GSBI1_H_CLK>;
clock-names = "core", "iface";
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
};
};
@@ -484,11 +485,12 @@
pinctrl-0 = <&i2c2_pins>;
pinctrl-1 = <&i2c2_pins_sleep>;
pinctrl-names = "default", "sleep";
- interrupts = <0 196 IRQ_TYPE_NONE>;
+ interrupts = <0 196 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GSBI2_QUP_CLK>, <&gcc GSBI2_H_CLK>;
clock-names = "core", "iface";
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
};
};
@@ -508,12 +510,13 @@
pinctrl-1 = <&i2c3_pins_sleep>;
pinctrl-names = "default", "sleep";
reg = <0x16280000 0x1000>;
- interrupts = <GIC_SPI 151 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GSBI3_QUP_CLK>,
<&gcc GSBI3_H_CLK>;
clock-names = "core", "iface";
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
};
};
@@ -534,10 +537,11 @@
pinctrl-1 = <&i2c4_pins_sleep>;
pinctrl-names = "default", "sleep";
reg = <0x16380000 0x1000>;
- interrupts = <GIC_SPI 153 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GSBI4_QUP_CLK>,
<&gcc GSBI4_H_CLK>;
clock-names = "core", "iface";
+ status = "disabled";
};
};
@@ -556,7 +560,7 @@
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
reg = <0x1a240000 0x100>,
<0x1a200000 0x03>;
- interrupts = <0 154 0x0>;
+ interrupts = <0 154 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GSBI5_UART_CLK>, <&gcc GSBI5_H_CLK>;
clock-names = "core", "iface";
status = "disabled";
@@ -565,7 +569,7 @@
gsbi5_spi: spi@1a280000 {
compatible = "qcom,spi-qup-v1.1.1";
reg = <0x1a280000 0x1000>;
- interrupts = <0 155 0>;
+ interrupts = <0 155 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-0 = <&spi5_default>;
pinctrl-1 = <&spi5_sleep>;
pinctrl-names = "default", "sleep";
@@ -592,7 +596,7 @@
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
reg = <0x16540000 0x100>,
<0x16500000 0x03>;
- interrupts = <0 156 0x0>;
+ interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GSBI6_UART_CLK>, <&gcc GSBI6_H_CLK>;
clock-names = "core", "iface";
status = "disabled";
@@ -604,7 +608,7 @@
pinctrl-1 = <&i2c6_pins_sleep>;
pinctrl-names = "default", "sleep";
reg = <0x16580000 0x1000>;
- interrupts = <GIC_SPI 157 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GSBI6_QUP_CLK>,
<&gcc GSBI6_H_CLK>;
clock-names = "core", "iface";
@@ -628,7 +632,7 @@
compatible = "qcom,msm-uartdm-v1.3", "qcom,msm-uartdm";
reg = <0x16640000 0x1000>,
<0x16600000 0x1000>;
- interrupts = <0 158 0x0>;
+ interrupts = <0 158 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GSBI7_UART_CLK>, <&gcc GSBI7_H_CLK>;
clock-names = "core", "iface";
status = "disabled";
@@ -640,7 +644,7 @@
pinctrl-1 = <&i2c7_pins_sleep>;
pinctrl-names = "default", "sleep";
reg = <0x16680000 0x1000>;
- interrupts = <GIC_SPI 159 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GSBI7_QUP_CLK>,
<&gcc GSBI7_H_CLK>;
clock-names = "core", "iface";
@@ -1056,7 +1060,7 @@
compatible = "qcom,apq8064-ahci", "generic-ahci";
status = "disabled";
reg = <0x29000000 0x180>;
- interrupts = <GIC_SPI 209 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc SFAB_SATA_S_H_CLK>,
<&gcc SATA_H_CLK>,
@@ -1082,7 +1086,7 @@
sdcc1bam:dma@12402000{
compatible = "qcom,bam-v1.3.0";
reg = <0x12402000 0x8000>;
- interrupts = <0 98 0>;
+ interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc SDC1_H_CLK>;
clock-names = "bam_clk";
#dma-cells = <1>;
@@ -1092,7 +1096,7 @@
sdcc3bam:dma@12182000{
compatible = "qcom,bam-v1.3.0";
reg = <0x12182000 0x8000>;
- interrupts = <0 96 0>;
+ interrupts = <0 96 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc SDC3_H_CLK>;
clock-names = "bam_clk";
#dma-cells = <1>;
@@ -1102,7 +1106,7 @@
sdcc4bam:dma@121c2000{
compatible = "qcom,bam-v1.3.0";
reg = <0x121c2000 0x8000>;
- interrupts = <0 95 0>;
+ interrupts = <0 95 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc SDC4_H_CLK>;
clock-names = "bam_clk";
#dma-cells = <1>;
@@ -1181,7 +1185,7 @@
compatible = "qcom,adreno-3xx";
reg = <0x04300000 0x20000>;
reg-names = "kgsl_3d0_reg_memory";
- interrupts = <GIC_SPI 80 0>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "kgsl_3d0_irq";
clock-names =
"core_clk",
@@ -1281,7 +1285,7 @@
label = "MDSS DSI CTRL->0";
#address-cells = <1>;
#size-cells = <0>;
- interrupts = <GIC_SPI 82 0>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
reg = <0x04700000 0x200>;
reg-names = "dsi_ctrl";
@@ -1350,8 +1354,8 @@
<&mmcc MDP_AXI_CLK>;
reg = <0x07500000 0x100000>;
interrupts =
- <GIC_SPI 63 0>,
- <GIC_SPI 64 0>;
+ <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
qcom,ncb = <2>;
};
@@ -1366,8 +1370,8 @@
<&mmcc MDP_AXI_CLK>;
reg = <0x07600000 0x100000>;
interrupts =
- <GIC_SPI 61 0>,
- <GIC_SPI 62 0>;
+ <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
qcom,ncb = <2>;
};
@@ -1382,8 +1386,8 @@
<&mmcc GFX3D_AXI_CLK>;
reg = <0x07c00000 0x100000>;
interrupts =
- <GIC_SPI 69 0>,
- <GIC_SPI 70 0>;
+ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
qcom,ncb = <3>;
};
@@ -1398,8 +1402,8 @@
<&mmcc GFX3D_AXI_CLK>;
reg = <0x07d00000 0x100000>;
interrupts =
- <GIC_SPI 210 0>,
- <GIC_SPI 211 0>;
+ <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>;
qcom,ncb = <3>;
};
@@ -1417,8 +1421,8 @@
#address-cells = <3>;
#size-cells = <2>;
ranges = <0x81000000 0 0 0x0fe00000 0 0x00100000 /* I/O */
- 0x82000000 0 0 0x08000000 0 0x07e00000>; /* memory */
- interrupts = <GIC_SPI 238 IRQ_TYPE_NONE>;
+ 0x82000000 0 0x08000000 0x08000000 0 0x07e00000>; /* memory */
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi
index e413b21e..418f9a0 100644
--- a/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk01.1.dtsi
@@ -20,6 +20,14 @@
model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK01.1";
compatible = "qcom,ipq4019";
+ aliases {
+ serial0 = &blsp1_uart1;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
soc {
rng@22000 {
status = "ok";
@@ -61,7 +69,7 @@
status = "ok";
};
- spi_0: spi@78b5000 {
+ spi@78b5000 {
pinctrl-0 = <&spi_0_pins>;
pinctrl-names = "default";
status = "ok";
diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts
new file mode 100644
index 0000000..7a96f30
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c1.dts
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include "qcom-ipq4019-ap.dk04.1.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK04.1-C1";
+ compatible = "qcom,ipq4019-dk04.1-c1";
+
+ soc {
+ dma@7984000 {
+ status = "ok";
+ };
+
+ qpic-nand@79b0000 {
+ status = "ok";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c3.dts b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c3.dts
new file mode 100644
index 0000000..2d1c4c6
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1-c3.dts
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include "qcom-ipq4019-ap.dk04.1.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK04.1-C3";
+ compatible = "qcom,ipq4019-ap-dk04.1-c3";
+};
diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi
new file mode 100644
index 0000000..7c1eb19
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk04.1.dtsi
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include "qcom-ipq4019.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK04.1";
+
+ aliases {
+ serial0 = &blsp1_uart1;
+ serial1 = &blsp1_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x10000000>; /* 256MB */
+ };
+
+ soc {
+ pinctrl@1000000 {
+ serial_0_pins: serial0-pinmux {
+ pins = "gpio16", "gpio17";
+ function = "blsp_uart0";
+ bias-disable;
+ };
+
+ serial_1_pins: serial1-pinmux {
+ pins = "gpio8", "gpio9",
+ "gpio10", "gpio11";
+ function = "blsp_uart1";
+ bias-disable;
+ };
+
+ spi_0_pins: spi-0-pinmux {
+ pinmux {
+ function = "blsp_spi0";
+ pins = "gpio13", "gpio14", "gpio15";
+ bias-disable;
+ };
+ pinmux_cs {
+ function = "gpio";
+ pins = "gpio12";
+ bias-disable;
+ output-high;
+ };
+ };
+
+ i2c_0_pins: i2c-0-pinmux {
+ pins = "gpio20", "gpio21";
+ function = "blsp_i2c0";
+ bias-disable;
+ };
+
+ nand_pins: nand-pins {
+ pins = "gpio53", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59",
+ "gpio60", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66",
+ "gpio67", "gpio68", "gpio69";
+ function = "qpic";
+ };
+ };
+
+ serial@78af000 {
+ pinctrl-0 = <&serial_0_pins>;
+ pinctrl-names = "default";
+ status = "ok";
+ };
+
+ serial@78b0000 {
+ pinctrl-0 = <&serial_1_pins>;
+ pinctrl-names = "default";
+ status = "ok";
+ };
+
+ dma@7884000 {
+ status = "ok";
+ };
+
+ spi@78b5000 { /* BLSP1 QUP1 */
+ pinctrl-0 = <&spi_0_pins>;
+ pinctrl-names = "default";
+ status = "ok";
+ cs-gpios = <&tlmm 12 0>;
+
+ m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0>;
+ compatible = "n25q128a11";
+ spi-max-frequency = <24000000>;
+ };
+ };
+
+ pci@40000000 {
+ status = "ok";
+ perst-gpio = <&tlmm 38 0x1>;
+ };
+
+ qpic-nand@79b0000 {
+ pinctrl-0 = <&nand_pins>;
+ pinctrl-names = "default";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c1.dts b/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c1.dts
new file mode 100644
index 0000000..8c7ef65
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c1.dts
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include "qcom-ipq4019-ap.dk07.1.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK07.1-C1";
+ compatible = "qcom,ipq4019-ap-dk07.1-c1";
+
+ soc {
+ pci@40000000 {
+ status = "ok";
+ perst-gpio = <&tlmm 38 0x1>;
+ };
+
+ spi@78b6000 {
+ status = "ok";
+ };
+
+ pinctrl@1000000 {
+ serial_1_pins: serial1-pinmux {
+ pins = "gpio8", "gpio9",
+ "gpio10", "gpio11";
+ function = "blsp_uart1";
+ bias-disable;
+ };
+
+ spi_0_pins: spi-0-pinmux {
+ pinmux {
+ function = "blsp_spi0";
+ pins = "gpio13", "gpio14", "gpio15";
+ bias-disable;
+ };
+ pinmux_cs {
+ function = "gpio";
+ pins = "gpio12";
+ bias-disable;
+ output-high;
+ };
+ };
+ };
+
+ serial@78b0000 {
+ pinctrl-0 = <&serial_1_pins>;
+ pinctrl-names = "default";
+ status = "ok";
+ };
+
+ spi@78b5000 {
+ pinctrl-0 = <&spi_0_pins>;
+ pinctrl-names = "default";
+ status = "ok";
+ cs-gpios = <&tlmm 12 0>;
+
+ m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0>;
+ compatible = "n25q128a11";
+ spi-max-frequency = <24000000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c2.dts b/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c2.dts
new file mode 100644
index 0000000..af7a902
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1-c2.dts
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include "qcom-ipq4019-ap.dk07.1.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK07.1-C2";
+ compatible = "qcom,ipq4019-ap-dk07.1-c2";
+
+ soc {
+ pinctrl@1000000 {
+ serial_1_pins: serial1-pinmux {
+ pins = "gpio8", "gpio9";
+ function = "blsp_uart1";
+ bias-disable;
+ };
+ };
+
+ serial@78b0000 {
+ pinctrl-0 = <&serial_1_pins>;
+ pinctrl-names = "default";
+ status = "ok";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi b/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi
new file mode 100644
index 0000000..9f1a5a66
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-ipq4019-ap.dk07.1.dtsi
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018, The Linux Foundation. All rights reserved.
+
+#include "qcom-ipq4019.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "Qualcomm Technologies, Inc. IPQ4019/AP-DK07.1";
+
+ memory {
+ device_type = "memory";
+ reg = <0x80000000 0x20000000>; /* 512MB */
+ };
+
+ aliases {
+ serial0 = &blsp1_uart1;
+ serial1 = &blsp1_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ soc {
+ pinctrl@1000000 {
+ serial_0_pins: serial0-pinmux {
+ pins = "gpio16", "gpio17";
+ function = "blsp_uart0";
+ bias-disable;
+ };
+
+ i2c_0_pins: i2c-0-pinmux {
+ pins = "gpio20", "gpio21";
+ function = "blsp_i2c0";
+ bias-disable;
+ };
+
+ nand_pins: nand-pins {
+ pins = "gpio53", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59",
+ "gpio60", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66",
+ "gpio67", "gpio68", "gpio69";
+ function = "qpic";
+ };
+ };
+
+ serial@78af000 {
+ pinctrl-0 = <&serial_0_pins>;
+ pinctrl-names = "default";
+ status = "ok";
+ };
+
+ dma@7884000 {
+ status = "ok";
+ };
+
+ i2c@78b7000 { /* BLSP1 QUP2 */
+ pinctrl-0 = <&i2c_0_pins>;
+ pinctrl-names = "default";
+ status = "ok";
+ };
+
+ dma@7984000 {
+ status = "ok";
+ };
+
+ qpic-nand@79b0000 {
+ pinctrl-0 = <&nand_pins>;
+ pinctrl-names = "default";
+ status = "ok";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi
index 10d112a..7bcd763 100644
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
@@ -23,9 +23,27 @@
compatible = "qcom,ipq4019";
interrupt-parent = <&intc>;
+ reserved-memory {
+ #address-cells = <0x1>;
+ #size-cells = <0x1>;
+ ranges;
+
+ smem_region: smem@87e00000 {
+ reg = <0x87e00000 0x080000>;
+ no-map;
+ };
+
+ tz@87e80000 {
+ reg = <0x87e80000 0x180000>;
+ no-map;
+ };
+ };
+
aliases {
- spi0 = &spi_0;
- i2c0 = &i2c_0;
+ spi0 = &blsp1_spi1;
+ spi1 = &blsp1_spi2;
+ i2c0 = &blsp1_i2c3;
+ i2c1 = &blsp1_i2c4;
};
cpus {
@@ -45,7 +63,7 @@
48000 1100000
200000 1100000
500000 1100000
- 666000 1100000
+ 716000 1100000
>;
clock-latency = <256000>;
};
@@ -104,6 +122,12 @@
};
};
+ firmware {
+ scm {
+ compatible = "qcom,scm-ipq4019";
+ };
+ };
+
timer {
compatible = "arm,armv7-timer";
interrupts = <1 2 0xf08>,
@@ -149,13 +173,13 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
- interrupts = <0 208 0>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
};
blsp_dma: dma@7884000 {
compatible = "qcom,bam-v1.7.0";
reg = <0x07884000 0x23000>;
- interrupts = <GIC_SPI 238 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_BLSP1_AHB_CLK>;
clock-names = "bam_clk";
#dma-cells = <1>;
@@ -163,7 +187,7 @@
status = "disabled";
};
- spi_0: spi@78b5000 {
+ blsp1_spi1: spi@78b5000 { /* BLSP1 QUP1 */
compatible = "qcom,spi-qup-v2.2.1";
reg = <0x78b5000 0x600>;
interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
@@ -172,10 +196,26 @@
clock-names = "core", "iface";
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&blsp_dma 5>, <&blsp_dma 4>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ blsp1_spi2: spi@78b6000 { /* BLSP1 QUP2 */
+ compatible = "qcom,spi-qup-v2.2.1";
+ reg = <0x78b6000 0x600>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_QUP2_SPI_APPS_CLK>,
+ <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dmas = <&blsp_dma 7>, <&blsp_dma 6>;
+ dma-names = "rx", "tx";
status = "disabled";
};
- i2c_0: i2c@78b7000 {
+ blsp1_i2c3: i2c@78b7000 { /* BLSP1 QUP3 */
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x78b7000 0x600>;
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
@@ -184,14 +224,29 @@
clock-names = "iface", "core";
#address-cells = <1>;
#size-cells = <0>;
+ dmas = <&blsp_dma 9>, <&blsp_dma 8>;
+ dma-names = "rx", "tx";
status = "disabled";
};
+ blsp1_i2c4: i2c@78b8000 { /* BLSP1 QUP4 */
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x78b8000 0x600>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>,
+ <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>;
+ clock-names = "iface", "core";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ dmas = <&blsp_dma 11>, <&blsp_dma 10>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
cryptobam: dma@8e04000 {
compatible = "qcom,bam-v1.7.0";
reg = <0x08e04000 0x20000>;
- interrupts = <GIC_SPI 207 0>;
+ interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_CRYPTO_AHB_CLK>;
clock-names = "bam_clk";
#dma-cells = <1>;
@@ -256,10 +311,10 @@
regulator;
};
- serial@78af000 {
+ blsp1_uart1: serial@78af000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0x78af000 0x200>;
- interrupts = <0 107 0>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>,
<&gcc GCC_BLSP1_AHB_CLK>;
@@ -268,10 +323,10 @@
dma-names = "rx", "tx";
};
- serial@78b0000 {
+ blsp1_uart2: serial@78b0000 {
compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
reg = <0x78b0000 0x200>;
- interrupts = <0 108 0>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>,
<&gcc GCC_BLSP1_AHB_CLK>;
@@ -293,6 +348,101 @@
reg = <0x4ab000 0x4>;
};
+ pcie0: pci@40000000 {
+ compatible = "qcom,pcie-ipq4019", "snps,dw-pcie";
+ reg = <0x40000000 0xf1d
+ 0x40000f20 0xa8
+ 0x80000 0x2000
+ 0x40100000 0x1000>;
+ reg-names = "dbi", "elbi", "parf", "config";
+ device_type = "pci";
+ linux,pci-domain = <0>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ ranges = <0x81000000 0 0x40200000 0x40200000 0 0x00100000
+ 0x82000000 0 0x48000000 0x48000000 0 0x10000000>;
+
+ interrupts = <GIC_SPI 141 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 142 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+ <0 0 0 2 &intc 0 143 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+ <0 0 0 3 &intc 0 144 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+ <0 0 0 4 &intc 0 145 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+ clocks = <&gcc GCC_PCIE_AHB_CLK>,
+ <&gcc GCC_PCIE_AXI_M_CLK>,
+ <&gcc GCC_PCIE_AXI_S_CLK>;
+ clock-names = "aux",
+ "master_bus",
+ "slave_bus";
+
+ resets = <&gcc PCIE_AXI_M_ARES>,
+ <&gcc PCIE_AXI_S_ARES>,
+ <&gcc PCIE_PIPE_ARES>,
+ <&gcc PCIE_AXI_M_VMIDMT_ARES>,
+ <&gcc PCIE_AXI_S_XPU_ARES>,
+ <&gcc PCIE_PARF_XPU_ARES>,
+ <&gcc PCIE_PHY_ARES>,
+ <&gcc PCIE_AXI_M_STICKY_ARES>,
+ <&gcc PCIE_PIPE_STICKY_ARES>,
+ <&gcc PCIE_PWR_ARES>,
+ <&gcc PCIE_AHB_ARES>,
+ <&gcc PCIE_PHY_AHB_ARES>;
+ reset-names = "axi_m",
+ "axi_s",
+ "pipe",
+ "axi_m_vmid",
+ "axi_s_xpu",
+ "parf",
+ "phy",
+ "axi_m_sticky",
+ "pipe_sticky",
+ "pwr",
+ "ahb",
+ "phy_ahb";
+
+ status = "disabled";
+ };
+
+ qpic_bam: dma@7984000 {
+ compatible = "qcom,bam-v1.7.0";
+ reg = <0x7984000 0x1a000>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QPIC_CLK>;
+ clock-names = "bam_clk";
+ #dma-cells = <1>;
+ qcom,ee = <0>;
+ status = "disabled";
+ };
+
+ nand: qpic-nand@79b0000 {
+ compatible = "qcom,ipq4019-nand";
+ reg = <0x79b0000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&gcc GCC_QPIC_CLK>,
+ <&gcc GCC_QPIC_AHB_CLK>;
+ clock-names = "core", "aon";
+
+ dmas = <&qpic_bam 0>,
+ <&qpic_bam 1>,
+ <&qpic_bam 2>;
+ dma-names = "tx", "rx", "cmd";
+ status = "disabled";
+
+ nand@0 {
+ reg = <0>;
+
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+ nand-bus-width = <8>;
+ };
+ };
+
wifi0: wifi@a000000 {
compatible = "qcom,ipq4019-wifi";
reg = <0xa000000 0x200000>;
@@ -326,7 +476,7 @@
<GIC_SPI 45 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 46 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 47 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 168 IRQ_TYPE_NONE>;
+ <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0", "msi1", "msi2", "msi3",
"msi4", "msi5", "msi6", "msi7",
"msi8", "msi9", "msi10", "msi11",
@@ -368,7 +518,7 @@
<GIC_SPI 61 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 62 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 63 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 169 IRQ_TYPE_NONE>;
+ <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi0", "msi1", "msi2", "msi3",
"msi4", "msi5", "msi6", "msi7",
"msi8", "msi9", "msi10", "msi11",
diff --git a/arch/arm/boot/dts/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom-msm8660.dtsi
index 33030f9..7069894 100644
--- a/arch/arm/boot/dts/qcom-msm8660.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8660.dtsi
@@ -452,7 +452,7 @@
clock-names = "ram";
rpmcc: clock-controller {
- compatible = "qcom,rpmcc-apq8660", "qcom,rpmcc";
+ compatible = "qcom,rpmcc-msm8660", "qcom,rpmcc";
#clock-cells = <1>;
};
diff --git a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-amami.dts b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-amami.dts
new file mode 100644
index 0000000..5669f5f
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-amami.dts
@@ -0,0 +1,436 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "qcom-msm8974.dtsi"
+#include "qcom-pm8841.dtsi"
+#include "qcom-pm8941.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+
+/ {
+ model = "Sony Xperia Z1 Compact";
+ compatible = "sony,xperia-amami", "qcom,msm8974";
+
+ aliases {
+ serial0 = &blsp1_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ input-name = "gpio-keys";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_keys_pin_a>;
+
+ volume-down {
+ label = "volume_down";
+ gpios = <&pm8941_gpios 2 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ camera-snapshot {
+ label = "camera_snapshot";
+ gpios = <&pm8941_gpios 3 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <KEY_CAMERA>;
+ };
+
+ camera-focus {
+ label = "camera_focus";
+ gpios = <&pm8941_gpios 4 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <KEY_CAMERA_FOCUS>;
+ };
+
+ volume-up {
+ label = "volume_up";
+ gpios = <&pm8941_gpios 5 GPIO_ACTIVE_LOW>;
+ linux,input-type = <1>;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+
+ memory@0 {
+ reg = <0 0x40000000>, <0x40000000 0x40000000>;
+ device_type = "memory";
+ };
+
+ smd {
+ rpm {
+ rpm_requests {
+ pm8841-regulators {
+ s1 {
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ s2 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ s3 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ s4 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1050000>;
+ };
+ };
+
+ pm8941-regulators {
+ vdd_l1_l3-supply = <&pm8941_s1>;
+ vdd_l2_lvs1_2_3-supply = <&pm8941_s3>;
+ vdd_l4_l11-supply = <&pm8941_s1>;
+ vdd_l5_l7-supply = <&pm8941_s2>;
+ vdd_l6_l12_l14_l15-supply = <&pm8941_s2>;
+ vdd_l9_l10_l17_l22-supply = <&vreg_boost>;
+ vdd_l13_l20_l23_l24-supply = <&vreg_boost>;
+ vdd_l21-supply = <&vreg_boost>;
+
+ s1 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ s2 {
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ regulator-boot-on;
+ };
+
+ s3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ s4 {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ l3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ l4 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-boot-on;
+ };
+
+ l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-boot-on;
+ };
+
+ l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ l11 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+
+ regulator-boot-on;
+ };
+
+ l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l15 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ l16 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+
+ l17 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+
+ l18 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ l19 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ l20 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+
+ regulator-allow-set-load;
+ regulator-boot-on;
+ regulator-system-load = <200000>;
+ };
+
+ l21 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+
+ regulator-boot-on;
+ };
+
+ l22 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ l23 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ l24 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+
+ regulator-boot-on;
+ };
+ };
+ };
+ };
+ };
+};
+
+&soc {
+ sdhci@f9824900 {
+ status = "ok";
+
+ vmmc-supply = <&pm8941_l20>;
+ vqmmc-supply = <&pm8941_s3>;
+
+ bus-width = <8>;
+ non-removable;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhc1_pin_a>;
+ };
+
+ sdhci@f98a4900 {
+ status = "ok";
+
+ bus-width = <4>;
+
+ vmmc-supply = <&pm8941_l21>;
+ vqmmc-supply = <&pm8941_l13>;
+
+ cd-gpios = <&msmgpio 62 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdhc2_pin_a>, <&sdhc2_cd_pin_a>;
+ };
+
+ serial@f991e000 {
+ status = "ok";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&blsp1_uart2_pin_a>;
+ };
+
+
+ pinctrl@fd510000 {
+ blsp1_uart2_pin_a: blsp1-uart2-pin-active {
+ rx {
+ pins = "gpio5";
+ function = "blsp_uart2";
+
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ tx {
+ pins = "gpio4";
+ function = "blsp_uart2";
+
+ drive-strength = <4>;
+ bias-disable;
+ };
+ };
+
+ i2c2_pins: i2c2 {
+ mux {
+ pins = "gpio6", "gpio7";
+ function = "blsp_i2c2";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ sdhc1_pin_a: sdhc1-pin-active {
+ clk {
+ pins = "sdc1_clk";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ cmd-data {
+ pins = "sdc1_cmd", "sdc1_data";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+ };
+
+ sdhc2_cd_pin_a: sdhc2-cd-pin-active {
+ pins = "gpio62";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ sdhc2_pin_a: sdhc2-pin-active {
+ clk {
+ pins = "sdc2_clk";
+ drive-strength = <10>;
+ bias-disable;
+ };
+
+ cmd-data {
+ pins = "sdc2_cmd", "sdc2_data";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ dma-controller@f9944000 {
+ qcom,controlled-remotely;
+ };
+
+ usb@f9a55000 {
+ status = "ok";
+
+ phys = <&usb_hs1_phy>;
+ phy-select = <&tcsr 0xb000 0>;
+ extcon = <&smbb>, <&usb_id>;
+ vbus-supply = <&chg_otg>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+
+ ulpi {
+ phy@a {
+ status = "ok";
+
+ v1p8-supply = <&pm8941_l6>;
+ v3p3-supply = <&pm8941_l24>;
+
+ extcon = <&smbb>;
+ qcom,init-seq = /bits/ 8 <0x1 0x64>;
+ };
+ };
+ };
+};
+
+&spmi_bus {
+ pm8941@0 {
+ charger@1000 {
+ qcom,fast-charge-safe-current = <1300000>;
+ qcom,fast-charge-current-limit = <1300000>;
+ qcom,dc-current-limit = <1300000>;
+ qcom,fast-charge-safe-voltage = <4400000>;
+ qcom,fast-charge-high-threshold-voltage = <4350000>;
+ qcom,fast-charge-low-threshold-voltage = <3400000>;
+ qcom,auto-recharge-threshold-voltage = <4200000>;
+ qcom,minimum-input-voltage = <4300000>;
+ };
+
+ gpios@c000 {
+ gpio_keys_pin_a: gpio-keys-active {
+ pins = "gpio2", "gpio3", "gpio4", "gpio5";
+ function = "normal";
+
+ bias-pull-up;
+ power-source = <PM8941_GPIO_S3>;
+ };
+ };
+
+ coincell@2800 {
+ status = "ok";
+ qcom,rset-ohms = <2100>;
+ qcom,vset-millivolts = <3000>;
+ };
+ };
+
+ pm8941@1 {
+ wled@d800 {
+ status = "ok";
+
+ qcom,cs-out;
+ qcom,current-limit = <20>;
+ qcom,current-boost-limit = <805>;
+ qcom,switching-freq = <1600>;
+ qcom,ovp = <29>;
+ qcom,num-strings = <2>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom-pm8941.dtsi b/arch/arm/boot/dts/qcom-pm8941.dtsi
index 1d5ef55..2515c5c 100644
--- a/arch/arm/boot/dts/qcom-pm8941.dtsi
+++ b/arch/arm/boot/dts/qcom-pm8941.dtsi
@@ -139,6 +139,9 @@
#size-cells = <0>;
#io-channel-cells = <1>;
+ bat_temp {
+ reg = <VADC_LR_MUX1_BAT_THERM>;
+ };
die_temp {
reg = <VADC_DIE_TEMP>;
};
@@ -154,6 +157,9 @@
ref_vdd {
reg = <VADC_VDD_VADC>;
};
+ vbat_sns {
+ reg = <VADC_VBAT_SNS>;
+ };
};
pm8941_iadc: iadc@3600 {
diff --git a/arch/arm/boot/dts/r7s72100.dtsi b/arch/arm/boot/dts/r7s72100.dtsi
index ab9645a..a54822e 100644
--- a/arch/arm/boot/dts/r7s72100.dtsi
+++ b/arch/arm/boot/dts/r7s72100.dtsi
@@ -15,7 +15,6 @@
/ {
compatible = "renesas,r7s72100";
- interrupt-parent = <&gic>;
#address-cells = <1>;
#size-cells = <1>;
@@ -31,61 +30,370 @@
spi4 = &spi4;
};
- clocks {
- ranges;
+ /* Fixed factor clocks */
+ b_clk: b {
+ #clock-cells = <0>;
+ compatible = "fixed-factor-clock";
+ clocks = <&cpg_clocks R7S72100_CLK_PLL>;
+ clock-mult = <1>;
+ clock-div = <3>;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0>;
+ clock-frequency = <400000000>;
+ clocks = <&cpg_clocks R7S72100_CLK_I>;
+ next-level-cache = <&L2>;
+ };
+ };
+
+ /* External clocks */
+ extal_clk: extal {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ /* If clk present, value must be set by board */
+ clock-frequency = <0>;
+ };
+
+ p0_clk: p0 {
+ #clock-cells = <0>;
+ compatible = "fixed-factor-clock";
+ clocks = <&cpg_clocks R7S72100_CLK_PLL>;
+ clock-mult = <1>;
+ clock-div = <12>;
+ };
+
+ p1_clk: p1 {
+ #clock-cells = <0>;
+ compatible = "fixed-factor-clock";
+ clocks = <&cpg_clocks R7S72100_CLK_PLL>;
+ clock-mult = <1>;
+ clock-div = <6>;
+ };
+
+ pmu {
+ compatible = "arm,cortex-a9-pmu";
+ interrupts-extended = <&gic GIC_PPI 0 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ 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>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+
#address-cells = <1>;
#size-cells = <1>;
+ ranges;
+
+ L2: cache-controller@3ffff000 {
+ compatible = "arm,pl310-cache";
+ reg = <0x3ffff000 0x1000>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ arm,early-bresp-disable;
+ arm,full-line-zero-disable;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ scif0: serial@e8007000 {
+ compatible = "renesas,scif-r7s72100", "renesas,scif";
+ reg = <0xe8007000 64>;
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp4_clks R7S72100_CLK_SCIF0>;
+ clock-names = "fck";
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
+ };
+
+ scif1: serial@e8007800 {
+ compatible = "renesas,scif-r7s72100", "renesas,scif";
+ reg = <0xe8007800 64>;
+ interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp4_clks R7S72100_CLK_SCIF1>;
+ clock-names = "fck";
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
+ };
+
+ scif2: serial@e8008000 {
+ compatible = "renesas,scif-r7s72100", "renesas,scif";
+ reg = <0xe8008000 64>;
+ interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp4_clks R7S72100_CLK_SCIF2>;
+ clock-names = "fck";
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
+ };
+
+ scif3: serial@e8008800 {
+ compatible = "renesas,scif-r7s72100", "renesas,scif";
+ reg = <0xe8008800 64>;
+ interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp4_clks R7S72100_CLK_SCIF3>;
+ clock-names = "fck";
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
+ };
- /* External clocks */
- extal_clk: extal {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- /* If clk present, value must be set by board */
- clock-frequency = <0>;
+ scif4: serial@e8009000 {
+ compatible = "renesas,scif-r7s72100", "renesas,scif";
+ reg = <0xe8009000 64>;
+ interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp4_clks R7S72100_CLK_SCIF4>;
+ clock-names = "fck";
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- usb_x1_clk: usb_x1 {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- /* If clk present, value must be set by board */
- clock-frequency = <0>;
+ scif5: serial@e8009800 {
+ compatible = "renesas,scif-r7s72100", "renesas,scif";
+ reg = <0xe8009800 64>;
+ interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp4_clks R7S72100_CLK_SCIF5>;
+ clock-names = "fck";
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- 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>;
+ scif6: serial@e800a000 {
+ compatible = "renesas,scif-r7s72100", "renesas,scif";
+ reg = <0xe800a000 64>;
+ interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp4_clks R7S72100_CLK_SCIF6>;
+ clock-names = "fck";
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- 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>;
+ scif7: serial@e800a800 {
+ compatible = "renesas,scif-r7s72100", "renesas,scif";
+ reg = <0xe800a800 64>;
+ interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp4_clks R7S72100_CLK_SCIF7>;
+ clock-names = "fck";
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- /* Fixed factor clocks */
- b_clk: b {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clocks = <&cpg_clocks R7S72100_CLK_PLL>;
- clock-mult = <1>;
- clock-div = <3>;
+ spi0: spi@e800c800 {
+ compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+ reg = <0xe800c800 0x24>;
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error", "rx", "tx";
+ clocks = <&mstp10_clks R7S72100_CLK_SPI0>;
+ power-domains = <&cpg_clocks>;
+ num-cs = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
};
- p1_clk: p1 {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clocks = <&cpg_clocks R7S72100_CLK_PLL>;
- clock-mult = <1>;
- clock-div = <6>;
+
+ spi1: spi@e800d000 {
+ compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+ reg = <0xe800d000 0x24>;
+ interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error", "rx", "tx";
+ clocks = <&mstp10_clks R7S72100_CLK_SPI1>;
+ power-domains = <&cpg_clocks>;
+ num-cs = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi2: spi@e800d800 {
+ compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+ reg = <0xe800d800 0x24>;
+ interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error", "rx", "tx";
+ clocks = <&mstp10_clks R7S72100_CLK_SPI2>;
+ power-domains = <&cpg_clocks>;
+ num-cs = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
};
- p0_clk: p0 {
- #clock-cells = <0>;
- compatible = "fixed-factor-clock";
- clocks = <&cpg_clocks R7S72100_CLK_PLL>;
- clock-mult = <1>;
- clock-div = <12>;
+
+ spi3: spi@e800e000 {
+ compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+ reg = <0xe800e000 0x24>;
+ interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error", "rx", "tx";
+ clocks = <&mstp10_clks R7S72100_CLK_SPI3>;
+ power-domains = <&cpg_clocks>;
+ num-cs = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi4: spi@e800e800 {
+ compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
+ reg = <0xe800e800 0x24>;
+ interrupts = <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error", "rx", "tx";
+ clocks = <&mstp10_clks R7S72100_CLK_SPI4>;
+ power-domains = <&cpg_clocks>;
+ num-cs = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ usbhs0: usb@e8010000 {
+ compatible = "renesas,usbhs-r7s72100", "renesas,rza1-usbhs";
+ reg = <0xe8010000 0x1a0>;
+ interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp7_clks R7S72100_CLK_USB0>;
+ renesas,buswait = <4>;
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
+ };
+
+ usbhs1: usb@e8207000 {
+ compatible = "renesas,usbhs-r7s72100", "renesas,rza1-usbhs";
+ reg = <0xe8207000 0x1a0>;
+ interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp7_clks R7S72100_CLK_USB1>;
+ renesas,buswait = <4>;
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
+ };
+
+ mmcif: mmc@e804c800 {
+ compatible = "renesas,mmcif-r7s72100", "renesas,sh-mmcif";
+ reg = <0xe804c800 0x80>;
+ interrupts = <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp8_clks R7S72100_CLK_MMCIF>;
+ power-domains = <&cpg_clocks>;
+ reg-io-width = <4>;
+ bus-width = <8>;
+ status = "disabled";
+ };
+
+ sdhi0: sd@e804e000 {
+ compatible = "renesas,sdhi-r7s72100";
+ reg = <0xe804e000 0x100>;
+ interrupts = <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
+
+ 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";
+ };
+
+ sdhi1: sd@e804e800 {
+ compatible = "renesas,sdhi-r7s72100";
+ reg = <0xe804e800 0x100>;
+ interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>;
+
+ 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";
+ };
+
+ gic: interrupt-controller@e8201000 {
+ compatible = "arm,pl390";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0xe8201000 0x1000>,
+ <0xe8202000 0x1000>;
+ };
+
+ ether: ethernet@e8203000 {
+ compatible = "renesas,ether-r7s72100";
+ reg = <0xe8203000 0x800>,
+ <0xe8204800 0x200>;
+ interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp7_clks R7S72100_CLK_ETHER>;
+ power-domains = <&cpg_clocks>;
+ phy-mode = "mii";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ ceu: camera@e8210000 {
+ reg = <0xe8210000 0x3000>;
+ compatible = "renesas,r7s72100-ceu";
+ interrupts = <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp6_clks R7S72100_CLK_CEU>;
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
+ };
+
+ wdt: watchdog@fcfe0000 {
+ compatible = "renesas,r7s72100-wdt", "renesas,rza-wdt";
+ reg = <0xfcfe0000 0x6>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&p0_clk>;
};
/* Special CPG clocks */
@@ -135,9 +443,9 @@
#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";
+ clocks = <&b_clk>, <&p0_clk>;
+ clock-indices = <R7S72100_CLK_CEU R7S72100_CLK_RTC>;
+ clock-output-names = "ceu", "rtc";
};
mstp7_clks: mstp7_clks@fcfe0430 {
@@ -192,479 +500,209 @@
>;
clock-output-names = "sdhi00", "sdhi01", "sdhi10", "sdhi11";
};
- };
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpu@0 {
- device_type = "cpu";
- compatible = "arm,cortex-a9";
- reg = <0>;
- clock-frequency = <400000000>;
- clocks = <&cpg_clocks R7S72100_CLK_I>;
- next-level-cache = <&L2>;
- };
- };
-
- pinctrl: pin-controller@fcfe3000 {
- compatible = "renesas,r7s72100-ports";
-
- reg = <0xfcfe3000 0x4230>;
-
- port0: gpio-0 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 0 6>;
- };
-
- port1: gpio-1 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 16 16>;
- };
- port2: gpio-2 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 32 16>;
+ pinctrl: pin-controller@fcfe3000 {
+ compatible = "renesas,r7s72100-ports";
+
+ reg = <0xfcfe3000 0x4230>;
+
+ port0: gpio-0 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 0 6>;
+ };
+
+ port1: gpio-1 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 16 16>;
+ };
+
+ port2: gpio-2 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 32 16>;
+ };
+
+ port3: gpio-3 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 48 16>;
+ };
+
+ port4: gpio-4 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 64 16>;
+ };
+
+ port5: gpio-5 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 80 11>;
+ };
+
+ port6: gpio-6 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 96 16>;
+ };
+
+ port7: gpio-7 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 112 16>;
+ };
+
+ port8: gpio-8 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 128 16>;
+ };
+
+ port9: gpio-9 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 144 8>;
+ };
+
+ port10: gpio-10 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 160 16>;
+ };
+
+ port11: gpio-11 {
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl 0 176 16>;
+ };
};
- port3: gpio-3 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 48 16>;
+ ostm0: timer@fcfec000 {
+ compatible = "renesas,r7s72100-ostm", "renesas,ostm";
+ reg = <0xfcfec000 0x30>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&mstp5_clks R7S72100_CLK_OSTM0>;
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- port4: gpio-4 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 64 16>;
+ ostm1: timer@fcfec400 {
+ compatible = "renesas,r7s72100-ostm", "renesas,ostm";
+ reg = <0xfcfec400 0x30>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&mstp5_clks R7S72100_CLK_OSTM1>;
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- port5: gpio-5 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 80 11>;
+ i2c0: i2c@fcfee000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+ reg = <0xfcfee000 0x44>;
+ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 159 IRQ_TYPE_EDGE_RISING>,
+ <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>;
+ clocks = <&mstp9_clks R7S72100_CLK_I2C0>;
+ clock-frequency = <100000>;
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- port6: gpio-6 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 96 16>;
+ i2c1: i2c@fcfee400 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+ reg = <0xfcfee400 0x44>;
+ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 166 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 167 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp9_clks R7S72100_CLK_I2C1>;
+ clock-frequency = <100000>;
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- port7: gpio-7 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 112 16>;
+ i2c2: i2c@fcfee800 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+ reg = <0xfcfee800 0x44>;
+ interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 174 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 175 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp9_clks R7S72100_CLK_I2C2>;
+ clock-frequency = <100000>;
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- port8: gpio-8 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 128 16>;
+ i2c3: i2c@fcfeec00 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
+ reg = <0xfcfeec00 0x44>;
+ interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 182 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 183 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp9_clks R7S72100_CLK_I2C3>;
+ clock-frequency = <100000>;
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- port9: gpio-9 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 144 8>;
+ mtu2: timer@fcff0000 {
+ compatible = "renesas,mtu2-r7s72100", "renesas,mtu2";
+ reg = <0xfcff0000 0x400>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "tgi0a";
+ clocks = <&mstp3_clks R7S72100_CLK_MTU2>;
+ clock-names = "fck";
+ power-domains = <&cpg_clocks>;
+ status = "disabled";
};
- port10: gpio-10 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 160 16>;
+ rtc: rtc@fcff1000 {
+ compatible = "renesas,r7s72100-rtc", "renesas,sh-rtc";
+ reg = <0xfcff1000 0x2e>;
+ interrupts = <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>;
+ 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";
};
-
- port11: gpio-11 {
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&pinctrl 0 176 16>;
- };
- };
-
- scif0: serial@e8007000 {
- compatible = "renesas,scif-r7s72100", "renesas,scif";
- reg = <0xe8007000 64>;
- interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp4_clks R7S72100_CLK_SCIF0>;
- clock-names = "fck";
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- scif1: serial@e8007800 {
- compatible = "renesas,scif-r7s72100", "renesas,scif";
- reg = <0xe8007800 64>;
- interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp4_clks R7S72100_CLK_SCIF1>;
- clock-names = "fck";
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- scif2: serial@e8008000 {
- compatible = "renesas,scif-r7s72100", "renesas,scif";
- reg = <0xe8008000 64>;
- interrupts = <GIC_SPI 198 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp4_clks R7S72100_CLK_SCIF2>;
- clock-names = "fck";
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- scif3: serial@e8008800 {
- compatible = "renesas,scif-r7s72100", "renesas,scif";
- reg = <0xe8008800 64>;
- interrupts = <GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp4_clks R7S72100_CLK_SCIF3>;
- clock-names = "fck";
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- scif4: serial@e8009000 {
- compatible = "renesas,scif-r7s72100", "renesas,scif";
- reg = <0xe8009000 64>;
- interrupts = <GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp4_clks R7S72100_CLK_SCIF4>;
- clock-names = "fck";
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- scif5: serial@e8009800 {
- compatible = "renesas,scif-r7s72100", "renesas,scif";
- reg = <0xe8009800 64>;
- interrupts = <GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp4_clks R7S72100_CLK_SCIF5>;
- clock-names = "fck";
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- scif6: serial@e800a000 {
- compatible = "renesas,scif-r7s72100", "renesas,scif";
- reg = <0xe800a000 64>;
- interrupts = <GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp4_clks R7S72100_CLK_SCIF6>;
- clock-names = "fck";
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- scif7: serial@e800a800 {
- compatible = "renesas,scif-r7s72100", "renesas,scif";
- reg = <0xe800a800 64>;
- interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp4_clks R7S72100_CLK_SCIF7>;
- clock-names = "fck";
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- spi0: spi@e800c800 {
- compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
- reg = <0xe800c800 0x24>;
- interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error", "rx", "tx";
- clocks = <&mstp10_clks R7S72100_CLK_SPI0>;
- power-domains = <&cpg_clocks>;
- num-cs = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- spi1: spi@e800d000 {
- compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
- reg = <0xe800d000 0x24>;
- interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error", "rx", "tx";
- clocks = <&mstp10_clks R7S72100_CLK_SPI1>;
- power-domains = <&cpg_clocks>;
- num-cs = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- spi2: spi@e800d800 {
- compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
- reg = <0xe800d800 0x24>;
- interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error", "rx", "tx";
- clocks = <&mstp10_clks R7S72100_CLK_SPI2>;
- power-domains = <&cpg_clocks>;
- num-cs = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- spi3: spi@e800e000 {
- compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
- reg = <0xe800e000 0x24>;
- interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error", "rx", "tx";
- clocks = <&mstp10_clks R7S72100_CLK_SPI3>;
- power-domains = <&cpg_clocks>;
- num-cs = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- spi4: spi@e800e800 {
- compatible = "renesas,rspi-r7s72100", "renesas,rspi-rz";
- reg = <0xe800e800 0x24>;
- interrupts = <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error", "rx", "tx";
- clocks = <&mstp10_clks R7S72100_CLK_SPI4>;
- power-domains = <&cpg_clocks>;
- num-cs = <1>;
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- gic: interrupt-controller@e8201000 {
- compatible = "arm,pl390";
- #interrupt-cells = <3>;
- #address-cells = <0>;
- interrupt-controller;
- reg = <0xe8201000 0x1000>,
- <0xe8202000 0x1000>;
- };
-
- L2: cache-controller@3ffff000 {
- compatible = "arm,pl310-cache";
- reg = <0x3ffff000 0x1000>;
- interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
- arm,early-bresp-disable;
- arm,full-line-zero-disable;
- cache-unified;
- 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>;
- compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
- reg = <0xfcfee000 0x44>;
- interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 159 IRQ_TYPE_EDGE_RISING>,
- <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>;
- clocks = <&mstp9_clks R7S72100_CLK_I2C0>;
- clock-frequency = <100000>;
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- i2c1: i2c@fcfee400 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
- reg = <0xfcfee400 0x44>;
- interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 166 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 167 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 172 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp9_clks R7S72100_CLK_I2C1>;
- clock-frequency = <100000>;
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- i2c2: i2c@fcfee800 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
- reg = <0xfcfee800 0x44>;
- interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 174 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 175 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 177 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 178 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 179 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp9_clks R7S72100_CLK_I2C2>;
- clock-frequency = <100000>;
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- i2c3: i2c@fcfeec00 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,riic-r7s72100", "renesas,riic-rz";
- reg = <0xfcfeec00 0x44>;
- interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 182 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 183 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp9_clks R7S72100_CLK_I2C3>;
- clock-frequency = <100000>;
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- mtu2: timer@fcff0000 {
- compatible = "renesas,mtu2-r7s72100", "renesas,mtu2";
- reg = <0xfcff0000 0x400>;
- interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "tgi0a";
- clocks = <&mstp3_clks R7S72100_CLK_MTU2>;
- clock-names = "fck";
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- ether: ethernet@e8203000 {
- compatible = "renesas,ether-r7s72100";
- reg = <0xe8203000 0x800>,
- <0xe8204800 0x200>;
- interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp7_clks R7S72100_CLK_ETHER>;
- power-domains = <&cpg_clocks>;
- phy-mode = "mii";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "disabled";
- };
-
- mmcif: mmc@e804c800 {
- compatible = "renesas,mmcif-r7s72100", "renesas,sh-mmcif";
- reg = <0xe804c800 0x80>;
- interrupts = <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&mstp8_clks R7S72100_CLK_MMCIF>;
- power-domains = <&cpg_clocks>;
- reg-io-width = <4>;
- bus-width = <8>;
- status = "disabled";
- };
-
- sdhi0: sd@e804e000 {
- compatible = "renesas,sdhi-r7s72100";
- reg = <0xe804e000 0x100>;
- interrupts = <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
-
- 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";
- };
-
- sdhi1: sd@e804e800 {
- compatible = "renesas,sdhi-r7s72100";
- reg = <0xe804e800 0x100>;
- interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>;
-
- 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";
- };
-
- ostm0: timer@fcfec000 {
- compatible = "renesas,r7s72100-ostm", "renesas,ostm";
- reg = <0xfcfec000 0x30>;
- interrupts = <GIC_SPI 102 IRQ_TYPE_EDGE_RISING>;
- clocks = <&mstp5_clks R7S72100_CLK_OSTM0>;
- power-domains = <&cpg_clocks>;
- status = "disabled";
- };
-
- ostm1: timer@fcfec400 {
- compatible = "renesas,r7s72100-ostm", "renesas,ostm";
- reg = <0xfcfec400 0x30>;
- interrupts = <GIC_SPI 103 IRQ_TYPE_EDGE_RISING>;
- clocks = <&mstp5_clks R7S72100_CLK_OSTM1>;
- 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";
+ usb_x1_clk: usb_x1 {
+ #clock-cells = <0>;
+ compatible = "fixed-clock";
+ /* If clk present, value must be set by board */
+ clock-frequency = <0>;
};
};
diff --git a/arch/arm/boot/dts/r8a73a4-ape6evm.dts b/arch/arm/boot/dts/r8a73a4-ape6evm.dts
index ec7c86e..125c39c 100644
--- a/arch/arm/boot/dts/r8a73a4-ape6evm.dts
+++ b/arch/arm/boot/dts/r8a73a4-ape6evm.dts
@@ -234,7 +234,7 @@
&sdhi0 {
vmmc-supply = <&vcc_sdhi0>;
bus-width = <4>;
- toshiba,mmc-wrprotect-disable;
+ disable-wp;
pinctrl-names = "default";
pinctrl-0 = <&sdhi0_pins>;
status = "okay";
@@ -244,7 +244,7 @@
vmmc-supply = <&ape6evm_fixed_3v3>;
bus-width = <4>;
broken-cd;
- toshiba,mmc-wrprotect-disable;
+ disable-wp;
pinctrl-names = "default";
pinctrl-0 = <&sdhi1_pins>;
status = "okay";
diff --git a/arch/arm/boot/dts/r8a73a4.dtsi b/arch/arm/boot/dts/r8a73a4.dtsi
index 8e48090..080d037 100644
--- a/arch/arm/boot/dts/r8a73a4.dtsi
+++ b/arch/arm/boot/dts/r8a73a4.dtsi
@@ -57,10 +57,10 @@
timer {
compatible = "arm,armv7-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)>;
+ 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)>;
};
dbsc1: memory-controller@e6790000 {
@@ -464,7 +464,7 @@
<0 0xf1002000 0 0x2000>,
<0 0xf1004000 0 0x2000>,
<0 0xf1006000 0 0x2000>;
- interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
clocks = <&mstp4_clks R8A73A4_CLK_INTC_SYS>;
clock-names = "clk";
power-domains = <&pd_c4>;
diff --git a/arch/arm/boot/dts/r8a7740.dtsi b/arch/arm/boot/dts/r8a7740.dtsi
index afd3bc5..eb9a911 100644
--- a/arch/arm/boot/dts/r8a7740.dtsi
+++ b/arch/arm/boot/dts/r8a7740.dtsi
@@ -67,6 +67,24 @@
power-domains = <&pd_d4>;
};
+ ceu0: ceu@fe910000 {
+ reg = <0xfe910000 0x3000>;
+ compatible = "renesas,r8a7740-ceu";
+ interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp1_clks R8A7740_CLK_CEU20>;
+ power-domains = <&pd_a4r>;
+ status = "disabled";
+ };
+
+ ceu1: ceu@fe914000 {
+ reg = <0xfe914000 0x3000>;
+ compatible = "renesas,r8a7740-ceu";
+ interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&mstp1_clks R8A7740_CLK_CEU21>;
+ power-domains = <&pd_a4r>;
+ status = "disabled";
+ };
+
cmt1: timer@e6138000 {
compatible = "renesas,cmt-48-r8a7740", "renesas,cmt-48";
reg = <0xe6138000 0x170>;
diff --git a/arch/arm/boot/dts/r8a7743-iwg20m.dtsi b/arch/arm/boot/dts/r8a7743-iwg20m.dtsi
index 1d3e950..d364685 100644
--- a/arch/arm/boot/dts/r8a7743-iwg20m.dtsi
+++ b/arch/arm/boot/dts/r8a7743-iwg20m.dtsi
@@ -91,6 +91,11 @@
};
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&sdhi0 {
pinctrl-0 = <&sdhi0_pins>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/r8a7743.dtsi b/arch/arm/boot/dts/r8a7743.dtsi
index 1d9073b..142949d 100644
--- a/arch/arm/boot/dts/r8a7743.dtsi
+++ b/arch/arm/boot/dts/r8a7743.dtsi
@@ -125,6 +125,13 @@
clock-frequency = <0>;
};
+ pmu {
+ compatible = "arm,cortex-a15-pmu";
+ interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+
/* External SCIF clock */
scif_clk: scif {
compatible = "fixed-clock";
@@ -297,6 +304,16 @@
reg = <0 0xe6160000 0 0x100>;
};
+ rwdt: watchdog@e6020000 {
+ compatible = "renesas,r8a7743-wdt",
+ "renesas,rcar-gen2-wdt";
+ reg = <0 0xe6020000 0 0x0c>;
+ clocks = <&cpg CPG_MOD 402>;
+ power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+ resets = <&cpg 402>;
+ status = "disabled";
+ };
+
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7743-sysc";
reg = <0 0xe6180000 0 0x200>;
@@ -407,7 +424,7 @@
smp-sram@0 {
compatible = "renesas,smp-sram";
- reg = <0 0x10>;
+ reg = <0 0x100>;
};
};
diff --git a/arch/arm/boot/dts/r8a7745-iwg22m.dtsi b/arch/arm/boot/dts/r8a7745-iwg22m.dtsi
index 8d0a392b..29b6e10 100644
--- a/arch/arm/boot/dts/r8a7745-iwg22m.dtsi
+++ b/arch/arm/boot/dts/r8a7745-iwg22m.dtsi
@@ -91,6 +91,11 @@
};
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&sdhi1 {
pinctrl-0 = <&sdhi1_pins>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/r8a7745.dtsi b/arch/arm/boot/dts/r8a7745.dtsi
index dd49a8b..1cb7a7a 100644
--- a/arch/arm/boot/dts/r8a7745.dtsi
+++ b/arch/arm/boot/dts/r8a7745.dtsi
@@ -105,6 +105,13 @@
clock-frequency = <0>;
};
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts-extended = <&gic GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+
/* External SCIF clock */
scif_clk: scif {
compatible = "fixed-clock";
@@ -262,6 +269,16 @@
reg = <0 0xe6160000 0 0x100>;
};
+ rwdt: watchdog@e6020000 {
+ compatible = "renesas,r8a7745-wdt",
+ "renesas,rcar-gen2-wdt";
+ reg = <0 0xe6020000 0 0x0c>;
+ clocks = <&cpg CPG_MOD 402>;
+ power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+ resets = <&cpg 402>;
+ status = "disabled";
+ };
+
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7745-sysc";
reg = <0 0xe6180000 0 0x200>;
@@ -360,7 +377,7 @@
smp-sram@0 {
compatible = "renesas,smp-sram";
- reg = <0 0x10>;
+ reg = <0 0x100>;
};
};
diff --git a/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts b/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts
new file mode 100644
index 0000000..e3585da
--- /dev/null
+++ b/arch/arm/boot/dts/r8a77470-iwg23s-sbc.dts
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the iWave-RZ/G1C single board computer
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a77470.dtsi"
+/ {
+ model = "iWave iW-RainboW-G23S single board computer based on RZ/G1C";
+ compatible = "iwave,g23s", "renesas,r8a77470";
+
+ aliases {
+ ethernet0 = &avb;
+ serial1 = &scif1;
+ };
+
+ chosen {
+ bootargs = "ignore_loglevel rw root=/dev/nfs ip=dhcp";
+ stdout-path = "serial1:115200n8";
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0 0x20000000>;
+ };
+};
+
+&avb {
+ phy-handle = <&phy3>;
+ phy-mode = "gmii";
+ renesas,no-ether-link;
+ status = "okay";
+
+ phy3: ethernet-phy@3 {
+ reg = <3>;
+ micrel,led-mode = <1>;
+ };
+};
+
+&extal_clk {
+ clock-frequency = <20000000>;
+};
+
+&scif1 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/r8a77470.dtsi b/arch/arm/boot/dts/r8a77470.dtsi
new file mode 100644
index 0000000..c85032f
--- /dev/null
+++ b/arch/arm/boot/dts/r8a77470.dtsi
@@ -0,0 +1,336 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the r8a77470 SoC
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+/ {
+ compatible = "renesas,r8a77470";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a7";
+ reg = <0>;
+ clock-frequency = <1000000000>;
+ clocks = <&cpg CPG_CORE 0>;
+ power-domains = <&sysc 5>;
+ next-level-cache = <&L2_CA7>;
+ };
+
+
+ L2_CA7: cache-controller-0 {
+ compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
+ power-domains = <&sysc 21>;
+ };
+ };
+
+ /* External root clock */
+ extal_clk: extal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board. */
+ clock-frequency = <0>;
+ };
+
+ /* External SCIF clock */
+ scif_clk: scif {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board. */
+ clock-frequency = <0>;
+ };
+
+ soc {
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ cpg: clock-controller@e6150000 {
+ compatible = "renesas,r8a77470-cpg-mssr";
+ reg = <0 0xe6150000 0 0x1000>;
+ clocks = <&extal_clk>, <&usb_extal_clk>;
+ clock-names = "extal", "usb_extal";
+ #clock-cells = <2>;
+ #power-domain-cells = <0>;
+ #reset-cells = <1>;
+ };
+
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a77470-rst";
+ reg = <0 0xe6160000 0 0x100>;
+ };
+
+ sysc: system-controller@e6180000 {
+ compatible = "renesas,r8a77470-sysc";
+ reg = <0 0xe6180000 0 0x200>;
+ #power-domain-cells = <1>;
+ };
+
+ irqc: interrupt-controller@e61c0000 {
+ compatible = "renesas,irqc-r8a77470", "renesas,irqc";
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ reg = <0 0xe61c0000 0 0x200>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 407>;
+ power-domains = <&sysc 32>;
+ resets = <&cpg 407>;
+ };
+
+ icram0: sram@e63a0000 {
+ compatible = "mmio-sram";
+ reg = <0 0xe63a0000 0 0x12000>;
+ };
+
+ icram1: sram@e63c0000 {
+ compatible = "mmio-sram";
+ reg = <0 0xe63c0000 0 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0xe63c0000 0x1000>;
+
+ smp-sram@0 {
+ compatible = "renesas,smp-sram";
+ reg = <0 0x100>;
+ };
+ };
+
+ icram2: sram@e6300000 {
+ compatible = "mmio-sram";
+ reg = <0 0xe6300000 0 0x20000>;
+ };
+
+ dmac0: dma-controller@e6700000 {
+ compatible = "renesas,dmac-r8a77470",
+ "renesas,rcar-dmac";
+ reg = <0 0xe6700000 0 0x20000>;
+ interrupts = <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14";
+ clocks = <&cpg CPG_MOD 219>;
+ clock-names = "fck";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 219>;
+ #dma-cells = <1>;
+ dma-channels = <15>;
+ };
+
+ dmac1: dma-controller@e6720000 {
+ compatible = "renesas,dmac-r8a77470",
+ "renesas,rcar-dmac";
+ reg = <0 0xe6720000 0 0x20000>;
+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14";
+ clocks = <&cpg CPG_MOD 218>;
+ clock-names = "fck";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 218>;
+ #dma-cells = <1>;
+ dma-channels = <15>;
+ };
+
+ avb: ethernet@e6800000 {
+ compatible = "renesas,etheravb-r8a77470",
+ "renesas,etheravb-rcar-gen2";
+ reg = <0 0xe6800000 0 0x800>, <0 0xee0e8000 0 0x4000>;
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 812>;
+ power-domains = <&sysc 32>;
+ resets = <&cpg 812>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ scif0: serial@e6e60000 {
+ compatible = "renesas,scif-r8a77470",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6e60000 0 0x40>;
+ interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 721>,
+ <&cpg CPG_CORE 5>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x29>, <&dmac0 0x2a>,
+ <&dmac1 0x29>, <&dmac1 0x2a>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 721>;
+ status = "disabled";
+ };
+
+ scif1: serial@e6e68000 {
+ compatible = "renesas,scif-r8a77470",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6e68000 0 0x40>;
+ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 720>,
+ <&cpg CPG_CORE 5>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x2d>, <&dmac0 0x2e>,
+ <&dmac1 0x2d>, <&dmac1 0x2e>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 720>;
+ status = "disabled";
+ };
+
+ scif2: serial@e6e58000 {
+ compatible = "renesas,scif-r8a77470",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6e58000 0 0x40>;
+ interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 719>,
+ <&cpg CPG_CORE 5>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x2b>, <&dmac0 0x2c>,
+ <&dmac1 0x2b>, <&dmac1 0x2c>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 719>;
+ status = "disabled";
+ };
+
+ scif3: serial@e6ea8000 {
+ compatible = "renesas,scif-r8a77470",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6ea8000 0 0x40>;
+ interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 718>,
+ <&cpg CPG_CORE 5>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x2f>, <&dmac0 0x30>,
+ <&dmac1 0x2f>, <&dmac1 0x30>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 718>;
+ status = "disabled";
+ };
+
+ scif4: serial@e6ee0000 {
+ compatible = "renesas,scif-r8a77470",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6ee0000 0 0x40>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 715>,
+ <&cpg CPG_CORE 5>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0xfb>, <&dmac0 0xfc>,
+ <&dmac1 0xfb>, <&dmac1 0xfc>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 715>;
+ status = "disabled";
+ };
+
+ scif5: serial@e6ee8000 {
+ compatible = "renesas,scif-r8a77470",
+ "renesas,rcar-gen2-scif", "renesas,scif";
+ reg = <0 0xe6ee8000 0 0x40>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 714>,
+ <&cpg CPG_CORE 5>, <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0xfd>, <&dmac0 0xfe>,
+ <&dmac1 0xfd>, <&dmac1 0xfe>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 714>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@f1001000 {
+ compatible = "arm,gic-400";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0 0xf1001000 0 0x1000>, <0 0xf1002000 0 0x2000>,
+ <0 0xf1004000 0 0x2000>, <0 0xf1006000 0 0x2000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+ clocks = <&cpg CPG_MOD 408>;
+ clock-names = "clk";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 408>;
+ };
+
+ prr: chipid@ff000044 {
+ compatible = "renesas,prr";
+ reg = <0 0xff000044 0 4>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv7-timer";
+ interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
+ /* External USB clock - can be overridden by the board */
+ usb_extal_clk: usb_extal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <48000000>;
+ };
+};
diff --git a/arch/arm/boot/dts/r8a7790-lager.dts b/arch/arm/boot/dts/r8a7790-lager.dts
index f07f9018..092610e 100644
--- a/arch/arm/boot/dts/r8a7790-lager.dts
+++ b/arch/arm/boot/dts/r8a7790-lager.dts
@@ -902,9 +902,6 @@
status = "okay";
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
vin1ep0: endpoint {
remote-endpoint = <&adv7180>;
bus-width = <8>;
@@ -929,6 +926,11 @@
};
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&ssi1 {
shared-pin;
};
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 05a0fc2..4d06b15 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -202,6 +202,24 @@
clock-frequency = <0>;
};
+ pmu-0 {
+ compatible = "arm,cortex-a15-pmu";
+ interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+ };
+
+ pmu-1 {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts-extended = <&gic GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu4>, <&cpu5>, <&cpu6>, <&cpu7>;
+ };
+
/* External SCIF clock */
scif_clk: scif {
compatible = "fixed-clock";
@@ -218,6 +236,16 @@
#size-cells = <2>;
ranges;
+ rwdt: watchdog@e6020000 {
+ compatible = "renesas,r8a7790-wdt",
+ "renesas,rcar-gen2-wdt";
+ reg = <0 0xe6020000 0 0x0c>;
+ clocks = <&cpg CPG_MOD 402>;
+ power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
+ resets = <&cpg 402>;
+ status = "disabled";
+ };
+
gpio0: gpio@e6050000 {
compatible = "renesas,gpio-r8a7790",
"renesas,rcar-gen2-gpio";
@@ -443,7 +471,7 @@
smp-sram@0 {
compatible = "renesas,smp-sram";
- reg = <0 0x10>;
+ reg = <0 0x100>;
};
};
@@ -1544,7 +1572,7 @@
interrupt-controller;
reg = <0 0xf1001000 0 0x1000>, <0 0xf1002000 0 0x2000>,
<0 0xf1004000 0 0x2000>, <0 0xf1006000 0 0x2000>;
- interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
clocks = <&cpg CPG_MOD 408>;
clock-names = "clk";
power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
@@ -1615,6 +1643,33 @@
resets = <&cpg 127>;
};
+ fdp1@fe940000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe940000 0 0x2400>;
+ interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 119>;
+ power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
+ resets = <&cpg 119>;
+ };
+
+ fdp1@fe944000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe944000 0 0x2400>;
+ interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 118>;
+ power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
+ resets = <&cpg 118>;
+ };
+
+ fdp1@fe948000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe948000 0 0x2400>;
+ interrupts = <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 117>;
+ power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
+ resets = <&cpg 117>;
+ };
+
jpu: jpeg-codec@fe980000 {
compatible = "renesas,jpu-r8a7790",
"renesas,rcar-gen2-jpu";
@@ -1773,10 +1828,10 @@
timer {
compatible = "arm,armv7-timer";
- interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
};
/* External USB clock - can be overridden by the board */
diff --git a/arch/arm/boot/dts/r8a7791-koelsch.dts b/arch/arm/boot/dts/r8a7791-koelsch.dts
index 9d7213a..8ab793d 100644
--- a/arch/arm/boot/dts/r8a7791-koelsch.dts
+++ b/arch/arm/boot/dts/r8a7791-koelsch.dts
@@ -643,6 +643,11 @@
status = "okay";
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&sata0 {
status = "okay";
};
@@ -850,9 +855,6 @@
pinctrl-names = "default";
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
vin0ep2: endpoint {
remote-endpoint = <&adv7612_out>;
bus-width = <24>;
@@ -871,9 +873,6 @@
pinctrl-names = "default";
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
vin1ep: endpoint {
remote-endpoint = <&adv7180>;
bus-width = <8>;
diff --git a/arch/arm/boot/dts/r8a7791-porter.dts b/arch/arm/boot/dts/r8a7791-porter.dts
index ae9ed9f..a01101b 100644
--- a/arch/arm/boot/dts/r8a7791-porter.dts
+++ b/arch/arm/boot/dts/r8a7791-porter.dts
@@ -386,9 +386,6 @@
pinctrl-names = "default";
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
vin0ep: endpoint {
remote-endpoint = <&adv7180>;
bus-width = <8>;
@@ -481,6 +478,11 @@
};
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&ssi1 {
shared-pin;
};
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 506b208..6e1dd7a 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -126,6 +126,13 @@
clock-frequency = <0>;
};
+ pmu {
+ compatible = "arm,cortex-a15-pmu";
+ interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+
/* External SCIF clock */
scif_clk: scif {
compatible = "fixed-clock";
@@ -142,6 +149,16 @@
#size-cells = <2>;
ranges;
+ rwdt: watchdog@e6020000 {
+ compatible = "renesas,r8a7791-wdt",
+ "renesas,rcar-gen2-wdt";
+ reg = <0 0xe6020000 0 0x0c>;
+ clocks = <&cpg CPG_MOD 402>;
+ power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
+ resets = <&cpg 402>;
+ status = "disabled";
+ };
+
gpio0: gpio@e6050000 {
compatible = "renesas,gpio-r8a7791",
"renesas,rcar-gen2-gpio";
@@ -407,7 +424,7 @@
smp-sram@0 {
compatible = "renesas,smp-sram";
- reg = <0 0x10>;
+ reg = <0 0x100>;
};
};
@@ -1621,6 +1638,24 @@
resets = <&cpg 127>;
};
+ fdp1@fe940000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe940000 0 0x2400>;
+ interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 119>;
+ power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
+ resets = <&cpg 119>;
+ };
+
+ fdp1@fe944000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe944000 0 0x2400>;
+ interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 118>;
+ power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
+ resets = <&cpg 118>;
+ };
+
jpu: jpeg-codec@fe980000 {
compatible = "renesas,jpu-r8a7791",
"renesas,rcar-gen2-jpu";
diff --git a/arch/arm/boot/dts/r8a7792-blanche.dts b/arch/arm/boot/dts/r8a7792-blanche.dts
index 9b67dca..04fb709 100644
--- a/arch/arm/boot/dts/r8a7792-blanche.dts
+++ b/arch/arm/boot/dts/r8a7792-blanche.dts
@@ -239,6 +239,11 @@
};
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&scif0 {
pinctrl-0 = <&scif0_pins>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/r8a7792-wheat.dts b/arch/arm/boot/dts/r8a7792-wheat.dts
index b9471b6..db01de7 100644
--- a/arch/arm/boot/dts/r8a7792-wheat.dts
+++ b/arch/arm/boot/dts/r8a7792-wheat.dts
@@ -168,6 +168,11 @@
};
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&scif0 {
pinctrl-0 = <&scif0_pins>;
pinctrl-names = "default";
@@ -240,9 +245,15 @@
status = "okay";
clock-frequency = <400000>;
+ /*
+ * The adv75xx resets its addresses to defaults during low power mode.
+ * Because we have two ADV7513 devices on the same bus, we must change
+ * both of them away from the defaults so that they do not conflict.
+ */
hdmi@3d {
compatible = "adi,adv7513";
- reg = <0x3d>;
+ reg = <0x3d>, <0x2d>, <0x4d>, <0x5d>;
+ reg-names = "main", "cec", "edid", "packet";
adi,input-depth = <8>;
adi,input-colorspace = "rgb";
@@ -272,7 +283,8 @@
hdmi@39 {
compatible = "adi,adv7513";
- reg = <0x39>;
+ reg = <0x39>, <0x29>, <0x49>, <0x59>;
+ reg-names = "main", "cec", "edid", "packet";
adi,input-depth = <8>;
adi,input-colorspace = "rgb";
diff --git a/arch/arm/boot/dts/r8a7792.dtsi b/arch/arm/boot/dts/r8a7792.dtsi
index 268987f..f44257d 100644
--- a/arch/arm/boot/dts/r8a7792.dtsi
+++ b/arch/arm/boot/dts/r8a7792.dtsi
@@ -85,6 +85,13 @@
clock-frequency = <0>;
};
+ pmu {
+ compatible = "arm,cortex-a15-pmu";
+ interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+
/* External SCIF clock */
scif_clk: scif {
compatible = "fixed-clock";
@@ -101,6 +108,16 @@
#size-cells = <2>;
ranges;
+ rwdt: watchdog@e6020000 {
+ compatible = "renesas,r8a7792-wdt",
+ "renesas,rcar-gen2-wdt";
+ reg = <0 0xe6020000 0 0x0c>;
+ clocks = <&cpg CPG_MOD 402>;
+ power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
+ resets = <&cpg 402>;
+ status = "disabled";
+ };
+
gpio0: gpio@e6050000 {
compatible = "renesas,gpio-r8a7792",
"renesas,rcar-gen2-gpio";
@@ -341,7 +358,7 @@
smp-sram@0 {
compatible = "renesas,smp-sram";
- reg = <0 0x10>;
+ reg = <0 0x100>;
};
};
diff --git a/arch/arm/boot/dts/r8a7793-gose.dts b/arch/arm/boot/dts/r8a7793-gose.dts
index 96e117d..aa209f6 100644
--- a/arch/arm/boot/dts/r8a7793-gose.dts
+++ b/arch/arm/boot/dts/r8a7793-gose.dts
@@ -599,6 +599,11 @@
status = "okay";
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&scif0 {
pinctrl-0 = <&scif0_pins>;
pinctrl-names = "default";
@@ -758,9 +763,6 @@
pinctrl-names = "default";
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
vin0ep2: endpoint {
remote-endpoint = <&adv7612_out>;
bus-width = <24>;
@@ -780,9 +782,6 @@
status = "okay";
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
vin1ep: endpoint {
remote-endpoint = <&adv7180_out>;
bus-width = <8>;
diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi
index 4f52603..4abecfc 100644
--- a/arch/arm/boot/dts/r8a7793.dtsi
+++ b/arch/arm/boot/dts/r8a7793.dtsi
@@ -110,6 +110,13 @@
clock-frequency = <0>;
};
+ pmu {
+ compatible = "arm,cortex-a15-pmu";
+ interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+
/* External SCIF clock */
scif_clk: scif {
compatible = "fixed-clock";
@@ -126,6 +133,16 @@
#size-cells = <2>;
ranges;
+ rwdt: watchdog@e6020000 {
+ compatible = "renesas,r8a7793-wdt",
+ "renesas,rcar-gen2-wdt";
+ reg = <0 0xe6020000 0 0x0c>;
+ clocks = <&cpg CPG_MOD 402>;
+ power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+ resets = <&cpg 402>;
+ status = "disabled";
+ };
+
gpio0: gpio@e6050000 {
compatible = "renesas,gpio-r8a7793",
"renesas,rcar-gen2-gpio";
@@ -392,7 +409,7 @@
smp-sram@0 {
compatible = "renesas,smp-sram";
- reg = <0 0x10>;
+ reg = <0 0x100>;
};
};
@@ -1290,6 +1307,24 @@
resets = <&cpg 408>;
};
+ fdp1@fe940000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe940000 0 0x2400>;
+ interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 119>;
+ power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+ resets = <&cpg 119>;
+ };
+
+ fdp1@fe944000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe944000 0 0x2400>;
+ interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 118>;
+ power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
+ resets = <&cpg 118>;
+ };
+
du: display@feb00000 {
compatible = "renesas,du-r8a7793";
reg = <0 0xfeb00000 0 0x40000>;
diff --git a/arch/arm/boot/dts/r8a7794-alt.dts b/arch/arm/boot/dts/r8a7794-alt.dts
index 26a8834..e170275 100644
--- a/arch/arm/boot/dts/r8a7794-alt.dts
+++ b/arch/arm/boot/dts/r8a7794-alt.dts
@@ -181,6 +181,12 @@
};
};
};
+
+ eeprom@50 {
+ compatible = "renesas,r1ex24002", "atmel,24c02";
+ reg = <0x50>;
+ pagesize = <16>;
+ };
};
/*
@@ -330,6 +336,11 @@
status = "okay";
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&sdhi0 {
pinctrl-0 = <&sdhi0_pins>;
pinctrl-1 = <&sdhi0_pins_uhs>;
@@ -375,9 +386,6 @@
pinctrl-names = "default";
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
vin0ep: endpoint {
remote-endpoint = <&adv7180>;
bus-width = <8>;
diff --git a/arch/arm/boot/dts/r8a7794-silk.dts b/arch/arm/boot/dts/r8a7794-silk.dts
index 351cb3b..7808aae 100644
--- a/arch/arm/boot/dts/r8a7794-silk.dts
+++ b/arch/arm/boot/dts/r8a7794-silk.dts
@@ -475,9 +475,6 @@
pinctrl-names = "default";
port {
- #address-cells = <1>;
- #size-cells = <0>;
-
vin0ep: endpoint {
remote-endpoint = <&adv7180>;
bus-width = <8>;
@@ -540,6 +537,11 @@
};
};
+&rwdt {
+ timeout-sec = <60>;
+ status = "okay";
+};
+
&ssi1 {
shared-pin;
};
diff --git a/arch/arm/boot/dts/r8a7794.dtsi b/arch/arm/boot/dts/r8a7794.dtsi
index d588efa..7361969 100644
--- a/arch/arm/boot/dts/r8a7794.dtsi
+++ b/arch/arm/boot/dts/r8a7794.dtsi
@@ -103,6 +103,13 @@
clock-frequency = <0>;
};
+ pmu {
+ compatible = "arm,cortex-a7-pmu";
+ interrupts-extended = <&gic GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
+ };
+
/* External SCIF clock */
scif_clk: scif {
compatible = "fixed-clock";
@@ -119,6 +126,16 @@
#size-cells = <2>;
ranges;
+ rwdt: watchdog@e6020000 {
+ compatible = "renesas,r8a7794-wdt",
+ "renesas,rcar-gen2-wdt";
+ reg = <0 0xe6020000 0 0x0c>;
+ clocks = <&cpg CPG_MOD 402>;
+ power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
+ resets = <&cpg 402>;
+ status = "disabled";
+ };
+
gpio0: gpio@e6050000 {
compatible = "renesas,gpio-r8a7794",
"renesas,rcar-gen2-gpio";
@@ -348,7 +365,7 @@
smp-sram@0 {
compatible = "renesas,smp-sram";
- reg = <0 0x10>;
+ reg = <0 0x100>;
};
};
@@ -1323,6 +1340,15 @@
resets = <&cpg 128>;
};
+ fdp1@fe940000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe940000 0 0x2400>;
+ interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 119>;
+ power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
+ resets = <&cpg 119>;
+ };
+
du: display@feb00000 {
compatible = "renesas,du-r8a7794";
reg = <0 0xfeb00000 0 0x40000>;
diff --git a/arch/arm/boot/dts/rk3036.dtsi b/arch/arm/boot/dts/rk3036.dtsi
index a974581..567a6a7 100644
--- a/arch/arm/boot/dts/rk3036.dtsi
+++ b/arch/arm/boot/dts/rk3036.dtsi
@@ -197,6 +197,8 @@
reg = <0x10118300 0x100>;
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vop_mmu";
+ clocks = <&cru ACLK_LCDC>, <&cru HCLK_LCDC>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/rk322x.dtsi b/arch/arm/boot/dts/rk322x.dtsi
index df1e478..be80e9a 100644
--- a/arch/arm/boot/dts/rk322x.dtsi
+++ b/arch/arm/boot/dts/rk322x.dtsi
@@ -584,6 +584,8 @@
reg = <0x20020800 0x100>;
interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vpu_mmu";
+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
+ clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
@@ -593,6 +595,8 @@
reg = <0x20030480 0x40>, <0x200304c0 0x40>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vdec_mmu";
+ clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>;
+ clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
@@ -602,6 +606,8 @@
reg = <0x20053f00 0x100>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vop_mmu";
+ clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
+ clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
@@ -611,6 +617,8 @@
reg = <0x20070800 0x100>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "iep_mmu";
+ clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>;
+ clock-names = "aclk", "iface";
iommu-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/rk3288-phycore-som.dtsi b/arch/arm/boot/dts/rk3288-phycore-som.dtsi
index f13bcb1..aaab2d1 100644
--- a/arch/arm/boot/dts/rk3288-phycore-som.dtsi
+++ b/arch/arm/boot/dts/rk3288-phycore-som.dtsi
@@ -151,6 +151,7 @@
ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
enet-phy-lane-no-swap;
+ ti,clk-output-sel = <DP83867_CLK_O_SEL_CHN_A_TCLK>;
};
};
};
diff --git a/arch/arm/boot/dts/rk3288-tinker.dts b/arch/arm/boot/dts/rk3288-tinker.dts
index 346b0d8..127488f 100644
--- a/arch/arm/boot/dts/rk3288-tinker.dts
+++ b/arch/arm/boot/dts/rk3288-tinker.dts
@@ -49,6 +49,10 @@
model = "Rockchip RK3288 Tinker Board";
compatible = "asus,rk3288-tinker", "rockchip,rk3288";
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
memory {
reg = <0x0 0x0 0x0 0x80000000>;
device_type = "memory";
diff --git a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi
index be48711..b16d570 100644
--- a/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi
+++ b/arch/arm/boot/dts/rk3288-veyron-chromebook.dtsi
@@ -95,7 +95,8 @@
pinctrl-names = "default";
pinctrl-0 = <&bl_en>;
pwms = <&pwm0 0 1000000 0>;
- pwm-delay-us = <10000>;
+ post-pwm-on-delay-ms = <10>;
+ pwm-off-delay-ms = <10>;
};
gpio-charger {
diff --git a/arch/arm/boot/dts/rk3288-veyron-minnie.dts b/arch/arm/boot/dts/rk3288-veyron-minnie.dts
index 544de60..4c5307e6 100644
--- a/arch/arm/boot/dts/rk3288-veyron-minnie.dts
+++ b/arch/arm/boot/dts/rk3288-veyron-minnie.dts
@@ -123,6 +123,8 @@
240 241 242 243 244 245 246 247
248 249 250 251 252 253 254 255>;
power-supply = <&backlight_regulator>;
+ post-pwm-on-delay-ms = <200>;
+ pwm-off-delay-ms = <200>;
};
&emmc {
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index 354aff4..d7e49d2 100644
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -959,6 +959,8 @@
reg = <0x0 0xff900800 0x0 0x40>;
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "iep_mmu";
+ clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -968,6 +970,8 @@
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "isp_mmu";
+ clocks = <&cru ACLK_ISP>, <&cru HCLK_ISP>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
rockchip,disable-mmu-reset;
status = "disabled";
@@ -1027,6 +1031,8 @@
reg = <0x0 0xff930300 0x0 0x100>;
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vopb_mmu";
+ clocks = <&cru ACLK_VOP0>, <&cru HCLK_VOP0>;
+ clock-names = "aclk", "iface";
power-domains = <&power RK3288_PD_VIO>;
#iommu-cells = <0>;
status = "disabled";
@@ -1075,6 +1081,8 @@
reg = <0x0 0xff940300 0x0 0x100>;
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vopl_mmu";
+ clocks = <&cru ACLK_VOP1>, <&cru HCLK_VOP1>;
+ clock-names = "aclk", "iface";
power-domains = <&power RK3288_PD_VIO>;
#iommu-cells = <0>;
status = "disabled";
@@ -1206,6 +1214,8 @@
reg = <0x0 0xff9a0800 0x0 0x100>;
interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vpu_mmu";
+ clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -1215,6 +1225,8 @@
reg = <0x0 0xff9c0440 0x0 0x40>, <0x0 0xff9c0480 0x0 0x40>;
interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hevc_mmu";
+ clocks = <&cru ACLK_HEVC>, <&cru HCLK_HEVC>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -1848,16 +1860,16 @@
uart4 {
uart4_xfer: uart4-xfer {
- rockchip,pins = <5 12 3 &pcfg_pull_up>,
- <5 13 3 &pcfg_pull_none>;
+ rockchip,pins = <5 15 3 &pcfg_pull_up>,
+ <5 14 3 &pcfg_pull_none>;
};
uart4_cts: uart4-cts {
- rockchip,pins = <5 14 3 &pcfg_pull_up>;
+ rockchip,pins = <5 12 3 &pcfg_pull_up>;
};
uart4_rts: uart4-rts {
- rockchip,pins = <5 15 3 &pcfg_pull_none>;
+ rockchip,pins = <5 13 3 &pcfg_pull_none>;
};
};
diff --git a/arch/arm/boot/dts/s3c2416-smdk2416.dts b/arch/arm/boot/dts/s3c2416-smdk2416.dts
index a1c9d8c..5164386 100644
--- a/arch/arm/boot/dts/s3c2416-smdk2416.dts
+++ b/arch/arm/boot/dts/s3c2416-smdk2416.dts
@@ -12,14 +12,13 @@
model = "SMDK2416";
compatible = "samsung,s3c2416";
- memory {
+ memory@30000000 {
+ device_type = "memory";
reg = <0x30000000 0x4000000>;
};
clocks {
compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
xti: xti {
compatible = "fixed-clock";
diff --git a/arch/arm/boot/dts/s3c2416.dtsi b/arch/arm/boot/dts/s3c2416.dtsi
index 3c7385c..6adf64e 100644
--- a/arch/arm/boot/dts/s3c2416.dtsi
+++ b/arch/arm/boot/dts/s3c2416.dtsi
@@ -18,9 +18,6 @@
};
cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
cpu {
compatible = "arm,arm926ej-s";
};
@@ -30,7 +27,7 @@
compatible = "samsung,s3c2416-irq";
};
- clocks: clock-controller@0x4c000000 {
+ clocks: clock-controller@4c000000 {
compatible = "samsung,s3c2416-clock";
reg = <0x4c000000 0x40>;
#clock-cells = <1>;
@@ -69,7 +66,7 @@
<&clocks SCLK_UART>;
};
- uart_3: serial@5000C000 {
+ uart_3: serial@5000c000 {
compatible = "samsung,s3c2440-uart";
reg = <0x5000C000 0x4000>;
interrupts = <1 18 24 4>, <1 18 25 4>;
@@ -80,7 +77,7 @@
status = "disabled";
};
- sdhci_1: sdhci@4AC00000 {
+ sdhci_1: sdhci@4ac00000 {
compatible = "samsung,s3c6410-sdhci";
reg = <0x4AC00000 0x100>;
interrupts = <0 0 21 3>;
@@ -91,7 +88,7 @@
status = "disabled";
};
- sdhci_0: sdhci@4A800000 {
+ sdhci_0: sdhci@4a800000 {
compatible = "samsung,s3c6410-sdhci";
reg = <0x4A800000 0x100>;
interrupts = <0 0 20 3>;
diff --git a/arch/arm/boot/dts/s3c24xx.dtsi b/arch/arm/boot/dts/s3c24xx.dtsi
index 34c7fe6..6d8dd3c 100644
--- a/arch/arm/boot/dts/s3c24xx.dtsi
+++ b/arch/arm/boot/dts/s3c24xx.dtsi
@@ -5,11 +5,11 @@
* Copyright (c) 2013 Heiko Stuebner <heiko@sntech.de>
*/
-#include "skeleton.dtsi"
-
/ {
compatible = "samsung,s3c24xx";
interrupt-parent = <&intc>;
+ #address-cells = <1>;
+ #size-cells = <1>;
aliases {
pinctrl0 = &pinctrl_0;
diff --git a/arch/arm/boot/dts/s3c6410-mini6410.dts b/arch/arm/boot/dts/s3c6410-mini6410.dts
index f68601b..0e159c8 100644
--- a/arch/arm/boot/dts/s3c6410-mini6410.dts
+++ b/arch/arm/boot/dts/s3c6410-mini6410.dts
@@ -19,7 +19,8 @@
model = "FriendlyARM Mini6410 board based on S3C6410";
compatible = "friendlyarm,mini6410", "samsung,s3c6410";
- memory {
+ memory@50000000 {
+ device_type = "memory";
reg = <0x50000000 0x10000000>;
};
diff --git a/arch/arm/boot/dts/s3c6410-smdk6410.dts b/arch/arm/boot/dts/s3c6410-smdk6410.dts
index b6b5afc..a9a5689 100644
--- a/arch/arm/boot/dts/s3c6410-smdk6410.dts
+++ b/arch/arm/boot/dts/s3c6410-smdk6410.dts
@@ -19,7 +19,8 @@
model = "SAMSUNG SMDK6410 board based on S3C6410";
compatible = "samsung,mini6410", "samsung,s3c6410";
- memory {
+ memory@50000000 {
+ device_type = "memory";
reg = <0x50000000 0x8000000>;
};
diff --git a/arch/arm/boot/dts/s3c64xx.dtsi b/arch/arm/boot/dts/s3c64xx.dtsi
index e2be3fb..2e611df 100644
--- a/arch/arm/boot/dts/s3c64xx.dtsi
+++ b/arch/arm/boot/dts/s3c64xx.dtsi
@@ -13,10 +13,12 @@
* nodes can be added to this file.
*/
-#include "skeleton.dtsi"
#include <dt-bindings/clock/samsung,s3c64xx-clock.h>
/ {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
aliases {
i2c0 = &i2c0;
pinctrl0 = &pinctrl0;
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
index 914a7c2..c953648 100644
--- a/arch/arm/boot/dts/sh73a0.dtsi
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -22,7 +22,7 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
@@ -31,7 +31,7 @@
power-domains = <&pd_a2sl>;
next-level-cache = <&L2>;
};
- cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <1>;
@@ -91,6 +91,7 @@
compatible = "arm,cortex-a9-pmu";
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
};
cmt1: timer@e6138000 {
@@ -336,7 +337,7 @@
GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks SH73A0_CLK_SDHI1>;
power-domains = <&pd_a3sp>;
- toshiba,mmc-wrprotect-disable;
+ disable-wp;
cap-sd-highspeed;
status = "disabled";
};
@@ -348,7 +349,7 @@
GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks SH73A0_CLK_SDHI2>;
power-domains = <&pd_a3sp>;
- toshiba,mmc-wrprotect-disable;
+ disable-wp;
cap-sd-highspeed;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/ste-ccu8540-pinctrl.dtsi b/arch/arm/boot/dts/ste-ccu8540-pinctrl.dtsi
deleted file mode 100644
index 52dba2e..0000000
--- a/arch/arm/boot/dts/ste-ccu8540-pinctrl.dtsi
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2012 ST-Ericsson
- *
- * 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 "ste-nomadik-pinctrl.dtsi"
-
-/ {
- soc {
- pinctrl {
- uart0 {
- uart0_default_mux: uart0_mux {
- default_mux {
- function = "u0";
- groups = "u0_a_1";
- };
- };
-
- uart0_default_mode: uart0_default {
- default_cfg1 {
- pins = "GPIO0", "GPIO2";
- ste,config = <&in_pu>;
- };
-
- default_cfg2 {
- pins = "GPIO1", "GPIO3";
- ste,config = <&out_hi>;
- };
- };
-
- uart0_sleep_mode: uart0_sleep {
- sleep_cfg1 {
- pins = "GPIO0", "GPIO2";
- ste,config = <&slpm_in_pu>;
- };
-
- sleep_cfg2 {
- pins = "GPIO1", "GPIO3";
- ste,config = <&slpm_out_hi>;
- };
- };
- };
-
- uart2 {
- uart2_default_mode: uart2_default {
- default_mux {
- function = "u2";
- groups = "u2txrx_a_1";
- };
-
- default_cfg1 {
- pins = "GPIO120";
- ste,config = <&in_pu>;
- };
-
- default_cfg2 {
- pins = "GPIO121";
- ste,config = <&out_hi>;
- };
- };
-
- uart2_sleep_mode: uart2_sleep {
- sleep_cfg1 {
- pins = "GPIO120";
- ste,config = <&slpm_in_pu>;
- };
-
- sleep_cfg2 {
- pins = "GPIO121";
- ste,config = <&slpm_out_hi>;
- };
- };
- };
-
- i2c0 {
- i2c0_default_mux: i2c_mux {
- default_mux {
- function = "i2c0";
- groups = "i2c0_a_1";
- };
- };
-
- i2c0_default_mode: i2c_default {
- default_cfg1 {
- pins = "GPIO147", "GPIO148";
- ste,config = <&in_pu>;
- };
- };
-
- i2c0_sleep_mode: i2c_sleep {
- sleep_cfg1 {
- pins = "GPIO147", "GPIO148";
- ste,config = <&slpm_in_pu>;
- };
- };
- };
-
- i2c1 {
- i2c1_default_mux: i2c_mux {
- default_mux {
- function = "i2c1";
- groups = "i2c1_b_2";
- };
- };
-
- i2c1_default_mode: i2c_default {
- default_cfg1 {
- pins = "GPIO16", "GPIO17";
- ste,config = <&in_pu>;
- };
- };
-
- i2c1_sleep_mode: i2c_sleep {
- sleep_cfg1 {
- pins = "GPIO16", "GPIO17";
- ste,config = <&slpm_in_pu>;
- };
- };
- };
-
- i2c2 {
- i2c2_default_mux: i2c_mux {
- default_mux {
- function = "i2c2";
- groups = "i2c2_b_2";
- };
- };
-
- i2c2_default_mode: i2c_default {
- default_cfg1 {
- pins = "GPIO10", "GPIO11";
- ste,config = <&in_pu>;
- };
- };
-
- i2c2_sleep_mode: i2c_sleep {
- sleep_cfg1 {
- pins = "GPIO11", "GPIO11";
- ste,config = <&slpm_in_pu>;
- };
- };
- };
-
- i2c4 {
- i2c4_default_mux: i2c_mux {
- default_mux {
- function = "i2c4";
- groups = "i2c4_b_2";
- };
- };
-
- i2c4_default_mode: i2c_default {
- default_cfg1 {
- pins = "GPIO122", "GPIO123";
- ste,config = <&in_pu>;
- };
- };
-
- i2c4_sleep_mode: i2c_sleep {
- sleep_cfg1 {
- pins = "GPIO122", "GPIO123";
- ste,config = <&slpm_in_pu>;
- };
- };
- };
-
- i2c5 {
- i2c5_default_mux: i2c_mux {
- default_mux {
- function = "i2c5";
- groups = "i2c5_c_2";
- };
- };
-
- i2c5_default_mode: i2c_default {
- default_cfg1 {
- pins = "GPIO118", "GPIO119";
- ste,config = <&in_pu>;
- };
- };
-
- i2c5_sleep_mode: i2c_sleep {
- sleep_cfg1 {
- pins = "GPIO118", "GPIO119";
- ste,config = <&slpm_in_pu>;
- };
- };
- };
- };
- };
-};
diff --git a/arch/arm/boot/dts/ste-ccu8540.dts b/arch/arm/boot/dts/ste-ccu8540.dts
deleted file mode 100644
index 6eaaf63..0000000
--- a/arch/arm/boot/dts/ste-ccu8540.dts
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2013 ST-Ericsson AB
- *
- * 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 "ste-dbx5x0.dtsi"
-#include "ste-ccu8540-pinctrl.dtsi"
-
-/ {
- model = "ST-Ericsson U8540 platform with Device Tree";
- compatible = "st-ericsson,ccu8540", "st-ericsson,u8540";
-
- /* This stablilizes the serial port enumeration */
- aliases {
- serial0 = &ux500_serial0;
- serial1 = &ux500_serial1;
- serial2 = &ux500_serial2;
- };
-
- memory@0 {
- device_type = "memory";
- reg = <0x20000000 0x1f000000>, <0xc0000000 0x3f000000>;
- };
-
- soc {
- pinctrl {
- compatible = "stericsson,db8540-pinctrl";
- };
-
- prcmu@80157000 {
- reg = <0x80157000 0x2000>, <0x801b0000 0x8000>, <0x801b8000 0x3000>;
- reg-names = "prcmu", "prcmu-tcpm", "prcmu-tcdm";
- };
-
- uart@80120000 {
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&uart0_default_mux>, <&uart0_default_mode>;
- pinctrl-1 = <&uart0_sleep_mode>;
- status = "okay";
- };
-
- uart@80121000 {
- status = "okay";
- };
-
- uart@80007000 {
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&uart2_default_mode>;
- pinctrl-1 = <&uart2_sleep_mode>;
- status = "okay";
- };
-
- i2c0: i2c@80004000 {
- pinctrl-names = "default","sleep";
- pinctrl-0 = <&i2c0_default_mux>, <&i2c0_default_mode>;
- pinctrl-1 = <&i2c0_sleep_mode>;
- };
-
- i2c1: i2c@80122000 {
- pinctrl-names = "default","sleep";
- pinctrl-0 = <&i2c1_default_mux>, <&i2c1_default_mode>;
- pinctrl-1 = <&i2c1_sleep_mode>;
- };
-
- i2c2: i2c@80128000 {
- pinctrl-names = "default","sleep";
- pinctrl-0 = <&i2c2_default_mux>, <&i2c2_default_mode>;
- pinctrl-1 = <&i2c2_sleep_mode>;
- };
-
- i2c3: i2c@80110000 {
- status = "disabled";
- };
-
- i2c4: i2c@8012a000 {
- pinctrl-names = "default","sleep";
- pinctrl-0 = <&i2c4_default_mux>, <&i2c4_default_mode>;
- pinctrl-1 = <&i2c4_sleep_mode>;
- };
-
- i2c5: i2c@80001000 {
- pinctrl-names = "default","sleep";
- pinctrl-0 = <&i2c5_default_mux>, <&i2c5_default_mode>;
- pinctrl-1 = <&i2c5_sleep_mode>;
- };
- };
-};
diff --git a/arch/arm/boot/dts/ste-ccu9540.dts b/arch/arm/boot/dts/ste-ccu9540.dts
deleted file mode 100644
index b3b9bb8..0000000
--- a/arch/arm/boot/dts/ste-ccu9540.dts
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2012 ST-Ericsson AB
- *
- * 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 "ste-dbx5x0.dtsi"
-
-/ {
- model = "ST-Ericsson CCU9540 platform with Device Tree";
- compatible = "st-ericsson,ccu9540", "st-ericsson,u9540";
-
- /* This stablilizes the serial port enumeration */
- aliases {
- serial0 = &ux500_serial0;
- serial1 = &ux500_serial1;
- serial2 = &ux500_serial2;
- };
-
- memory {
- reg = <0x00000000 0x20000000>;
- };
-
- soc {
- uart@80120000 {
- status = "okay";
- };
-
- uart@80121000 {
- status = "okay";
- };
-
- uart@80007000 {
- status = "okay";
- };
-
- // External Micro SD slot
- sdi0_per1@80126000 {
- arm,primecell-periphid = <0x10480180>;
- max-frequency = <100000000>;
- bus-width = <4>;
- cap-sd-highspeed;
- cap-mmc-highspeed;
- vmmc-supply = <&ab8500_ldo_aux3_reg>;
-
- cd-gpios = <&gpio7 6 GPIO_ACTIVE_HIGH>; // 230
- cd-inverted;
-
- status = "okay";
- };
-
-
- // WLAN SDIO channel
- sdi1_per2@80118000 {
- arm,primecell-periphid = <0x10480180>;
- max-frequency = <100000000>;
- bus-width = <4>;
-
- status = "okay";
- };
-
- // On-board eMMC
- sdi4_per2@80114000 {
- arm,primecell-periphid = <0x10480180>;
- max-frequency = <100000000>;
- bus-width = <8>;
- cap-mmc-highspeed;
- vmmc-supply = <&ab8500_ldo_aux2_reg>;
-
- status = "okay";
- };
- };
-};
diff --git a/arch/arm/boot/dts/ste-snowball.dts b/arch/arm/boot/dts/ste-snowball.dts
index ade1d0d..b0b94d0 100644
--- a/arch/arm/boot/dts/ste-snowball.dts
+++ b/arch/arm/boot/dts/ste-snowball.dts
@@ -46,35 +46,35 @@
#size-cells = <0>;
button@1 {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <2>;
label = "userpb";
gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
};
button@2 {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <3>;
label = "extkb1";
gpios = <&gpio4 23 GPIO_ACTIVE_HIGH>;
};
button@3 {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <4>;
label = "extkb2";
gpios = <&gpio4 24 GPIO_ACTIVE_HIGH>;
};
button@4 {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <5>;
label = "extkb3";
gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
};
button@5 {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <6>;
label = "extkb4";
diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
index f7362c3..9e29a44 100644
--- a/arch/arm/boot/dts/stih407-family.dtsi
+++ b/arch/arm/boot/dts/stih407-family.dtsi
@@ -206,19 +206,19 @@
vtg_main: sti-vtg-main@8d02800 {
compatible = "st,vtg";
reg = <0x8d02800 0x200>;
- interrupts = <GIC_SPI 108 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
};
vtg_aux: sti-vtg-aux@8d00200 {
compatible = "st,vtg";
reg = <0x8d00200 0x100>;
- interrupts = <GIC_SPI 109 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
};
serial@9830000 {
compatible = "st,asc";
reg = <0x9830000 0x2c>;
- interrupts = <GIC_SPI 122 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
/* Pinctrl moved out to a per-board configuration */
@@ -228,7 +228,7 @@
serial@9831000 {
compatible = "st,asc";
reg = <0x9831000 0x2c>;
- interrupts = <GIC_SPI 123 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_serial1>;
clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
@@ -239,7 +239,7 @@
serial@9832000 {
compatible = "st,asc";
reg = <0x9832000 0x2c>;
- interrupts = <GIC_SPI 124 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_serial2>;
clocks = <&clk_s_c0_flexgen CLK_EXT2F_A9>;
@@ -251,7 +251,7 @@
sbc_serial0: serial@9530000 {
compatible = "st,asc";
reg = <0x9530000 0x2c>;
- interrupts = <GIC_SPI 138 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sbc_serial0>;
clocks = <&clk_sysin>;
@@ -262,7 +262,7 @@
serial@9531000 {
compatible = "st,asc";
reg = <0x9531000 0x2c>;
- interrupts = <GIC_SPI 139 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sbc_serial1>;
clocks = <&clk_sysin>;
@@ -574,7 +574,7 @@
status = "disabled";
reg = <0x09060000 0x7ff>, <0x9061008 0x20>;
reg-names = "mmc", "top-mmc-delay";
- interrupts = <GIC_SPI 92 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "mmcirq";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mmc0>;
@@ -589,7 +589,7 @@
status = "disabled";
reg = <0x09080000 0x7ff>;
reg-names = "mmc";
- interrupts = <GIC_SPI 90 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "mmcirq";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sd1>;
@@ -623,7 +623,7 @@
compatible = "st,ahci";
reg = <0x9b20000 0x1000>;
- interrupts = <GIC_SPI 159 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hostc";
phys = <&phy_port0 PHY_TYPE_SATA>;
@@ -646,7 +646,7 @@
compatible = "st,ahci";
reg = <0x9b28000 0x1000>;
- interrupts = <GIC_SPI 170 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hostc";
phys = <&phy_port1 PHY_TYPE_SATA>;
@@ -687,7 +687,7 @@
dwc3: dwc3@9900000 {
compatible = "snps,dwc3";
reg = <0x09900000 0x100000>;
- interrupts = <GIC_SPI 155 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
dr_mode = "host";
phy-names = "usb2-phy", "usb3-phy";
phys = <&usb2_picophy0>,
@@ -701,7 +701,7 @@
compatible = "st,sti-pwm";
#pwm-cells = <2>;
reg = <0x9810000 0x68>;
- interrupts = <GIC_SPI 128 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm0_chan0_default>;
clock-names = "pwm";
@@ -716,7 +716,7 @@
compatible = "st,sti-pwm";
#pwm-cells = <2>;
reg = <0x9510000 0x68>;
- interrupts = <GIC_SPI 131 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm1_chan0_default
&pinctrl_pwm1_chan1_default
@@ -755,8 +755,8 @@
resets = <&softreset STIH407_ETH1_SOFTRESET>;
reset-names = "stmmaceth";
- interrupts = <GIC_SPI 98 IRQ_TYPE_NONE>,
- <GIC_SPI 99 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq", "eth_wake_irq";
/* DMA Bus Mode */
@@ -787,7 +787,7 @@
mailbox0: mailbox@8f00000 {
compatible = "st,stih407-mailbox";
reg = <0x8f00000 0x1000>;
- interrupts = <GIC_SPI 1 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
#mbox-cells = <2>;
mbox-name = "a9";
status = "okay";
@@ -857,7 +857,7 @@
<&clk_s_c0_flexgen CLK_EXT2F_A9>,
<&clk_s_c0_flexgen CLK_EXT2F_A9>,
<&clk_s_c0_flexgen CLK_EXT2F_A9>;
- interrupts = <GIC_SPI 5 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
dma-channels = <16>;
#dma-cells = <3>;
};
@@ -875,7 +875,7 @@
<&clk_s_c0_flexgen CLK_TX_ICN_DMU>,
<&clk_s_c0_flexgen CLK_EXT2F_A9>;
- interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
dma-channels = <16>;
#dma-cells = <3>;
@@ -890,7 +890,7 @@
<0x8e77000 0x1000>,
<0x8e78000 0x8000>;
reg-names = "slimcore", "dmem", "peripherals", "imem";
- interrupts = <GIC_SPI 9 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
dma-channels = <16>;
#dma-cells = <3>;
clocks = <&clk_s_c0_flexgen CLK_FDMA>,
@@ -910,7 +910,7 @@
assigned-clock-parents = <0>, <&clk_s_d0_quadfs 0>;
assigned-clock-rates = <50000000>;
reg = <0x8d80000 0x158>;
- interrupts = <GIC_SPI 84 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&fdma0 2 0 1>;
dma-names = "tx";
@@ -926,7 +926,7 @@
assigned-clock-parents = <0>, <&clk_s_d0_quadfs 1>;
assigned-clock-rates = <50000000>;
reg = <0x8d81000 0x158>;
- interrupts = <GIC_SPI 85 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&fdma0 3 0 1>;
dma-names = "tx";
@@ -942,7 +942,7 @@
assigned-clock-parents = <0>, <&clk_s_d0_quadfs 2>;
assigned-clock-rates = <50000000>;
reg = <0x8d82000 0x158>;
- interrupts = <GIC_SPI 86 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&fdma0 4 0 1>;
dma-names = "tx";
@@ -958,7 +958,7 @@
assigned-clock-parents = <0>, <&clk_s_d0_quadfs 3>;
assigned-clock-rates = <50000000>;
reg = <0x8d85000 0x158>;
- interrupts = <GIC_SPI 89 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&fdma0 7 0 1>;
dma-names = "tx";
@@ -970,7 +970,7 @@
#sound-dai-cells = <0>;
st,syscfg = <&syscfg_core>;
reg = <0x8d83000 0x158>;
- interrupts = <GIC_SPI 87 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&fdma0 5 0 1>;
dma-names = "rx";
@@ -982,7 +982,7 @@
#sound-dai-cells = <0>;
st,syscfg = <&syscfg_core>;
reg = <0x8d84000 0x158>;
- interrupts = <GIC_SPI 88 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&fdma0 6 0 1>;
dma-names = "rx";
diff --git a/arch/arm/boot/dts/stih407-pinctrl.dtsi b/arch/arm/boot/dts/stih407-pinctrl.dtsi
index 53c6888..e393519 100644
--- a/arch/arm/boot/dts/stih407-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stih407-pinctrl.dtsi
@@ -52,7 +52,7 @@
st,syscfg = <&syscfg_sbc>;
reg = <0x0961f080 0x4>;
reg-names = "irqmux";
- interrupts = <GIC_SPI 188 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irqmux";
ranges = <0 0x09610000 0x6000>;
@@ -376,7 +376,7 @@
st,syscfg = <&syscfg_front>;
reg = <0x0920f080 0x4>;
reg-names = "irqmux";
- interrupts = <GIC_SPI 189 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irqmux";
ranges = <0 0x09200000 0x10000>;
@@ -936,7 +936,7 @@
st,syscfg = <&syscfg_front>;
reg = <0x0921f080 0x4>;
reg-names = "irqmux";
- interrupts = <GIC_SPI 190 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irqmux";
ranges = <0 0x09210000 0x10000>;
@@ -969,7 +969,7 @@
st,syscfg = <&syscfg_rear>;
reg = <0x0922f080 0x4>;
reg-names = "irqmux";
- interrupts = <GIC_SPI 191 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irqmux";
ranges = <0 0x09220000 0x6000>;
@@ -1164,7 +1164,7 @@
st,syscfg = <&syscfg_flash>;
reg = <0x0923f080 0x4>;
reg-names = "irqmux";
- interrupts = <GIC_SPI 192 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irqmux";
ranges = <0 0x09230000 0x3000>;
diff --git a/arch/arm/boot/dts/stih407.dtsi b/arch/arm/boot/dts/stih407.dtsi
index 57efc87..5b7951f 100644
--- a/arch/arm/boot/dts/stih407.dtsi
+++ b/arch/arm/boot/dts/stih407.dtsi
@@ -108,7 +108,7 @@
reg = <0x8d04000 0x1000>;
reg-names = "hdmi-reg";
#sound-dai-cells = <0>;
- interrupts = <GIC_SPI 106 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irq";
clock-names = "pix",
"tmds",
diff --git a/arch/arm/boot/dts/stih410.dtsi b/arch/arm/boot/dts/stih410.dtsi
index 3313005..888548e 100644
--- a/arch/arm/boot/dts/stih410.dtsi
+++ b/arch/arm/boot/dts/stih410.dtsi
@@ -43,7 +43,7 @@
ohci0: usb@9a03c00 {
compatible = "st,st-ohci-300x";
reg = <0x9a03c00 0x100>;
- interrupts = <GIC_SPI 180 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 180 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
<&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>;
resets = <&powerdown STIH407_USB2_PORT0_POWERDOWN>,
@@ -58,7 +58,7 @@
ehci0: usb@9a03e00 {
compatible = "st,st-ehci-300x";
reg = <0x9a03e00 0x100>;
- interrupts = <GIC_SPI 151 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb0>;
clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
@@ -75,7 +75,7 @@
ohci1: usb@9a83c00 {
compatible = "st,st-ohci-300x";
reg = <0x9a83c00 0x100>;
- interrupts = <GIC_SPI 181 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
<&clk_s_c0_flexgen CLK_RX_ICN_DISP_0>;
resets = <&powerdown STIH407_USB2_PORT1_POWERDOWN>,
@@ -90,7 +90,7 @@
ehci1: usb@9a83e00 {
compatible = "st,st-ehci-300x";
reg = <0x9a83e00 0x100>;
- interrupts = <GIC_SPI 153 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usb1>;
clocks = <&clk_s_c0_flexgen CLK_TX_ICN_DISP_0>,
@@ -202,7 +202,7 @@
reg = <0x8d04000 0x1000>;
reg-names = "hdmi-reg";
#sound-dai-cells = <0>;
- interrupts = <GIC_SPI 106 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "irq";
clock-names = "pix",
"tmds",
@@ -254,7 +254,7 @@
bdisp0:bdisp@9f10000 {
compatible = "st,stih407-bdisp";
reg = <0x9f10000 0x1000>;
- interrupts = <GIC_SPI 38 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "bdisp";
clocks = <&clk_s_c0_flexgen CLK_IC_BDISP_0>;
};
@@ -263,8 +263,8 @@
compatible = "st,st-hva";
reg = <0x8c85000 0x400>, <0x6000000 0x40000>;
reg-names = "hva_registers", "hva_esram";
- interrupts = <GIC_SPI 58 IRQ_TYPE_NONE>,
- <GIC_SPI 59 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "clk_hva";
clocks = <&clk_s_c0_flexgen CLK_HVA>;
};
@@ -292,7 +292,7 @@
reg = <0x94a087c 0x64>;
clocks = <&clk_sysin>;
clock-names = "cec-clk";
- interrupts = <GIC_SPI 140 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "cec-irq";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_cec0_default>;
diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi
index c67edb1..4dedfcb 100644
--- a/arch/arm/boot/dts/stihxxx-b2120.dtsi
+++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi
@@ -154,8 +154,8 @@
reg = <0x08a20000 0x10000>,
<0x08a00000 0x4000>;
reg-names = "c8sectpfe", "c8sectpfe-ram";
- interrupts = <GIC_SPI 34 IRQ_TYPE_NONE>,
- <GIC_SPI 35 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "c8sectpfe-error-irq",
"c8sectpfe-idle-irq";
pinctrl-0 = <&pinctrl_tsin0_serial>;
diff --git a/arch/arm/boot/dts/stm32f469-disco.dts b/arch/arm/boot/dts/stm32f469-disco.dts
index 2f76726..3ee768c 100644
--- a/arch/arm/boot/dts/stm32f469-disco.dts
+++ b/arch/arm/boot/dts/stm32f469-disco.dts
@@ -46,7 +46,7 @@
*/
/dts-v1/;
-#include "stm32f429.dtsi"
+#include "stm32f469.dtsi"
#include "stm32f469-pinctrl.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
@@ -112,7 +112,7 @@
vcc5v_otg: vcc5v-otg-regulator {
compatible = "regulator-fixed";
enable-active-high;
- gpio = <&gpiob 2 0>;
+ gpio = <&gpiob 2 GPIO_ACTIVE_HIGH>;
regulator-name = "vcc5_host1";
regulator-always-on;
};
@@ -126,6 +126,55 @@
clock-frequency = <8000000>;
};
+&dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi_in: endpoint {
+ remote-endpoint = <&ltdc_out_dsi>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi_out: endpoint {
+ remote-endpoint = <&dsi_panel_in>;
+ };
+ };
+ };
+
+ panel-dsi@0 {
+ compatible = "orisetech,otm8009a";
+ reg = <0>; /* dsi virtual channel (0..3) */
+ reset-gpios = <&gpioh 7 GPIO_ACTIVE_LOW>;
+ status = "okay";
+
+ port {
+ dsi_panel_in: endpoint {
+ remote-endpoint = <&dsi_out>;
+ };
+ };
+ };
+};
+
+&ltdc {
+ dma-ranges;
+ status = "okay";
+
+ port {
+ ltdc_out_dsi: endpoint@0 {
+ remote-endpoint = <&dsi_in>;
+ };
+ };
+};
+
&rtc {
status = "okay";
};
diff --git a/arch/arm/boot/dts/stm32f469.dtsi b/arch/arm/boot/dts/stm32f469.dtsi
new file mode 100644
index 0000000..5ae5213
--- /dev/null
+++ b/arch/arm/boot/dts/stm32f469.dtsi
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/* Copyright (C) STMicroelectronics 2017 - All Rights Reserved */
+
+#include "stm32f429.dtsi"
+
+/ {
+ soc {
+ dsi: dsi@40016c00 {
+ compatible = "st,stm32-dsi";
+ reg = <0x40016c00 0x800>;
+ interrupts = <92>;
+ resets = <&rcc STM32F4_APB2_RESET(DSI)>;
+ reset-names = "apb";
+ clocks = <&rcc 1 CLK_F469_DSI>, <&clk_hse>;
+ clock-names = "pclk", "ref";
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/stm32f746-disco.dts b/arch/arm/boot/dts/stm32f746-disco.dts
index be94c6a..f9ad71f 100644
--- a/arch/arm/boot/dts/stm32f746-disco.dts
+++ b/arch/arm/boot/dts/stm32f746-disco.dts
@@ -90,6 +90,14 @@
clock-frequency = <25000000>;
};
+&i2c1 {
+ pinctrl-0 = <&i2c1_pins_b>;
+ pinctrl-names = "default";
+ i2c-scl-rising-time-ns = <185>;
+ i2c-scl-falling-time-ns = <20>;
+ status = "okay";
+};
+
&sdio1 {
status = "okay";
vmmc-supply = <&mmc_vcard>;
diff --git a/arch/arm/boot/dts/stm32f746.dtsi b/arch/arm/boot/dts/stm32f746.dtsi
index 4be2ee5..1479e3e 100644
--- a/arch/arm/boot/dts/stm32f746.dtsi
+++ b/arch/arm/boot/dts/stm32f746.dtsi
@@ -345,6 +345,42 @@
status = "disabled";
};
+ i2c2: i2c@40005800 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x40005800 0x400>;
+ interrupts = <33>,
+ <34>;
+ resets = <&rcc STM32F7_APB1_RESET(I2C2)>;
+ clocks = <&rcc 1 CLK_I2C2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@40005C00 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x40005C00 0x400>;
+ interrupts = <72>,
+ <73>;
+ resets = <&rcc STM32F7_APB1_RESET(I2C3)>;
+ clocks = <&rcc 1 CLK_I2C3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@40006000 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x40006000 0x400>;
+ interrupts = <95>,
+ <96>;
+ resets = <&rcc STM32F7_APB1_RESET(I2C4)>;
+ clocks = <&rcc 1 CLK_I2C4>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
cec: cec@40006c00 {
compatible = "st,stm32-cec";
reg = <0x40006C00 0x400>;
diff --git a/arch/arm/boot/dts/stm32f769-disco.dts b/arch/arm/boot/dts/stm32f769-disco.dts
index 2241eec..677276ba 100644
--- a/arch/arm/boot/dts/stm32f769-disco.dts
+++ b/arch/arm/boot/dts/stm32f769-disco.dts
@@ -111,6 +111,14 @@
clock-frequency = <25000000>;
};
+&i2c1 {
+ pinctrl-0 = <&i2c1_pins_b>;
+ pinctrl-names = "default";
+ i2c-scl-rising-time-ns = <185>;
+ i2c-scl-falling-time-ns = <20>;
+ status = "okay";
+};
+
&rtc {
status = "okay";
};
diff --git a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
index 0f15dfb..24be8e6 100644
--- a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
@@ -163,6 +163,16 @@
#interrupt-cells = <2>;
};
+ i2c1_pins_a: i2c1@0 {
+ pins {
+ pinmux = <STM32_PINMUX('B', 6, AF4)>, /* I2C1_SCL */
+ <STM32_PINMUX('B', 7, AF4)>; /* I2C1_SDA */
+ bias-disable;
+ drive-open-drain;
+ slew-rate = <0>;
+ };
+ };
+
usart1_pins: usart1@0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF4)>; /* USART1_TX */
diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi
index 2bb103e..637beff 100644
--- a/arch/arm/boot/dts/stm32h743.dtsi
+++ b/arch/arm/boot/dts/stm32h743.dtsi
@@ -86,6 +86,7 @@
pwm {
compatible = "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -130,6 +131,42 @@
clocks = <&rcc USART2_CK>;
};
+ i2c1: i2c@40005400 {
+ compatible = "st,stm32f7-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x40005400 0x400>;
+ interrupts = <31>,
+ <32>;
+ resets = <&rcc STM32H7_APB1L_RESET(I2C1)>;
+ clocks = <&rcc I2C1_CK>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@40005800 {
+ compatible = "st,stm32f7-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x40005800 0x400>;
+ interrupts = <33>,
+ <34>;
+ resets = <&rcc STM32H7_APB1L_RESET(I2C2)>;
+ clocks = <&rcc I2C2_CK>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@40005C00 {
+ compatible = "st,stm32f7-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x40005C00 0x400>;
+ interrupts = <72>,
+ <73>;
+ resets = <&rcc STM32H7_APB1L_RESET(I2C3)>;
+ clocks = <&rcc I2C3_CK>;
+ status = "disabled";
+ };
+
dac: dac@40007400 {
compatible = "st,stm32h7-dac-core";
reg = <0x40007400 0x400>;
@@ -323,6 +360,18 @@
status = "disabled";
};
+ i2c4: i2c@58001C00 {
+ compatible = "st,stm32f7-i2c";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x58001C00 0x400>;
+ interrupts = <95>,
+ <96>;
+ resets = <&rcc STM32H7_APB4_RESET(I2C4)>;
+ clocks = <&rcc I2C4_CK>;
+ status = "disabled";
+ };
+
lptimer2: timer@58002400 {
#address-cells = <1>;
#size-cells = <0>;
@@ -334,6 +383,7 @@
pwm {
compatible = "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -360,6 +410,7 @@
pwm {
compatible = "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
status = "disabled";
};
@@ -381,6 +432,7 @@
pwm {
compatible = "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
status = "disabled";
};
};
@@ -396,6 +448,7 @@
pwm {
compatible = "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/stm32h743i-eval.dts b/arch/arm/boot/dts/stm32h743i-eval.dts
index c7187e1..3f8e0c4 100644
--- a/arch/arm/boot/dts/stm32h743i-eval.dts
+++ b/arch/arm/boot/dts/stm32h743i-eval.dts
@@ -92,6 +92,14 @@
clock-frequency = <25000000>;
};
+&i2c1 {
+ pinctrl-0 = <&i2c1_pins_a>;
+ pinctrl-names = "default";
+ i2c-scl-rising-time-ns = <185>;
+ i2c-scl-falling-time-ns = <20>;
+ status = "okay";
+};
+
&rtc {
status = "okay";
};
diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
index eb96ac3..4839db1 100644
--- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
@@ -7,7 +7,7 @@
/ {
soc {
- pinctrl: pin-controller {
+ pinctrl: pin-controller@50002000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "st,stm32mp157-pinctrl";
@@ -22,7 +22,7 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x0 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOA>;
st,bank-name = "GPIOA";
ngpios = <16>;
gpio-ranges = <&pinctrl 0 0 16>;
@@ -34,7 +34,7 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x1000 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOB>;
st,bank-name = "GPIOB";
ngpios = <16>;
gpio-ranges = <&pinctrl 0 16 16>;
@@ -46,7 +46,7 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x2000 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOC>;
st,bank-name = "GPIOC";
ngpios = <16>;
gpio-ranges = <&pinctrl 0 32 16>;
@@ -58,7 +58,7 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x3000 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOD>;
st,bank-name = "GPIOD";
ngpios = <16>;
gpio-ranges = <&pinctrl 0 48 16>;
@@ -70,7 +70,7 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x4000 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOE>;
st,bank-name = "GPIOE";
ngpios = <16>;
gpio-ranges = <&pinctrl 0 64 16>;
@@ -82,7 +82,7 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x5000 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOF>;
st,bank-name = "GPIOF";
ngpios = <16>;
gpio-ranges = <&pinctrl 0 80 16>;
@@ -94,7 +94,7 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x6000 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOG>;
st,bank-name = "GPIOG";
ngpios = <16>;
gpio-ranges = <&pinctrl 0 96 16>;
@@ -106,7 +106,7 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x7000 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOH>;
st,bank-name = "GPIOH";
ngpios = <16>;
gpio-ranges = <&pinctrl 0 112 16>;
@@ -118,7 +118,7 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x8000 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOI>;
st,bank-name = "GPIOI";
ngpios = <16>;
gpio-ranges = <&pinctrl 0 128 16>;
@@ -130,7 +130,7 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x9000 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOJ>;
st,bank-name = "GPIOJ";
ngpios = <16>;
gpio-ranges = <&pinctrl 0 144 16>;
@@ -142,13 +142,124 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0xa000 0x400>;
- clocks = <&clk_pll3_p>;
+ clocks = <&rcc GPIOK>;
st,bank-name = "GPIOK";
ngpios = <8>;
gpio-ranges = <&pinctrl 0 160 8>;
};
- uart4_pins_a: uart4@0 {
+ cec_pins_a: cec-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 15, AF4)>;
+ bias-disable;
+ drive-open-drain;
+ slew-rate = <0>;
+ };
+ };
+
+ i2c1_pins_a: i2c1-0 {
+ pins {
+ pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
+ <STM32_PINMUX('F', 15, AF5)>; /* I2C1_SDA */
+ bias-disable;
+ drive-open-drain;
+ slew-rate = <0>;
+ };
+ };
+
+ i2c2_pins_a: i2c2-0 {
+ pins {
+ pinmux = <STM32_PINMUX('H', 4, AF4)>, /* I2C2_SCL */
+ <STM32_PINMUX('H', 5, AF4)>; /* I2C2_SDA */
+ bias-disable;
+ drive-open-drain;
+ slew-rate = <0>;
+ };
+ };
+
+ i2c5_pins_a: i2c5-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 11, AF4)>, /* I2C5_SCL */
+ <STM32_PINMUX('A', 12, AF4)>; /* I2C5_SDA */
+ bias-disable;
+ drive-open-drain;
+ slew-rate = <0>;
+ };
+ };
+
+ pwm2_pins_a: pwm2-0 {
+ pins {
+ pinmux = <STM32_PINMUX('A', 3, AF1)>; /* TIM2_CH4 */
+ bias-pull-down;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ };
+
+ pwm8_pins_a: pwm8-0 {
+ pins {
+ pinmux = <STM32_PINMUX('I', 2, AF3)>; /* TIM8_CH4 */
+ bias-pull-down;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ };
+
+ pwm12_pins_a: pwm12-0 {
+ pins {
+ pinmux = <STM32_PINMUX('H', 6, AF2)>; /* TIM12_CH1 */
+ bias-pull-down;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ };
+
+ qspi_clk_pins_a: qspi-clk-0 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 10, AF9)>; /* QSPI_CLK */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <3>;
+ };
+ };
+
+ qspi_bk1_pins_a: qspi-bk1-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */
+ <STM32_PINMUX('F', 9, AF10)>, /* QSPI_BK1_IO1 */
+ <STM32_PINMUX('F', 7, AF9)>, /* QSPI_BK1_IO2 */
+ <STM32_PINMUX('F', 6, AF9)>; /* QSPI_BK1_IO3 */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <3>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('B', 6, AF10)>; /* QSPI_BK1_NCS */
+ bias-pull-up;
+ drive-push-pull;
+ slew-rate = <3>;
+ };
+ };
+
+ qspi_bk2_pins_a: qspi-bk2-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('H', 2, AF9)>, /* QSPI_BK2_IO0 */
+ <STM32_PINMUX('H', 3, AF9)>, /* QSPI_BK2_IO1 */
+ <STM32_PINMUX('G', 10, AF11)>, /* QSPI_BK2_IO2 */
+ <STM32_PINMUX('G', 7, AF11)>; /* QSPI_BK2_IO3 */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <3>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('C', 0, AF10)>; /* QSPI_BK2_NCS */
+ bias-pull-up;
+ drive-push-pull;
+ slew-rate = <3>;
+ };
+ };
+
+ uart4_pins_a: uart4-0 {
pins1 {
pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
bias-disable;
@@ -162,7 +273,7 @@
};
};
- pinctrl_z: pin-controller-z {
+ pinctrl_z: pin-controller-z@54004000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "st,stm32mp157-z-pinctrl";
@@ -178,12 +289,22 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0 0x400>;
- clocks = <&clk_pll2_p>;
+ clocks = <&rcc GPIOZ>;
st,bank-name = "GPIOZ";
st,bank-ioport = <11>;
ngpios = <8>;
gpio-ranges = <&pinctrl_z 0 400 8>;
};
+
+ i2c4_pins_a: i2c4-0 {
+ pins {
+ pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
+ <STM32_PINMUX('Z', 5, AF6)>; /* I2C4_SDA */
+ bias-disable;
+ drive-open-drain;
+ slew-rate = <0>;
+ };
+ };
};
};
};
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts b/arch/arm/boot/dts/stm32mp157c-ed1.dts
index 9f90337a..ae33653 100644
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
@@ -16,13 +16,56 @@
stdout-path = "serial0:115200n8";
};
- memory {
+ memory@c0000000 {
reg = <0xC0000000 0x40000000>;
};
aliases {
serial0 = &uart4;
};
+
+ reg11: reg11 {
+ compatible = "regulator-fixed";
+ regulator-name = "reg11";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ };
+
+ reg18: reg18 {
+ compatible = "regulator-fixed";
+ regulator-name = "reg18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ vdd_usb: vdd-usb {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_usb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+};
+
+&rng1 {
+ status = "okay";
+};
+
+&timers6 {
+ status = "okay";
+ timer@5 {
+ status = "okay";
+ };
+};
+
+&i2c4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c4_pins_a>;
+ i2c-scl-rising-time-ns = <185>;
+ i2c-scl-falling-time-ns = <20>;
+ status = "okay";
};
&uart4 {
@@ -30,3 +73,15 @@
pinctrl-0 = <&uart4_pins_a>;
status = "okay";
};
+
+&usbphyc_port0 {
+ phy-supply = <&vdd_usb>;
+ vdda1v1-supply = <&reg11>;
+ vdda1v8-supply = <&reg18>;
+};
+
+&usbphyc_port1 {
+ phy-supply = <&vdd_usb>;
+ vdda1v1-supply = <&reg11>;
+ vdda1v8-supply = <&reg18>;
+};
diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts
index 57e6dbc..9382d80 100644
--- a/arch/arm/boot/dts/stm32mp157c-ev1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts
@@ -19,3 +19,90 @@
serial0 = &uart4;
};
};
+
+&cec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&cec_pins_a>;
+ status = "okay";
+};
+
+&i2c2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins_a>;
+ i2c-scl-rising-time-ns = <185>;
+ i2c-scl-falling-time-ns = <20>;
+ status = "okay";
+};
+
+&i2c5 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c5_pins_a>;
+ i2c-scl-rising-time-ns = <185>;
+ i2c-scl-falling-time-ns = <20>;
+ status = "okay";
+};
+
+&qspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>;
+ reg = <0x58003000 0x1000>, <0x70000000 0x4000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ flash0: mx66l51235l@0 {
+ reg = <0>;
+ spi-rx-bus-width = <4>;
+ spi-max-frequency = <108000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+
+ flash1: mx66l51235l@1 {
+ reg = <1>;
+ spi-rx-bus-width = <4>;
+ spi-max-frequency = <108000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
+&timers2 {
+ status = "disabled";
+ pwm {
+ pinctrl-0 = <&pwm2_pins_a>;
+ pinctrl-names = "default";
+ status = "okay";
+ };
+ timer@1 {
+ status = "okay";
+ };
+};
+
+&timers8 {
+ status = "disabled";
+ pwm {
+ pinctrl-0 = <&pwm8_pins_a>;
+ pinctrl-names = "default";
+ status = "okay";
+ };
+ timer@7 {
+ status = "okay";
+ };
+};
+
+&timers12 {
+ status = "disabled";
+ pwm {
+ pinctrl-0 = <&pwm12_pins_a>;
+ pinctrl-names = "default";
+ status = "okay";
+ };
+ timer@11 {
+ status = "okay";
+ };
+};
+
+&usbphyc {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi b/arch/arm/boot/dts/stm32mp157c.dtsi
index 4fa0df8..7d17538 100644
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
@@ -4,6 +4,8 @@
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
+#include <dt-bindings/reset/stm32mp1-resets.h>
/ {
#address-cells = <1>;
@@ -71,12 +73,6 @@
clock-frequency = <24000000>;
};
- clk_pll_per: clk-pll-per {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <64000000>;
- };
-
clk_hsi: clk-hsi {
#clock-cells = <0>;
compatible = "fixed-clock";
@@ -100,24 +96,6 @@
compatible = "fixed-clock";
clock-frequency = <4000000>;
};
-
- clk_pclk1: clk-pclk1 {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <86000000>;
- };
-
- clk_pll3_p: clk-pll3_p {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <172000000>;
- };
-
- clk_pll2_p: clk-pll2_p {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <264000000>;
- };
};
soc {
@@ -127,60 +105,506 @@
interrupt-parent = <&intc>;
ranges;
+ timers2: timer@40000000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x40000000 0x400>;
+ clocks = <&rcc TIM2_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@1 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <1>;
+ status = "disabled";
+ };
+ };
+
+ timers3: timer@40001000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x40001000 0x400>;
+ clocks = <&rcc TIM3_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@2 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <2>;
+ status = "disabled";
+ };
+ };
+
+ timers4: timer@40002000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x40002000 0x400>;
+ clocks = <&rcc TIM4_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@3 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <3>;
+ status = "disabled";
+ };
+ };
+
+ timers5: timer@40003000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x40003000 0x400>;
+ clocks = <&rcc TIM5_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@4 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <4>;
+ status = "disabled";
+ };
+ };
+
+ timers6: timer@40004000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x40004000 0x400>;
+ clocks = <&rcc TIM6_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ timer@5 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <5>;
+ status = "disabled";
+ };
+ };
+
+ timers7: timer@40005000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x40005000 0x400>;
+ clocks = <&rcc TIM7_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ timer@6 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <6>;
+ status = "disabled";
+ };
+ };
+
+ timers12: timer@40006000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x40006000 0x400>;
+ clocks = <&rcc TIM12_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@11 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <11>;
+ status = "disabled";
+ };
+ };
+
+ timers13: timer@40007000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x40007000 0x400>;
+ clocks = <&rcc TIM13_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@12 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <12>;
+ status = "disabled";
+ };
+ };
+
+ timers14: timer@40008000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x40008000 0x400>;
+ clocks = <&rcc TIM14_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@13 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <13>;
+ status = "disabled";
+ };
+ };
+
+ lptimer1: timer@40009000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-lptimer";
+ reg = <0x40009000 0x400>;
+ clocks = <&rcc LPTIM1_K>;
+ clock-names = "mux";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ trigger@0 {
+ compatible = "st,stm32-lptimer-trigger";
+ reg = <0>;
+ status = "disabled";
+ };
+
+ counter {
+ compatible = "st,stm32-lptimer-counter";
+ status = "disabled";
+ };
+ };
+
usart2: serial@4000e000 {
compatible = "st,stm32h7-uart";
reg = <0x4000e000 0x400>;
- interrupts = <GIC_SPI 38 IRQ_TYPE_NONE>;
- clocks = <&clk_pclk1>;
+ interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc USART2_K>;
status = "disabled";
};
usart3: serial@4000f000 {
compatible = "st,stm32h7-uart";
reg = <0x4000f000 0x400>;
- interrupts = <GIC_SPI 39 IRQ_TYPE_NONE>;
- clocks = <&clk_pclk1>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc USART3_K>;
status = "disabled";
};
uart4: serial@40010000 {
compatible = "st,stm32h7-uart";
reg = <0x40010000 0x400>;
- interrupts = <GIC_SPI 52 IRQ_TYPE_NONE>;
- clocks = <&clk_pclk1>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc UART4_K>;
status = "disabled";
};
uart5: serial@40011000 {
compatible = "st,stm32h7-uart";
reg = <0x40011000 0x400>;
- interrupts = <GIC_SPI 53 IRQ_TYPE_NONE>;
- clocks = <&clk_pclk1>;
+ interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc UART5_K>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@40012000 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x40012000 0x400>;
+ interrupt-names = "event", "error";
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc I2C1_K>;
+ resets = <&rcc I2C1_R>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@40013000 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x40013000 0x400>;
+ interrupt-names = "event", "error";
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc I2C2_K>;
+ resets = <&rcc I2C2_R>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@40014000 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x40014000 0x400>;
+ interrupt-names = "event", "error";
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc I2C3_K>;
+ resets = <&rcc I2C3_R>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c5: i2c@40015000 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x40015000 0x400>;
+ interrupt-names = "event", "error";
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc I2C5_K>;
+ resets = <&rcc I2C5_R>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
+ cec: cec@40016000 {
+ compatible = "st,stm32-cec";
+ reg = <0x40016000 0x400>;
+ interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CEC_K>, <&clk_lse>;
+ clock-names = "cec", "hdmi-cec";
+ status = "disabled";
+ };
+
+ dac: dac@40017000 {
+ compatible = "st,stm32h7-dac-core";
+ reg = <0x40017000 0x400>;
+ clocks = <&rcc DAC12>;
+ clock-names = "pclk";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ dac1: dac@1 {
+ compatible = "st,stm32-dac";
+ #io-channels-cells = <1>;
+ reg = <1>;
+ status = "disabled";
+ };
+
+ dac2: dac@2 {
+ compatible = "st,stm32-dac";
+ #io-channels-cells = <1>;
+ reg = <2>;
+ status = "disabled";
+ };
+ };
+
uart7: serial@40018000 {
compatible = "st,stm32h7-uart";
reg = <0x40018000 0x400>;
- interrupts = <GIC_SPI 82 IRQ_TYPE_NONE>;
- clocks = <&clk_pclk1>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc UART7_K>;
status = "disabled";
};
uart8: serial@40019000 {
compatible = "st,stm32h7-uart";
reg = <0x40019000 0x400>;
- interrupts = <GIC_SPI 83 IRQ_TYPE_NONE>;
- clocks = <&clk_pclk1>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc UART8_K>;
status = "disabled";
};
+ timers1: timer@44000000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x44000000 0x400>;
+ clocks = <&rcc TIM1_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@0 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <0>;
+ status = "disabled";
+ };
+ };
+
+ timers8: timer@44001000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x44001000 0x400>;
+ clocks = <&rcc TIM8_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@7 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <7>;
+ status = "disabled";
+ };
+ };
+
usart6: serial@44003000 {
compatible = "st,stm32h7-uart";
reg = <0x44003000 0x400>;
- interrupts = <GIC_SPI 71 IRQ_TYPE_NONE>;
- clocks = <&clk_pclk1>;
+ interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc USART6_K>;
+ status = "disabled";
+ };
+
+ timers15: timer@44006000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x44006000 0x400>;
+ clocks = <&rcc TIM15_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@14 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <14>;
+ status = "disabled";
+ };
+ };
+
+ timers16: timer@44007000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x44007000 0x400>;
+ clocks = <&rcc TIM16_K>;
+ clock-names = "int";
status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+ timer@15 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <15>;
+ status = "disabled";
+ };
+ };
+
+ timers17: timer@44008000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-timers";
+ reg = <0x44008000 0x400>;
+ clocks = <&rcc TIM17_K>;
+ clock-names = "int";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm";
+ status = "disabled";
+ };
+
+ timer@16 {
+ compatible = "st,stm32h7-timer-trigger";
+ reg = <16>;
+ status = "disabled";
+ };
+ };
+
+ dma1: dma@48000000 {
+ compatible = "st,stm32-dma";
+ reg = <0x48000000 0x400>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc DMA1>;
+ #dma-cells = <4>;
+ st,mem2mem;
+ dma-requests = <8>;
+ };
+
+ dma2: dma@48001000 {
+ compatible = "st,stm32-dma";
+ reg = <0x48001000 0x400>;
+ interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc DMA2>;
+ #dma-cells = <4>;
+ st,mem2mem;
+ dma-requests = <8>;
+ };
+
+ dmamux1: dma-router@48002000 {
+ compatible = "st,stm32h7-dmamux";
+ reg = <0x48002000 0x1c>;
+ #dma-cells = <3>;
+ dma-requests = <128>;
+ dma-masters = <&dma1 &dma2>;
+ dma-channels = <16>;
+ clocks = <&rcc DMAMUX>;
+ };
+
+ rcc: rcc@50000000 {
+ compatible = "st,stm32mp1-rcc", "syscon";
+ reg = <0x50000000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
};
exti: interrupt-controller@5000d000 {
@@ -190,11 +614,227 @@
reg = <0x5000d000 0x400>;
};
+ lptimer2: timer@50021000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-lptimer";
+ reg = <0x50021000 0x400>;
+ clocks = <&rcc LPTIM2_K>;
+ clock-names = "mux";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ trigger@1 {
+ compatible = "st,stm32-lptimer-trigger";
+ reg = <1>;
+ status = "disabled";
+ };
+
+ counter {
+ compatible = "st,stm32-lptimer-counter";
+ status = "disabled";
+ };
+ };
+
+ lptimer3: timer@50022000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32-lptimer";
+ reg = <0x50022000 0x400>;
+ clocks = <&rcc LPTIM3_K>;
+ clock-names = "mux";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ trigger@2 {
+ compatible = "st,stm32-lptimer-trigger";
+ reg = <2>;
+ status = "disabled";
+ };
+ };
+
+ lptimer4: timer@50023000 {
+ compatible = "st,stm32-lptimer";
+ reg = <0x50023000 0x400>;
+ clocks = <&rcc LPTIM4_K>;
+ clock-names = "mux";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+ };
+
+ lptimer5: timer@50024000 {
+ compatible = "st,stm32-lptimer";
+ reg = <0x50024000 0x400>;
+ clocks = <&rcc LPTIM5_K>;
+ clock-names = "mux";
+ status = "disabled";
+
+ pwm {
+ compatible = "st,stm32-pwm-lp";
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+ };
+
+ vrefbuf: vrefbuf@50025000 {
+ compatible = "st,stm32-vrefbuf";
+ reg = <0x50025000 0x8>;
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <2500000>;
+ clocks = <&rcc VREF>;
+ status = "disabled";
+ };
+
+ cryp1: cryp@54001000 {
+ compatible = "st,stm32mp1-cryp";
+ reg = <0x54001000 0x400>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc CRYP1>;
+ resets = <&rcc CRYP1_R>;
+ status = "disabled";
+ };
+
+ rng1: rng@54003000 {
+ compatible = "st,stm32-rng";
+ reg = <0x54003000 0x400>;
+ clocks = <&rcc RNG1_K>;
+ resets = <&rcc RNG1_R>;
+ status = "disabled";
+ };
+
+ mdma1: dma@58000000 {
+ compatible = "st,stm32h7-mdma";
+ reg = <0x58000000 0x1000>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc MDMA>;
+ #dma-cells = <5>;
+ dma-channels = <32>;
+ dma-requests = <48>;
+ };
+
+ qspi: qspi@58003000 {
+ compatible = "st,stm32f469-qspi";
+ reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
+ reg-names = "qspi", "qspi_mm";
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc QSPI_K>;
+ resets = <&rcc QSPI_R>;
+ status = "disabled";
+ };
+
+ crc1: crc@58009000 {
+ compatible = "st,stm32f7-crc";
+ reg = <0x58009000 0x400>;
+ clocks = <&rcc CRC1>;
+ status = "disabled";
+ };
+
+ usbh_ohci: usbh-ohci@5800c000 {
+ compatible = "generic-ohci";
+ reg = <0x5800c000 0x1000>;
+ clocks = <&rcc USBH>;
+ resets = <&rcc USBH_R>;
+ interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ usbh_ehci: usbh-ehci@5800d000 {
+ compatible = "generic-ehci";
+ reg = <0x5800d000 0x1000>;
+ clocks = <&rcc USBH>;
+ resets = <&rcc USBH_R>;
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ companion = <&usbh_ohci>;
+ status = "disabled";
+ };
+
+ dsi: dsi@5a000000 {
+ compatible = "st,stm32-dsi";
+ reg = <0x5a000000 0x800>;
+ clocks = <&rcc DSI_K>, <&clk_hse>, <&rcc DSI_PX>;
+ clock-names = "pclk", "ref", "px_clk";
+ resets = <&rcc DSI_R>;
+ reset-names = "apb";
+ status = "disabled";
+ };
+
+ ltdc: display-controller@5a001000 {
+ compatible = "st,stm32-ltdc";
+ reg = <0x5a001000 0x400>;
+ interrupts = <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc LTDC_PX>;
+ clock-names = "lcd";
+ resets = <&rcc LTDC_R>;
+ status = "disabled";
+ };
+
+ usbphyc: usbphyc@5a006000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "st,stm32mp1-usbphyc";
+ reg = <0x5a006000 0x1000>;
+ clocks = <&rcc USBPHY_K>;
+ resets = <&rcc USBPHY_R>;
+ status = "disabled";
+
+ usbphyc_port0: usb-phy@0 {
+ #phy-cells = <0>;
+ reg = <0>;
+ };
+
+ usbphyc_port1: usb-phy@1 {
+ #phy-cells = <1>;
+ reg = <1>;
+ };
+ };
+
usart1: serial@5c000000 {
compatible = "st,stm32h7-uart";
reg = <0x5c000000 0x400>;
- interrupts = <GIC_SPI 37 IRQ_TYPE_NONE>;
- clocks = <&clk_pclk1>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc USART1_K>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@5c002000 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x5c002000 0x400>;
+ interrupt-names = "event", "error";
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc I2C4_K>;
+ resets = <&rcc I2C4_R>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c6: i2c@5c009000 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x5c009000 0x400>;
+ interrupt-names = "event", "error";
+ interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc I2C6_K>;
+ resets = <&rcc I2C6_R>;
+ #address-cells = <1>;
+ #size-cells = <0>;
status = "disabled";
};
};
diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som-evb-emmc.dts b/arch/arm/boot/dts/sun7i-a20-olimex-som-evb-emmc.dts
new file mode 100644
index 0000000..81ebc97
--- /dev/null
+++ b/arch/arm/boot/dts/sun7i-a20-olimex-som-evb-emmc.dts
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree Source for A20-Olimex-SOM-EVB-eMMC Board
+ *
+ * Copyright (C) 2018 Olimex Ltd.
+ * Author: Stefan Mavrodiev <stefan@olimex.com>
+ */
+
+/dts-v1/;
+#include "sun7i-a20-olimex-som-evb.dts"
+
+/ {
+
+ model = "Olimex A20-Olimex-SOM-EVB-eMMC";
+ compatible = "olimex,a20-olimex-som-evb-emmc", "allwinner,sun7i-a20";
+
+ mmc2_pwrseq: mmc2_pwrseq {
+ compatible = "mmc-pwrseq-emmc";
+ reset-gpios = <&pio 2 18 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&mmc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc2_pins_a>;
+ vmmc-supply = <&reg_vcc3v3>;
+ mmc-pwrseq = <&mmc2_pwrseq>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+
+ emmc: emmc@0 {
+ reg = <0>;
+ compatible = "mmc-card";
+ broken-hpi;
+ };
+};
diff --git a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts
index eae8e26..3d7b5c8 100644
--- a/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts
+++ b/arch/arm/boot/dts/sun7i-a20-olimex-som204-evb.dts
@@ -172,8 +172,7 @@
pinctrl-0 = <&mmc0_pins_a>;
vmmc-supply = <&reg_vcc3v3>;
bus-width = <4>;
- cd-gpios = <&pio 7 1 GPIO_ACTIVE_HIGH>;
- cd-inverted;
+ cd-gpios = <&pio 7 1 GPIO_ACTIVE_LOW>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun8i-a23-a33.dtsi b/arch/arm/boot/dts/sun8i-a23-a33.dtsi
index 971f9be..44f3cad 100644
--- a/arch/arm/boot/dts/sun8i-a23-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a23-a33.dtsi
@@ -198,6 +198,8 @@
clock-names = "ahb", "mod";
resets = <&ccu RST_BUS_NAND>;
reset-names = "ahb";
+ pinctrl-names = "default";
+ pinctrl-0 = <&nand_pins &nand_pins_cs0 &nand_pins_rb0>;
status = "disabled";
#address-cells = <1>;
#size-cells = <0>;
@@ -315,6 +317,37 @@
bias-pull-up;
};
+ nand_pins: nand-pins {
+ pins = "PC0", "PC1", "PC2", "PC5",
+ "PC8", "PC9", "PC10", "PC11",
+ "PC12", "PC13", "PC14", "PC15";
+ function = "nand0";
+ };
+
+ nand_pins_cs0: nand-pins-cs0 {
+ pins = "PC4";
+ function = "nand0";
+ bias-pull-up;
+ };
+
+ nand_pins_cs1: nand-pins-cs1 {
+ pins = "PC3";
+ function = "nand0";
+ bias-pull-up;
+ };
+
+ nand_pins_rb0: nand-pins-rb0 {
+ pins = "PC6";
+ function = "nand0";
+ bias-pull-up;
+ };
+
+ nand_pins_rb1: nand-pins-rb1 {
+ pins = "PC7";
+ function = "nand0";
+ bias-pull-up;
+ };
+
pwm0_pins: pwm0 {
pins = "PH0";
function = "pwm0";
diff --git a/arch/arm/boot/dts/sun8i-a33.dtsi b/arch/arm/boot/dts/sun8i-a33.dtsi
index a21f2ed..8d278ee 100644
--- a/arch/arm/boot/dts/sun8i-a33.dtsi
+++ b/arch/arm/boot/dts/sun8i-a33.dtsi
@@ -236,6 +236,11 @@
#address-cells = <1>;
#size-cells = <0>;
reg = <1>;
+
+ tcon0_out_dsi: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&dsi_in_tcon0>;
+ };
};
};
};
@@ -280,6 +285,45 @@
#io-channel-cells = <0>;
};
+ dsi: dsi@1ca0000 {
+ compatible = "allwinner,sun6i-a31-mipi-dsi";
+ reg = <0x01ca0000 0x1000>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&ccu CLK_DSI_SCLK>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ phys = <&dphy>;
+ phy-names = "dphy";
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ dsi_in_tcon0: endpoint {
+ remote-endpoint = <&tcon0_out_dsi>;
+ };
+ };
+ };
+ };
+
+ dphy: d-phy@1ca1000 {
+ compatible = "allwinner,sun6i-a31-mipi-dphy";
+ reg = <0x01ca1000 0x1000>;
+ clocks = <&ccu CLK_BUS_MIPI_DSI>,
+ <&ccu CLK_DSI_DPHY>;
+ clock-names = "bus", "mod";
+ resets = <&ccu RST_BUS_MIPI_DSI>;
+ status = "disabled";
+ #phy-cells = <0>;
+ };
+
fe0: display-frontend@1e00000 {
compatible = "allwinner,sun8i-a33-display-frontend";
reg = <0x01e00000 0x20000>;
diff --git a/arch/arm/boot/dts/sun8i-a83t.dtsi b/arch/arm/boot/dts/sun8i-a83t.dtsi
index 5683076..2be23d6 100644
--- a/arch/arm/boot/dts/sun8i-a83t.dtsi
+++ b/arch/arm/boot/dts/sun8i-a83t.dtsi
@@ -66,6 +66,8 @@
compatible = "arm,cortex-a7";
device_type = "cpu";
operating-points-v2 = <&cpu0_opp_table>;
+ cci-control-port = <&cci_control0>;
+ enable-method = "allwinner,sun8i-a83t-smp";
reg = <0>;
};
@@ -73,6 +75,8 @@
compatible = "arm,cortex-a7";
device_type = "cpu";
operating-points-v2 = <&cpu0_opp_table>;
+ cci-control-port = <&cci_control0>;
+ enable-method = "allwinner,sun8i-a83t-smp";
reg = <1>;
};
@@ -80,6 +84,8 @@
compatible = "arm,cortex-a7";
device_type = "cpu";
operating-points-v2 = <&cpu0_opp_table>;
+ cci-control-port = <&cci_control0>;
+ enable-method = "allwinner,sun8i-a83t-smp";
reg = <2>;
};
@@ -87,6 +93,8 @@
compatible = "arm,cortex-a7";
device_type = "cpu";
operating-points-v2 = <&cpu0_opp_table>;
+ cci-control-port = <&cci_control0>;
+ enable-method = "allwinner,sun8i-a83t-smp";
reg = <3>;
};
@@ -96,6 +104,8 @@
compatible = "arm,cortex-a7";
device_type = "cpu";
operating-points-v2 = <&cpu1_opp_table>;
+ cci-control-port = <&cci_control1>;
+ enable-method = "allwinner,sun8i-a83t-smp";
reg = <0x100>;
};
@@ -103,6 +113,8 @@
compatible = "arm,cortex-a7";
device_type = "cpu";
operating-points-v2 = <&cpu1_opp_table>;
+ cci-control-port = <&cci_control1>;
+ enable-method = "allwinner,sun8i-a83t-smp";
reg = <0x101>;
};
@@ -110,6 +122,8 @@
compatible = "arm,cortex-a7";
device_type = "cpu";
operating-points-v2 = <&cpu1_opp_table>;
+ cci-control-port = <&cci_control1>;
+ enable-method = "allwinner,sun8i-a83t-smp";
reg = <0x102>;
};
@@ -117,6 +131,8 @@
compatible = "arm,cortex-a7";
device_type = "cpu";
operating-points-v2 = <&cpu1_opp_table>;
+ cci-control-port = <&cci_control1>;
+ enable-method = "allwinner,sun8i-a83t-smp";
reg = <0x103>;
};
};
@@ -349,6 +365,44 @@
};
};
+ cpucfg@1700000 {
+ compatible = "allwinner,sun8i-a83t-cpucfg";
+ reg = <0x01700000 0x400>;
+ };
+
+ cci@1790000 {
+ compatible = "arm,cci-400";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x01790000 0x10000>;
+ ranges = <0x0 0x01790000 0x10000>;
+
+ cci_control0: slave-if@4000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace";
+ reg = <0x4000 0x1000>;
+ };
+
+ cci_control1: slave-if@5000 {
+ compatible = "arm,cci-400-ctrl-if";
+ interface-type = "ace";
+ reg = <0x5000 0x1000>;
+ };
+
+ pmu@9000 {
+ compatible = "arm,cci-400-pmu,r1";
+ reg = <0x9000 0x5000>;
+ interrupts = <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 151 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>;
+ };
+ };
+
syscon: syscon@1c00000 {
compatible = "allwinner,sun8i-a83t-system-controller",
"syscon";
@@ -492,6 +546,11 @@
#size-cells = <0>;
};
+ sid: eeprom@1c14000 {
+ compatible = "allwinner,sun8i-a83t-sid";
+ reg = <0x1c14000 0x400>;
+ };
+
usb_otg: usb@1c19000 {
compatible = "allwinner,sun8i-a83t-musb",
"allwinner,sun8i-a33-musb";
@@ -928,6 +987,11 @@
#reset-cells = <1>;
};
+ r_cpucfg@1f01c00 {
+ compatible = "allwinner,sun8i-a83t-r-cpucfg";
+ reg = <0x1f01c00 0x400>;
+ };
+
r_pio: pinctrl@1f02c00 {
compatible = "allwinner,sun8i-a83t-r-pinctrl";
reg = <0x01f02c00 0x400>;
diff --git a/arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts b/arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts
new file mode 100644
index 0000000..4db0d4b
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-h2-plus-libretech-all-h3-cc.dts
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 Chen-Yu Tsai <wens@csie.org>
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-libretech-all-h3-cc.dtsi"
+
+/ {
+ model = "Libre Computer Board ALL-H3-CC H2+";
+ compatible = "libretech,all-h3-cc-h2-plus", "allwinner,sun8i-h2-plus";
+};
diff --git a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
index 0bc031fe..84cd9c0 100644
--- a/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
+++ b/arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
@@ -89,6 +89,23 @@
gpio = <&pio 0 20 GPIO_ACTIVE_HIGH>;
};
+ reg_vdd_cpux: vdd-cpux-regulator {
+ compatible = "regulator-gpio";
+ regulator-name = "vdd-cpux";
+ regulator-type = "voltage";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-ramp-delay = <50>; /* 4ms */
+
+ gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */
+ enable-active-high;
+ gpios-states = <1>;
+ states = <1100000 0
+ 1300000 1>;
+ };
+
wifi_pwrseq: wifi_pwrseq {
compatible = "mmc-pwrseq-simple";
reset-gpios = <&r_pio 0 7 GPIO_ACTIVE_LOW>;
@@ -96,6 +113,10 @@
};
};
+&cpu0 {
+ cpu-supply = <&reg_vdd_cpux>;
+};
+
&ehci0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts b/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts
index b20a710..a8b2f0f 100644
--- a/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts
+++ b/arch/arm/boot/dts/sun8i-h3-libretech-all-h3-cc.dts
@@ -6,213 +6,9 @@
/dts-v1/;
#include "sun8i-h3.dtsi"
-
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/input/input.h>
+#include "sunxi-libretech-all-h3-cc.dtsi"
/ {
model = "Libre Computer Board ALL-H3-CC H3";
compatible = "libretech,all-h3-cc-h3", "allwinner,sun8i-h3";
-
- aliases {
- ethernet0 = &emac;
- serial0 = &uart0;
- };
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- connector {
- compatible = "hdmi-connector";
- type = "a";
-
- port {
- hdmi_con_in: endpoint {
- remote-endpoint = <&hdmi_out_con>;
- };
- };
- };
-
- leds {
- compatible = "gpio-leds";
-
- pwr_led {
- label = "librecomputer:green:pwr";
- gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
- default-state = "on";
- };
-
- status_led {
- label = "librecomputer:blue:status";
- gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>; /* PA7 */
- };
- };
-
- gpio_keys {
- compatible = "gpio-keys";
-
- power {
- label = "power";
- linux,code = <KEY_POWER>;
- gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
- };
- };
-
- reg_vcc1v2: vcc1v2 {
- compatible = "regulator-fixed";
- regulator-name = "vcc1v2";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&reg_vcc5v0>;
- gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
- enable-active-high;
- };
-
- reg_vcc3v3: vcc3v3 {
- compatible = "regulator-fixed";
- regulator-name = "vcc3v3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- vin-supply = <&reg_vcc5v0>;
- };
-
- /* This represents the board's 5V input */
- reg_vcc5v0: vcc5v0 {
- compatible = "regulator-fixed";
- regulator-name = "vcc5v0";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- };
-
- reg_vcc_dram: vcc-dram {
- compatible = "regulator-fixed";
- regulator-name = "vcc-dram";
- regulator-min-microvolt = <1500000>;
- regulator-max-microvolt = <1500000>;
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&reg_vcc5v0>;
- gpio = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */
- enable-active-high;
- };
-
- reg_vcc_io: vcc-io {
- compatible = "regulator-fixed";
- regulator-name = "vcc-io";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&reg_vcc3v3>;
- gpio = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */
- };
-
- reg_vdd_cpux: vdd-cpux {
- compatible = "regulator-fixed";
- regulator-name = "vdd-cpux";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&reg_vcc5v0>;
- gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
- enable-active-high;
- };
-};
-
-&codec {
- allwinner,audio-routing =
- "Line Out", "LINEOUT",
- "MIC1", "Mic",
- "Mic", "MBIAS";
- status = "okay";
-};
-
-&de {
- status = "okay";
-};
-
-&ehci0 {
- status = "okay";
-};
-
-&ehci1 {
- status = "okay";
-};
-
-&ehci2 {
- status = "okay";
-};
-
-&ehci3 {
- status = "okay";
-};
-
-&emac {
- phy-handle = <&int_mii_phy>;
- phy-mode = "mii";
- allwinner,leds-active-low;
- status = "okay";
-};
-
-&hdmi {
- status = "okay";
-};
-
-&hdmi_out {
- hdmi_out_con: endpoint {
- remote-endpoint = <&hdmi_con_in>;
- };
-};
-
-&ir {
- pinctrl-names = "default";
- pinctrl-0 = <&ir_pins_a>;
- status = "okay";
-};
-
-&mmc0 {
- vmmc-supply = <&reg_vcc_io>;
- 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";
-};
-
-&usb_otg {
- dr_mode = "host";
- status = "okay";
-};
-
-&usbphy {
- /* VBUS on USB ports are always on */
- usb0_vbus-supply = <&reg_vcc5v0>;
- usb1_vbus-supply = <&reg_vcc5v0>;
- usb2_vbus-supply = <&reg_vcc5v0>;
- usb3_vbus-supply = <&reg_vcc5v0>;
- status = "okay";
};
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
index 232f124..245fd65 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
@@ -99,6 +99,27 @@
gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
};
};
+
+ reg_vdd_cpux: vdd-cpux-regulator {
+ compatible = "regulator-gpio";
+ regulator-name = "vdd-cpux";
+ regulator-type = "voltage";
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-ramp-delay = <50>; /* 4ms */
+
+ gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */
+ enable-active-high;
+ gpios-states = <0x1>;
+ states = <1100000 0x0
+ 1300000 0x1>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&reg_vdd_cpux>;
};
&de {
diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
index cea4d64..4624033 100644
--- a/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
+++ b/arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
@@ -113,6 +113,10 @@
status = "okay";
};
+&cpu0 {
+ cpu-supply = <&reg_vdd_cpux>;
+};
+
&ehci0 {
status = "okay";
};
@@ -182,6 +186,30 @@
};
};
+&r_i2c {
+ status = "okay";
+
+ reg_vdd_cpux: regulator@65 {
+ compatible = "silergy,sy8106a";
+ reg = <0x65>;
+ regulator-name = "vdd-cpux";
+ silergy,fixed-microvolt = <1200000>;
+ /*
+ * The datasheet uses 1.1V as the minimum value of VDD-CPUX,
+ * however both the Armbian DVFS table and the official one
+ * have operating points with voltage under 1.1V, and both
+ * DVFS table are known to work properly at the lowest
+ * operating point.
+ *
+ * Use 1.0V as the minimum voltage instead.
+ */
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+};
+
&r_pio {
leds_r_opc: led_pins {
pins = "PL10";
diff --git a/arch/arm/boot/dts/sun8i-h3.dtsi b/arch/arm/boot/dts/sun8i-h3.dtsi
index 10da8ed..41d57c7 100644
--- a/arch/arm/boot/dts/sun8i-h3.dtsi
+++ b/arch/arm/boot/dts/sun8i-h3.dtsi
@@ -43,32 +43,62 @@
#include "sunxi-h3-h5.dtsi"
/ {
+ cpu0_opp_table: opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp@648000000 {
+ opp-hz = /bits/ 64 <648000000>;
+ opp-microvolt = <1040000 1040000 1300000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ };
+
+ opp@816000000 {
+ opp-hz = /bits/ 64 <816000000>;
+ opp-microvolt = <1100000 1100000 1300000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ };
+
+ opp@1008000000 {
+ opp-hz = /bits/ 64 <1008000000>;
+ opp-microvolt = <1200000 1200000 1300000>;
+ clock-latency-ns = <244144>; /* 8 32k periods */
+ };
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu0: cpu@0 {
compatible = "arm,cortex-a7";
device_type = "cpu";
reg = <0>;
+ clocks = <&ccu CLK_CPUX>;
+ clock-names = "cpu";
+ operating-points-v2 = <&cpu0_opp_table>;
+ #cooling-cells = <2>;
};
cpu@1 {
compatible = "arm,cortex-a7";
device_type = "cpu";
reg = <1>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
cpu@2 {
compatible = "arm,cortex-a7";
device_type = "cpu";
reg = <2>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
cpu@3 {
compatible = "arm,cortex-a7";
device_type = "cpu";
reg = <3>;
+ operating-points-v2 = <&cpu0_opp_table>;
};
};
diff --git a/arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts b/arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts
new file mode 100644
index 0000000..fc0658c
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-r16-nintendo-nes-classic.dts
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+/* Copyright (c) 2016 FUKAUMI Naoki <naobsd@gmail.com> */
+
+/dts-v1/;
+#include "sun8i-a33.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+/ {
+ model = "Nintendo NES Classic Edition";
+ compatible = "nintendo,nes-classic", "allwinner,sun8i-r16",
+ "allwinner,sun8i-a33";
+
+ aliases {
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&uart0 {
+ /*
+ * UART0 is available on two ports: PB and PF, both are accessible.
+ * PF can also be used for the SD card so PB is preferred.
+ */
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins_a>;
+ status = "okay";
+};
+
+&nfc {
+ status = "okay";
+
+ /* 2Gb Macronix MX30LF2G18AC (3V) */
+ nand@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0>;
+ allwinner,rb = <0>;
+ nand-ecc-mode = "hw";
+ nand-ecc-strength = <16>;
+ nand-ecc-step-size = <1024>;
+ };
+};
+
+&usb_otg {
+ status = "okay";
+ dr_mode = "otg";
+};
+
+&usbphy {
+ /* VBUS is always on because it is wired to the power supply */
+ usb1_vbus-supply = <&reg_vcc5v0>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/sun8i-r16-nintendo-super-nes-classic.dts b/arch/arm/boot/dts/sun8i-r16-nintendo-super-nes-classic.dts
new file mode 100644
index 0000000..80761d7
--- /dev/null
+++ b/arch/arm/boot/dts/sun8i-r16-nintendo-super-nes-classic.dts
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0 OR X11
+/* Copyright (c) 2018 Miquèl RAYNAL <miquel.raynal@bootlin.com> */
+
+/dts-v1/;
+#include "sun8i-r16-nintendo-nes-classic.dts"
+
+/ {
+ model = "Nintendo SuperNES Classic Edition";
+ compatible = "nintendo,super-nes-classic", "nintendo,nes-classic",
+ "allwinner,sun8i-r16", "allwinner,sun8i-a33";
+};
diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
index 27d9ccd..25fb048 100644
--- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
+++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
@@ -51,6 +51,7 @@
compatible = "sinovoip,bpi-m2-ultra", "allwinner,sun8i-r40";
aliases {
+ ethernet0 = &gmac;
serial0 = &uart0;
};
@@ -101,6 +102,22 @@
status = "okay";
};
+&gmac {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac_rgmii_pins>;
+ phy-handle = <&phy1>;
+ phy-mode = "rgmii";
+ phy-supply = <&reg_dc1sw>;
+ status = "okay";
+};
+
+&gmac_mdio {
+ phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <1>;
+ };
+};
+
&i2c0 {
status = "okay";
@@ -114,6 +131,48 @@
#include "axp22x.dtsi"
+&mmc0 {
+ vmmc-supply = <&reg_dcdc1>;
+ bus-width = <4>;
+ cd-gpios = <&pio 7 13 GPIO_ACTIVE_HIGH>; /* PH13 */
+ cd-inverted;
+ status = "okay";
+};
+
+&mmc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mmc1_pg_pins>;
+ vmmc-supply = <&reg_dldo2>;
+ vqmmc-supply = <&reg_dldo1>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ bus-width = <4>;
+ non-removable;
+ status = "okay";
+};
+
+&mmc2 {
+ vmmc-supply = <&reg_dcdc1>;
+ vqmmc-supply = <&reg_dcdc1>;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&ohci1 {
+ status = "okay";
+};
+
+&ohci2 {
+ status = "okay";
+};
+
+&reg_aldo2 {
+ regulator-always-on;
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-name = "vcc-pa";
+};
+
&reg_aldo3 {
regulator-always-on;
regulator-min-microvolt = <2700000>;
@@ -121,6 +180,12 @@
regulator-name = "avcc";
};
+&reg_dc1sw {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-name = "vcc-gmac-phy";
+};
+
&reg_dcdc1 {
regulator-always-on;
regulator-min-microvolt = <3000000>;
@@ -161,40 +226,6 @@
regulator-name = "vcc-wifi";
};
-&mmc0 {
- vmmc-supply = <&reg_dcdc1>;
- bus-width = <4>;
- cd-gpios = <&pio 7 13 GPIO_ACTIVE_LOW>; /* PH13 */
- status = "okay";
-};
-
-&mmc1 {
- pinctrl-names = "default";
- pinctrl-0 = <&mmc1_pg_pins>;
- vmmc-supply = <&reg_dldo2>;
- vqmmc-supply = <&reg_dldo1>;
- mmc-pwrseq = <&wifi_pwrseq>;
- bus-width = <4>;
- non-removable;
- status = "okay";
-};
-
-&mmc2 {
- vmmc-supply = <&reg_dcdc1>;
- vqmmc-supply = <&reg_dcdc1>;
- bus-width = <8>;
- non-removable;
- status = "okay";
-};
-
-&ohci1 {
- status = "okay";
-};
-
-&ohci2 {
- status = "okay";
-};
-
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_pb_pins>;
diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index 173dcc1..bd97ca3 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -265,6 +265,19 @@
#interrupt-cells = <3>;
#gpio-cells = <3>;
+ gmac_rgmii_pins: gmac-rgmii-pins {
+ pins = "PA0", "PA1", "PA2", "PA3",
+ "PA4", "PA5", "PA6", "PA7",
+ "PA8", "PA10", "PA11", "PA12",
+ "PA13", "PA15", "PA16";
+ function = "gmac";
+ /*
+ * data lines in RGMII mode use DDR mode
+ * and need a higher signal drive strength
+ */
+ drive-strength = <40>;
+ };
+
i2c0_pins: i2c0-pins {
pins = "PB0", "PB1";
function = "i2c0";
@@ -451,6 +464,27 @@
#size-cells = <0>;
};
+ gmac: ethernet@1c50000 {
+ compatible = "allwinner,sun8i-r40-gmac";
+ syscon = <&ccu>;
+ reg = <0x01c50000 0x10000>;
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ resets = <&ccu RST_BUS_GMAC>;
+ reset-names = "stmmaceth";
+ clocks = <&ccu CLK_BUS_GMAC>;
+ clock-names = "stmmaceth";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ gmac_mdio: mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
gic: interrupt-controller@1c81000 {
compatible = "arm,gic-400";
reg = <0x01c81000 0x1000>,
diff --git a/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts b/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts
index a26d72c..35859d8 100644
--- a/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts
+++ b/arch/arm/boot/dts/sun8i-v40-bananapi-m2-berry.dts
@@ -87,6 +87,11 @@
};
};
+&ehci1 {
+ /* Terminus Tech FE 1.1s 4-port USB 2.0 hub here */
+ status = "okay";
+};
+
&i2c0 {
status = "okay";
@@ -170,3 +175,8 @@
pinctrl-0 = <&uart0_pb_pins>;
status = "okay";
};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_vcc5v0>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 1be1a02d6..c3bff11 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -822,6 +822,19 @@
status = "disabled";
};
+ r_i2c: i2c@1f02400 {
+ compatible = "allwinner,sun6i-a31-i2c";
+ reg = <0x01f02400 0x400>;
+ interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_i2c_pins>;
+ clocks = <&r_ccu CLK_APB0_I2C>;
+ resets = <&r_ccu RST_APB0_I2C>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
r_pio: pinctrl@1f02c00 {
compatible = "allwinner,sun8i-h3-r-pinctrl";
reg = <0x01f02c00 0x400>;
@@ -837,6 +850,11 @@
pins = "PL11";
function = "s_cir_rx";
};
+
+ r_i2c_pins: r-i2c {
+ pins = "PL0", "PL1";
+ function = "s_i2c";
+ };
};
};
};
diff --git a/arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi b/arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi
new file mode 100644
index 0000000..f7ffdd6
--- /dev/null
+++ b/arch/arm/boot/dts/sunxi-libretech-all-h3-cc.dtsi
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2017 Chen-Yu Tsai <wens@csie.org>
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ aliases {
+ ethernet0 = &emac;
+ serial0 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ connector {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ pwr_led {
+ label = "librecomputer:green:pwr";
+ gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
+ default-state = "on";
+ };
+
+ status_led {
+ label = "librecomputer:blue:status";
+ gpios = <&pio 0 7 GPIO_ACTIVE_HIGH>; /* PA7 */
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ power {
+ label = "power";
+ linux,code = <KEY_POWER>;
+ gpios = <&r_pio 0 2 GPIO_ACTIVE_LOW>; /* PL2 */
+ };
+ };
+
+ reg_vcc1v2: vcc1v2 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc1v2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&reg_vcc5v0>;
+ gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
+ enable-active-high;
+ };
+
+ reg_vcc3v3: vcc3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&reg_vcc5v0>;
+ };
+
+ /* This represents the board's 5V input */
+ reg_vcc5v0: vcc5v0 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+
+ reg_vcc_dram: vcc-dram {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-dram";
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&reg_vcc5v0>;
+ gpio = <&r_pio 0 9 GPIO_ACTIVE_HIGH>; /* PL9 */
+ enable-active-high;
+ };
+
+ reg_vcc_io: vcc-io {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc-io";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&reg_vcc3v3>;
+ gpio = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */
+ };
+
+ reg_vdd_cpux: vdd-cpux {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd-cpux";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&reg_vcc5v0>;
+ gpio = <&r_pio 0 8 GPIO_ACTIVE_HIGH>; /* PL8 */
+ enable-active-high;
+ };
+};
+
+&codec {
+ allwinner,audio-routing =
+ "Line Out", "LINEOUT",
+ "MIC1", "Mic",
+ "Mic", "MBIAS";
+ status = "okay";
+};
+
+&cpu0 {
+ cpu-supply = <&reg_vdd_cpux>;
+};
+
+&de {
+ status = "okay";
+};
+
+&ehci0 {
+ status = "okay";
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&ehci2 {
+ status = "okay";
+};
+
+&ehci3 {
+ status = "okay";
+};
+
+&emac {
+ phy-handle = <&int_mii_phy>;
+ phy-mode = "mii";
+ allwinner,leds-active-low;
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&ir {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_pins_a>;
+ status = "okay";
+};
+
+&mmc0 {
+ vmmc-supply = <&reg_vcc_io>;
+ 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";
+};
+
+&usb_otg {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usbphy {
+ /* VBUS on USB ports are always on */
+ usb0_vbus-supply = <&reg_vcc5v0>;
+ usb1_vbus-supply = <&reg_vcc5v0>;
+ usb2_vbus-supply = <&reg_vcc5v0>;
+ usb3_vbus-supply = <&reg_vcc5v0>;
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 0e4a132..84c4358 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -19,6 +19,7 @@
clocks = <&tegra_car TEGRA114_CLK_HOST1X>;
resets = <&tegra_car 28>;
reset-names = "host1x";
+ iommus = <&mc TEGRA_SWGROUP_HC>;
#address-cells = <1>;
#size-cells = <1>;
@@ -32,6 +33,8 @@
clocks = <&tegra_car TEGRA114_CLK_GR2D>;
resets = <&tegra_car 21>;
reset-names = "2d";
+
+ iommus = <&mc TEGRA_SWGROUP_G2>;
};
gr3d@54180000 {
@@ -40,6 +43,8 @@
clocks = <&tegra_car TEGRA114_CLK_GR3D>;
resets = <&tegra_car 24>;
reset-names = "3d";
+
+ iommus = <&mc TEGRA_SWGROUP_NV>;
};
dc@54200000 {
diff --git a/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi b/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi
index bb67edb..3455822 100644
--- a/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi
+++ b/arch/arm/boot/dts/tegra124-apalis-v1.2.dtsi
@@ -1536,15 +1536,15 @@
};
serial@70006040 {
- compatible = "nvidia,tegra124-hsuart";
+ compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
};
serial@70006200 {
- compatible = "nvidia,tegra124-hsuart";
+ compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
};
serial@70006300 {
- compatible = "nvidia,tegra124-hsuart";
+ compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
};
hdmi_ddc: i2c@7000c700 {
diff --git a/arch/arm/boot/dts/tegra124-apalis.dtsi b/arch/arm/boot/dts/tegra124-apalis.dtsi
index 65a2161..9f960c8 100644
--- a/arch/arm/boot/dts/tegra124-apalis.dtsi
+++ b/arch/arm/boot/dts/tegra124-apalis.dtsi
@@ -1565,15 +1565,15 @@
};
serial@70006040 {
- compatible = "nvidia,tegra124-hsuart";
+ compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
};
serial@70006200 {
- compatible = "nvidia,tegra124-hsuart";
+ compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
};
serial@70006300 {
- compatible = "nvidia,tegra124-hsuart";
+ compatible = "nvidia,tegra124-hsuart", "nvidia,tegra30-hsuart";
};
hdmi_ddc: i2c@7000c400 {
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index a110cf8..09087b9 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -112,6 +112,7 @@
clocks = <&tegra_car TEGRA30_CLK_HOST1X>;
resets = <&tegra_car 28>;
reset-names = "host1x";
+ iommus = <&mc TEGRA_SWGROUP_HC>;
#address-cells = <1>;
#size-cells = <1>;
@@ -125,6 +126,8 @@
clocks = <&tegra_car TEGRA30_CLK_MPE>;
resets = <&tegra_car 60>;
reset-names = "mpe";
+
+ iommus = <&mc TEGRA_SWGROUP_MPE>;
};
vi@54080000 {
@@ -134,6 +137,8 @@
clocks = <&tegra_car TEGRA30_CLK_VI>;
resets = <&tegra_car 20>;
reset-names = "vi";
+
+ iommus = <&mc TEGRA_SWGROUP_VI>;
};
epp@540c0000 {
@@ -143,6 +148,8 @@
clocks = <&tegra_car TEGRA30_CLK_EPP>;
resets = <&tegra_car 19>;
reset-names = "epp";
+
+ iommus = <&mc TEGRA_SWGROUP_EPP>;
};
isp@54100000 {
@@ -152,6 +159,8 @@
clocks = <&tegra_car TEGRA30_CLK_ISP>;
resets = <&tegra_car 23>;
reset-names = "isp";
+
+ iommus = <&mc TEGRA_SWGROUP_ISP>;
};
gr2d@54140000 {
@@ -161,6 +170,8 @@
clocks = <&tegra_car TEGRA30_CLK_GR2D>;
resets = <&tegra_car 21>;
reset-names = "2d";
+
+ iommus = <&mc TEGRA_SWGROUP_G2>;
};
gr3d@54180000 {
@@ -172,6 +183,9 @@
resets = <&tegra_car 24>,
<&tegra_car 98>;
reset-names = "3d", "3d2";
+
+ iommus = <&mc TEGRA_SWGROUP_NV>,
+ <&mc TEGRA_SWGROUP_NV2>;
};
dc@54200000 {
diff --git a/arch/arm/boot/dts/uniphier-pro4.dtsi b/arch/arm/boot/dts/uniphier-pro4.dtsi
index 844124b..49539f0 100644
--- a/arch/arm/boot/dts/uniphier-pro4.dtsi
+++ b/arch/arm/boot/dts/uniphier-pro4.dtsi
@@ -286,7 +286,7 @@
has-transaction-translator;
};
- soc-glue@5f800000 {
+ soc_glue: soc-glue@5f800000 {
compatible = "socionext,uniphier-pro4-soc-glue",
"simple-mfd", "syscon";
reg = <0x5f800000 0x2000>;
@@ -371,10 +371,14 @@
interrupts = <0 66 4>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ether_rgmii>;
- clocks = <&sys_clk 6>;
- resets = <&sys_rst 6>;
+ clock-names = "gio", "ether", "ether-gb", "ether-phy";
+ clocks = <&sys_clk 12>, <&sys_clk 6>, <&sys_clk 7>,
+ <&sys_clk 10>;
+ reset-names = "gio", "ether";
+ resets = <&sys_rst 12>, <&sys_rst 6>;
phy-mode = "rgmii";
local-mac-address = [00 00 00 00 00 00];
+ socionext,syscon-phy-mode = <&soc_glue 0>;
mdio: mdio {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/uniphier-pxs2.dtsi b/arch/arm/boot/dts/uniphier-pxs2.dtsi
index debcbd1..641d961 100644
--- a/arch/arm/boot/dts/uniphier-pxs2.dtsi
+++ b/arch/arm/boot/dts/uniphier-pxs2.dtsi
@@ -506,10 +506,13 @@
interrupts = <0 66 4>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ether_rgmii>;
+ clock-names = "ether";
clocks = <&sys_clk 6>;
+ reset-names = "ether";
resets = <&sys_rst 6>;
phy-mode = "rgmii";
local-mac-address = [00 00 00 00 00 00];
+ socionext,syscon-phy-mode = <&soc_glue 0>;
mdio: mdio {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
index 35714ff..4488c8f 100644
--- a/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
@@ -17,426 +17,436 @@
* CHANGES TO vexpress-v2m.dtsi!
*/
- motherboard {
- model = "V2M-P1";
- arm,hbi = <0x190>;
- arm,vexpress,site = <0>;
- arm,v2m-memory-map = "rs1";
- compatible = "arm,vexpress,v2m-p1", "simple-bus";
- #address-cells = <2>; /* SMB chipselect number and offset */
- #size-cells = <1>;
- #interrupt-cells = <1>;
- ranges;
-
- flash@0,00000000 {
- compatible = "arm,vexpress-flash", "cfi-flash";
- reg = <0 0x00000000 0x04000000>,
- <4 0x00000000 0x04000000>;
- bank-width = <4>;
- };
+/ {
+ smb@8000000 {
+ motherboard {
+ model = "V2M-P1";
+ arm,hbi = <0x190>;
+ arm,vexpress,site = <0>;
+ arm,v2m-memory-map = "rs1";
+ compatible = "arm,vexpress,v2m-p1", "simple-bus";
+ #address-cells = <2>; /* SMB chipselect number and offset */
+ #size-cells = <1>;
+ #interrupt-cells = <1>;
+ ranges;
- psram@1,00000000 {
- compatible = "arm,vexpress-psram", "mtd-ram";
- reg = <1 0x00000000 0x02000000>;
- bank-width = <4>;
- };
+ flash@0,00000000 {
+ compatible = "arm,vexpress-flash", "cfi-flash";
+ reg = <0 0x00000000 0x04000000>,
+ <4 0x00000000 0x04000000>;
+ bank-width = <4>;
+ };
- v2m_video_ram: vram@2,00000000 {
- compatible = "arm,vexpress-vram";
- reg = <2 0x00000000 0x00800000>;
- };
+ psram@1,00000000 {
+ compatible = "arm,vexpress-psram", "mtd-ram";
+ reg = <1 0x00000000 0x02000000>;
+ bank-width = <4>;
+ };
- ethernet@2,02000000 {
- compatible = "smsc,lan9118", "smsc,lan9115";
- reg = <2 0x02000000 0x10000>;
- interrupts = <15>;
- phy-mode = "mii";
- reg-io-width = <4>;
- smsc,irq-active-high;
- smsc,irq-push-pull;
- vdd33a-supply = <&v2m_fixed_3v3>;
- vddvario-supply = <&v2m_fixed_3v3>;
- };
+ v2m_video_ram: vram@2,00000000 {
+ compatible = "arm,vexpress-vram";
+ reg = <2 0x00000000 0x00800000>;
+ };
- usb@2,03000000 {
- compatible = "nxp,usb-isp1761";
- reg = <2 0x03000000 0x20000>;
- interrupts = <16>;
- port1-otg;
- };
+ ethernet@2,02000000 {
+ compatible = "smsc,lan9118", "smsc,lan9115";
+ reg = <2 0x02000000 0x10000>;
+ interrupts = <15>;
+ phy-mode = "mii";
+ reg-io-width = <4>;
+ smsc,irq-active-high;
+ smsc,irq-push-pull;
+ vdd33a-supply = <&v2m_fixed_3v3>;
+ vddvario-supply = <&v2m_fixed_3v3>;
+ };
- iofpga@3,00000000 {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0 3 0 0x200000>;
+ usb@2,03000000 {
+ compatible = "nxp,usb-isp1761";
+ reg = <2 0x03000000 0x20000>;
+ interrupts = <16>;
+ port1-otg;
+ };
- v2m_sysreg: sysreg@10000 {
- compatible = "arm,vexpress-sysreg";
- reg = <0x010000 0x1000>;
+ iofpga@3,00000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 3 0 0x200000>;
+
+ v2m_sysreg: sysreg@10000 {
+ compatible = "arm,vexpress-sysreg";
+ reg = <0x010000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x10000 0x1000>;
+
+ v2m_led_gpios: gpio@8 {
+ compatible = "arm,vexpress-sysreg,sys_led";
+ reg = <0x008 4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
- v2m_led_gpios: sys_led {
- compatible = "arm,vexpress-sysreg,sys_led";
- gpio-controller;
- #gpio-cells = <2>;
- };
+ v2m_mmc_gpios: gpio@48 {
+ compatible = "arm,vexpress-sysreg,sys_mci";
+ reg = <0x048 4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
- v2m_mmc_gpios: sys_mci {
- compatible = "arm,vexpress-sysreg,sys_mci";
- gpio-controller;
- #gpio-cells = <2>;
+ v2m_flash_gpios: gpio@4c {
+ compatible = "arm,vexpress-sysreg,sys_flash";
+ reg = <0x04c 4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
};
- v2m_flash_gpios: sys_flash {
- compatible = "arm,vexpress-sysreg,sys_flash";
- gpio-controller;
- #gpio-cells = <2>;
+ v2m_sysctl: sysctl@20000 {
+ compatible = "arm,sp810", "arm,primecell";
+ reg = <0x020000 0x1000>;
+ clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
+ clock-names = "refclk", "timclk", "apb_pclk";
+ #clock-cells = <1>;
+ clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+ assigned-clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_sysctl 3>, <&v2m_sysctl 3>;
+ assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
};
- };
- v2m_sysctl: sysctl@20000 {
- compatible = "arm,sp810", "arm,primecell";
- reg = <0x020000 0x1000>;
- clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
- clock-names = "refclk", "timclk", "apb_pclk";
- #clock-cells = <1>;
- clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
- assigned-clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_sysctl 3>, <&v2m_sysctl 3>;
- assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
- };
+ /* PCI-E I2C bus */
+ v2m_i2c_pcie: i2c@30000 {
+ compatible = "arm,versatile-i2c";
+ reg = <0x030000 0x1000>;
- /* PCI-E I2C bus */
- v2m_i2c_pcie: i2c@30000 {
- compatible = "arm,versatile-i2c";
- reg = <0x030000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
+ pcie-switch@60 {
+ compatible = "idt,89hpes32h8";
+ reg = <0x60>;
+ };
+ };
- pcie-switch@60 {
- compatible = "idt,89hpes32h8";
- reg = <0x60>;
+ aaci@40000 {
+ compatible = "arm,pl041", "arm,primecell";
+ reg = <0x040000 0x1000>;
+ interrupts = <11>;
+ clocks = <&smbclk>;
+ clock-names = "apb_pclk";
};
- };
- aaci@40000 {
- compatible = "arm,pl041", "arm,primecell";
- reg = <0x040000 0x1000>;
- interrupts = <11>;
- clocks = <&smbclk>;
- clock-names = "apb_pclk";
- };
+ mmci@50000 {
+ compatible = "arm,pl180", "arm,primecell";
+ reg = <0x050000 0x1000>;
+ interrupts = <9 10>;
+ cd-gpios = <&v2m_mmc_gpios 0 0>;
+ wp-gpios = <&v2m_mmc_gpios 1 0>;
+ max-frequency = <12000000>;
+ vmmc-supply = <&v2m_fixed_3v3>;
+ clocks = <&v2m_clk24mhz>, <&smbclk>;
+ clock-names = "mclk", "apb_pclk";
+ };
- mmci@50000 {
- compatible = "arm,pl180", "arm,primecell";
- reg = <0x050000 0x1000>;
- interrupts = <9 10>;
- cd-gpios = <&v2m_mmc_gpios 0 0>;
- wp-gpios = <&v2m_mmc_gpios 1 0>;
- max-frequency = <12000000>;
- vmmc-supply = <&v2m_fixed_3v3>;
- clocks = <&v2m_clk24mhz>, <&smbclk>;
- clock-names = "mclk", "apb_pclk";
- };
+ kmi@60000 {
+ compatible = "arm,pl050", "arm,primecell";
+ reg = <0x060000 0x1000>;
+ interrupts = <12>;
+ clocks = <&v2m_clk24mhz>, <&smbclk>;
+ clock-names = "KMIREFCLK", "apb_pclk";
+ };
- kmi@60000 {
- compatible = "arm,pl050", "arm,primecell";
- reg = <0x060000 0x1000>;
- interrupts = <12>;
- clocks = <&v2m_clk24mhz>, <&smbclk>;
- clock-names = "KMIREFCLK", "apb_pclk";
- };
+ kmi@70000 {
+ compatible = "arm,pl050", "arm,primecell";
+ reg = <0x070000 0x1000>;
+ interrupts = <13>;
+ clocks = <&v2m_clk24mhz>, <&smbclk>;
+ clock-names = "KMIREFCLK", "apb_pclk";
+ };
- kmi@70000 {
- compatible = "arm,pl050", "arm,primecell";
- reg = <0x070000 0x1000>;
- interrupts = <13>;
- clocks = <&v2m_clk24mhz>, <&smbclk>;
- clock-names = "KMIREFCLK", "apb_pclk";
- };
+ v2m_serial0: uart@90000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x090000 0x1000>;
+ interrupts = <5>;
+ clocks = <&v2m_oscclk2>, <&smbclk>;
+ clock-names = "uartclk", "apb_pclk";
+ };
- v2m_serial0: uart@90000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x090000 0x1000>;
- interrupts = <5>;
- clocks = <&v2m_oscclk2>, <&smbclk>;
- clock-names = "uartclk", "apb_pclk";
- };
+ v2m_serial1: uart@a0000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0a0000 0x1000>;
+ interrupts = <6>;
+ clocks = <&v2m_oscclk2>, <&smbclk>;
+ clock-names = "uartclk", "apb_pclk";
+ };
- v2m_serial1: uart@a0000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x0a0000 0x1000>;
- interrupts = <6>;
- clocks = <&v2m_oscclk2>, <&smbclk>;
- clock-names = "uartclk", "apb_pclk";
- };
+ v2m_serial2: uart@b0000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0b0000 0x1000>;
+ interrupts = <7>;
+ clocks = <&v2m_oscclk2>, <&smbclk>;
+ clock-names = "uartclk", "apb_pclk";
+ };
- v2m_serial2: uart@b0000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x0b0000 0x1000>;
- interrupts = <7>;
- clocks = <&v2m_oscclk2>, <&smbclk>;
- clock-names = "uartclk", "apb_pclk";
- };
+ v2m_serial3: uart@c0000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0c0000 0x1000>;
+ interrupts = <8>;
+ clocks = <&v2m_oscclk2>, <&smbclk>;
+ clock-names = "uartclk", "apb_pclk";
+ };
- v2m_serial3: uart@c0000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x0c0000 0x1000>;
- interrupts = <8>;
- clocks = <&v2m_oscclk2>, <&smbclk>;
- clock-names = "uartclk", "apb_pclk";
- };
+ wdt@f0000 {
+ compatible = "arm,sp805", "arm,primecell";
+ reg = <0x0f0000 0x1000>;
+ interrupts = <0>;
+ clocks = <&v2m_refclk32khz>, <&smbclk>;
+ clock-names = "wdogclk", "apb_pclk";
+ };
- wdt@f0000 {
- compatible = "arm,sp805", "arm,primecell";
- reg = <0x0f0000 0x1000>;
- interrupts = <0>;
- clocks = <&v2m_refclk32khz>, <&smbclk>;
- clock-names = "wdogclk", "apb_pclk";
- };
+ v2m_timer01: timer@110000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x110000 0x1000>;
+ interrupts = <2>;
+ clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
+ };
- v2m_timer01: timer@110000 {
- compatible = "arm,sp804", "arm,primecell";
- reg = <0x110000 0x1000>;
- interrupts = <2>;
- clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
- clock-names = "timclken1", "timclken2", "apb_pclk";
- };
+ v2m_timer23: timer@120000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x120000 0x1000>;
+ interrupts = <3>;
+ clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&smbclk>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
+ };
- v2m_timer23: timer@120000 {
- compatible = "arm,sp804", "arm,primecell";
- reg = <0x120000 0x1000>;
- interrupts = <3>;
- clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&smbclk>;
- clock-names = "timclken1", "timclken2", "apb_pclk";
- };
+ /* DVI I2C bus */
+ v2m_i2c_dvi: i2c@160000 {
+ compatible = "arm,versatile-i2c";
+ reg = <0x160000 0x1000>;
- /* DVI I2C bus */
- v2m_i2c_dvi: i2c@160000 {
- compatible = "arm,versatile-i2c";
- reg = <0x160000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dvi-transmitter@39 {
+ compatible = "sil,sii9022-tpi", "sil,sii9022";
+ reg = <0x39>;
+ };
- dvi-transmitter@39 {
- compatible = "sil,sii9022-tpi", "sil,sii9022";
- reg = <0x39>;
+ dvi-transmitter@60 {
+ compatible = "sil,sii9022-cpi", "sil,sii9022";
+ reg = <0x60>;
+ };
};
- dvi-transmitter@60 {
- compatible = "sil,sii9022-cpi", "sil,sii9022";
- reg = <0x60>;
+ rtc@170000 {
+ compatible = "arm,pl031", "arm,primecell";
+ reg = <0x170000 0x1000>;
+ interrupts = <4>;
+ clocks = <&smbclk>;
+ clock-names = "apb_pclk";
};
- };
- rtc@170000 {
- compatible = "arm,pl031", "arm,primecell";
- reg = <0x170000 0x1000>;
- interrupts = <4>;
- clocks = <&smbclk>;
- clock-names = "apb_pclk";
- };
-
- compact-flash@1a0000 {
- compatible = "arm,vexpress-cf", "ata-generic";
- reg = <0x1a0000 0x100
- 0x1a0100 0xf00>;
- reg-shift = <2>;
- };
-
- clcd@1f0000 {
- compatible = "arm,pl111", "arm,primecell";
- reg = <0x1f0000 0x1000>;
- interrupt-names = "combined";
- interrupts = <14>;
- clocks = <&v2m_oscclk1>, <&smbclk>;
- clock-names = "clcdclk", "apb_pclk";
- memory-region = <&v2m_video_ram>;
- max-memory-bandwidth = <50350000>; /* 16bpp @ 25.175MHz */
-
- port {
- v2m_clcd_pads: endpoint {
- remote-endpoint = <&v2m_clcd_panel>;
- arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
- };
+ compact-flash@1a0000 {
+ compatible = "arm,vexpress-cf", "ata-generic";
+ reg = <0x1a0000 0x100
+ 0x1a0100 0xf00>;
+ reg-shift = <2>;
};
- panel {
- compatible = "panel-dpi";
+ clcd@1f0000 {
+ compatible = "arm,pl111", "arm,primecell";
+ reg = <0x1f0000 0x1000>;
+ interrupt-names = "combined";
+ interrupts = <14>;
+ clocks = <&v2m_oscclk1>, <&smbclk>;
+ clock-names = "clcdclk", "apb_pclk";
+ memory-region = <&v2m_video_ram>;
+ max-memory-bandwidth = <50350000>; /* 16bpp @ 25.175MHz */
port {
- v2m_clcd_panel: endpoint {
- remote-endpoint = <&v2m_clcd_pads>;
+ v2m_clcd_pads: endpoint {
+ remote-endpoint = <&v2m_clcd_panel>;
+ arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
};
};
- panel-timing {
- clock-frequency = <25175000>;
- hactive = <640>;
- hback-porch = <40>;
- hfront-porch = <24>;
- hsync-len = <96>;
- vactive = <480>;
- vback-porch = <32>;
- vfront-porch = <11>;
- vsync-len = <2>;
+ panel {
+ compatible = "panel-dpi";
+
+ port {
+ v2m_clcd_panel: endpoint {
+ remote-endpoint = <&v2m_clcd_pads>;
+ };
+ };
+
+ panel-timing {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ hsync-len = <96>;
+ vactive = <480>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ vsync-len = <2>;
+ };
};
};
};
- };
- v2m_fixed_3v3: fixed-regulator-0 {
- compatible = "regulator-fixed";
- regulator-name = "3V3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
+ v2m_fixed_3v3: fixed-regulator-0 {
+ compatible = "regulator-fixed";
+ regulator-name = "3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
- v2m_clk24mhz: clk24mhz {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <24000000>;
- clock-output-names = "v2m:clk24mhz";
- };
+ v2m_clk24mhz: clk24mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "v2m:clk24mhz";
+ };
- v2m_refclk1mhz: refclk1mhz {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <1000000>;
- clock-output-names = "v2m:refclk1mhz";
- };
+ v2m_refclk1mhz: refclk1mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1000000>;
+ clock-output-names = "v2m:refclk1mhz";
+ };
- v2m_refclk32khz: refclk32khz {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- clock-output-names = "v2m:refclk32khz";
- };
+ v2m_refclk32khz: refclk32khz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "v2m:refclk32khz";
+ };
- leds {
- compatible = "gpio-leds";
+ leds {
+ compatible = "gpio-leds";
- user1 {
- label = "v2m:green:user1";
- gpios = <&v2m_led_gpios 0 0>;
- linux,default-trigger = "heartbeat";
- };
+ user1 {
+ label = "v2m:green:user1";
+ gpios = <&v2m_led_gpios 0 0>;
+ linux,default-trigger = "heartbeat";
+ };
- user2 {
- label = "v2m:green:user2";
- gpios = <&v2m_led_gpios 1 0>;
- linux,default-trigger = "mmc0";
- };
+ user2 {
+ label = "v2m:green:user2";
+ gpios = <&v2m_led_gpios 1 0>;
+ linux,default-trigger = "mmc0";
+ };
- user3 {
- label = "v2m:green:user3";
- gpios = <&v2m_led_gpios 2 0>;
- linux,default-trigger = "cpu0";
- };
+ user3 {
+ label = "v2m:green:user3";
+ gpios = <&v2m_led_gpios 2 0>;
+ linux,default-trigger = "cpu0";
+ };
- user4 {
- label = "v2m:green:user4";
- gpios = <&v2m_led_gpios 3 0>;
- linux,default-trigger = "cpu1";
- };
+ user4 {
+ label = "v2m:green:user4";
+ gpios = <&v2m_led_gpios 3 0>;
+ linux,default-trigger = "cpu1";
+ };
- user5 {
- label = "v2m:green:user5";
- gpios = <&v2m_led_gpios 4 0>;
- linux,default-trigger = "cpu2";
- };
+ user5 {
+ label = "v2m:green:user5";
+ gpios = <&v2m_led_gpios 4 0>;
+ linux,default-trigger = "cpu2";
+ };
- user6 {
- label = "v2m:green:user6";
- gpios = <&v2m_led_gpios 5 0>;
- linux,default-trigger = "cpu3";
- };
+ user6 {
+ label = "v2m:green:user6";
+ gpios = <&v2m_led_gpios 5 0>;
+ linux,default-trigger = "cpu3";
+ };
- user7 {
- label = "v2m:green:user7";
- gpios = <&v2m_led_gpios 6 0>;
- linux,default-trigger = "cpu4";
- };
+ user7 {
+ label = "v2m:green:user7";
+ gpios = <&v2m_led_gpios 6 0>;
+ linux,default-trigger = "cpu4";
+ };
- user8 {
- label = "v2m:green:user8";
- gpios = <&v2m_led_gpios 7 0>;
- linux,default-trigger = "cpu5";
+ user8 {
+ label = "v2m:green:user8";
+ gpios = <&v2m_led_gpios 7 0>;
+ linux,default-trigger = "cpu5";
+ };
};
- };
- mcc {
- compatible = "arm,vexpress,config-bus";
- arm,vexpress,config-bridge = <&v2m_sysreg>;
+ mcc {
+ compatible = "arm,vexpress,config-bus";
+ arm,vexpress,config-bridge = <&v2m_sysreg>;
- oscclk0 {
- /* MCC static memory clock */
- compatible = "arm,vexpress-osc";
- arm,vexpress-sysreg,func = <1 0>;
- freq-range = <25000000 60000000>;
- #clock-cells = <0>;
- clock-output-names = "v2m:oscclk0";
- };
+ oscclk0 {
+ /* MCC static memory clock */
+ compatible = "arm,vexpress-osc";
+ arm,vexpress-sysreg,func = <1 0>;
+ freq-range = <25000000 60000000>;
+ #clock-cells = <0>;
+ clock-output-names = "v2m:oscclk0";
+ };
- v2m_oscclk1: oscclk1 {
- /* CLCD clock */
- compatible = "arm,vexpress-osc";
- arm,vexpress-sysreg,func = <1 1>;
- freq-range = <23750000 65000000>;
- #clock-cells = <0>;
- clock-output-names = "v2m:oscclk1";
- };
+ v2m_oscclk1: oscclk1 {
+ /* CLCD clock */
+ compatible = "arm,vexpress-osc";
+ arm,vexpress-sysreg,func = <1 1>;
+ freq-range = <23750000 65000000>;
+ #clock-cells = <0>;
+ clock-output-names = "v2m:oscclk1";
+ };
- v2m_oscclk2: oscclk2 {
- /* IO FPGA peripheral clock */
- compatible = "arm,vexpress-osc";
- arm,vexpress-sysreg,func = <1 2>;
- freq-range = <24000000 24000000>;
- #clock-cells = <0>;
- clock-output-names = "v2m:oscclk2";
- };
+ v2m_oscclk2: oscclk2 {
+ /* IO FPGA peripheral clock */
+ compatible = "arm,vexpress-osc";
+ arm,vexpress-sysreg,func = <1 2>;
+ freq-range = <24000000 24000000>;
+ #clock-cells = <0>;
+ clock-output-names = "v2m:oscclk2";
+ };
- volt-vio {
- /* Logic level voltage */
- compatible = "arm,vexpress-volt";
- arm,vexpress-sysreg,func = <2 0>;
- regulator-name = "VIO";
- regulator-always-on;
- label = "VIO";
- };
+ volt-vio {
+ /* Logic level voltage */
+ compatible = "arm,vexpress-volt";
+ arm,vexpress-sysreg,func = <2 0>;
+ regulator-name = "VIO";
+ regulator-always-on;
+ label = "VIO";
+ };
- temp-mcc {
- /* MCC internal operating temperature */
- compatible = "arm,vexpress-temp";
- arm,vexpress-sysreg,func = <4 0>;
- label = "MCC";
- };
+ temp-mcc {
+ /* MCC internal operating temperature */
+ compatible = "arm,vexpress-temp";
+ arm,vexpress-sysreg,func = <4 0>;
+ label = "MCC";
+ };
- reset {
- compatible = "arm,vexpress-reset";
- arm,vexpress-sysreg,func = <5 0>;
- };
+ reset {
+ compatible = "arm,vexpress-reset";
+ arm,vexpress-sysreg,func = <5 0>;
+ };
- muxfpga {
- compatible = "arm,vexpress-muxfpga";
- arm,vexpress-sysreg,func = <7 0>;
- };
+ muxfpga {
+ compatible = "arm,vexpress-muxfpga";
+ arm,vexpress-sysreg,func = <7 0>;
+ };
- shutdown {
- compatible = "arm,vexpress-shutdown";
- arm,vexpress-sysreg,func = <8 0>;
- };
+ shutdown {
+ compatible = "arm,vexpress-shutdown";
+ arm,vexpress-sysreg,func = <8 0>;
+ };
- reboot {
- compatible = "arm,vexpress-reboot";
- arm,vexpress-sysreg,func = <9 0>;
- };
+ reboot {
+ compatible = "arm,vexpress-reboot";
+ arm,vexpress-sysreg,func = <9 0>;
+ };
- dvimode {
- compatible = "arm,vexpress-dvimode";
- arm,vexpress-sysreg,func = <11 0>;
+ dvimode {
+ compatible = "arm,vexpress-dvimode";
+ arm,vexpress-sysreg,func = <11 0>;
+ };
};
};
};
+};
diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi
index b0021a8..4db42f6 100644
--- a/arch/arm/boot/dts/vexpress-v2m.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m.dtsi
@@ -18,425 +18,435 @@
* CHANGES TO vexpress-v2m-rs1.dtsi!
*/
- motherboard {
- model = "V2M-P1";
- arm,hbi = <0x190>;
- arm,vexpress,site = <0>;
- compatible = "arm,vexpress,v2m-p1", "simple-bus";
- #address-cells = <2>; /* SMB chipselect number and offset */
- #size-cells = <1>;
- #interrupt-cells = <1>;
- ranges;
-
- flash@0,00000000 {
- compatible = "arm,vexpress-flash", "cfi-flash";
- reg = <0 0x00000000 0x04000000>,
- <1 0x00000000 0x04000000>;
- bank-width = <4>;
- };
+/ {
+ smb@4000000 {
+ motherboard {
+ model = "V2M-P1";
+ arm,hbi = <0x190>;
+ arm,vexpress,site = <0>;
+ compatible = "arm,vexpress,v2m-p1", "simple-bus";
+ #address-cells = <2>; /* SMB chipselect number and offset */
+ #size-cells = <1>;
+ #interrupt-cells = <1>;
+ ranges;
- psram@2,00000000 {
- compatible = "arm,vexpress-psram", "mtd-ram";
- reg = <2 0x00000000 0x02000000>;
- bank-width = <4>;
- };
+ flash@0,00000000 {
+ compatible = "arm,vexpress-flash", "cfi-flash";
+ reg = <0 0x00000000 0x04000000>,
+ <1 0x00000000 0x04000000>;
+ bank-width = <4>;
+ };
- v2m_video_ram: vram@3,00000000 {
- compatible = "arm,vexpress-vram";
- reg = <3 0x00000000 0x00800000>;
- };
+ psram@2,00000000 {
+ compatible = "arm,vexpress-psram", "mtd-ram";
+ reg = <2 0x00000000 0x02000000>;
+ bank-width = <4>;
+ };
- ethernet@3,02000000 {
- compatible = "smsc,lan9118", "smsc,lan9115";
- reg = <3 0x02000000 0x10000>;
- interrupts = <15>;
- phy-mode = "mii";
- reg-io-width = <4>;
- smsc,irq-active-high;
- smsc,irq-push-pull;
- vdd33a-supply = <&v2m_fixed_3v3>;
- vddvario-supply = <&v2m_fixed_3v3>;
- };
+ v2m_video_ram: vram@3,00000000 {
+ compatible = "arm,vexpress-vram";
+ reg = <3 0x00000000 0x00800000>;
+ };
- usb@3,03000000 {
- compatible = "nxp,usb-isp1761";
- reg = <3 0x03000000 0x20000>;
- interrupts = <16>;
- port1-otg;
- };
+ ethernet@3,02000000 {
+ compatible = "smsc,lan9118", "smsc,lan9115";
+ reg = <3 0x02000000 0x10000>;
+ interrupts = <15>;
+ phy-mode = "mii";
+ reg-io-width = <4>;
+ smsc,irq-active-high;
+ smsc,irq-push-pull;
+ vdd33a-supply = <&v2m_fixed_3v3>;
+ vddvario-supply = <&v2m_fixed_3v3>;
+ };
- iofpga@7,00000000 {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges = <0 7 0 0x20000>;
+ usb@3,03000000 {
+ compatible = "nxp,usb-isp1761";
+ reg = <3 0x03000000 0x20000>;
+ interrupts = <16>;
+ port1-otg;
+ };
- v2m_sysreg: sysreg@0 {
- compatible = "arm,vexpress-sysreg";
- reg = <0x00000 0x1000>;
+ iofpga@7,00000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 7 0 0x20000>;
+
+ v2m_sysreg: sysreg@0 {
+ compatible = "arm,vexpress-sysreg";
+ reg = <0x00000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0x1000>;
+
+ v2m_led_gpios: gpio@8 {
+ compatible = "arm,vexpress-sysreg,sys_led";
+ reg = <0x008 4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
- v2m_led_gpios: sys_led {
- compatible = "arm,vexpress-sysreg,sys_led";
- gpio-controller;
- #gpio-cells = <2>;
- };
+ v2m_mmc_gpios: gpio@48 {
+ compatible = "arm,vexpress-sysreg,sys_mci";
+ reg = <0x048 4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
- v2m_mmc_gpios: sys_mci {
- compatible = "arm,vexpress-sysreg,sys_mci";
- gpio-controller;
- #gpio-cells = <2>;
+ v2m_flash_gpios: gpio@4c {
+ compatible = "arm,vexpress-sysreg,sys_flash";
+ reg = <0x04c 4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
};
- v2m_flash_gpios: sys_flash {
- compatible = "arm,vexpress-sysreg,sys_flash";
- gpio-controller;
- #gpio-cells = <2>;
+ v2m_sysctl: sysctl@1000 {
+ compatible = "arm,sp810", "arm,primecell";
+ reg = <0x01000 0x1000>;
+ clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
+ clock-names = "refclk", "timclk", "apb_pclk";
+ #clock-cells = <1>;
+ clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+ assigned-clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_sysctl 3>, <&v2m_sysctl 3>;
+ assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
};
- };
- v2m_sysctl: sysctl@1000 {
- compatible = "arm,sp810", "arm,primecell";
- reg = <0x01000 0x1000>;
- clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
- clock-names = "refclk", "timclk", "apb_pclk";
- #clock-cells = <1>;
- clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
- assigned-clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_sysctl 3>, <&v2m_sysctl 3>;
- assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
- };
+ /* PCI-E I2C bus */
+ v2m_i2c_pcie: i2c@2000 {
+ compatible = "arm,versatile-i2c";
+ reg = <0x02000 0x1000>;
- /* PCI-E I2C bus */
- v2m_i2c_pcie: i2c@2000 {
- compatible = "arm,versatile-i2c";
- reg = <0x02000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
+ pcie-switch@60 {
+ compatible = "idt,89hpes32h8";
+ reg = <0x60>;
+ };
+ };
- pcie-switch@60 {
- compatible = "idt,89hpes32h8";
- reg = <0x60>;
+ aaci@4000 {
+ compatible = "arm,pl041", "arm,primecell";
+ reg = <0x04000 0x1000>;
+ interrupts = <11>;
+ clocks = <&smbclk>;
+ clock-names = "apb_pclk";
};
- };
- aaci@4000 {
- compatible = "arm,pl041", "arm,primecell";
- reg = <0x04000 0x1000>;
- interrupts = <11>;
- clocks = <&smbclk>;
- clock-names = "apb_pclk";
- };
+ mmci@5000 {
+ compatible = "arm,pl180", "arm,primecell";
+ reg = <0x05000 0x1000>;
+ interrupts = <9 10>;
+ cd-gpios = <&v2m_mmc_gpios 0 0>;
+ wp-gpios = <&v2m_mmc_gpios 1 0>;
+ max-frequency = <12000000>;
+ vmmc-supply = <&v2m_fixed_3v3>;
+ clocks = <&v2m_clk24mhz>, <&smbclk>;
+ clock-names = "mclk", "apb_pclk";
+ };
- mmci@5000 {
- compatible = "arm,pl180", "arm,primecell";
- reg = <0x05000 0x1000>;
- interrupts = <9 10>;
- cd-gpios = <&v2m_mmc_gpios 0 0>;
- wp-gpios = <&v2m_mmc_gpios 1 0>;
- max-frequency = <12000000>;
- vmmc-supply = <&v2m_fixed_3v3>;
- clocks = <&v2m_clk24mhz>, <&smbclk>;
- clock-names = "mclk", "apb_pclk";
- };
+ kmi@6000 {
+ compatible = "arm,pl050", "arm,primecell";
+ reg = <0x06000 0x1000>;
+ interrupts = <12>;
+ clocks = <&v2m_clk24mhz>, <&smbclk>;
+ clock-names = "KMIREFCLK", "apb_pclk";
+ };
- kmi@6000 {
- compatible = "arm,pl050", "arm,primecell";
- reg = <0x06000 0x1000>;
- interrupts = <12>;
- clocks = <&v2m_clk24mhz>, <&smbclk>;
- clock-names = "KMIREFCLK", "apb_pclk";
- };
+ kmi@7000 {
+ compatible = "arm,pl050", "arm,primecell";
+ reg = <0x07000 0x1000>;
+ interrupts = <13>;
+ clocks = <&v2m_clk24mhz>, <&smbclk>;
+ clock-names = "KMIREFCLK", "apb_pclk";
+ };
- kmi@7000 {
- compatible = "arm,pl050", "arm,primecell";
- reg = <0x07000 0x1000>;
- interrupts = <13>;
- clocks = <&v2m_clk24mhz>, <&smbclk>;
- clock-names = "KMIREFCLK", "apb_pclk";
- };
+ v2m_serial0: uart@9000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x09000 0x1000>;
+ interrupts = <5>;
+ clocks = <&v2m_oscclk2>, <&smbclk>;
+ clock-names = "uartclk", "apb_pclk";
+ };
- v2m_serial0: uart@9000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x09000 0x1000>;
- interrupts = <5>;
- clocks = <&v2m_oscclk2>, <&smbclk>;
- clock-names = "uartclk", "apb_pclk";
- };
+ v2m_serial1: uart@a000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0a000 0x1000>;
+ interrupts = <6>;
+ clocks = <&v2m_oscclk2>, <&smbclk>;
+ clock-names = "uartclk", "apb_pclk";
+ };
- v2m_serial1: uart@a000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x0a000 0x1000>;
- interrupts = <6>;
- clocks = <&v2m_oscclk2>, <&smbclk>;
- clock-names = "uartclk", "apb_pclk";
- };
+ v2m_serial2: uart@b000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0b000 0x1000>;
+ interrupts = <7>;
+ clocks = <&v2m_oscclk2>, <&smbclk>;
+ clock-names = "uartclk", "apb_pclk";
+ };
- v2m_serial2: uart@b000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x0b000 0x1000>;
- interrupts = <7>;
- clocks = <&v2m_oscclk2>, <&smbclk>;
- clock-names = "uartclk", "apb_pclk";
- };
+ v2m_serial3: uart@c000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0c000 0x1000>;
+ interrupts = <8>;
+ clocks = <&v2m_oscclk2>, <&smbclk>;
+ clock-names = "uartclk", "apb_pclk";
+ };
- v2m_serial3: uart@c000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x0c000 0x1000>;
- interrupts = <8>;
- clocks = <&v2m_oscclk2>, <&smbclk>;
- clock-names = "uartclk", "apb_pclk";
- };
+ wdt@f000 {
+ compatible = "arm,sp805", "arm,primecell";
+ reg = <0x0f000 0x1000>;
+ interrupts = <0>;
+ clocks = <&v2m_refclk32khz>, <&smbclk>;
+ clock-names = "wdogclk", "apb_pclk";
+ };
- wdt@f000 {
- compatible = "arm,sp805", "arm,primecell";
- reg = <0x0f000 0x1000>;
- interrupts = <0>;
- clocks = <&v2m_refclk32khz>, <&smbclk>;
- clock-names = "wdogclk", "apb_pclk";
- };
+ v2m_timer01: timer@11000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x11000 0x1000>;
+ interrupts = <2>;
+ clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
+ };
- v2m_timer01: timer@11000 {
- compatible = "arm,sp804", "arm,primecell";
- reg = <0x11000 0x1000>;
- interrupts = <2>;
- clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&smbclk>;
- clock-names = "timclken1", "timclken2", "apb_pclk";
- };
+ v2m_timer23: timer@12000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x12000 0x1000>;
+ interrupts = <3>;
+ clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&smbclk>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
+ };
- v2m_timer23: timer@12000 {
- compatible = "arm,sp804", "arm,primecell";
- reg = <0x12000 0x1000>;
- interrupts = <3>;
- clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&smbclk>;
- clock-names = "timclken1", "timclken2", "apb_pclk";
- };
+ /* DVI I2C bus */
+ v2m_i2c_dvi: i2c@16000 {
+ compatible = "arm,versatile-i2c";
+ reg = <0x16000 0x1000>;
- /* DVI I2C bus */
- v2m_i2c_dvi: i2c@16000 {
- compatible = "arm,versatile-i2c";
- reg = <0x16000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
- #address-cells = <1>;
- #size-cells = <0>;
+ dvi-transmitter@39 {
+ compatible = "sil,sii9022-tpi", "sil,sii9022";
+ reg = <0x39>;
+ };
- dvi-transmitter@39 {
- compatible = "sil,sii9022-tpi", "sil,sii9022";
- reg = <0x39>;
+ dvi-transmitter@60 {
+ compatible = "sil,sii9022-cpi", "sil,sii9022";
+ reg = <0x60>;
+ };
};
- dvi-transmitter@60 {
- compatible = "sil,sii9022-cpi", "sil,sii9022";
- reg = <0x60>;
+ rtc@17000 {
+ compatible = "arm,pl031", "arm,primecell";
+ reg = <0x17000 0x1000>;
+ interrupts = <4>;
+ clocks = <&smbclk>;
+ clock-names = "apb_pclk";
};
- };
- rtc@17000 {
- compatible = "arm,pl031", "arm,primecell";
- reg = <0x17000 0x1000>;
- interrupts = <4>;
- clocks = <&smbclk>;
- clock-names = "apb_pclk";
- };
-
- compact-flash@1a000 {
- compatible = "arm,vexpress-cf", "ata-generic";
- reg = <0x1a000 0x100
- 0x1a100 0xf00>;
- reg-shift = <2>;
- };
-
- clcd@1f000 {
- compatible = "arm,pl111", "arm,primecell";
- reg = <0x1f000 0x1000>;
- interrupt-names = "combined";
- interrupts = <14>;
- clocks = <&v2m_oscclk1>, <&smbclk>;
- clock-names = "clcdclk", "apb_pclk";
- memory-region = <&v2m_video_ram>;
- max-memory-bandwidth = <50350000>; /* 16bpp @ 25.175MHz */
-
- port {
- v2m_clcd_pads: endpoint {
- remote-endpoint = <&v2m_clcd_panel>;
- arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
- };
+ compact-flash@1a000 {
+ compatible = "arm,vexpress-cf", "ata-generic";
+ reg = <0x1a000 0x100
+ 0x1a100 0xf00>;
+ reg-shift = <2>;
};
- panel {
- compatible = "panel-dpi";
+ clcd@1f000 {
+ compatible = "arm,pl111", "arm,primecell";
+ reg = <0x1f000 0x1000>;
+ interrupt-names = "combined";
+ interrupts = <14>;
+ clocks = <&v2m_oscclk1>, <&smbclk>;
+ clock-names = "clcdclk", "apb_pclk";
+ memory-region = <&v2m_video_ram>;
+ max-memory-bandwidth = <50350000>; /* 16bpp @ 25.175MHz */
port {
- v2m_clcd_panel: endpoint {
- remote-endpoint = <&v2m_clcd_pads>;
+ v2m_clcd_pads: endpoint {
+ remote-endpoint = <&v2m_clcd_panel>;
+ arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
};
};
- panel-timing {
- clock-frequency = <25175000>;
- hactive = <640>;
- hback-porch = <40>;
- hfront-porch = <24>;
- hsync-len = <96>;
- vactive = <480>;
- vback-porch = <32>;
- vfront-porch = <11>;
- vsync-len = <2>;
+ panel {
+ compatible = "panel-dpi";
+
+ port {
+ v2m_clcd_panel: endpoint {
+ remote-endpoint = <&v2m_clcd_pads>;
+ };
+ };
+
+ panel-timing {
+ clock-frequency = <25175000>;
+ hactive = <640>;
+ hback-porch = <40>;
+ hfront-porch = <24>;
+ hsync-len = <96>;
+ vactive = <480>;
+ vback-porch = <32>;
+ vfront-porch = <11>;
+ vsync-len = <2>;
+ };
};
};
};
- };
- v2m_fixed_3v3: fixed-regulator-0 {
- compatible = "regulator-fixed";
- regulator-name = "3V3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
+ v2m_fixed_3v3: fixed-regulator-0 {
+ compatible = "regulator-fixed";
+ regulator-name = "3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
- v2m_clk24mhz: clk24mhz {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <24000000>;
- clock-output-names = "v2m:clk24mhz";
- };
+ v2m_clk24mhz: clk24mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "v2m:clk24mhz";
+ };
- v2m_refclk1mhz: refclk1mhz {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <1000000>;
- clock-output-names = "v2m:refclk1mhz";
- };
+ v2m_refclk1mhz: refclk1mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1000000>;
+ clock-output-names = "v2m:refclk1mhz";
+ };
- v2m_refclk32khz: refclk32khz {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- clock-output-names = "v2m:refclk32khz";
- };
+ v2m_refclk32khz: refclk32khz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "v2m:refclk32khz";
+ };
- leds {
- compatible = "gpio-leds";
+ leds {
+ compatible = "gpio-leds";
- user1 {
- label = "v2m:green:user1";
- gpios = <&v2m_led_gpios 0 0>;
- linux,default-trigger = "heartbeat";
- };
+ user1 {
+ label = "v2m:green:user1";
+ gpios = <&v2m_led_gpios 0 0>;
+ linux,default-trigger = "heartbeat";
+ };
- user2 {
- label = "v2m:green:user2";
- gpios = <&v2m_led_gpios 1 0>;
- linux,default-trigger = "mmc0";
- };
+ user2 {
+ label = "v2m:green:user2";
+ gpios = <&v2m_led_gpios 1 0>;
+ linux,default-trigger = "mmc0";
+ };
- user3 {
- label = "v2m:green:user3";
- gpios = <&v2m_led_gpios 2 0>;
- linux,default-trigger = "cpu0";
- };
+ user3 {
+ label = "v2m:green:user3";
+ gpios = <&v2m_led_gpios 2 0>;
+ linux,default-trigger = "cpu0";
+ };
- user4 {
- label = "v2m:green:user4";
- gpios = <&v2m_led_gpios 3 0>;
- linux,default-trigger = "cpu1";
- };
+ user4 {
+ label = "v2m:green:user4";
+ gpios = <&v2m_led_gpios 3 0>;
+ linux,default-trigger = "cpu1";
+ };
- user5 {
- label = "v2m:green:user5";
- gpios = <&v2m_led_gpios 4 0>;
- linux,default-trigger = "cpu2";
- };
+ user5 {
+ label = "v2m:green:user5";
+ gpios = <&v2m_led_gpios 4 0>;
+ linux,default-trigger = "cpu2";
+ };
- user6 {
- label = "v2m:green:user6";
- gpios = <&v2m_led_gpios 5 0>;
- linux,default-trigger = "cpu3";
- };
+ user6 {
+ label = "v2m:green:user6";
+ gpios = <&v2m_led_gpios 5 0>;
+ linux,default-trigger = "cpu3";
+ };
- user7 {
- label = "v2m:green:user7";
- gpios = <&v2m_led_gpios 6 0>;
- linux,default-trigger = "cpu4";
- };
+ user7 {
+ label = "v2m:green:user7";
+ gpios = <&v2m_led_gpios 6 0>;
+ linux,default-trigger = "cpu4";
+ };
- user8 {
- label = "v2m:green:user8";
- gpios = <&v2m_led_gpios 7 0>;
- linux,default-trigger = "cpu5";
+ user8 {
+ label = "v2m:green:user8";
+ gpios = <&v2m_led_gpios 7 0>;
+ linux,default-trigger = "cpu5";
+ };
};
- };
- mcc {
- compatible = "arm,vexpress,config-bus";
- arm,vexpress,config-bridge = <&v2m_sysreg>;
+ mcc {
+ compatible = "arm,vexpress,config-bus";
+ arm,vexpress,config-bridge = <&v2m_sysreg>;
- oscclk0 {
- /* MCC static memory clock */
- compatible = "arm,vexpress-osc";
- arm,vexpress-sysreg,func = <1 0>;
- freq-range = <25000000 60000000>;
- #clock-cells = <0>;
- clock-output-names = "v2m:oscclk0";
- };
+ oscclk0 {
+ /* MCC static memory clock */
+ compatible = "arm,vexpress-osc";
+ arm,vexpress-sysreg,func = <1 0>;
+ freq-range = <25000000 60000000>;
+ #clock-cells = <0>;
+ clock-output-names = "v2m:oscclk0";
+ };
- v2m_oscclk1: oscclk1 {
- /* CLCD clock */
- compatible = "arm,vexpress-osc";
- arm,vexpress-sysreg,func = <1 1>;
- freq-range = <23750000 65000000>;
- #clock-cells = <0>;
- clock-output-names = "v2m:oscclk1";
- };
+ v2m_oscclk1: oscclk1 {
+ /* CLCD clock */
+ compatible = "arm,vexpress-osc";
+ arm,vexpress-sysreg,func = <1 1>;
+ freq-range = <23750000 65000000>;
+ #clock-cells = <0>;
+ clock-output-names = "v2m:oscclk1";
+ };
- v2m_oscclk2: oscclk2 {
- /* IO FPGA peripheral clock */
- compatible = "arm,vexpress-osc";
- arm,vexpress-sysreg,func = <1 2>;
- freq-range = <24000000 24000000>;
- #clock-cells = <0>;
- clock-output-names = "v2m:oscclk2";
- };
+ v2m_oscclk2: oscclk2 {
+ /* IO FPGA peripheral clock */
+ compatible = "arm,vexpress-osc";
+ arm,vexpress-sysreg,func = <1 2>;
+ freq-range = <24000000 24000000>;
+ #clock-cells = <0>;
+ clock-output-names = "v2m:oscclk2";
+ };
- volt-vio {
- /* Logic level voltage */
- compatible = "arm,vexpress-volt";
- arm,vexpress-sysreg,func = <2 0>;
- regulator-name = "VIO";
- regulator-always-on;
- label = "VIO";
- };
+ volt-vio {
+ /* Logic level voltage */
+ compatible = "arm,vexpress-volt";
+ arm,vexpress-sysreg,func = <2 0>;
+ regulator-name = "VIO";
+ regulator-always-on;
+ label = "VIO";
+ };
- temp-mcc {
- /* MCC internal operating temperature */
- compatible = "arm,vexpress-temp";
- arm,vexpress-sysreg,func = <4 0>;
- label = "MCC";
- };
+ temp-mcc {
+ /* MCC internal operating temperature */
+ compatible = "arm,vexpress-temp";
+ arm,vexpress-sysreg,func = <4 0>;
+ label = "MCC";
+ };
- reset {
- compatible = "arm,vexpress-reset";
- arm,vexpress-sysreg,func = <5 0>;
- };
+ reset {
+ compatible = "arm,vexpress-reset";
+ arm,vexpress-sysreg,func = <5 0>;
+ };
- muxfpga {
- compatible = "arm,vexpress-muxfpga";
- arm,vexpress-sysreg,func = <7 0>;
- };
+ muxfpga {
+ compatible = "arm,vexpress-muxfpga";
+ arm,vexpress-sysreg,func = <7 0>;
+ };
- shutdown {
- compatible = "arm,vexpress-shutdown";
- arm,vexpress-sysreg,func = <8 0>;
- };
+ shutdown {
+ compatible = "arm,vexpress-shutdown";
+ arm,vexpress-sysreg,func = <8 0>;
+ };
- reboot {
- compatible = "arm,vexpress-reboot";
- arm,vexpress-sysreg,func = <9 0>;
- };
+ reboot {
+ compatible = "arm,vexpress-reboot";
+ arm,vexpress-sysreg,func = <9 0>;
+ };
- dvimode {
- compatible = "arm,vexpress-dvimode";
- arm,vexpress-sysreg,func = <11 0>;
+ dvimode {
+ compatible = "arm,vexpress-dvimode";
+ arm,vexpress-sysreg,func = <11 0>;
+ };
};
};
};
+}; \ No newline at end of file
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
index a8ac4e2..3971427 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
@@ -9,6 +9,7 @@
*/
/dts-v1/;
+#include "vexpress-v2m-rs1.dtsi"
/ {
model = "V2P-CA15";
@@ -278,8 +279,6 @@
<0 0 40 &gic 0 40 4>,
<0 0 41 &gic 0 41 4>,
<0 0 42 &gic 0 42 4>;
-
- /include/ "vexpress-v2m-rs1.dtsi"
};
site2: hsb@40000000 {
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index a4c7713..ac6b90e 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
@@ -9,6 +9,7 @@
*/
/dts-v1/;
+#include "vexpress-v2m-rs1.dtsi"
/ {
model = "V2P-CA15_CA7";
@@ -203,7 +204,7 @@
<1 10 0xf08>;
};
- pmu_a15 {
+ pmu-a15 {
compatible = "arm,cortex-a15-pmu";
interrupts = <0 68 4>,
<0 69 4>;
@@ -211,7 +212,7 @@
<&cpu1>;
};
- pmu_a7 {
+ pmu-a7 {
compatible = "arm,cortex-a7-pmu";
interrupts = <0 128 4>,
<0 129 4>,
@@ -584,7 +585,7 @@
};
};
- smb@8000000 {
+ smb: smb@8000000 {
compatible = "simple-bus";
#address-cells = <2>;
@@ -641,8 +642,6 @@
<0 0 40 &gic 0 40 4>,
<0 0 41 &gic 0 41 4>,
<0 0 42 &gic 0 42 4>;
-
- /include/ "vexpress-v2m-rs1.dtsi"
};
site2: hsb@40000000 {
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
index 32f1906..e5b4a75 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts
@@ -9,6 +9,7 @@
*/
/dts-v1/;
+#include "vexpress-v2m-rs1.dtsi"
/ {
model = "V2P-CA5s";
@@ -191,7 +192,7 @@
};
};
- smb@8000000 {
+ smb: smb@8000000 {
compatible = "simple-bus";
#address-cells = <2>;
@@ -248,8 +249,6 @@
<0 0 40 &gic 0 40 4>,
<0 0 41 &gic 0 41 4>,
<0 0 42 &gic 0 42 4>;
-
- /include/ "vexpress-v2m-rs1.dtsi"
};
site2: hsb@40000000 {
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca9.dts b/arch/arm/boot/dts/vexpress-v2p-ca9.dts
index 5814460..fc43873 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca9.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca9.dts
@@ -9,6 +9,7 @@
*/
/dts-v1/;
+#include "vexpress-v2m.dtsi"
/ {
model = "V2P-CA9";
@@ -301,7 +302,7 @@
};
};
- smb@4000000 {
+ smb: smb@4000000 {
compatible = "simple-bus";
#address-cells = <2>;
@@ -357,8 +358,6 @@
<0 0 40 &gic 0 40 4>,
<0 0 41 &gic 0 41 4>,
<0 0 42 &gic 0 42 4>;
-
- /include/ "vexpress-v2m.dtsi"
};
site2: hsb@e0000000 {
diff --git a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
index d8b2972..e2da122 100644
--- a/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
+++ b/arch/arm/boot/dts/vf-colibri-eval-v3.dtsi
@@ -117,7 +117,7 @@
clocks = <&clk16m>;
spi-max-frequency = <10000000>;
interrupt-parent = <&gpio1>;
- interrupts = <11 GPIO_ACTIVE_LOW>;
+ interrupts = <11 IRQ_TYPE_EDGE_RISING>;
};
};
diff --git a/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts b/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
index 782b69a..bd79e00 100644
--- a/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
+++ b/arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
@@ -70,8 +70,6 @@
compatible = "marvell,mv88e6085";
pinctrl-0 = <&pinctrl_gpio_switch0>;
pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0>;
dsa,member = <0 0>;
interrupt-parent = <&gpio0>;
@@ -156,8 +154,6 @@
compatible = "marvell,mv88e6085";
pinctrl-0 = <&pinctrl_gpio_switch1>;
pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0>;
dsa,member = <0 1>;
interrupt-parent = <&gpio0>;
@@ -243,8 +239,6 @@
switch2: switch@0 {
compatible = "marvell,mv88e6085";
- #address-cells = <1>;
- #size-cells = <0>;
reg = <0>;
dsa,member = <0 2>;
diff --git a/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts b/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts
index c6f134c..0b1e94c 100644
--- a/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts
+++ b/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts
@@ -69,8 +69,6 @@
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 = <65536>;
@@ -166,8 +164,6 @@
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 = <65536>;
diff --git a/arch/arm/boot/dts/vf610-zii-dev.dtsi b/arch/arm/boot/dts/vf610-zii-dev.dtsi
index 4890b8a..5ae5abf 100644
--- a/arch/arm/boot/dts/vf610-zii-dev.dtsi
+++ b/arch/arm/boot/dts/vf610-zii-dev.dtsi
@@ -222,6 +222,10 @@
status = "okay";
};
+&tempsensor {
+ io-channels = <&adc0 16>;
+};
+
&iomuxc {
pinctrl_adc0_ad5: adc0ad5grp {
fsl,pins = <
diff --git a/arch/arm/boot/dts/vfxxx.dtsi b/arch/arm/boot/dts/vfxxx.dtsi
index c3f09b7..d392794 100644
--- a/arch/arm/boot/dts/vfxxx.dtsi
+++ b/arch/arm/boot/dts/vfxxx.dtsi
@@ -84,7 +84,7 @@
mask = <0x1000>;
};
- iio-hwmon {
+ tempsensor: iio-hwmon {
compatible = "iio-hwmon";
io-channels = <&adc0 16>, <&adc1 16>;
};
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 70b4a14..1e9f7af 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_DMABOUNCE) += dmabounce.o
obj-$(CONFIG_SHARP_LOCOMO) += locomo.o
obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
obj-$(CONFIG_SHARP_SCOOP) += scoop.o
+obj-$(CONFIG_SMP) += secure_cntvoff.o
obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o
CFLAGS_REMOVE_mcpm_entry.o = -pg
diff --git a/arch/arm/common/secure_cntvoff.S b/arch/arm/common/secure_cntvoff.S
new file mode 100644
index 0000000..53fc7bd
--- /dev/null
+++ b/arch/arm/common/secure_cntvoff.S
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014 Renesas Electronics Corporation
+ *
+ * Initialization of CNTVOFF register from secure mode
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ENTRY(secure_cntvoff_init)
+ .arch armv7-a
+ /*
+ * CNTVOFF has to be initialized either from non-secure Hypervisor
+ * mode or secure Monitor mode with SCR.NS==1. If TrustZone is enabled
+ * then it should be handled by the secure code. The CPU must implement
+ * the virtualization extensions.
+ */
+ cps #MON_MODE
+ mrc p15, 0, r1, c1, c1, 0 /* Get Secure Config */
+ orr r0, r1, #1
+ mcr p15, 0, r0, c1, c1, 0 /* Set Non Secure bit */
+ isb
+ mov r0, #0
+ mcrr p15, 4, r0, r0, c14 /* CNTVOFF = 0 */
+ isb
+ mcr p15, 0, r1, c1, c1, 0 /* Set Secure bit */
+ isb
+ cps #SVC_MODE
+ ret lr
+ENDPROC(secure_cntvoff_init)
diff --git a/arch/arm/configs/bcm2835_defconfig b/arch/arm/configs/bcm2835_defconfig
index 8682b15..e4d188f 100644
--- a/arch/arm/configs/bcm2835_defconfig
+++ b/arch/arm/configs/bcm2835_defconfig
@@ -64,6 +64,7 @@ CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_NETDEVICES=y
+CONFIG_USB_LAN78XX=y
CONFIG_USB_USBNET=y
CONFIG_USB_NET_SMSC95XX=y
CONFIG_BRCMFMAC=m
@@ -127,6 +128,7 @@ CONFIG_LEDS_TRIGGER_CAMERA=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2835=y
CONFIG_STAGING=y
+CONFIG_BCM2835_VCHIQ=m
CONFIG_MAILBOX=y
CONFIG_BCM2835_MBOX=y
# CONFIG_IOMMU_SUPPORT is not set
diff --git a/arch/arm/configs/davinci_all_defconfig b/arch/arm/configs/davinci_all_defconfig
index c302a04..21b2d77 100644
--- a/arch/arm/configs/davinci_all_defconfig
+++ b/arch/arm/configs/davinci_all_defconfig
@@ -56,7 +56,7 @@ CONFIG_IP_PNP_DHCP=y
CONFIG_NETFILTER=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
-# CONFIG_FW_LOADER is not set
+CONFIG_FW_LOADER=m
CONFIG_DMA_CMA=y
CONFIG_DA8XX_MSTPRI=y
CONFIG_MTD=m
@@ -212,6 +212,8 @@ CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_OMAP=m
CONFIG_DMADEVICES=y
CONFIG_TI_EDMA=y
+CONFIG_REMOTEPROC=m
+CONFIG_DA8XX_REMOTEPROC=m
CONFIG_MEMORY=y
CONFIG_TI_AEMIF=m
CONFIG_DA8XX_DDRCTL=y
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
index 629189c..85b2369 100644
--- a/arch/arm/configs/exynos_defconfig
+++ b/arch/arm/configs/exynos_defconfig
@@ -208,6 +208,7 @@ CONFIG_DRM_EXYNOS_DSI=y
CONFIG_DRM_EXYNOS_HDMI=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_PANEL_SAMSUNG_LD9040=y
+CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=y
CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=y
CONFIG_DRM_NXP_PTN3460=y
CONFIG_DRM_PARADE_PS8622=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 3a30843..f70507a 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -38,6 +38,7 @@ CONFIG_SOC_IMX51=y
CONFIG_SOC_IMX53=y
CONFIG_SOC_IMX6Q=y
CONFIG_SOC_IMX6SL=y
+CONFIG_SOC_IMX6SLL=y
CONFIG_SOC_IMX6SX=y
CONFIG_SOC_IMX6UL=y
CONFIG_SOC_IMX7D=y
@@ -153,6 +154,9 @@ CONFIG_USB_RTL8152=m
CONFIG_USB_USBNET=y
CONFIG_USB_NET_CDC_EEM=m
CONFIG_BRCMFMAC=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_SDIO=m
+CONFIG_MWIFIEX_PCIE=m
CONFIG_WL12XX=m
CONFIG_WL18XX=m
CONFIG_WLCORE_SDIO=m
@@ -199,6 +203,7 @@ CONFIG_SPI_GPIO=y
CONFIG_SPI_IMX=y
CONFIG_SPI_FSL_DSPI=y
CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_MAX732X=y
CONFIG_GPIO_MC9S08DZ60=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_STMPE=y
@@ -214,11 +219,13 @@ CONFIG_CPU_THERMAL=y
CONFIG_IMX_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_DA9062_WATCHDOG=y
+CONFIG_RN5T618_WATCHDOG=y
CONFIG_IMX2_WDT=y
CONFIG_MFD_DA9052_I2C=y
CONFIG_MFD_DA9062=y
CONFIG_MFD_MC13XXX_SPI=y
CONFIG_MFD_MC13XXX_I2C=y
+CONFIG_MFD_RN5T618=y
CONFIG_MFD_STMPE=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -229,6 +236,7 @@ CONFIG_REGULATOR_GPIO=y
CONFIG_REGULATOR_MC13783=y
CONFIG_REGULATOR_MC13892=y
CONFIG_REGULATOR_PFUZE100=y
+CONFIG_REGULATOR_RN5T618=y
CONFIG_RC_CORE=y
CONFIG_RC_DEVICES=y
CONFIG_IR_GPIO_CIR=y
@@ -374,6 +382,7 @@ CONFIG_PWM=y
CONFIG_PWM_FSL_FTM=y
CONFIG_PWM_IMX=y
CONFIG_NVMEM_IMX_OCOTP=y
+CONFIG_NVMEM_VF610_OCOTP=y
CONFIG_TEE=y
CONFIG_OPTEE=y
CONFIG_MUX_MMIO=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index e6b3c96..7e1c543 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -90,6 +90,7 @@ CONFIG_ARCH_R8A73A4=y
CONFIG_ARCH_R8A7740=y
CONFIG_ARCH_R8A7743=y
CONFIG_ARCH_R8A7745=y
+CONFIG_ARCH_R8A77470=y
CONFIG_ARCH_R8A7778=y
CONFIG_ARCH_R8A7779=y
CONFIG_ARCH_R8A7790=y
@@ -187,6 +188,8 @@ CONFIG_B53_MMAP_DRIVER=m
CONFIG_B53_SRAB_DRIVER=m
CONFIG_CAN_SUN4I=y
CONFIG_BT=m
+CONFIG_BT_HCIUART=m
+CONFIG_BT_HCIUART_BCM=y
CONFIG_BT_MRVL=m
CONFIG_BT_MRVL_SDIO=m
CONFIG_CFG80211=m
@@ -280,6 +283,7 @@ CONFIG_FIXED_PHY=y
CONFIG_ROCKCHIP_PHY=y
CONFIG_USB_PEGASUS=y
CONFIG_USB_RTL8152=m
+CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=y
CONFIG_USB_NET_SMSC75XX=y
CONFIG_USB_NET_SMSC95XX=y
@@ -360,10 +364,12 @@ CONFIG_SERIAL_ST_ASC=y
CONFIG_SERIAL_ST_ASC_CONSOLE=y
CONFIG_SERIAL_STM32=y
CONFIG_SERIAL_STM32_CONSOLE=y
+CONFIG_SERIAL_DEV_BUS=y
CONFIG_HVC_DRIVER=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_DAVINCI=y
+CONFIG_I2C_MESON=y
CONFIG_I2C_MUX=y
CONFIG_I2C_ARB_GPIO_CHALLENGE=m
CONFIG_I2C_MUX_PCA954x=y
@@ -385,6 +391,7 @@ CONFIG_I2C_S3C2410=y
CONFIG_I2C_SH_MOBILE=y
CONFIG_I2C_SIRF=y
CONFIG_I2C_ST=y
+CONFIG_I2C_STM32F7=y
CONFIG_I2C_SUN6I_P2WI=y
CONFIG_I2C_TEGRA=y
CONFIG_I2C_UNIPHIER=y
@@ -497,6 +504,7 @@ CONFIG_TEGRA_WATCHDOG=m
CONFIG_MESON_WATCHDOG=y
CONFIG_DW_WATCHDOG=y
CONFIG_DIGICOLOR_WATCHDOG=y
+CONFIG_RENESAS_WDT=m
CONFIG_BCM2835_WDT=y
CONFIG_BCM47XX_WDT=y
CONFIG_BCM7038_WDT=m
@@ -638,6 +646,7 @@ CONFIG_DRM_SUN4I=m
CONFIG_DRM_FSL_DCU=m
CONFIG_DRM_TEGRA=y
CONFIG_DRM_PANEL_SAMSUNG_LD9040=m
+CONFIG_DRM_PANEL_SAMSUNG_S6E63J0X03=m
CONFIG_DRM_PANEL_SAMSUNG_S6E8AA0=m
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_DRM_SII9234=m
@@ -650,7 +659,6 @@ CONFIG_FB_EFI=y
CONFIG_FB_WM8505=y
CONFIG_FB_SH_MOBILE_LCDC=y
CONFIG_FB_SIMPLE=y
-CONFIG_FB_SH_MOBILE_MERAM=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_LCD_PLATFORM=m
@@ -947,6 +955,7 @@ CONFIG_PWM_ATMEL=m
CONFIG_PWM_ATMEL_HLCDC_PWM=m
CONFIG_PWM_ATMEL_TCB=m
CONFIG_PWM_FSL_FTM=m
+CONFIG_PWM_MESON=m
CONFIG_PWM_RCAR=m
CONFIG_PWM_RENESAS_TPU=y
CONFIG_PWM_ROCKCHIP=m
@@ -972,6 +981,7 @@ CONFIG_PHY_QCOM_APQ8064_SATA=m
CONFIG_PHY_MIPHY28LP=y
CONFIG_PHY_RCAR_GEN2=m
CONFIG_PHY_STIH407_USB=y
+CONFIG_PHY_STM32_USBPHYC=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_PHY_SUN9I_USB=y
CONFIG_PHY_SAMSUNG_USB2=m
diff --git a/arch/arm/configs/shmobile_defconfig b/arch/arm/configs/shmobile_defconfig
index a701601..b49887e 100644
--- a/arch/arm/configs/shmobile_defconfig
+++ b/arch/arm/configs/shmobile_defconfig
@@ -14,6 +14,7 @@ CONFIG_ARCH_R8A73A4=y
CONFIG_ARCH_R8A7740=y
CONFIG_ARCH_R8A7743=y
CONFIG_ARCH_R8A7745=y
+CONFIG_ARCH_R8A77470=y
CONFIG_ARCH_R8A7778=y
CONFIG_ARCH_R8A7779=y
CONFIG_ARCH_R8A7790=y
@@ -127,6 +128,7 @@ CONFIG_CPU_THERMAL=y
CONFIG_RCAR_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_DA9063_WATCHDOG=y
+CONFIG_RENESAS_WDT=y
CONFIG_MFD_AS3711=y
CONFIG_MFD_DA9063=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -156,7 +158,6 @@ CONFIG_DRM_DUMB_VGA_DAC=y
CONFIG_DRM_I2C_ADV7511=y
CONFIG_DRM_I2C_ADV7511_AUDIO=y
CONFIG_FB_SH_MOBILE_LCDC=y
-CONFIG_FB_SH_MOBILE_MERAM=y
# CONFIG_LCD_CLASS_DEVICE is not set
# CONFIG_BACKLIGHT_GENERIC is not set
CONFIG_BACKLIGHT_PWM=y
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index 869080b..ec1a5fd 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -35,7 +35,7 @@
* Start addresses are inclusive and end addresses are exclusive;
* start addresses should be rounded down, end addresses up.
*
- * See Documentation/cachetlb.txt for more information.
+ * See Documentation/core-api/cachetlb.rst for more information.
* Please note that the implementation of these, and the required
* effects are cache-type (VIVT/VIPT/PIPT) specific.
*
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 2602198..0d28924 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -2,9 +2,6 @@
#ifndef __ASM_ARM_CPUTYPE_H
#define __ASM_ARM_CPUTYPE_H
-#include <linux/stringify.h>
-#include <linux/kernel.h>
-
#define CPUID_ID 0
#define CPUID_CACHETYPE 1
#define CPUID_TCM 2
@@ -62,6 +59,7 @@
((mpidr >> (MPIDR_LEVEL_BITS * level)) & MPIDR_LEVEL_MASK)
#define ARM_CPU_IMP_ARM 0x41
+#define ARM_CPU_IMP_BRCM 0x42
#define ARM_CPU_IMP_DEC 0x44
#define ARM_CPU_IMP_INTEL 0x69
@@ -84,8 +82,9 @@
#define ARM_CPU_PART_CORTEX_A75 0x4100d0a0
#define ARM_CPU_PART_MASK 0xff00fff0
-/* Broadcom cores */
+/* Broadcom implemented processors */
#define ARM_CPU_PART_BRAHMA_B15 0x420000f0
+#define ARM_CPU_PART_BRAHMA_B53 0x42001000
/* DEC implemented cores */
#define ARM_CPU_PART_SA1100 0x4400a110
@@ -106,6 +105,11 @@
/* Qualcomm implemented cores */
#define ARM_CPU_PART_SCORPION 0x510002d0
+#ifndef __ASSEMBLY__
+
+#include <linux/stringify.h>
+#include <linux/kernel.h>
+
extern unsigned int processor_id;
#ifdef CONFIG_CPU_CP15
@@ -334,4 +338,6 @@ static inline int __attribute_const__ cpuid_feature_extract_field(u32 features,
#define cpuid_feature_extract(reg, field) \
cpuid_feature_extract_field(read_cpuid_ext(reg), field)
+#endif /* __ASSEMBLY__ */
+
#endif
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 2d75e77..1f1fe41 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -281,6 +281,7 @@ void kvm_mmu_wp_memory_region(struct kvm *kvm, int slot);
struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr);
+static inline bool kvm_arch_check_sve_has_vhe(void) { return true; }
static inline void kvm_arch_hardware_unsetup(void) {}
static inline void kvm_arch_sync_events(struct kvm *kvm) {}
static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
@@ -304,8 +305,13 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
struct kvm_device_attr *attr);
-/* All host FP/SIMD state is restored on guest exit, so nothing to save: */
-static inline void kvm_fpsimd_flush_cpu_state(void) {}
+/*
+ * VFP/NEON switching is all done by the hyp switch code, so no need to
+ * coordinate with host context handling for this state:
+ */
+static inline void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) {}
+static inline void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu) {}
static inline void kvm_arm_vhe_guest_enter(void) {}
static inline void kvm_arm_vhe_guest_exit(void) {}
@@ -340,4 +346,8 @@ static inline int kvm_arm_have_ssbd(void)
static inline void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu) {}
static inline void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu) {}
+#define __KVM_HAVE_ARCH_VM_ALLOC
+struct kvm *kvm_arch_alloc_vm(void);
+void kvm_arch_free_vm(struct kvm *kvm);
+
#endif /* __ARM_KVM_HOST_H__ */
diff --git a/arch/arm/include/asm/secure_cntvoff.h b/arch/arm/include/asm/secure_cntvoff.h
new file mode 100644
index 0000000..1f93aee
--- /dev/null
+++ b/arch/arm/include/asm/secure_cntvoff.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ASMARM_ARCH_CNTVOFF_H
+#define __ASMARM_ARCH_CNTVOFF_H
+
+extern void secure_cntvoff_init(void);
+
+#endif
diff --git a/arch/arm/include/debug/brcmstb.S b/arch/arm/include/debug/brcmstb.S
index c826f15..0f580ca 100644
--- a/arch/arm/include/debug/brcmstb.S
+++ b/arch/arm/include/debug/brcmstb.S
@@ -11,20 +11,25 @@
* GNU General Public License for more details.
*/
#include <linux/serial_reg.h>
+#include <asm/cputype.h>
/* Physical register offset and virtual register offset */
#define REG_PHYS_BASE 0xf0000000
+#define REG_PHYS_BASE_V7 0x08000000
#define REG_VIRT_BASE 0xfc000000
#define REG_PHYS_ADDR(x) ((x) + REG_PHYS_BASE)
+#define REG_PHYS_ADDR_V7(x) ((x) + REG_PHYS_BASE_V7)
/* Product id can be read from here */
#define SUN_TOP_CTRL_BASE REG_PHYS_ADDR(0x404000)
+#define SUN_TOP_CTRL_BASE_V7 REG_PHYS_ADDR_V7(0x404000)
#define UARTA_3390 REG_PHYS_ADDR(0x40a900)
#define UARTA_7250 REG_PHYS_ADDR(0x40b400)
#define UARTA_7260 REG_PHYS_ADDR(0x40c000)
#define UARTA_7268 UARTA_7260
#define UARTA_7271 UARTA_7268
+#define UARTA_7278 REG_PHYS_ADDR_V7(0x40c000)
#define UARTA_7364 REG_PHYS_ADDR(0x40b000)
#define UARTA_7366 UARTA_7364
#define UARTA_74371 REG_PHYS_ADDR(0x406b00)
@@ -55,8 +60,21 @@
mov \rv, #0 @ yes; record init is done
str \rv, [\tmp]
+ /* Check for V7 memory map if B53 */
+ mrc p15, 0, \rv, c0, c0, 0 @ get Main ID register
+ ldr \rp, =ARM_CPU_PART_MASK
+ and \rv, \rv, \rp
+ ldr \rp, =ARM_CPU_PART_BRAHMA_B53 @ check for B53 CPU
+ cmp \rv, \rp
+ bne 10f
+
+ /* if PERIPHBASE doesn't overlap REG_PHYS_BASE use V7 map */
+ mrc p15, 1, \rv, c15, c3, 0 @ get PERIPHBASE from CBAR
+ ands \rv, \rv, #REG_PHYS_BASE
+ ldreq \rp, =SUN_TOP_CTRL_BASE_V7
+
/* Check SUN_TOP_CTRL base */
- ldr \rp, =SUN_TOP_CTRL_BASE @ load SUN_TOP_CTRL PA
+10: ldrne \rp, =SUN_TOP_CTRL_BASE @ load SUN_TOP_CTRL PA
ldr \rv, [\rp, #0] @ get register contents
ARM_BE8( rev \rv, \rv )
and \rv, \rv, #0xffffff00 @ strip revision bits [7:0]
@@ -72,6 +90,7 @@ ARM_BE8( rev \rv, \rv )
27: checkuart(\rp, \rv, 0x07437100, 74371)
28: checkuart(\rp, \rv, 0x74390000, 7439)
29: checkuart(\rp, \rv, 0x74450000, 7445)
+30: checkuart(\rp, \rv, 0x72780000, 7278)
/* No valid UART found */
90: mov \rp, #0
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index caae484..16e006f 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -91,6 +91,7 @@ struct kvm_regs {
#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
#define KVM_VGIC_ITS_ADDR_TYPE 4
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION 5
#define KVM_VGIC_V3_DIST_SIZE SZ_64K
#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 27c5381..974d8d7 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -61,7 +61,7 @@
int main(void)
{
DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
DEFINE(TSK_STACK_CANARY, offsetof(struct task_struct, stack_canary));
#endif
BLANK();
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 1752033..179a9f6 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -791,7 +791,7 @@ ENTRY(__switch_to)
ldr r6, [r2, #TI_CPU_DOMAIN]
#endif
switch_tls r1, r4, r5, r3, r7
-#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
+#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
ldr r7, [r2, #TI_TASK]
ldr r8, =__stack_chk_guard
.if (TSK_STACK_CANARY > IMM12_MASK)
@@ -807,7 +807,7 @@ ENTRY(__switch_to)
ldr r0, =thread_notify_head
mov r1, #THREAD_NOTIFY_SWITCH
bl atomic_notifier_call_chain
-#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
+#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
str r7, [r8]
#endif
THUMB( mov ip, r4 )
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 1523cb1..225d1c5 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -39,7 +39,7 @@
#include <asm/tls.h>
#include <asm/vdso.h>
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index f09e9d66..dec130e 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -544,7 +544,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
* Increment event counter and perform fixup for the pre-signal
* frame.
*/
- rseq_signal_deliver(regs);
+ rseq_signal_deliver(ksig, regs);
/*
* Set up the stack frame
@@ -666,7 +666,7 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
} else {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
- rseq_handle_notify_resume(regs);
+ rseq_handle_notify_resume(NULL, regs);
}
}
local_irq_disable();
diff --git a/arch/arm/kernel/sys_oabi-compat.c b/arch/arm/kernel/sys_oabi-compat.c
index b9786f4..1df21a6 100644
--- a/arch/arm/kernel/sys_oabi-compat.c
+++ b/arch/arm/kernel/sys_oabi-compat.c
@@ -286,7 +286,7 @@ asmlinkage long sys_oabi_epoll_wait(int epfd,
return -EINVAL;
if (!access_ok(VERIFY_WRITE, events, sizeof(*events) * maxevents))
return -EFAULT;
- kbuf = kmalloc(sizeof(*kbuf) * maxevents, GFP_KERNEL);
+ kbuf = kmalloc_array(maxevents, sizeof(*kbuf), GFP_KERNEL);
if (!kbuf)
return -ENOMEM;
fs = get_fs();
@@ -324,7 +324,7 @@ asmlinkage long sys_oabi_semtimedop(int semid,
return -EINVAL;
if (!access_ok(VERIFY_READ, tsops, sizeof(*tsops) * nsops))
return -EFAULT;
- sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
+ sops = kmalloc_array(nsops, sizeof(*sops), GFP_KERNEL);
if (!sops)
return -ENOMEM;
err = 0;
diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile
index 7fc0638..d2b5ec9 100644
--- a/arch/arm/kvm/hyp/Makefile
+++ b/arch/arm/kvm/hyp/Makefile
@@ -23,3 +23,11 @@ obj-$(CONFIG_KVM_ARM_HOST) += hyp-entry.o
obj-$(CONFIG_KVM_ARM_HOST) += switch.o
CFLAGS_switch.o += $(CFLAGS_ARMV7VE)
obj-$(CONFIG_KVM_ARM_HOST) += s2-setup.o
+
+# KVM code is run at a different exception code with a different map, so
+# compiler instrumentation that inserts callbacks or checks into the code may
+# cause crashes. Just disable it.
+GCOV_PROFILE := n
+KASAN_SANITIZE := n
+UBSAN_SANITIZE := n
+KCOV_INSTRUMENT := n
diff --git a/arch/arm/mach-berlin/Kconfig b/arch/arm/mach-berlin/Kconfig
index 63ab1d3..3d719cf 100644
--- a/arch/arm/mach-berlin/Kconfig
+++ b/arch/arm/mach-berlin/Kconfig
@@ -23,8 +23,12 @@ config MACH_BERLIN_BG2
config MACH_BERLIN_BG2CD
bool "Marvell Armada 1500-mini (BG2CD)"
+ select ARM_ERRATA_754322
+ select ARM_ERRATA_775420
+ select ARM_GLOBAL_TIMER
select CACHE_L2X0
- select HAVE_ARM_TWD if SMP
+ select HAVE_ARM_SCU
+ select HAVE_ARM_TWD
select PINCTRL_BERLIN_BG2CD
config MACH_BERLIN_BG2Q
diff --git a/arch/arm/mach-berlin/berlin.c b/arch/arm/mach-berlin/berlin.c
index ac181c6..2424ad4 100644
--- a/arch/arm/mach-berlin/berlin.c
+++ b/arch/arm/mach-berlin/berlin.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Device Tree support for Marvell Berlin SoCs.
*
@@ -5,10 +6,6 @@
*
* based on GPL'ed 2.6 kernel sources
* (c) Marvell International Ltd.
- *
- * 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/init.h>
diff --git a/arch/arm/mach-berlin/headsmp.S b/arch/arm/mach-berlin/headsmp.S
index dc82a34..3057885 100644
--- a/arch/arm/mach-berlin/headsmp.S
+++ b/arch/arm/mach-berlin/headsmp.S
@@ -1,11 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
* Antoine Ténart <antoine.tenart@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 version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/linkage.h>
diff --git a/arch/arm/mach-berlin/platsmp.c b/arch/arm/mach-berlin/platsmp.c
index 7586b7a..593fc4a 100644
--- a/arch/arm/mach-berlin/platsmp.c
+++ b/arch/arm/mach-berlin/platsmp.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2014 Marvell Technology Group Ltd.
*
* Antoine Ténart <antoine.tenart@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 version 2 as
- * published by the Free Software Foundation.
*/
#include <linux/io.h>
@@ -81,7 +78,6 @@ static void __init berlin_smp_prepare_cpus(unsigned int max_cpus)
goto unmap_scu;
scu_enable(scu_base);
- flush_cache_all();
/*
* Write the first instruction the CPU will execute after being reset
diff --git a/arch/arm/mach-davinci/aemif.c b/arch/arm/mach-davinci/aemif.c
index ff8b7e7..e4ab3f3 100644
--- a/arch/arm/mach-davinci/aemif.c
+++ b/arch/arm/mach-davinci/aemif.c
@@ -189,7 +189,7 @@ int davinci_aemif_setup(struct platform_device *pdev)
* Setup Async configuration register in case we did not boot
* from NAND and so bootloader did not bother to set it up.
*/
- val = davinci_aemif_readl(base, A1CR_OFFSET + pdev->id * 4);
+ val = davinci_aemif_readl(base, A1CR_OFFSET + pdata->core_chipsel * 4);
/*
* Extended Wait is not valid and Select Strobe mode is not
* used
@@ -198,13 +198,13 @@ int davinci_aemif_setup(struct platform_device *pdev)
if (pdata->options & NAND_BUSWIDTH_16)
val |= 0x1;
- davinci_aemif_writel(base, A1CR_OFFSET + pdev->id * 4, val);
+ davinci_aemif_writel(base, A1CR_OFFSET + pdata->core_chipsel * 4, val);
clkrate = clk_get_rate(clk);
if (pdata->timing)
- ret = davinci_aemif_setup_timing(pdata->timing, base, pdev->id,
- clkrate);
+ ret = davinci_aemif_setup_timing(pdata->timing, base,
+ pdata->core_chipsel, clkrate);
if (ret < 0)
dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index d1e8ce7..14a6fc0 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -315,6 +315,7 @@ static struct davinci_aemif_timing da830_evm_nandflash_timing = {
};
static struct davinci_nand_pdata da830_evm_nand_pdata = {
+ .core_chipsel = 1,
.parts = da830_evm_nand_partitions,
.nr_parts = ARRAY_SIZE(da830_evm_nand_partitions),
.ecc_mode = NAND_ECC_HW,
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 158ed9a..e22fb40 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -244,6 +244,7 @@ static struct davinci_aemif_timing da850_evm_nandflash_timing = {
};
static struct davinci_nand_pdata da850_evm_nandflash_data = {
+ .core_chipsel = 1,
.parts = da850_evm_nandflash_partition,
.nr_parts = ARRAY_SIZE(da850_evm_nandflash_partition),
.ecc_mode = NAND_ECC_HW,
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index 23ab9e8..a3377f9 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -78,6 +78,7 @@ static struct mtd_partition davinci_nand_partitions[] = {
};
static struct davinci_nand_pdata davinci_nand_data = {
+ .core_chipsel = 0,
.mask_chipsel = BIT(14),
.parts = davinci_nand_partitions,
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index 59743bd..8249a0b 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -72,6 +72,7 @@ static struct mtd_partition davinci_nand_partitions[] = {
};
static struct davinci_nand_pdata davinci_nand_data = {
+ .core_chipsel = 0,
.mask_chipsel = BIT(14),
.parts = davinci_nand_partitions,
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 0ac085b..435f7ec 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -138,6 +138,7 @@ static struct mtd_partition davinci_nand_partitions[] = {
};
static struct davinci_nand_pdata davinci_nand_data = {
+ .core_chipsel = 0,
.mask_chipsel = BIT(14),
.parts = davinci_nand_partitions,
.nr_parts = ARRAY_SIZE(davinci_nand_partitions),
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index 509e64a..48436f7 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -153,6 +153,7 @@ static struct davinci_aemif_timing davinci_evm_nandflash_timing = {
};
static struct davinci_nand_pdata davinci_evm_nandflash_data = {
+ .core_chipsel = 0,
.parts = davinci_evm_nandflash_partition,
.nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition),
.ecc_mode = NAND_ECC_HW,
@@ -772,6 +773,8 @@ static __init void davinci_evm_init(void)
struct clk *aemif_clk;
struct davinci_soc_info *soc_info = &davinci_soc_info;
+ dm644x_init_devices();
+
ret = dm644x_gpio_register();
if (ret)
pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index a3c0d1e..584064f 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -84,6 +84,7 @@ static struct davinci_aemif_timing dm6467tevm_nandflash_timing = {
};
static struct davinci_nand_pdata davinci_nand_data = {
+ .core_chipsel = 0,
.mask_cle = 0x80000,
.mask_ale = 0x40000,
.parts = davinci_nand_partitions,
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index d1c8548..37b3e48 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -400,6 +400,7 @@ static struct mtd_partition mityomapl138_nandflash_partition[] = {
};
static struct davinci_nand_pdata mityomapl138_nandflash_data = {
+ .core_chipsel = 1,
.parts = mityomapl138_nandflash_partition,
.nr_parts = ARRAY_SIZE(mityomapl138_nandflash_partition),
.ecc_mode = NAND_ECC_HW,
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index f287577..25ad9b0 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -87,6 +87,7 @@ static struct mtd_partition davinci_ntosd2_nandflash_partition[] = {
};
static struct davinci_nand_pdata davinci_ntosd2_nandflash_data = {
+ .core_chipsel = 0,
.parts = davinci_ntosd2_nandflash_partition,
.nr_parts = ARRAY_SIZE(davinci_ntosd2_nandflash_partition),
.ecc_mode = NAND_ECC_HW,
@@ -174,6 +175,8 @@ static __init void davinci_ntosd2_init(void)
struct clk *aemif_clk;
struct davinci_soc_info *soc_info = &davinci_soc_info;
+ dm644x_init_devices();
+
ret = dm644x_gpio_register();
if (ret)
pr_warn("%s: GPIO init failed: %d\n", __func__, ret);
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 2922da9..e7c1728 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -134,6 +134,8 @@ static __init void davinci_sffsdr_init(void)
{
struct davinci_soc_info *soc_info = &davinci_soc_info;
+ dm644x_init_devices();
+
platform_add_devices(davinci_sffsdr_devices,
ARRAY_SIZE(davinci_sffsdr_devices));
sffsdr_init_i2c();
diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h
index 270cef8..376cdd5 100644
--- a/arch/arm/mach-davinci/davinci.h
+++ b/arch/arm/mach-davinci/davinci.h
@@ -104,6 +104,7 @@ int dm365_gpio_register(void);
/* DM644x function declarations */
void dm644x_init(void);
+void dm644x_init_devices(void);
void dm644x_init_time(void);
void dm644x_init_asp(void);
int dm644x_init_video(struct vpfe_config *, struct vpbe_config *);
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c
index b409801..a2e8586 100644
--- a/arch/arm/mach-davinci/dm644x.c
+++ b/arch/arm/mach-davinci/dm644x.c
@@ -961,19 +961,14 @@ int __init dm644x_init_video(struct vpfe_config *vpfe_cfg,
return 0;
}
-static int __init dm644x_init_devices(void)
+void __init dm644x_init_devices(void)
{
struct platform_device *edma_pdev;
- int ret = 0;
-
- if (!cpu_is_davinci_dm644x())
- return 0;
+ int ret;
edma_pdev = platform_device_register_full(&dm644x_edma_device);
- if (IS_ERR(edma_pdev)) {
+ if (IS_ERR(edma_pdev))
pr_warn("%s: Failed to register eDMA\n", __func__);
- return PTR_ERR(edma_pdev);
- }
platform_device_register(&dm644x_mdio_device);
platform_device_register(&dm644x_emac_device);
@@ -982,6 +977,4 @@ static int __init dm644x_init_devices(void)
if (ret)
pr_warn("%s: watchdog init failed: %d\n", __func__, ret);
- return ret;
}
-postcore_initcall(dm644x_init_devices);
diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index 2ca4058..b40963c 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -8,7 +8,6 @@
menuconfig ARCH_EXYNOS
bool "Samsung EXYNOS"
depends on ARCH_MULTI_V7
- select ARCH_HAS_BANDGAP
select ARCH_HAS_HOLES_MEMORYMODEL
select ARCH_SUPPORTS_BIG_ENDIAN
select ARM_AMBA
@@ -108,17 +107,6 @@ config SOC_EXYNOS5420
default y
depends on ARCH_EXYNOS5
-config SOC_EXYNOS5440
- bool "SAMSUNG EXYNOS5440"
- default y
- depends on ARCH_EXYNOS5
- select HAVE_ARM_ARCH_TIMER
- select AUTO_ZRELADDR
- select PINCTRL_EXYNOS5440
- select PM_OPP
- help
- Enable EXYNOS5440 SoC support
-
config SOC_EXYNOS5800
bool "SAMSUNG EXYNOS5800"
default y
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 098f84a..dcd21bb 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -21,7 +21,6 @@
#define EXYNOS5250_SOC_ID 0x43520000
#define EXYNOS5410_SOC_ID 0xE5410000
#define EXYNOS5420_SOC_ID 0xE5420000
-#define EXYNOS5440_SOC_ID 0xE5440000
#define EXYNOS5800_SOC_ID 0xE5422000
#define EXYNOS5_SOC_MASK 0xFFFFF000
@@ -39,7 +38,6 @@ IS_SAMSUNG_CPU(exynos4412, EXYNOS4412_CPU_ID, EXYNOS4_CPU_MASK)
IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
IS_SAMSUNG_CPU(exynos5410, EXYNOS5410_SOC_ID, EXYNOS5_SOC_MASK)
IS_SAMSUNG_CPU(exynos5420, EXYNOS5420_SOC_ID, EXYNOS5_SOC_MASK)
-IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
#if defined(CONFIG_SOC_EXYNOS3250)
@@ -82,22 +80,12 @@ IS_SAMSUNG_CPU(exynos5800, EXYNOS5800_SOC_ID, EXYNOS5_SOC_MASK)
# define soc_is_exynos5420() 0
#endif
-#if defined(CONFIG_SOC_EXYNOS5440)
-# define soc_is_exynos5440() is_samsung_exynos5440()
-#else
-# define soc_is_exynos5440() 0
-#endif
-
#if defined(CONFIG_SOC_EXYNOS5800)
# define soc_is_exynos5800() is_samsung_exynos5800()
#else
# define soc_is_exynos5800() 0
#endif
-#define soc_is_exynos4() (soc_is_exynos4210() || soc_is_exynos4412())
-#define soc_is_exynos5() (soc_is_exynos5250() || soc_is_exynos5410() || \
- soc_is_exynos5420() || soc_is_exynos5800())
-
extern u32 cp15_save_diag;
extern u32 cp15_save_power;
@@ -149,6 +137,11 @@ extern void exynos_cpu_restore_register(void);
extern void exynos_pm_central_suspend(void);
extern int exynos_pm_central_resume(void);
extern void exynos_enter_aftr(void);
+#ifdef CONFIG_SMP
+extern void exynos_scu_enable(void);
+#else
+static inline void exynos_scu_enable(void) { }
+#endif
extern struct cpuidle_exynos_data cpuidle_coupled_exynos_data;
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 8c4f5e3..f4b6c93 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -24,15 +24,6 @@
#include "common.h"
-static struct map_desc exynos4_iodesc[] __initdata = {
- {
- .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
- .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
- .length = SZ_8K,
- .type = MT_DEVICE,
- },
-};
-
static struct platform_device exynos_cpuidle = {
.name = "exynos_cpuidle",
#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
@@ -63,15 +54,6 @@ void __init exynos_sysram_init(void)
}
}
-static void __init exynos_init_late(void)
-{
- if (of_machine_is_compatible("samsung,exynos5440"))
- /* to be supported later */
- return;
-
- exynos_pm_init();
-}
-
static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
int depth, void *data)
{
@@ -79,8 +61,7 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
const __be32 *reg;
int len;
- if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid") &&
- !of_flat_dt_is_compatible(node, "samsung,exynos5440-clock"))
+ if (!of_flat_dt_is_compatible(node, "samsung,exynos4210-chipid"))
return 0;
reg = of_get_flat_dt_prop(node, "reg", &len);
@@ -95,17 +76,6 @@ static int __init exynos_fdt_map_chipid(unsigned long node, const char *uname,
return 1;
}
-/*
- * exynos_map_io
- *
- * register the standard cpu IO areas
- */
-static void __init exynos_map_io(void)
-{
- if (soc_is_exynos4())
- iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
-}
-
static void __init exynos_init_io(void)
{
debug_ll_io_init();
@@ -114,8 +84,6 @@ static void __init exynos_init_io(void)
/* detect cpu id and rev. */
s5p_init_cpu(S5P_VA_CHIPID);
-
- exynos_map_io();
}
/*
@@ -209,7 +177,6 @@ static char const *const exynos_dt_compat[] __initconst = {
"samsung,exynos5250",
"samsung,exynos5260",
"samsung,exynos5420",
- "samsung,exynos5440",
NULL
};
@@ -232,7 +199,7 @@ DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
.init_early = exynos_firmware_init,
.init_irq = exynos_init_irq,
.init_machine = exynos_dt_machine_init,
- .init_late = exynos_init_late,
+ .init_late = exynos_pm_init,
.dt_compat = exynos_dt_compat,
.dt_fixup = exynos_dt_fixup,
MACHINE_END
diff --git a/arch/arm/mach-exynos/include/mach/map.h b/arch/arm/mach-exynos/include/mach/map.h
index 37a5ea5..22ebe36 100644
--- a/arch/arm/mach-exynos/include/mach/map.h
+++ b/arch/arm/mach-exynos/include/mach/map.h
@@ -15,6 +15,4 @@
#define EXYNOS_PA_CHIPID 0x10000000
-#define EXYNOS4_PA_COREPERI 0x10500000
-
#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index 5156fe7..6a1e682 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -163,6 +163,26 @@ int exynos_cluster_power_state(int cluster)
S5P_CORE_LOCAL_PWR_EN);
}
+/**
+ * exynos_scu_enable : enables SCU for Cortex-A9 based system
+ */
+void exynos_scu_enable(void)
+{
+ struct device_node *np;
+ static void __iomem *scu_base;
+
+ if (!scu_base) {
+ np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
+ if (np) {
+ scu_base = of_iomap(np, 0);
+ of_node_put(np);
+ } else {
+ scu_base = ioremap(scu_a9_get_base(), SZ_4K);
+ }
+ }
+ scu_enable(scu_base);
+}
+
static void __iomem *cpu_boot_reg_base(void)
{
if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
@@ -219,11 +239,6 @@ static void write_pen_release(int val)
sync_cache_w(&pen_release);
}
-static void __iomem *scu_base_addr(void)
-{
- return (void __iomem *)(S5P_VA_SCU);
-}
-
static DEFINE_SPINLOCK(boot_lock);
static void exynos_secondary_init(unsigned int cpu)
@@ -389,7 +404,7 @@ static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
exynos_set_delayed_reset_assertion(true);
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
- scu_enable(scu_base_addr());
+ exynos_scu_enable();
/*
* Write the address of secondary startup into the
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index a822c50..48e7fb3 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -22,8 +22,6 @@
#include <asm/suspend.h>
#include <asm/cacheflush.h>
-#include <mach/map.h>
-
#include "common.h"
static inline void __iomem *exynos_boot_vector_addr(void)
@@ -172,7 +170,7 @@ void exynos_enter_aftr(void)
cpu_suspend(0, exynos_aftr_finisher);
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
- scu_enable(S5P_VA_SCU);
+ exynos_scu_enable();
if (call_firmware_op(resume) == -ENOSYS)
exynos_cpu_restore_register();
}
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index c2ed997..d3db306 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -30,8 +30,6 @@
#include <asm/smp_scu.h>
#include <asm/suspend.h>
-#include <mach/map.h>
-
#include <plat/pm-common.h>
#include "common.h"
@@ -401,7 +399,7 @@ static void exynos_pm_resume(void)
goto early_wakeup;
if (cpuid == ARM_CPU_PART_CORTEX_A9)
- scu_enable(S5P_VA_SCU);
+ exynos_scu_enable();
if (call_firmware_op(resume) == -ENOSYS
&& cpuid == ARM_CPU_PART_CORTEX_A9)
diff --git a/arch/arm/mach-footbridge/dc21285.c b/arch/arm/mach-footbridge/dc21285.c
index e7b350f..16d71ba 100644
--- a/arch/arm/mach-footbridge/dc21285.c
+++ b/arch/arm/mach-footbridge/dc21285.c
@@ -252,7 +252,7 @@ int __init dc21285_setup(int nr, struct pci_sys_data *sys)
if (nr || !footbridge_cfn_mode())
return 0;
- res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+ res = kcalloc(2, sizeof(struct resource), GFP_KERNEL);
if (!res) {
printk("out of memory for root bus resources");
return 0;
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index e47fa13..6f42323 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -501,6 +501,7 @@ config SOC_IMX6SL
config SOC_IMX6SLL
bool "i.MX6 SoloLiteLite support"
+ select PINCTRL_IMX6SLL
select SOC_IMX6
help
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index 68c3f07..9d87f1d 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -374,26 +374,12 @@ 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),
-};
-
static const struct spi_imx_master spi0_pdata __initconst = {
- .chipselect = spi0_internal_chipselect,
- .num_chipselect = ARRAY_SIZE(spi0_internal_chipselect),
-};
-
-static int spi1_internal_chipselect[] = {
- MXC_SPI_CS(0),
- MXC_SPI_CS(1),
- MXC_SPI_CS(2),
+ .num_chipselect = 3,
};
static const struct spi_imx_master spi1_pdata __initconst = {
- .chipselect = spi1_internal_chipselect,
- .num_chipselect = ARRAY_SIZE(spi1_internal_chipselect),
+ .num_chipselect = 3,
};
static struct spi_board_info mx31_3ds_spi_devs[] __initdata = {
diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c
index 6fd4636..8bf5281 100644
--- a/arch/arm/mach-imx/mach-mx31lilly.c
+++ b/arch/arm/mach-imx/mach-mx31lilly.c
@@ -226,20 +226,12 @@ static void __init lilly1131_usb_init(void)
/* SPI */
-static int spi_internal_chipselect[] = {
- MXC_SPI_CS(0),
- MXC_SPI_CS(1),
- MXC_SPI_CS(2),
-};
-
static const struct spi_imx_master spi0_pdata __initconst = {
- .chipselect = spi_internal_chipselect,
- .num_chipselect = ARRAY_SIZE(spi_internal_chipselect),
+ .num_chipselect = 3,
};
static const struct spi_imx_master spi1_pdata __initconst = {
- .chipselect = spi_internal_chipselect,
- .num_chipselect = ARRAY_SIZE(spi_internal_chipselect),
+ .num_chipselect = 3,
};
static struct mc13xxx_platform_data mc13783_pdata __initdata = {
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index a3250bc..a3cbba6 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -83,15 +83,8 @@ static const struct imxuart_platform_data uart_pdata __initconst = {
};
/* SPI */
-static int spi0_internal_chipselect[] = {
- MXC_SPI_CS(0),
- MXC_SPI_CS(1),
- MXC_SPI_CS(2),
-};
-
static const struct spi_imx_master spi0_pdata __initconst = {
- .chipselect = spi0_internal_chipselect,
- .num_chipselect = ARRAY_SIZE(spi0_internal_chipselect),
+ .num_chipselect = 3,
};
static const struct mxc_nand_platform_data
@@ -133,13 +126,8 @@ static struct platform_device smsc911x_device = {
* The MC13783 is the only hard-wired SPI device on the module.
*/
-static int spi1_internal_chipselect[] = {
- MXC_SPI_CS(0),
-};
-
static const struct spi_imx_master spi1_pdata __initconst = {
- .chipselect = spi1_internal_chipselect,
- .num_chipselect = ARRAY_SIZE(spi1_internal_chipselect),
+ .num_chipselect = 1,
};
static struct mc13xxx_platform_data mc13783_pdata __initdata = {
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index 7716f83..643a3d7 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -152,14 +152,8 @@ static const struct imxi2c_platform_data moboard_i2c1_data __initconst = {
.bitrate = 100000,
};
-static int moboard_spi1_cs[] = {
- MXC_SPI_CS(0),
- MXC_SPI_CS(2),
-};
-
static const struct spi_imx_master moboard_spi1_pdata __initconst = {
- .chipselect = moboard_spi1_cs,
- .num_chipselect = ARRAY_SIZE(moboard_spi1_cs),
+ .num_chipselect = 3,
};
static struct regulator_consumer_supply sdhc_consumers[] = {
@@ -296,19 +290,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 = 1,
+ .chip_select = 0,
.platform_data = &moboard_pmic,
.mode = SPI_CS_HIGH,
},
};
-static int moboard_spi2_cs[] = {
- MXC_SPI_CS(0), MXC_SPI_CS(1),
-};
-
static const struct spi_imx_master moboard_spi2_pdata __initconst = {
- .chipselect = moboard_spi2_cs,
- .num_chipselect = ARRAY_SIZE(moboard_spi2_cs),
+ .num_chipselect = 2,
};
#define SDHC1_CD IOMUX_TO_GPIO(MX31_PIN_ATA_CS0)
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index ed67586..5714e2f 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -20,7 +20,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/i2c.h>
-#include <linux/platform_data/at24.h>
+#include <linux/property.h>
#include <linux/dma-mapping.h>
#include <linux/spi/spi.h>
#include <linux/spi/eeprom.h>
@@ -168,16 +168,15 @@ static const struct imxi2c_platform_data pca100_i2c1_data __initconst = {
.bitrate = 100000,
};
-static struct at24_platform_data board_eeprom = {
- .byte_len = 4096,
- .page_size = 32,
- .flags = AT24_FLAG_ADDR16,
+static const struct property_entry board_eeprom_properties[] = {
+ PROPERTY_ENTRY_U32("pagesize", 32),
+ { }
};
static struct i2c_board_info pca100_i2c_devices[] = {
{
- I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
- .platform_data = &board_eeprom,
+ I2C_BOARD_INFO("24c32", 0x52), /* E0=0, E1=1, E2=0 */
+ .properties = board_eeprom_properties,
}, {
I2C_BOARD_INFO("pcf8563", 0x51),
}, {
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index b787ba6..004737c 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -23,7 +23,7 @@
#include <linux/smsc911x.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
-#include <linux/platform_data/at24.h>
+#include <linux/property.h>
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include <linux/irq.h>
@@ -263,16 +263,15 @@ static const struct imxi2c_platform_data pcm037_i2c2_data __initconst = {
.bitrate = 20000,
};
-static struct at24_platform_data board_eeprom = {
- .byte_len = 4096,
- .page_size = 32,
- .flags = AT24_FLAG_ADDR16,
+static const struct property_entry board_eeprom_properties[] = {
+ PROPERTY_ENTRY_U32("pagesize", 32),
+ { }
};
static struct i2c_board_info pcm037_i2c_devices[] = {
{
- I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
- .platform_data = &board_eeprom,
+ I2C_BOARD_INFO("24c32", 0x52), /* E0=0, E1=1, E2=0 */
+ .properties = board_eeprom_properties,
}, {
I2C_BOARD_INFO("pcf8563", 0x51),
}
diff --git a/arch/arm/mach-imx/mach-pcm037_eet.c b/arch/arm/mach-imx/mach-pcm037_eet.c
index 95bd977..15bc956 100644
--- a/arch/arm/mach-imx/mach-pcm037_eet.c
+++ b/arch/arm/mach-imx/mach-pcm037_eet.c
@@ -56,11 +56,8 @@ static struct spi_board_info pcm037_spi_dev[] = {
};
/* Platform Data for MXC CSPI */
-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,
- .num_chipselect = ARRAY_SIZE(pcm037_spi1_cs),
+ .num_chipselect = 2,
};
/* GPIO-keys input device */
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 78e2bf8..e595e53 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -24,7 +24,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/platform_data/at24.h>
+#include <linux/property.h>
#include <linux/usb/otg.h>
#include <linux/usb/ulpi.h>
@@ -110,16 +110,15 @@ static const struct imxi2c_platform_data pcm043_i2c0_data __initconst = {
.bitrate = 50000,
};
-static struct at24_platform_data board_eeprom = {
- .byte_len = 4096,
- .page_size = 32,
- .flags = AT24_FLAG_ADDR16,
+static const struct property_entry board_eeprom_properties[] = {
+ PROPERTY_ENTRY_U32("pagesize", 32),
+ { }
};
static struct i2c_board_info pcm043_i2c_devices[] = {
{
- I2C_BOARD_INFO("at24", 0x52), /* E0=0, E1=1, E2=0 */
- .platform_data = &board_eeprom,
+ I2C_BOARD_INFO("24c32", 0x52), /* E0=0, E1=1, E2=0 */
+ .properties = board_eeprom_properties,
}, {
I2C_BOARD_INFO("pcf8563", 0x51),
},
diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c
index 5ff154c..da3336a 100644
--- a/arch/arm/mach-imx/mach-vpr200.c
+++ b/arch/arm/mach-imx/mach-vpr200.c
@@ -29,7 +29,6 @@
#include <asm/mach/time.h>
#include <linux/i2c.h>
-#include <linux/platform_data/at24.h>
#include <linux/mfd/mc13xxx.h>
#include "common.h"
@@ -145,15 +144,9 @@ static const struct imxi2c_platform_data vpr200_i2c0_data __initconst = {
.bitrate = 50000,
};
-static struct at24_platform_data vpr200_eeprom = {
- .byte_len = 2048 / 8,
- .page_size = 1,
-};
-
static struct i2c_board_info vpr200_i2c_devices[] = {
{
- I2C_BOARD_INFO("at24", 0x50), /* E0=0, E1=0, E2=0 */
- .platform_data = &vpr200_eeprom,
+ I2C_BOARD_INFO("24c02", 0x50), /* E0=0, E1=0, E2=0 */
}, {
I2C_BOARD_INFO("mc13892", 0x08),
.platform_data = &vpr200_pmic,
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index bcf3df5..6835b17 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -421,7 +421,7 @@ int ixp4xx_setup(int nr, struct pci_sys_data *sys)
if (nr >= 1)
return 0;
- res = kzalloc(sizeof(*res) * 2, GFP_KERNEL);
+ res = kcalloc(2, sizeof(*res), GFP_KERNEL);
if (res == NULL) {
/*
* If we're out of memory this early, something is wrong,
diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c
index 937eb1d..ef835d8 100644
--- a/arch/arm/mach-ks8695/board-acs5k.c
+++ b/arch/arm/mach-ks8695/board-acs5k.c
@@ -19,7 +19,7 @@
#include <linux/gpio/machine.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
#include <linux/platform_data/pca953x.h>
#include <linux/mtd/mtd.h>
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index d90f61e..d51cfda 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -19,14 +19,7 @@ config MACH_MESON6
select MESON6_TIMER
config MACH_MESON8
- bool "Amlogic Meson8 SoCs support"
- default ARCH_MESON
- select MESON6_TIMER
- select COMMON_CLK_MESON8B
- select MESON_IRQ_GPIO
-
-config MACH_MESON8B
- bool "Amlogic Meson8b SoCs support"
+ bool "Amlogic Meson8, Meson8b and Meson8m2 SoCs support"
default ARCH_MESON
select MESON6_TIMER
select COMMON_CLK_MESON8B
diff --git a/arch/arm/mach-meson/meson.c b/arch/arm/mach-meson/meson.c
index 4e23571..c8d99df 100644
--- a/arch/arm/mach-meson/meson.c
+++ b/arch/arm/mach-meson/meson.c
@@ -20,6 +20,7 @@ static const char * const meson_common_board_compat[] = {
"amlogic,meson6",
"amlogic,meson8",
"amlogic,meson8b",
+ "amlogic,meson8m2",
NULL,
};
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 52e8e53..80f54cb 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -12,6 +12,7 @@
* published by the Free Software Foundation.
*/
#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -202,7 +203,10 @@ static struct resource latch2_resources[] = {
},
};
+#define LATCH2_LABEL "latch2"
+
static struct bgpio_pdata latch2_pdata = {
+ .label = LATCH2_LABEL,
.base = AMS_DELTA_LATCH2_GPIO_BASE,
.ngpio = AMS_DELTA_LATCH2_NGPIO,
};
@@ -217,6 +221,23 @@ static struct platform_device latch2_gpio_device = {
},
};
+#define LATCH2_PIN_LCD_VBLEN 0
+#define LATCH2_PIN_LCD_NDISP 1
+#define LATCH2_PIN_NAND_NCE 2
+#define LATCH2_PIN_NAND_NRE 3
+#define LATCH2_PIN_NAND_NWP 4
+#define LATCH2_PIN_NAND_NWE 5
+#define LATCH2_PIN_NAND_ALE 6
+#define LATCH2_PIN_NAND_CLE 7
+#define LATCH2_PIN_KEYBRD_PWR 8
+#define LATCH2_PIN_KEYBRD_DATAOUT 9
+#define LATCH2_PIN_SCARD_RSTIN 10
+#define LATCH2_PIN_SCARD_CMDVCC 11
+#define LATCH2_PIN_MODEM_NRESET 12
+#define LATCH2_PIN_MODEM_CODEC 13
+#define LATCH2_PIN_HOOKFLASH1 14
+#define LATCH2_PIN_HOOKFLASH2 15
+
static const struct gpio latch_gpios[] __initconst = {
{
.gpio = LATCH1_GPIO_BASE + 6,
@@ -239,11 +260,6 @@ static const struct gpio latch_gpios[] __initconst = {
.label = "scard_cmdvcc",
},
{
- .gpio = AMS_DELTA_GPIO_PIN_MODEM_CODEC,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "modem_codec",
- },
- {
.gpio = AMS_DELTA_LATCH2_GPIO_BASE + 14,
.flags = GPIOF_OUT_INIT_LOW,
.label = "hookflash1",
@@ -323,6 +339,22 @@ static struct platform_device ams_delta_nand_device = {
.resource = ams_delta_nand_resources,
};
+#define OMAP_GPIO_LABEL "gpio-0-15"
+
+static struct gpiod_lookup_table ams_delta_nand_gpio_table = {
+ .table = {
+ GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_NAND_RB, "rdy",
+ 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NCE, "nce", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NRE, "nre", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWP, "nwp", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_ALE, "ale", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_CLE, "cle", 0),
+ { },
+ },
+};
+
static struct resource ams_delta_kp_resources[] = {
[0] = {
.start = INT_KEYBOARD,
@@ -358,6 +390,14 @@ static struct platform_device ams_delta_lcd_device = {
.id = -1,
};
+static struct gpiod_lookup_table ams_delta_lcd_gpio_table = {
+ .table = {
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_LCD_VBLEN, "vblen", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_LCD_NDISP, "ndisp", 0),
+ { },
+ },
+};
+
static const struct gpio_led gpio_leds[] __initconst = {
{
.name = "camera",
@@ -449,11 +489,35 @@ static struct platform_device ams_delta_audio_device = {
.id = -1,
};
+static struct gpiod_lookup_table ams_delta_audio_gpio_table = {
+ .table = {
+ GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_HOOK_SWITCH,
+ "hook_switch", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_CODEC,
+ "modem_codec", 0),
+ { },
+ },
+};
+
static struct platform_device cx20442_codec_device = {
.name = "cx20442-codec",
.id = -1,
};
+static struct gpiod_lookup_table ams_delta_serio_gpio_table = {
+ .table = {
+ GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
+ "data", 0),
+ GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
+ "clock", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_PWR,
+ "power", 0),
+ GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT,
+ "dataout", 0),
+ { },
+ },
+};
+
static struct platform_device *ams_delta_devices[] __initdata = {
&latch1_gpio_device,
&latch2_gpio_device,
@@ -468,6 +532,16 @@ static struct platform_device *late_devices[] __initdata = {
&cx20442_codec_device,
};
+static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
+ &ams_delta_audio_gpio_table,
+ &ams_delta_serio_gpio_table,
+};
+
+static struct gpiod_lookup_table *late_gpio_tables[] __initdata = {
+ &ams_delta_lcd_gpio_table,
+ &ams_delta_nand_gpio_table,
+};
+
static void __init ams_delta_init(void)
{
/* mux pins for uarts */
@@ -500,6 +574,20 @@ static void __init ams_delta_init(void)
gpio_led_register_device(-1, &leds_pdata);
platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
+ /*
+ * As soon as devices have been registered, assign their dev_names
+ * to respective GPIO lookup tables before they are added.
+ */
+ ams_delta_audio_gpio_table.dev_id =
+ dev_name(&ams_delta_audio_device.dev);
+ /*
+ * No device name is assigned to GPIO lookup table for serio device
+ * as long as serio driver is not converted to platform device driver.
+ */
+
+ gpiod_add_lookup_tables(ams_delta_gpio_tables,
+ ARRAY_SIZE(ams_delta_gpio_tables));
+
ams_delta_init_fiq();
omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
@@ -570,6 +658,15 @@ static int __init late_init(void)
platform_add_devices(late_devices, ARRAY_SIZE(late_devices));
+ /*
+ * As soon as devices have been registered, assign their dev_names
+ * to respective GPIO lookup tables before they are added.
+ */
+ ams_delta_lcd_gpio_table.dev_id = dev_name(&ams_delta_lcd_device.dev);
+ ams_delta_nand_gpio_table.dev_id = dev_name(&ams_delta_nand_device.dev);
+
+ gpiod_add_lookup_tables(late_gpio_tables, ARRAY_SIZE(late_gpio_tables));
+
err = platform_device_register(&modem_nreset_device);
if (err) {
pr_err("Couldn't register the modem regulator device\n");
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index 67d4669..da8f3fc3 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -31,7 +31,7 @@
#include <linux/gpio.h>
#include <linux/gpio_keys.h>
#include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
#include <linux/htcpld.h>
#include <linux/leds.h>
#include <linux/spi/spi.h>
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index c66372e..9ffa8d7 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -303,22 +303,22 @@ static const struct omap_lcd_config osk_lcd_config __initconst = {
#ifdef CONFIG_OMAP_OSK_MISTRAL
#include <linux/input.h>
-#include <linux/platform_data/at24.h>
+#include <linux/property.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/platform_data/keypad-omap.h>
-static struct at24_platform_data at24c04 = {
- .byte_len = SZ_4K / 8,
- .page_size = 16,
+static const struct property_entry mistral_at24_properties[] = {
+ PROPERTY_ENTRY_U32("pagesize", 16),
+ { }
};
static struct i2c_board_info __initdata mistral_i2c_board_info[] = {
{
/* NOTE: powered from LCD supply */
I2C_BOARD_INFO("24c04", 0x50),
- .platform_data = &at24c04,
+ .properties = mistral_at24_properties,
},
/* TODO when driver support is ready:
* - optionally ov9640 camera sensor at 0x30
diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h
index d83ff25..c6537d2 100644
--- a/arch/arm/mach-omap1/common.h
+++ b/arch/arm/mach-omap1/common.h
@@ -27,7 +27,7 @@
#define __ARCH_ARM_MACH_OMAP1_COMMON_H
#include <linux/mtd/mtd.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include <linux/reboot.h>
#include <asm/exception.h>
diff --git a/arch/arm/mach-omap1/i2c.c b/arch/arm/mach-omap1/i2c.c
index 5bdf3c4..9250f26 100644
--- a/arch/arm/mach-omap1/i2c.c
+++ b/arch/arm/mach-omap1/i2c.c
@@ -20,7 +20,7 @@
*/
#include <linux/i2c.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include <mach/mux.h>
#include "soc.h"
diff --git a/arch/arm/mach-omap1/mcbsp.c b/arch/arm/mach-omap1/mcbsp.c
index 8ed67f8d..27e22e7 100644
--- a/arch/arm/mach-omap1/mcbsp.c
+++ b/arch/arm/mach-omap1/mcbsp.c
@@ -389,7 +389,7 @@ static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
{
int i;
- omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
+ omap_mcbsp_devices = kcalloc(size, sizeof(struct platform_device *),
GFP_KERNEL);
if (!omap_mcbsp_devices) {
printk(KERN_ERR "Could not register McBSP devices\n");
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 0d9ce58..01377c2 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -78,7 +78,6 @@ endif
omap-4-5-pm-common = omap-mpuss-lowpower.o
obj-$(CONFIG_ARCH_OMAP4) += $(omap-4-5-pm-common)
obj-$(CONFIG_SOC_OMAP5) += $(omap-4-5-pm-common)
-obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
ifeq ($(CONFIG_PM),y)
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 6c61ecc..6b4f497 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -31,8 +31,6 @@ static const struct of_device_id omap_dt_match_table[] __initconst = {
static void __init __maybe_unused omap_generic_init(void)
{
pdata_quirks_init(omap_dt_match_table);
-
- omapdss_init_of();
omap_soc_device_init();
}
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index b79b1ca..6d44fe0 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -23,6 +23,7 @@
#include <linux/limits.h>
#include <linux/err.h>
#include <linux/clk-provider.h>
+#include <linux/cpu_pm.h>
#include <linux/io.h>
@@ -31,6 +32,7 @@
#include "soc.h"
#include "clock.h"
#include "clockdomain.h"
+#include "pm.h"
/* clkdm_list contains all registered struct clockdomains */
static LIST_HEAD(clkdm_list);
@@ -39,6 +41,8 @@ static LIST_HEAD(clkdm_list);
static struct clkdm_autodep *autodeps;
static struct clkdm_ops *arch_clkdm;
+void clkdm_save_context(void);
+void clkdm_restore_context(void);
/* Private functions */
@@ -449,6 +453,22 @@ int clkdm_register_autodeps(struct clkdm_autodep *ia)
return 0;
}
+static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
+{
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ if (enable_off_mode)
+ clkdm_save_context();
+ break;
+ case CPU_CLUSTER_PM_EXIT:
+ if (enable_off_mode)
+ clkdm_restore_context();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
/**
* clkdm_complete_init - set up the clockdomain layer
*
@@ -460,6 +480,7 @@ int clkdm_register_autodeps(struct clkdm_autodep *ia)
int clkdm_complete_init(void)
{
struct clockdomain *clkdm;
+ static struct notifier_block nb;
if (list_empty(&clkdm_list))
return -EACCES;
@@ -474,6 +495,12 @@ int clkdm_complete_init(void)
clkdm_clear_all_sleepdeps(clkdm);
}
+ /* Only AM43XX can lose clkdm context during rtc-ddr suspend */
+ if (soc_is_am43xx()) {
+ nb.notifier_call = cpu_notifier;
+ cpu_pm_register_notifier(&nb);
+ }
+
return 0;
}
@@ -1307,3 +1334,49 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
return 0;
}
+/**
+ * _clkdm_save_context - save the context for the control of this clkdm
+ *
+ * Due to a suspend or hibernation operation, the state of the registers
+ * controlling this clkdm will be lost, save their context.
+ */
+static int _clkdm_save_context(struct clockdomain *clkdm, void *ununsed)
+{
+ if (!arch_clkdm || !arch_clkdm->clkdm_save_context)
+ return -EINVAL;
+
+ return arch_clkdm->clkdm_save_context(clkdm);
+}
+
+/**
+ * _clkdm_restore_context - restore context for control of this clkdm
+ *
+ * Restore the register values for this clockdomain.
+ */
+static int _clkdm_restore_context(struct clockdomain *clkdm, void *ununsed)
+{
+ if (!arch_clkdm || !arch_clkdm->clkdm_restore_context)
+ return -EINVAL;
+
+ return arch_clkdm->clkdm_restore_context(clkdm);
+}
+
+/**
+ * clkdm_save_context - Saves the context for each registered clkdm
+ *
+ * Save the context for each registered clockdomain.
+ */
+void clkdm_save_context(void)
+{
+ clkdm_for_each(_clkdm_save_context, NULL);
+}
+
+/**
+ * clkdm_restore_context - Restores the context for each registered clkdm
+ *
+ * Restore the context for each registered clockdomain.
+ */
+void clkdm_restore_context(void)
+{
+ clkdm_for_each(_clkdm_restore_context, NULL);
+}
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index 24667a5..c7d0953 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -141,6 +141,7 @@ struct clockdomain {
int usecount;
int forcewake_count;
struct list_head node;
+ u32 context;
};
/**
@@ -159,6 +160,8 @@ struct clockdomain {
* @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain
* @clkdm_clk_enable: Put the clkdm in right state for a clock enable
* @clkdm_clk_disable: Put the clkdm in right state for a clock disable
+ * @clkdm_save_context: Save the current clkdm context
+ * @clkdm_restore_context: Restore the clkdm context
*/
struct clkdm_ops {
int (*clkdm_add_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
@@ -175,6 +178,8 @@ struct clkdm_ops {
void (*clkdm_deny_idle)(struct clockdomain *clkdm);
int (*clkdm_clk_enable)(struct clockdomain *clkdm);
int (*clkdm_clk_disable)(struct clockdomain *clkdm);
+ int (*clkdm_save_context)(struct clockdomain *clkdm);
+ int (*clkdm_restore_context)(struct clockdomain *clkdm);
};
int clkdm_register_platform_funcs(struct clkdm_ops *co);
@@ -214,6 +219,9 @@ int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
int clkdm_hwmod_enable(struct clockdomain *clkdm, struct omap_hwmod *oh);
int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
+void clkdm_save_context(void);
+void clkdm_restore_context(void);
+
extern void __init omap242x_clockdomains_init(void);
extern void __init omap243x_clockdomains_init(void);
extern void __init omap3xxx_clockdomains_init(void);
diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c
index 1cc0247..084d454 100644
--- a/arch/arm/mach-omap2/cm33xx.c
+++ b/arch/arm/mach-omap2/cm33xx.c
@@ -72,6 +72,17 @@ static inline u32 am33xx_cm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
return v;
}
+static inline u32 am33xx_cm_read_reg_bits(u16 inst, s16 idx, u32 mask)
+{
+ u32 v;
+
+ v = am33xx_cm_read_reg(inst, idx);
+ v &= mask;
+ v >>= __ffs(mask);
+
+ return v;
+}
+
/**
* _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield
* @inst: CM instance register offset (*_INST macro)
@@ -338,6 +349,46 @@ static u32 am33xx_cm_xlate_clkctrl(u8 part, u16 inst, u16 offset)
return cm_base.pa + inst + offset;
}
+/**
+ * am33xx_clkdm_save_context - Save the clockdomain transition context
+ * @clkdm: The clockdomain pointer whose context needs to be saved
+ *
+ * Save the clockdomain transition context.
+ */
+static int am33xx_clkdm_save_context(struct clockdomain *clkdm)
+{
+ clkdm->context = am33xx_cm_read_reg_bits(clkdm->cm_inst,
+ clkdm->clkdm_offs,
+ AM33XX_CLKTRCTRL_MASK);
+
+ return 0;
+}
+
+/**
+ * am33xx_restore_save_context - Restore the clockdomain transition context
+ * @clkdm: The clockdomain pointer whose context needs to be restored
+ *
+ * Restore the clockdomain transition context.
+ */
+static int am33xx_clkdm_restore_context(struct clockdomain *clkdm)
+{
+ switch (clkdm->context) {
+ case OMAP34XX_CLKSTCTRL_DISABLE_AUTO:
+ am33xx_clkdm_deny_idle(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_FORCE_SLEEP:
+ am33xx_clkdm_sleep(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_FORCE_WAKEUP:
+ am33xx_clkdm_wakeup(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_ENABLE_AUTO:
+ am33xx_clkdm_allow_idle(clkdm);
+ break;
+ }
+ return 0;
+}
+
struct clkdm_ops am33xx_clkdm_operations = {
.clkdm_sleep = am33xx_clkdm_sleep,
.clkdm_wakeup = am33xx_clkdm_wakeup,
@@ -345,6 +396,8 @@ struct clkdm_ops am33xx_clkdm_operations = {
.clkdm_deny_idle = am33xx_clkdm_deny_idle,
.clkdm_clk_enable = am33xx_clkdm_clk_enable,
.clkdm_clk_disable = am33xx_clkdm_clk_disable,
+ .clkdm_save_context = am33xx_clkdm_save_context,
+ .clkdm_restore_context = am33xx_clkdm_restore_context,
};
static const struct cm_ll_data am33xx_cm_ll_data = {
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index 7deefee..c11ac49 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -481,6 +481,47 @@ static u32 omap4_cminst_xlate_clkctrl(u8 part, u16 inst, u16 offset)
return _cm_bases[part].pa + inst + offset;
}
+/**
+ * omap4_clkdm_save_context - Save the clockdomain modulemode context
+ * @clkdm: The clockdomain pointer whose context needs to be saved
+ *
+ * Save the clockdomain modulemode context.
+ */
+static int omap4_clkdm_save_context(struct clockdomain *clkdm)
+{
+ clkdm->context = omap4_cminst_read_inst_reg(clkdm->prcm_partition,
+ clkdm->cm_inst,
+ clkdm->clkdm_offs +
+ OMAP4_CM_CLKSTCTRL);
+ clkdm->context &= OMAP4430_MODULEMODE_MASK;
+ return 0;
+}
+
+/**
+ * omap4_clkdm_restore_context - Restore the clockdomain modulemode context
+ * @clkdm: The clockdomain pointer whose context needs to be restored
+ *
+ * Restore the clockdomain modulemode context.
+ */
+static int omap4_clkdm_restore_context(struct clockdomain *clkdm)
+{
+ switch (clkdm->context) {
+ case OMAP34XX_CLKSTCTRL_DISABLE_AUTO:
+ omap4_clkdm_deny_idle(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_FORCE_SLEEP:
+ omap4_clkdm_sleep(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_FORCE_WAKEUP:
+ omap4_clkdm_wakeup(clkdm);
+ break;
+ case OMAP34XX_CLKSTCTRL_ENABLE_AUTO:
+ omap4_clkdm_allow_idle(clkdm);
+ break;
+ }
+ return 0;
+}
+
struct clkdm_ops omap4_clkdm_operations = {
.clkdm_add_wkdep = omap4_clkdm_add_wkup_sleep_dep,
.clkdm_del_wkdep = omap4_clkdm_del_wkup_sleep_dep,
@@ -496,6 +537,8 @@ struct clkdm_ops omap4_clkdm_operations = {
.clkdm_deny_idle = omap4_clkdm_deny_idle,
.clkdm_clk_enable = omap4_clkdm_clk_enable,
.clkdm_clk_disable = omap4_clkdm_clk_disable,
+ .clkdm_save_context = omap4_clkdm_save_context,
+ .clkdm_restore_context = omap4_clkdm_restore_context,
};
struct clkdm_ops am43xx_clkdm_operations = {
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index fbe0b78..129455e 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -30,7 +30,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/mfd/twl.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include <linux/reboot.h>
#include <linux/irqchip/irq-omap-intc.h>
@@ -44,6 +44,9 @@
#define OMAP_INTC_START NR_IRQS
+extern int (*omap_pm_soc_init)(void);
+int omap_pm_nop_init(void);
+
#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP2)
int omap2_pm_init(void);
#else
@@ -79,9 +82,12 @@ static inline int omap4_pm_init_early(void)
#if defined(CONFIG_PM) && (defined(CONFIG_SOC_AM33XX) || \
defined(CONFIG_SOC_AM43XX))
-void amx3_common_pm_init(void);
+int amx3_common_pm_init(void);
#else
-static inline void amx3_common_pm_init(void) { }
+static inline int amx3_common_pm_init(void)
+{
+ return 0;
+}
#endif
extern void omap2_init_common_infrastructure(void);
@@ -122,14 +128,10 @@ void am43xx_init_early(void);
void am43xx_init_late(void);
void omap4430_init_early(void);
void omap5_init_early(void);
-void omap3_init_late(void); /* Do not use this one */
+void omap3_init_late(void);
void omap4430_init_late(void);
void omap2420_init_late(void);
void omap2430_init_late(void);
-void omap3430_init_late(void);
-void omap35xx_init_late(void);
-void omap3630_init_late(void);
-void am35xx_init_late(void);
void ti81xx_init_late(void);
void am33xx_init_late(void);
void omap5_init_late(void);
@@ -350,7 +352,5 @@ extern int omap_dss_reset(struct omap_hwmod *);
/* SoC specific clock initializer */
int omap_clk_init(void);
-int __init omapdss_init_of(void);
-
#endif /* __ASSEMBLER__ */
#endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 180da403..0bbfb20 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
+#include <linux/cpu_pm.h>
#include "soc.h"
#include "iomap.h"
@@ -621,6 +622,110 @@ void __init omap3_ctrl_init(void)
}
#endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
+static unsigned long am43xx_control_reg_offsets[] = {
+ AM33XX_CONTROL_SYSCONFIG_OFFSET,
+ AM33XX_CONTROL_STATUS_OFFSET,
+ AM43XX_CONTROL_MPU_L2_CTRL_OFFSET,
+ AM33XX_CONTROL_CORE_SLDO_CTRL_OFFSET,
+ AM33XX_CONTROL_MPU_SLDO_CTRL_OFFSET,
+ AM33XX_CONTROL_CLK32KDIVRATIO_CTRL_OFFSET,
+ AM33XX_CONTROL_BANDGAP_CTRL_OFFSET,
+ AM33XX_CONTROL_BANDGAP_TRIM_OFFSET,
+ AM33XX_CONTROL_PLL_CLKINPULOW_CTRL_OFFSET,
+ AM33XX_CONTROL_MOSC_CTRL_OFFSET,
+ AM33XX_CONTROL_DEEPSLEEP_CTRL_OFFSET,
+ AM43XX_CONTROL_DISPLAY_PLL_SEL_OFFSET,
+ AM33XX_CONTROL_INIT_PRIORITY_0_OFFSET,
+ AM33XX_CONTROL_INIT_PRIORITY_1_OFFSET,
+ AM33XX_CONTROL_TPTC_CFG_OFFSET,
+ AM33XX_CONTROL_USB_CTRL0_OFFSET,
+ AM33XX_CONTROL_USB_CTRL1_OFFSET,
+ AM43XX_CONTROL_USB_CTRL2_OFFSET,
+ AM43XX_CONTROL_GMII_SEL_OFFSET,
+ AM43XX_CONTROL_MPUSS_CTRL_OFFSET,
+ AM43XX_CONTROL_TIMER_CASCADE_CTRL_OFFSET,
+ AM43XX_CONTROL_PWMSS_CTRL_OFFSET,
+ AM33XX_CONTROL_MREQPRIO_0_OFFSET,
+ AM33XX_CONTROL_MREQPRIO_1_OFFSET,
+ AM33XX_CONTROL_HW_EVENT_SEL_GRP1_OFFSET,
+ AM33XX_CONTROL_HW_EVENT_SEL_GRP2_OFFSET,
+ AM33XX_CONTROL_HW_EVENT_SEL_GRP3_OFFSET,
+ AM33XX_CONTROL_HW_EVENT_SEL_GRP4_OFFSET,
+ AM33XX_CONTROL_SMRT_CTRL_OFFSET,
+ AM33XX_CONTROL_MPUSS_HW_DEBUG_SEL_OFFSET,
+ AM43XX_CONTROL_CQDETECT_STS_OFFSET,
+ AM43XX_CONTROL_CQDETECT_STS2_OFFSET,
+ AM43XX_CONTROL_VTP_CTRL_OFFSET,
+ AM33XX_CONTROL_VREF_CTRL_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_0_3_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_4_7_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_8_11_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_12_15_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_16_19_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_20_23_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_24_27_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_28_31_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_32_35_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_36_39_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_40_43_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_44_47_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_48_51_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_52_55_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_56_59_OFFSET,
+ AM33XX_CONTROL_TPCC_EVT_MUX_60_63_OFFSET,
+ AM33XX_CONTROL_TIMER_EVT_CAPT_OFFSET,
+ AM33XX_CONTROL_ECAP_EVT_CAPT_OFFSET,
+ AM33XX_CONTROL_ADC_EVT_CAPT_OFFSET,
+ AM43XX_CONTROL_ADC1_EVT_CAPT_OFFSET,
+ AM33XX_CONTROL_RESET_ISO_OFFSET,
+};
+
+static u32 am33xx_control_vals[ARRAY_SIZE(am43xx_control_reg_offsets)];
+
+/**
+ * am43xx_control_save_context - Save the wakeup domain registers
+ *
+ * Save the wkup domain registers
+ */
+void am43xx_control_save_context(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(am43xx_control_reg_offsets); i++)
+ am33xx_control_vals[i] =
+ omap_ctrl_readl(am43xx_control_reg_offsets[i]);
+}
+
+/**
+ * am43xx_control_restore_context - Restore the wakeup domain registers
+ *
+ * Restore the wkup domain registers
+ */
+void am43xx_control_restore_context(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(am43xx_control_reg_offsets); i++)
+ omap_ctrl_writel(am33xx_control_vals[i],
+ am43xx_control_reg_offsets[i]);
+}
+
+static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
+{
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ if (enable_off_mode)
+ am43xx_control_save_context();
+ break;
+ case CPU_CLUSTER_PM_EXIT:
+ if (enable_off_mode)
+ am43xx_control_restore_context();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
struct control_init_data {
int index;
void __iomem *mem;
@@ -699,6 +804,7 @@ int __init omap_control_init(void)
const struct omap_prcm_init_data *data;
int ret;
struct regmap *syscon;
+ static struct notifier_block nb;
for_each_matching_node_and_match(np, omap_scrm_dt_match_table, &match) {
data = match->data;
@@ -731,6 +837,12 @@ int __init omap_control_init(void)
}
}
+ /* Only AM43XX can lose ctrl registers context during rtc-ddr suspend */
+ if (soc_is_am43xx()) {
+ nb.notifier_call = cpu_notifier;
+ cpu_pm_register_notifier(&nb);
+ }
+
return 0;
}
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index ec406bc..393b421 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -409,6 +409,67 @@
#define AM33XX_DEV_FEATURE 0x604
#define AM33XX_SGX_MASK BIT(29)
+/* Additional AM33XX/AM43XX CONTROL registers */
+#define AM33XX_CONTROL_SYSCONFIG_OFFSET 0x0010
+#define AM33XX_CONTROL_STATUS_OFFSET 0x0040
+#define AM43XX_CONTROL_MPU_L2_CTRL_OFFSET 0x01e0
+#define AM33XX_CONTROL_CORTEX_VBBLDO_CTRL_OFFSET 0x041c
+#define AM33XX_CONTROL_CORE_SLDO_CTRL_OFFSET 0x0428
+#define AM33XX_CONTROL_MPU_SLDO_CTRL_OFFSET 0x042c
+#define AM33XX_CONTROL_CLK32KDIVRATIO_CTRL_OFFSET 0x0444
+#define AM33XX_CONTROL_BANDGAP_CTRL_OFFSET 0x0448
+#define AM33XX_CONTROL_BANDGAP_TRIM_OFFSET 0x044c
+#define AM33XX_CONTROL_PLL_CLKINPULOW_CTRL_OFFSET 0x0458
+#define AM33XX_CONTROL_MOSC_CTRL_OFFSET 0x0468
+#define AM33XX_CONTROL_RCOSC_CTRL_OFFSET 0x046c
+#define AM33XX_CONTROL_DEEPSLEEP_CTRL_OFFSET 0x0470
+#define AM43XX_CONTROL_DISPLAY_PLL_SEL_OFFSET 0x0534
+#define AM33XX_CONTROL_INIT_PRIORITY_0_OFFSET 0x0608
+#define AM33XX_CONTROL_INIT_PRIORITY_1_OFFSET 0x060c
+#define AM33XX_CONTROL_MMU_CFG_OFFSET 0x0610
+#define AM33XX_CONTROL_TPTC_CFG_OFFSET 0x0614
+#define AM33XX_CONTROL_USB_CTRL0_OFFSET 0x0620
+#define AM33XX_CONTROL_USB_CTRL1_OFFSET 0x0628
+#define AM33XX_CONTROL_USB_WKUP_CTRL_OFFSET 0x0648
+#define AM43XX_CONTROL_USB_CTRL2_OFFSET 0x064c
+#define AM43XX_CONTROL_GMII_SEL_OFFSET 0x0650
+#define AM43XX_CONTROL_MPUSS_CTRL_OFFSET 0x0654
+#define AM43XX_CONTROL_TIMER_CASCADE_CTRL_OFFSET 0x0658
+#define AM43XX_CONTROL_PWMSS_CTRL_OFFSET 0x0664
+#define AM33XX_CONTROL_MREQPRIO_0_OFFSET 0x0670
+#define AM33XX_CONTROL_MREQPRIO_1_OFFSET 0x0674
+#define AM33XX_CONTROL_HW_EVENT_SEL_GRP1_OFFSET 0x0690
+#define AM33XX_CONTROL_HW_EVENT_SEL_GRP2_OFFSET 0x0694
+#define AM33XX_CONTROL_HW_EVENT_SEL_GRP3_OFFSET 0x0698
+#define AM33XX_CONTROL_HW_EVENT_SEL_GRP4_OFFSET 0x069c
+#define AM33XX_CONTROL_SMRT_CTRL_OFFSET 0x06a0
+#define AM33XX_CONTROL_MPUSS_HW_DEBUG_SEL_OFFSET 0x06a4
+#define AM43XX_CONTROL_CQDETECT_STS_OFFSET 0x0e00
+#define AM43XX_CONTROL_CQDETECT_STS2_OFFSET 0x0e08
+#define AM43XX_CONTROL_VTP_CTRL_OFFSET 0x0e0c
+#define AM33XX_CONTROL_VREF_CTRL_OFFSET 0x0e14
+#define AM33XX_CONTROL_TPCC_EVT_MUX_0_3_OFFSET 0x0f90
+#define AM33XX_CONTROL_TPCC_EVT_MUX_4_7_OFFSET 0x0f94
+#define AM33XX_CONTROL_TPCC_EVT_MUX_8_11_OFFSET 0x0f98
+#define AM33XX_CONTROL_TPCC_EVT_MUX_12_15_OFFSET 0x0f9c
+#define AM33XX_CONTROL_TPCC_EVT_MUX_16_19_OFFSET 0x0fa0
+#define AM33XX_CONTROL_TPCC_EVT_MUX_20_23_OFFSET 0x0fa4
+#define AM33XX_CONTROL_TPCC_EVT_MUX_24_27_OFFSET 0x0fa8
+#define AM33XX_CONTROL_TPCC_EVT_MUX_28_31_OFFSET 0x0fac
+#define AM33XX_CONTROL_TPCC_EVT_MUX_32_35_OFFSET 0x0fb0
+#define AM33XX_CONTROL_TPCC_EVT_MUX_36_39_OFFSET 0x0fb4
+#define AM33XX_CONTROL_TPCC_EVT_MUX_40_43_OFFSET 0x0fb8
+#define AM33XX_CONTROL_TPCC_EVT_MUX_44_47_OFFSET 0x0fbc
+#define AM33XX_CONTROL_TPCC_EVT_MUX_48_51_OFFSET 0x0fc0
+#define AM33XX_CONTROL_TPCC_EVT_MUX_52_55_OFFSET 0x0fc4
+#define AM33XX_CONTROL_TPCC_EVT_MUX_56_59_OFFSET 0x0fc8
+#define AM33XX_CONTROL_TPCC_EVT_MUX_60_63_OFFSET 0x0fcc
+#define AM33XX_CONTROL_TIMER_EVT_CAPT_OFFSET 0x0fd0
+#define AM33XX_CONTROL_ECAP_EVT_CAPT_OFFSET 0x0fd4
+#define AM33XX_CONTROL_ADC_EVT_CAPT_OFFSET 0x0fd8
+#define AM43XX_CONTROL_ADC1_EVT_CAPT_OFFSET 0x0fdc
+#define AM33XX_CONTROL_RESET_ISO_OFFSET 0x1000
+
/* CONTROL OMAP STATUS register to identify OMAP3 features */
#define OMAP3_CONTROL_OMAP_STATUS 0x044c
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index b3f6eb5..9500b6e 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -32,7 +32,6 @@
#include <linux/platform_data/omapdss.h>
#include "omap_hwmod.h"
#include "omap_device.h"
-#include "omap-pm.h"
#include "common.h"
#include "soc.h"
@@ -126,11 +125,6 @@ static void omap_dsi_disable_pads(int dsi_id, unsigned lane_mask)
omap4_dsi_mux_pads(dsi_id, 0);
}
-static int omap_dss_set_min_bus_tput(struct device *dev, unsigned long tput)
-{
- return omap_pm_set_min_bus_tput(dev, OCP_INITIATOR_AGENT, tput);
-}
-
static enum omapdss_version __init omap_display_get_version(void)
{
if (cpu_is_omap24xx())
@@ -169,7 +163,6 @@ static int __init omapdss_init_fbdev(void)
static struct omap_dss_board_info board_data = {
.dsi_enable_pads = omap_dsi_enable_pads,
.dsi_disable_pads = omap_dsi_disable_pads,
- .set_min_bus_tput = omap_dss_set_min_bus_tput,
};
struct device_node *node;
int r;
@@ -392,7 +385,7 @@ static struct device_node * __init omapdss_find_dss_of_node(void)
return NULL;
}
-int __init omapdss_init_of(void)
+static int __init omapdss_init_of(void)
{
int r;
struct device_node *node;
@@ -422,3 +415,4 @@ int __init omapdss_init_of(void)
return omapdss_init_fbdev();
}
+omap_device_initcall(omapdss_init_of);
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index b064066..af54519 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -18,7 +18,6 @@
#include "soc.h"
#include "omap_device.h"
-#include "omap-pm.h"
#include "hsmmc.h"
#include "control.h"
@@ -35,7 +34,7 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
{
char *hc_name;
- hc_name = kzalloc(sizeof(char) * (HSMMC_NAME_LEN + 1), GFP_KERNEL);
+ hc_name = kzalloc(HSMMC_NAME_LEN + 1, GFP_KERNEL);
if (!hc_name) {
kfree(hc_name);
return -ENOMEM;
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
index 91a21c3..37ff25e 100644
--- a/arch/arm/mach-omap2/i2c.c
+++ b/arch/arm/mach-omap2/i2c.c
@@ -22,7 +22,6 @@
#include "soc.h"
#include "omap_hwmod.h"
#include "omap_device.h"
-#include "omap-pm.h"
#include "prm.h"
#include "common.h"
diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c
index cf546df..bb8e0bb 100644
--- a/arch/arm/mach-omap2/io.c
+++ b/arch/arm/mach-omap2/io.c
@@ -37,7 +37,6 @@
#include "clock.h"
#include "clock2xxx.h"
#include "clock3xxx.h"
-#include "omap-pm.h"
#include "sdrc.h"
#include "control.h"
#include "serial.h"
@@ -421,13 +420,6 @@ static void __init __maybe_unused omap_hwmod_init_postsetup(void)
postsetup_state = _HWMOD_STATE_ENABLED;
#endif
omap_hwmod_for_each(_set_hwmod_postsetup_state, &postsetup_state);
-
- omap_pm_if_early_init();
-}
-
-static void __init __maybe_unused omap_common_late_init(void)
-{
- omap2_common_pm_late_init();
}
#ifdef CONFIG_SOC_OMAP2420
@@ -450,9 +442,7 @@ void __init omap2420_init_early(void)
void __init omap2420_init_late(void)
{
- omap_common_late_init();
- omap2_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap2_pm_init;
}
#endif
@@ -476,9 +466,7 @@ void __init omap2430_init_early(void)
void __init omap2430_init_late(void)
{
- omap_common_late_init();
- omap2_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap2_pm_init;
}
#endif
@@ -529,43 +517,12 @@ void __init am35xx_init_early(void)
void __init omap3_init_late(void)
{
- omap_common_late_init();
- omap3_pm_init();
- omap2_clk_enable_autoidle_all();
-}
-
-void __init omap3430_init_late(void)
-{
- omap_common_late_init();
- omap3_pm_init();
- omap2_clk_enable_autoidle_all();
-}
-
-void __init omap35xx_init_late(void)
-{
- omap_common_late_init();
- omap3_pm_init();
- omap2_clk_enable_autoidle_all();
-}
-
-void __init omap3630_init_late(void)
-{
- omap_common_late_init();
- omap3_pm_init();
- omap2_clk_enable_autoidle_all();
-}
-
-void __init am35xx_init_late(void)
-{
- omap_common_late_init();
- omap3_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap3_pm_init;
}
void __init ti81xx_init_late(void)
{
- omap_common_late_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap_pm_nop_init;
}
#endif
@@ -621,8 +578,7 @@ void __init am33xx_init_early(void)
void __init am33xx_init_late(void)
{
- omap_common_late_init();
- amx3_common_pm_init();
+ omap_pm_soc_init = amx3_common_pm_init;
}
#endif
@@ -645,9 +601,7 @@ void __init am43xx_init_early(void)
void __init am43xx_init_late(void)
{
- omap_common_late_init();
- omap2_clk_enable_autoidle_all();
- amx3_common_pm_init();
+ omap_pm_soc_init = amx3_common_pm_init;
}
#endif
@@ -675,9 +629,7 @@ void __init omap4430_init_early(void)
void __init omap4430_init_late(void)
{
- omap_common_late_init();
- omap4_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap4_pm_init;
}
#endif
@@ -703,9 +655,7 @@ void __init omap5_init_early(void)
void __init omap5_init_late(void)
{
- omap_common_late_init();
- omap4_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap4_pm_init;
}
#endif
@@ -728,9 +678,7 @@ void __init dra7xx_init_early(void)
void __init dra7xx_init_late(void)
{
- omap_common_late_init();
- omap4_pm_init();
- omap2_clk_enable_autoidle_all();
+ omap_pm_soc_init = omap4_pm_init;
}
#endif
diff --git a/arch/arm/mach-omap2/omap-pm-noop.c b/arch/arm/mach-omap2/omap-pm-noop.c
deleted file mode 100644
index 4ead077..0000000
--- a/arch/arm/mach-omap2/omap-pm-noop.c
+++ /dev/null
@@ -1,176 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * omap-pm-noop.c - OMAP power management interface - dummy version
- *
- * This code implements the OMAP power management interface to
- * drivers, CPUIdle, CPUFreq, and DSP Bridge. It is strictly for
- * debug/demonstration use, as it does nothing but printk() whenever a
- * function is called (when DEBUG is defined, below)
- *
- * Copyright (C) 2008-2009 Texas Instruments, Inc.
- * Copyright (C) 2008-2009 Nokia Corporation
- * Paul Walmsley
- *
- * Interface developed by (in alphabetical order):
- * Karthik Dasu, Tony Lindgren, Rajendra Nayak, Sakari Poussa, Veeramanikandan
- * Raju, Anand Sawant, Igor Stoppa, Paul Walmsley, Richard Woodruff
- */
-
-#undef DEBUG
-
-#include <linux/init.h>
-#include <linux/cpufreq.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-
-#include "omap_device.h"
-#include "omap-pm.h"
-
-static bool off_mode_enabled;
-static int dummy_context_loss_counter;
-
-/*
- * Device-driver-originated constraints (via board-*.c files)
- */
-
-int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
-{
- if (!dev || t < -1) {
- WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
- return -EINVAL;
- }
-
- if (t == -1)
- pr_debug("OMAP PM: remove max MPU wakeup latency constraint: dev %s\n",
- dev_name(dev));
- else
- pr_debug("OMAP PM: add max MPU wakeup latency constraint: dev %s, t = %ld usec\n",
- dev_name(dev), t);
-
- /*
- * For current Linux, this needs to map the MPU to a
- * powerdomain, then go through the list of current max lat
- * constraints on the MPU and find the smallest. If
- * the latency constraint has changed, the code should
- * recompute the state to enter for the next powerdomain
- * state.
- *
- * TI CDP code can call constraint_set here.
- */
-
- return 0;
-}
-
-int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
-{
- if (!dev || (agent_id != OCP_INITIATOR_AGENT &&
- agent_id != OCP_TARGET_AGENT)) {
- WARN(1, "OMAP PM: %s: invalid parameter(s)", __func__);
- return -EINVAL;
- }
-
- if (r == 0)
- pr_debug("OMAP PM: remove min bus tput constraint: dev %s for agent_id %d\n",
- dev_name(dev), agent_id);
- else
- pr_debug("OMAP PM: add min bus tput constraint: dev %s for agent_id %d: rate %ld KiB\n",
- dev_name(dev), agent_id, r);
-
- /*
- * This code should model the interconnect and compute the
- * required clock frequency, convert that to a VDD2 OPP ID, then
- * set the VDD2 OPP appropriately.
- *
- * TI CDP code can call constraint_set here on the VDD2 OPP.
- */
-
- return 0;
-}
-
-/*
- * DSP Bridge-specific constraints
- */
-
-
-/**
- * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled
- *
- * Intended for use only by OMAP PM core code to notify this layer
- * that off mode has been enabled.
- */
-void omap_pm_enable_off_mode(void)
-{
- off_mode_enabled = true;
-}
-
-/**
- * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled
- *
- * Intended for use only by OMAP PM core code to notify this layer
- * that off mode has been disabled.
- */
-void omap_pm_disable_off_mode(void)
-{
- off_mode_enabled = false;
-}
-
-/*
- * Device context loss tracking
- */
-
-#ifdef CONFIG_ARCH_OMAP2PLUS
-
-int omap_pm_get_dev_context_loss_count(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- int count;
-
- if (WARN_ON(!dev))
- return -ENODEV;
-
- if (dev->pm_domain == &omap_device_pm_domain) {
- count = omap_device_get_context_loss_count(pdev);
- } else {
- WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device",
- dev_name(dev));
-
- count = dummy_context_loss_counter;
-
- if (off_mode_enabled) {
- count++;
- /*
- * Context loss count has to be a non-negative value.
- * Clear the sign bit to get a value range from 0 to
- * INT_MAX.
- */
- count &= INT_MAX;
- dummy_context_loss_counter = count;
- }
- }
-
- pr_debug("OMAP PM: context loss count for dev %s = %d\n",
- dev_name(dev), count);
-
- return count;
-}
-
-#else
-
-int omap_pm_get_dev_context_loss_count(struct device *dev)
-{
- return dummy_context_loss_counter;
-}
-
-#endif
-
-/* Should be called before clk framework init */
-int __init omap_pm_if_early_init(void)
-{
- return 0;
-}
-
-/* Must be called after clock framework is initialized */
-int __init omap_pm_if_init(void)
-{
- return 0;
-}
diff --git a/arch/arm/mach-omap2/omap-pm.h b/arch/arm/mach-omap2/omap-pm.h
deleted file mode 100644
index 5ba5df4..0000000
--- a/arch/arm/mach-omap2/omap-pm.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * omap-pm.h - OMAP power management interface
- *
- * Copyright (C) 2008-2010 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
- * Paul Walmsley
- *
- * Interface developed by (in alphabetical order): Karthik Dasu, Jouni
- * Högander, Tony Lindgren, Rajendra Nayak, Sakari Poussa,
- * Veeramanikandan Raju, Anand Sawant, Igor Stoppa, Paul Walmsley,
- * Richard Woodruff
- */
-
-#ifndef ASM_ARM_ARCH_OMAP_OMAP_PM_H
-#define ASM_ARM_ARCH_OMAP_OMAP_PM_H
-
-#include <linux/device.h>
-#include <linux/cpufreq.h>
-#include <linux/clk.h>
-#include <linux/pm_opp.h>
-
-/*
- * agent_id values for use with omap_pm_set_min_bus_tput():
- *
- * OCP_INITIATOR_AGENT is only valid for devices that can act as
- * initiators -- it represents the device's L3 interconnect
- * connection. OCP_TARGET_AGENT represents the device's L4
- * interconnect connection.
- */
-#define OCP_TARGET_AGENT 1
-#define OCP_INITIATOR_AGENT 2
-
-/**
- * omap_pm_if_early_init - OMAP PM init code called before clock fw init
- * @mpu_opp_table: array ptr to struct omap_opp for MPU
- * @dsp_opp_table: array ptr to struct omap_opp for DSP
- * @l3_opp_table : array ptr to struct omap_opp for CORE
- *
- * Initialize anything that must be configured before the clock
- * framework starts. The "_if_" is to avoid name collisions with the
- * PM idle-loop code.
- */
-int __init omap_pm_if_early_init(void);
-
-/**
- * omap_pm_if_init - OMAP PM init code called after clock fw init
- *
- * The main initialization code. OPP tables are passed in here. The
- * "_if_" is to avoid name collisions with the PM idle-loop code.
- */
-int __init omap_pm_if_init(void);
-
-/*
- * Device-driver-originated constraints (via board-*.c files, platform_data)
- */
-
-
-/**
- * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency
- * @dev: struct device * requesting the constraint
- * @t: maximum MPU wakeup latency in microseconds
- *
- * Request that the maximum interrupt latency for the MPU to be no
- * greater than @t microseconds. "Interrupt latency" in this case is
- * defined as the elapsed time from the occurrence of a hardware or
- * timer interrupt to the time when the device driver's interrupt
- * service routine has been entered by the MPU.
- *
- * It is intended that underlying PM code will use this information to
- * determine what power state to put the MPU powerdomain into, and
- * possibly the CORE powerdomain as well, since interrupt handling
- * code currently runs from SDRAM. Advanced PM or board*.c code may
- * also configure interrupt controller priorities, OCP bus priorities,
- * CPU speed(s), etc.
- *
- * This function will not affect device wakeup latency, e.g., time
- * elapsed from when a device driver enables a hardware device with
- * clk_enable(), to when the device is ready for register access or
- * other use. To control this device wakeup latency, use
- * omap_pm_set_max_dev_wakeup_lat()
- *
- * Multiple calls to omap_pm_set_max_mpu_wakeup_lat() will replace the
- * previous t value. To remove the latency target for the MPU, call
- * with t = -1.
- *
- * XXX This constraint will be deprecated soon in favor of the more
- * general omap_pm_set_max_dev_wakeup_lat()
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t);
-
-
-/**
- * omap_pm_set_min_bus_tput - set minimum bus throughput needed by device
- * @dev: struct device * requesting the constraint
- * @tbus_id: interconnect to operate on (OCP_{INITIATOR,TARGET}_AGENT)
- * @r: minimum throughput (in KiB/s)
- *
- * Request that the minimum data throughput on the OCP interconnect
- * attached to device @dev interconnect agent @tbus_id be no less
- * than @r KiB/s.
- *
- * It is expected that the OMAP PM or bus code will use this
- * information to set the interconnect clock to run at the lowest
- * possible speed that satisfies all current system users. The PM or
- * bus code will adjust the estimate based on its model of the bus, so
- * device driver authors should attempt to specify an accurate
- * quantity for their device use case, and let the PM or bus code
- * overestimate the numbers as necessary to handle request/response
- * latency, other competing users on the system, etc. On OMAP2/3, if
- * a driver requests a minimum L4 interconnect speed constraint, the
- * code will also need to add an minimum L3 interconnect speed
- * constraint,
- *
- * Multiple calls to omap_pm_set_min_bus_tput() will replace the
- * previous rate value for this device. To remove the interconnect
- * throughput restriction for this device, call with r = 0.
- *
- * Returns -EINVAL for an invalid argument, -ERANGE if the constraint
- * is not satisfiable, or 0 upon success.
- */
-int omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r);
-
-
-/*
- * CPUFreq-originated constraint
- *
- * In the future, this should be handled by custom OPP clocktype
- * functions.
- */
-
-
-/*
- * Device context loss tracking
- */
-
-/**
- * omap_pm_get_dev_context_loss_count - return count of times dev has lost ctx
- * @dev: struct device *
- *
- * This function returns the number of times that the device @dev has
- * lost its internal context. This generally occurs on a powerdomain
- * transition to OFF. Drivers use this as an optimization to avoid restoring
- * context if the device hasn't lost it. To use, drivers should initially
- * call this in their context save functions and store the result. Early in
- * the driver's context restore function, the driver should call this function
- * again, and compare the result to the stored counter. If they differ, the
- * driver must restore device context. If the number of context losses
- * exceeds the maximum positive integer, the function will wrap to 0 and
- * continue counting. Returns the number of context losses for this device,
- * or negative value upon error.
- */
-int omap_pm_get_dev_context_loss_count(struct device *dev);
-
-void omap_pm_enable_off_mode(void);
-void omap_pm_disable_off_mode(void);
-
-#endif
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index 3b829a5..41c7b90 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -143,7 +143,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
struct resource res;
const char *oh_name;
int oh_cnt, i, ret = 0;
- bool device_active = false;
+ bool device_active = false, skip_pm_domain = false;
oh_cnt = of_property_count_strings(node, "ti,hwmods");
if (oh_cnt <= 0) {
@@ -151,11 +151,18 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
return -ENODEV;
}
+ /* SDMA still needs special handling for omap_device_build() */
+ ret = of_property_read_string_index(node, "ti,hwmods", 0, &oh_name);
+ if (!ret && (!strncmp("dma_system", oh_name, 10) ||
+ !strncmp("dma", oh_name, 3)))
+ skip_pm_domain = true;
+
/* Use ti-sysc driver instead of omap_device? */
- if (!omap_hwmod_parse_module_range(NULL, node, &res))
+ if (!skip_pm_domain &&
+ !omap_hwmod_parse_module_range(NULL, node, &res))
return -ENODEV;
- hwmods = kzalloc(sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL);
+ hwmods = kcalloc(oh_cnt, sizeof(struct omap_hwmod *), GFP_KERNEL);
if (!hwmods) {
ret = -ENOMEM;
goto odbfd_exit;
@@ -191,11 +198,12 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
r->name = dev_name(&pdev->dev);
}
- dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
-
- if (device_active) {
- omap_device_enable(pdev);
- pm_runtime_set_active(&pdev->dev);
+ if (!skip_pm_domain) {
+ dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
+ if (device_active) {
+ omap_device_enable(pdev);
+ pm_runtime_set_active(&pdev->dev);
+ }
}
odbfd_exit1:
@@ -405,7 +413,7 @@ omap_device_copy_resources(struct omap_hwmod *oh,
goto error;
}
- res = kzalloc(sizeof(*res) * 2, GFP_KERNEL);
+ res = kcalloc(2, sizeof(*res), GFP_KERNEL);
if (!res)
return -ENOMEM;
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index e7d23e20..2ceffd8 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -481,7 +481,7 @@ static int _wait_softreset_complete(struct omap_hwmod *oh)
sysc = oh->class->sysc;
- if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
+ if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS && sysc->syss_offs > 0)
omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs)
& SYSS_RESETDONE_MASK),
MAX_MODULE_SOFTRESET_WAIT, c);
@@ -3171,19 +3171,19 @@ static int omap_hwmod_init_regbits(struct device *dev,
*/
int omap_hwmod_init_reg_offs(struct device *dev,
const struct ti_sysc_module_data *data,
- u32 *rev_offs, u32 *sysc_offs, u32 *syss_offs)
+ s32 *rev_offs, s32 *sysc_offs, s32 *syss_offs)
{
- *rev_offs = 0;
+ *rev_offs = -ENODEV;
*sysc_offs = 0;
*syss_offs = 0;
- if (data->offsets[SYSC_REVISION] > 0)
+ if (data->offsets[SYSC_REVISION] >= 0)
*rev_offs = data->offsets[SYSC_REVISION];
- if (data->offsets[SYSC_SYSCONFIG] > 0)
+ if (data->offsets[SYSC_SYSCONFIG] >= 0)
*sysc_offs = data->offsets[SYSC_SYSCONFIG];
- if (data->offsets[SYSC_SYSSTATUS] > 0)
+ if (data->offsets[SYSC_SYSSTATUS] >= 0)
*syss_offs = data->offsets[SYSC_SYSSTATUS];
return 0;
@@ -3312,8 +3312,8 @@ static int omap_hwmod_check_module(struct device *dev,
struct omap_hwmod *oh,
const struct ti_sysc_module_data *data,
struct sysc_regbits *sysc_fields,
- u32 rev_offs, u32 sysc_offs,
- u32 syss_offs, u32 sysc_flags,
+ s32 rev_offs, s32 sysc_offs,
+ s32 syss_offs, u32 sysc_flags,
u32 idlemodes)
{
if (!oh->class->sysc)
@@ -3365,7 +3365,7 @@ static int omap_hwmod_check_module(struct device *dev,
int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh,
const struct ti_sysc_module_data *data,
struct sysc_regbits *sysc_fields,
- u32 rev_offs, u32 sysc_offs, u32 syss_offs,
+ s32 rev_offs, s32 sysc_offs, s32 syss_offs,
u32 sysc_flags, u32 idlemodes)
{
struct omap_hwmod_class_sysconfig *sysc;
@@ -3425,7 +3425,8 @@ int omap_hwmod_init_module(struct device *dev,
{
struct omap_hwmod *oh;
struct sysc_regbits *sysc_fields;
- u32 rev_offs, sysc_offs, syss_offs, sysc_flags, idlemodes;
+ s32 rev_offs, sysc_offs, syss_offs;
+ u32 sysc_flags, idlemodes;
int error;
if (!dev || !data)
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
index c7122ab..b70cdc2 100644
--- a/arch/arm/mach-omap2/omap_hwmod.h
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -317,9 +317,9 @@ struct omap_hwmod_ocp_if {
* then this field has to be populated with the correct offset structure.
*/
struct omap_hwmod_class_sysconfig {
- u32 rev_offs;
- u32 sysc_offs;
- u32 syss_offs;
+ s32 rev_offs;
+ s32 sysc_offs;
+ s32 syss_offs;
u16 sysc_flags;
struct sysc_regbits *sysc_fields;
u8 srst_udelay;
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index fe66cf2..d684fac 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -13,7 +13,7 @@
* XXX these should be marked initdata for multi-OMAP kernels
*/
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include <linux/omap-dma.h>
#include "omap_hwmod.h"
diff --git a/arch/arm/mach-omap2/omap_hwmod_2430_data.c b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
index 74eefd3..abef9f6 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2430_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2430_data.c
@@ -13,7 +13,7 @@
* XXX these should be marked initdata for multi-OMAP kernels
*/
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include <linux/platform_data/hsmmc-omap.h>
#include <linux/omap-dma.h>
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
index 5efe91c..9ded7bf 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_43xx_ipblock_data.c
@@ -629,6 +629,7 @@ struct omap_hwmod am33xx_gpmc_hwmod = {
/* 'i2c' class */
static struct omap_hwmod_class_sysconfig am33xx_i2c_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.syss_offs = 0x0090,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
index 53e1ac3..c9483bc 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -14,7 +14,7 @@
* GNU General Public License for more details.
*/
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include "omap_hwmod.h"
#include "omap_hwmod_common_data.h"
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 23336b6..23e6a41 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -15,7 +15,7 @@
* XXX these should be marked initdata for multi-OMAP kernels
*/
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include <linux/power/smartreflex.h>
#include <linux/platform_data/hsmmc-omap.h>
@@ -885,6 +885,7 @@ static struct omap_hwmod omap3xxx_dma_system_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x008c,
.sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP |
SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
@@ -990,6 +991,7 @@ static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
/* 'mcbsp sidetone' class */
static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sidetone_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x0010,
.sysc_flags = SYSC_HAS_AUTOIDLE,
.sysc_fields = &omap_hwmod_sysc_type1,
@@ -1018,6 +1020,7 @@ static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
/* SR common */
static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x24,
.sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE),
.sysc_fields = &omap34xx_sr_sysc_fields,
@@ -1030,6 +1033,7 @@ static struct omap_hwmod_class omap34xx_smartreflex_hwmod_class = {
};
static struct omap_hwmod_class_sysconfig omap36xx_sr_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x38,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
.sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
diff --git a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
index 5f73b73..aa271ac 100644
--- a/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_43xx_data.c
@@ -378,6 +378,7 @@ static struct omap_hwmod am43xx_usb_otg_ss1_hwmod = {
};
static struct omap_hwmod_class_sysconfig am43xx_qspi_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index e4f8ae9..a95dbac 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -23,7 +23,7 @@
#include <linux/io.h>
#include <linux/platform_data/hsmmc-omap.h>
#include <linux/power/smartreflex.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include <linux/omap-dma.h>
@@ -1360,6 +1360,7 @@ static struct omap_hwmod omap44xx_hsi_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.syss_offs = 0x0090,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
@@ -1634,6 +1635,7 @@ static struct omap_hwmod omap44xx_mailbox_hwmod = {
/* The IP is not compliant to type1 / type2 scheme */
static struct omap_hwmod_class_sysconfig omap44xx_mcasp_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0004,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -1667,6 +1669,7 @@ static struct omap_hwmod omap44xx_mcasp_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap44xx_mcbsp_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x008c,
.sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP |
SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
@@ -2353,6 +2356,7 @@ static struct omap_hwmod omap44xx_slimbus2_hwmod = {
/* The IP is not compliant to type1 / type2 scheme */
static struct omap_hwmod_class_sysconfig omap44xx_smartreflex_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x0038,
.sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
diff --git a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
index c72cd84..115473d 100644
--- a/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_54xx_data.c
@@ -20,7 +20,7 @@
#include <linux/io.h>
#include <linux/platform_data/hsmmc-omap.h>
#include <linux/power/smartreflex.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include <linux/omap-dma.h>
@@ -804,6 +804,7 @@ static struct omap_hwmod omap54xx_gpio8_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap54xx_i2c_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.syss_offs = 0x0090,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
@@ -974,6 +975,7 @@ static struct omap_hwmod omap54xx_mailbox_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap54xx_mcbsp_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x008c,
.sysc_flags = (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP |
SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
@@ -1997,6 +1999,7 @@ static struct omap_hwmod omap54xx_ocp2scp3_hwmod = {
*/
static struct omap_hwmod_class_sysconfig omap54xx_sata_sysc = {
+ .rev_offs = 0x00fc,
.sysc_offs = 0x0000,
.sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
index 62352d1..e6c7061 100644
--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
@@ -20,7 +20,7 @@
#include <linux/io.h>
#include <linux/platform_data/hsmmc-omap.h>
#include <linux/power/smartreflex.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include <linux/omap-dma.h>
@@ -1070,6 +1070,7 @@ static struct omap_hwmod dra7xx_hdq1w_hwmod = {
*/
static struct omap_hwmod_class_sysconfig dra7xx_i2c_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.syss_offs = 0x0090,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
@@ -1440,6 +1441,7 @@ static struct omap_hwmod dra7xx_mcspi4_hwmod = {
*
*/
static struct omap_hwmod_class_sysconfig dra7xx_mcasp_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0004,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
@@ -1898,6 +1900,7 @@ static struct omap_hwmod dra7xx_pciess2_hwmod = {
*/
static struct omap_hwmod_class_sysconfig dra7xx_qspi_sysc = {
+ .rev_offs = 0,
.sysc_offs = 0x0010,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -1930,6 +1933,7 @@ static struct omap_hwmod dra7xx_qspi_hwmod = {
*
*/
static struct omap_hwmod_class_sysconfig dra7xx_rtcss_sysc = {
+ .rev_offs = 0x0074,
.sysc_offs = 0x0078,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -1965,6 +1969,7 @@ static struct omap_hwmod dra7xx_rtcss_hwmod = {
*/
static struct omap_hwmod_class_sysconfig dra7xx_sata_sysc = {
+ .rev_offs = 0x00fc,
.sysc_offs = 0x0000,
.sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
@@ -2003,6 +2008,7 @@ static struct omap_hwmod dra7xx_sata_hwmod = {
/* The IP is not compliant to type1 / type2 scheme */
static struct omap_hwmod_class_sysconfig dra7xx_smartreflex_sysc = {
+ .rev_offs = -ENODEV,
.sysc_offs = 0x0038,
.sysc_flags = (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE),
.idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
diff --git a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c
index 686655f..8e44e27 100644
--- a/arch/arm/mach-omap2/omap_hwmod_81xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_81xx_data.c
@@ -954,6 +954,7 @@ static struct omap_hwmod_ocp_if dm816x_l4_hs__emac1 = {
};
static struct omap_hwmod_class_sysconfig dm81xx_sata_sysc = {
+ .rev_offs = 0x00fc,
.sysc_offs = 0x1100,
.sysc_flags = SYSC_HAS_SIDLEMODE,
.idlemodes = SIDLE_FORCE,
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 6459816..7f02743 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -26,14 +26,12 @@
#include <linux/platform_data/iommu-omap.h>
#include <linux/platform_data/ti-sysc.h>
#include <linux/platform_data/wkup_m3.h>
-#include <linux/platform_data/media/ir-rx51.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "common.h"
#include "common-board-devices.h"
#include "control.h"
#include "omap_device.h"
-#include "omap-pm.h"
#include "omap-secure.h"
#include "soc.h"
#include "hsmmc.h"
@@ -514,18 +512,6 @@ void omap_auxdata_legacy_init(struct device *dev)
dev->platform_data = &twl_gpio_auxdata;
}
-static struct ir_rx51_platform_data __maybe_unused rx51_ir_data = {
- .set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
-};
-
-static struct platform_device __maybe_unused rx51_ir_device = {
- .name = "ir_rx51",
- .id = -1,
- .dev = {
- .platform_data = &rx51_ir_data,
- },
-};
-
#if IS_ENABLED(CONFIG_SND_OMAP_SOC_MCBSP)
static struct omap_mcbsp_platform_data mcbsp_pdata;
static void __init omap3_mcbsp_init(void)
@@ -569,7 +555,6 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = {
"480c9000.smartreflex", &omap_sr_pdata[OMAP_SR_MPU]),
OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x4809c000, "4809c000.mmc", &mmc_pdata[0]),
OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x480b4000, "480b4000.mmc", &mmc_pdata[1]),
- OF_DEV_AUXDATA("nokia,n900-ir", 0, "n900-ir", &rx51_ir_data),
/* Only on am3517 */
OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index 5c46ea6..acb698d 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -31,7 +31,6 @@
#include "clock.h"
#include "powerdomain.h"
#include "clockdomain.h"
-#include "omap-pm.h"
#include "soc.h"
#include "cm2xxx_3xxx.h"
@@ -240,10 +239,6 @@ static int option_set(void *data, u64 val)
*option = val;
if (option == &enable_off_mode) {
- if (val)
- omap_pm_enable_off_mode();
- else
- omap_pm_disable_off_mode();
if (cpu_is_omap34xx())
omap3_pm_off_mode_enable(val);
}
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index 6f68576..ca03af8 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -16,11 +16,11 @@
#include <linux/pm_opp.h>
#include <linux/export.h>
#include <linux/suspend.h>
+#include <linux/clk.h>
#include <linux/cpu.h>
#include <asm/system_misc.h>
-#include "omap-pm.h"
#include "omap_device.h"
#include "common.h"
@@ -230,16 +230,20 @@ static void __init omap4_init_voltages(void)
omap2_set_init_voltage("iva", "dpll_iva_m5x2_ck", "iva");
}
-static int __init omap2_common_pm_init(void)
+int __maybe_unused omap_pm_nop_init(void)
{
- omap_pm_if_init();
-
return 0;
}
-omap_postcore_initcall(omap2_common_pm_init);
+
+int (*omap_pm_soc_init)(void);
int __init omap2_common_pm_late_init(void)
{
+ int error;
+
+ if (!omap_pm_soc_init)
+ return 0;
+
/* Init the voltage layer */
omap3_twl_init();
omap4_twl_init();
@@ -252,5 +256,12 @@ int __init omap2_common_pm_late_init(void)
/* Smartreflex device init */
omap_devinit_smartreflex();
+ error = omap_pm_soc_init();
+ if (error)
+ pr_warn("%s: pm soc init failed: %i\n", __func__, error);
+
+ omap2_clk_enable_autoidle_all();
+
return 0;
}
+omap_late_initcall(omap2_common_pm_late_init);
diff --git a/arch/arm/mach-omap2/pm33xx-core.c b/arch/arm/mach-omap2/pm33xx-core.c
index 93c0b5b..9b3755a 100644
--- a/arch/arm/mach-omap2/pm33xx-core.c
+++ b/arch/arm/mach-omap2/pm33xx-core.c
@@ -173,7 +173,7 @@ static struct am33xx_pm_platform_data *am33xx_pm_get_pdata(void)
return NULL;
}
-void __init amx3_common_pm_init(void)
+int __init amx3_common_pm_init(void)
{
struct am33xx_pm_platform_data *pdata;
struct platform_device_info devinfo;
@@ -186,4 +186,6 @@ void __init amx3_common_pm_init(void)
devinfo.size_data = sizeof(*pdata);
devinfo.id = -1;
platform_device_register_full(&devinfo);
+
+ return 0;
}
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
index b387022..78e1ace 100644
--- a/arch/arm/mach-omap2/pm44xx.c
+++ b/arch/arm/mach-omap2/pm44xx.c
@@ -131,6 +131,19 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused)
return 0;
}
+ /*
+ * Bootloader or kexec boot may have LOGICRETSTATE cleared
+ * for some domains. This is the case when kexec booting from
+ * Android kernels that support off mode for example.
+ * Make sure it's set at least for core and per, otherwise
+ * we currently will see lost GPIO interrupts for wlcore and
+ * smsc911x at least if per hits retention during idle.
+ */
+ if (!strncmp(pwrdm->name, "core", 4) ||
+ !strncmp(pwrdm->name, "l4per", 5) ||
+ !strncmp(pwrdm->name, "wkup", 4))
+ pwrdm_set_logic_retst(pwrdm, PWRDM_POWER_RET);
+
pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC);
if (!pwrst)
return -ENOMEM;
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index 1e6a967..1a0f69c 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -14,6 +14,7 @@
*/
#undef DEBUG
+#include <linux/cpu_pm.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/list.h>
@@ -39,6 +40,9 @@
#define PWRDM_TRACE_STATES_FLAG (1<<31)
+void pwrdms_save_context(void);
+void pwrdms_restore_context(void);
+
enum {
PWRDM_STATE_NOW = 0,
PWRDM_STATE_PREV,
@@ -333,6 +337,22 @@ int pwrdm_register_pwrdms(struct powerdomain **ps)
return 0;
}
+static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
+{
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ if (enable_off_mode)
+ pwrdms_save_context();
+ break;
+ case CPU_CLUSTER_PM_EXIT:
+ if (enable_off_mode)
+ pwrdms_restore_context();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
/**
* pwrdm_complete_init - set up the powerdomain layer
*
@@ -347,6 +367,7 @@ int pwrdm_register_pwrdms(struct powerdomain **ps)
int pwrdm_complete_init(void)
{
struct powerdomain *temp_p;
+ static struct notifier_block nb;
if (list_empty(&pwrdm_list))
return -EACCES;
@@ -354,6 +375,12 @@ int pwrdm_complete_init(void)
list_for_each_entry(temp_p, &pwrdm_list, node)
pwrdm_set_next_pwrst(temp_p, PWRDM_POWER_ON);
+ /* Only AM43XX can lose pwrdm context during rtc-ddr suspend */
+ if (soc_is_am43xx()) {
+ nb.notifier_call = cpu_notifier;
+ cpu_pm_register_notifier(&nb);
+ }
+
return 0;
}
@@ -1199,3 +1226,63 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm)
return 0;
}
+
+/**
+ * pwrdm_save_context - save powerdomain registers
+ *
+ * Register state is going to be lost due to a suspend or hibernate
+ * event. Save the powerdomain registers.
+ */
+static int pwrdm_save_context(struct powerdomain *pwrdm, void *unused)
+{
+ if (arch_pwrdm && arch_pwrdm->pwrdm_save_context)
+ arch_pwrdm->pwrdm_save_context(pwrdm);
+ return 0;
+}
+
+/**
+ * pwrdm_save_context - restore powerdomain registers
+ *
+ * Restore powerdomain control registers after a suspend or resume
+ * event.
+ */
+static int pwrdm_restore_context(struct powerdomain *pwrdm, void *unused)
+{
+ if (arch_pwrdm && arch_pwrdm->pwrdm_restore_context)
+ arch_pwrdm->pwrdm_restore_context(pwrdm);
+ return 0;
+}
+
+static int pwrdm_lost_power(struct powerdomain *pwrdm, void *unused)
+{
+ int state;
+
+ /*
+ * Power has been lost across all powerdomains, increment the
+ * counter.
+ */
+
+ state = pwrdm_read_pwrst(pwrdm);
+ if (state != PWRDM_POWER_OFF) {
+ pwrdm->state_counter[state]++;
+ pwrdm->state_counter[PWRDM_POWER_OFF]++;
+ }
+ pwrdm->state = state;
+
+ return 0;
+}
+
+void pwrdms_save_context(void)
+{
+ pwrdm_for_each(pwrdm_save_context, NULL);
+}
+
+void pwrdms_restore_context(void)
+{
+ pwrdm_for_each(pwrdm_restore_context, NULL);
+}
+
+void pwrdms_lost_power(void)
+{
+ pwrdm_for_each(pwrdm_lost_power, NULL);
+}
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 28a796c..9a907fb 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -144,6 +144,7 @@ struct powerdomain {
s64 timer;
s64 state_timer[PWRDM_MAX_PWRSTS];
#endif
+ u32 context;
};
/**
@@ -198,6 +199,8 @@ struct pwrdm_ops {
int (*pwrdm_set_lowpwrstchange)(struct powerdomain *pwrdm);
int (*pwrdm_wait_transition)(struct powerdomain *pwrdm);
int (*pwrdm_has_voltdm)(void);
+ void (*pwrdm_save_context)(struct powerdomain *pwrdm);
+ void (*pwrdm_restore_context)(struct powerdomain *pwrdm);
};
int pwrdm_register_platform_funcs(struct pwrdm_ops *custom_funcs);
@@ -273,4 +276,8 @@ extern struct powerdomain gfx_omap2_pwrdm;
extern void pwrdm_lock(struct powerdomain *pwrdm);
extern void pwrdm_unlock(struct powerdomain *pwrdm);
+extern void pwrdms_save_context(void);
+extern void pwrdms_restore_context(void);
+
+extern void pwrdms_lost_power(void);
#endif
diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c
index ebaf80d..d514166 100644
--- a/arch/arm/mach-omap2/prm33xx.c
+++ b/arch/arm/mach-omap2/prm33xx.c
@@ -342,6 +342,35 @@ static void am33xx_prm_global_warm_sw_reset(void)
AM33XX_PRM_RSTCTRL_OFFSET);
}
+static void am33xx_pwrdm_save_context(struct powerdomain *pwrdm)
+{
+ pwrdm->context = am33xx_prm_read_reg(pwrdm->prcm_offs,
+ pwrdm->pwrstctrl_offs);
+ /*
+ * Do not save LOWPOWERSTATECHANGE, writing a 1 indicates a request,
+ * reading back a 1 indicates a request in progress.
+ */
+ pwrdm->context &= ~AM33XX_LOWPOWERSTATECHANGE_MASK;
+}
+
+static void am33xx_pwrdm_restore_context(struct powerdomain *pwrdm)
+{
+ int st, ctrl;
+
+ st = am33xx_prm_read_reg(pwrdm->prcm_offs,
+ pwrdm->pwrstst_offs);
+
+ am33xx_prm_write_reg(pwrdm->context, pwrdm->prcm_offs,
+ pwrdm->pwrstctrl_offs);
+
+ /* Make sure we only wait for a transition if there is one */
+ st &= OMAP_POWERSTATEST_MASK;
+ ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context;
+
+ if (st != ctrl)
+ am33xx_pwrdm_wait_transition(pwrdm);
+}
+
struct pwrdm_ops am33xx_pwrdm_operations = {
.pwrdm_set_next_pwrst = am33xx_pwrdm_set_next_pwrst,
.pwrdm_read_next_pwrst = am33xx_pwrdm_read_next_pwrst,
@@ -357,6 +386,8 @@ struct pwrdm_ops am33xx_pwrdm_operations = {
.pwrdm_set_mem_retst = am33xx_pwrdm_set_mem_retst,
.pwrdm_wait_transition = am33xx_pwrdm_wait_transition,
.pwrdm_has_voltdm = am33xx_check_vcvp,
+ .pwrdm_save_context = am33xx_pwrdm_save_context,
+ .pwrdm_restore_context = am33xx_pwrdm_restore_context,
};
static struct prm_ll_data am33xx_prm_ll_data = {
diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c
index acb9593..7b95729 100644
--- a/arch/arm/mach-omap2/prm44xx.c
+++ b/arch/arm/mach-omap2/prm44xx.c
@@ -12,6 +12,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/cpu_pm.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/errno.h>
@@ -30,6 +31,7 @@
#include "prcm44xx.h"
#include "prminst44xx.h"
#include "powerdomain.h"
+#include "pm.h"
/* Static data */
@@ -57,6 +59,13 @@ static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
.reconfigure_io_chain = &omap44xx_prm_reconfigure_io_chain,
};
+struct omap_prm_irq_context {
+ unsigned long irq_enable;
+ unsigned long pm_ctrl;
+};
+
+static struct omap_prm_irq_context omap_prm_context;
+
/*
* omap44xx_prm_reset_src_map - map from bits in the PRM_RSTST
* hardware register (which are specific to OMAP44xx SoCs) to reset
@@ -667,6 +676,54 @@ static int omap4_check_vcvp(void)
return 0;
}
+/**
+ * omap4_pwrdm_save_context - Saves the powerdomain state
+ * @pwrdm: pointer to individual powerdomain
+ *
+ * The function saves the powerdomain state control information.
+ * This is needed in rtc+ddr modes where we lose powerdomain context.
+ */
+static void omap4_pwrdm_save_context(struct powerdomain *pwrdm)
+{
+ pwrdm->context = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
+ pwrdm->prcm_offs,
+ pwrdm->pwrstctrl_offs);
+
+ /*
+ * Do not save LOWPOWERSTATECHANGE, writing a 1 indicates a request,
+ * reading back a 1 indicates a request in progress.
+ */
+ pwrdm->context &= ~OMAP4430_LOWPOWERSTATECHANGE_MASK;
+}
+
+/**
+ * omap4_pwrdm_restore_context - Restores the powerdomain state
+ * @pwrdm: pointer to individual powerdomain
+ *
+ * The function restores the powerdomain state control information.
+ * This is needed in rtc+ddr modes where we lose powerdomain context.
+ */
+static void omap4_pwrdm_restore_context(struct powerdomain *pwrdm)
+{
+ int st, ctrl;
+
+ st = omap4_prminst_read_inst_reg(pwrdm->prcm_partition,
+ pwrdm->prcm_offs,
+ pwrdm->pwrstctrl_offs);
+
+ omap4_prminst_write_inst_reg(pwrdm->context,
+ pwrdm->prcm_partition,
+ pwrdm->prcm_offs,
+ pwrdm->pwrstctrl_offs);
+
+ /* Make sure we only wait for a transition if there is one */
+ st &= OMAP_POWERSTATEST_MASK;
+ ctrl = OMAP_POWERSTATEST_MASK & pwrdm->context;
+
+ if (st != ctrl)
+ omap4_pwrdm_wait_transition(pwrdm);
+}
+
struct pwrdm_ops omap4_pwrdm_operations = {
.pwrdm_set_next_pwrst = omap4_pwrdm_set_next_pwrst,
.pwrdm_read_next_pwrst = omap4_pwrdm_read_next_pwrst,
@@ -685,10 +742,50 @@ struct pwrdm_ops omap4_pwrdm_operations = {
.pwrdm_set_mem_retst = omap4_pwrdm_set_mem_retst,
.pwrdm_wait_transition = omap4_pwrdm_wait_transition,
.pwrdm_has_voltdm = omap4_check_vcvp,
+ .pwrdm_save_context = omap4_pwrdm_save_context,
+ .pwrdm_restore_context = omap4_pwrdm_restore_context,
};
static int omap44xx_prm_late_init(void);
+void prm_save_context(void)
+{
+ omap_prm_context.irq_enable =
+ omap4_prm_read_inst_reg(AM43XX_PRM_OCP_SOCKET_INST,
+ omap4_prcm_irq_setup.mask);
+
+ omap_prm_context.pm_ctrl =
+ omap4_prm_read_inst_reg(AM43XX_PRM_DEVICE_INST,
+ omap4_prcm_irq_setup.pm_ctrl);
+}
+
+void prm_restore_context(void)
+{
+ omap4_prm_write_inst_reg(omap_prm_context.irq_enable,
+ OMAP4430_PRM_OCP_SOCKET_INST,
+ omap4_prcm_irq_setup.mask);
+
+ omap4_prm_write_inst_reg(omap_prm_context.pm_ctrl,
+ AM43XX_PRM_DEVICE_INST,
+ omap4_prcm_irq_setup.pm_ctrl);
+}
+
+static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v)
+{
+ switch (cmd) {
+ case CPU_CLUSTER_PM_ENTER:
+ if (enable_off_mode)
+ prm_save_context();
+ break;
+ case CPU_CLUSTER_PM_EXIT:
+ if (enable_off_mode)
+ prm_restore_context();
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
/*
* XXX document
*/
@@ -709,6 +806,7 @@ static const struct omap_prcm_init_data *prm_init_data;
int __init omap44xx_prm_init(const struct omap_prcm_init_data *data)
{
+ static struct notifier_block nb;
omap_prm_base_init();
prm_init_data = data;
@@ -730,6 +828,12 @@ int __init omap44xx_prm_init(const struct omap_prcm_init_data *data)
omap4_prcm_irq_setup.mask = AM43XX_PRM_IRQENABLE_MPU_OFFSET;
}
+ /* Only AM43XX can lose prm context during rtc-ddr suspend */
+ if (soc_is_am43xx()) {
+ nb.notifier_call = cpu_notifier;
+ cpu_pm_register_notifier(&nb);
+ }
+
return prm_register(&omap44xx_prm_ll_data);
}
diff --git a/arch/arm/mach-omap2/prm_common.c b/arch/arm/mach-omap2/prm_common.c
index 021b5a8..058a37e 100644
--- a/arch/arm/mach-omap2/prm_common.c
+++ b/arch/arm/mach-omap2/prm_common.c
@@ -285,10 +285,11 @@ int omap_prcm_register_chain_handler(struct omap_prcm_irq_setup *irq_setup)
prcm_irq_setup = irq_setup;
- prcm_irq_chips = kzalloc(sizeof(void *) * nr_regs, GFP_KERNEL);
- prcm_irq_setup->saved_mask = kzalloc(sizeof(u32) * nr_regs, GFP_KERNEL);
- prcm_irq_setup->priority_mask = kzalloc(sizeof(u32) * nr_regs,
- GFP_KERNEL);
+ prcm_irq_chips = kcalloc(nr_regs, sizeof(void *), GFP_KERNEL);
+ prcm_irq_setup->saved_mask = kcalloc(nr_regs, sizeof(u32),
+ GFP_KERNEL);
+ prcm_irq_setup->priority_mask = kcalloc(nr_regs, sizeof(u32),
+ GFP_KERNEL);
if (!prcm_irq_chips || !prcm_irq_setup->saved_mask ||
!prcm_irq_setup->priority_mask)
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 4fb4dc2..98ed5ac 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -50,7 +50,6 @@
#include "omap_device.h"
#include <plat/counter-32k.h>
#include <clocksource/timer-ti-dm.h>
-#include "omap-pm.h"
#include "soc.h"
#include "common.h"
@@ -71,6 +70,9 @@ static struct clock_event_device clockevent_gpt;
/* Clockevent hwmod for am335x and am437x suspend */
static struct omap_hwmod *clockevent_gpt_hwmod;
+/* Clockesource hwmod for am437x suspend */
+static struct omap_hwmod *clocksource_gpt_hwmod;
+
#ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
static unsigned long arch_timer_freq;
@@ -168,6 +170,43 @@ static const struct of_device_id omap_timer_match[] __initconst = {
{ }
};
+static int omap_timer_add_disabled_property(struct device_node *np)
+{
+ struct property *prop;
+
+ prop = kzalloc(sizeof(*prop), GFP_KERNEL);
+ if (!prop)
+ return -ENOMEM;
+
+ prop->name = "status";
+ prop->value = "disabled";
+ prop->length = strlen(prop->value);
+
+ return of_add_property(np, prop);
+}
+
+static int omap_timer_update_dt(struct device_node *np)
+{
+ int error = 0;
+
+ if (!of_device_is_compatible(np, "ti,omap-counter32k")) {
+ error = omap_timer_add_disabled_property(np);
+ if (error)
+ return error;
+ }
+
+ /* No parent interconnect target module configured? */
+ if (of_get_property(np, "ti,hwmods", NULL))
+ return error;
+
+ /* Tag parent interconnect target module disabled */
+ error = omap_timer_add_disabled_property(np->parent);
+ if (error)
+ return error;
+
+ return 0;
+}
+
/**
* omap_get_timer_dt - get a timer using device-tree
* @match - device-tree match structure for matching a device type
@@ -183,6 +222,7 @@ static struct device_node * __init omap_get_timer_dt(const struct of_device_id *
const char *property)
{
struct device_node *np;
+ int error;
for_each_matching_node(np, match) {
if (!of_device_is_available(np))
@@ -197,17 +237,9 @@ static struct device_node * __init omap_get_timer_dt(const struct of_device_id *
of_get_property(np, "ti,timer-secure", NULL)))
continue;
- if (!of_device_is_compatible(np, "ti,omap-counter32k")) {
- struct property *prop;
+ error = omap_timer_update_dt(np);
+ WARN(error, "%s: Could not update dt: %i\n", __func__, error);
- prop = kzalloc(sizeof(*prop), GFP_KERNEL);
- if (!prop)
- return NULL;
- prop->name = "status";
- prop->value = "disabled";
- prop->length = strlen(prop->value);
- of_add_property(np, prop);
- }
return np;
}
@@ -266,8 +298,12 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
return -ENODEV;
of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
- if (!oh_name)
- return -ENODEV;
+ if (!oh_name) {
+ of_property_read_string_index(np->parent, "ti,hwmods", 0,
+ &oh_name);
+ if (!oh_name)
+ return -ENODEV;
+ }
timer->irq = irq_of_parse_and_map(np, 0);
if (!timer->irq)
@@ -419,9 +455,12 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
if (!np)
return -ENODEV;
- of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
- if (!oh_name)
- return -ENODEV;
+ of_property_read_string_index(np->parent, "ti,hwmods", 0, &oh_name);
+ if (!oh_name) {
+ of_property_read_string_index(np, "ti,hwmods", 0, &oh_name);
+ if (!oh_name)
+ return -ENODEV;
+ }
/*
* First check hwmod data is available for sync32k counter
@@ -442,6 +481,26 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
return ret;
}
+static unsigned int omap2_gptimer_clksrc_load;
+
+static void omap2_gptimer_clksrc_suspend(struct clocksource *unused)
+{
+ omap2_gptimer_clksrc_load =
+ __omap_dm_timer_read_counter(&clksrc, OMAP_TIMER_NONPOSTED);
+
+ omap_hwmod_idle(clocksource_gpt_hwmod);
+}
+
+static void omap2_gptimer_clksrc_resume(struct clocksource *unused)
+{
+ omap_hwmod_enable(clocksource_gpt_hwmod);
+
+ __omap_dm_timer_load_start(&clksrc,
+ OMAP_TIMER_CTRL_ST | OMAP_TIMER_CTRL_AR,
+ omap2_gptimer_clksrc_load,
+ OMAP_TIMER_NONPOSTED);
+}
+
static void __init omap2_gptimer_clocksource_init(int gptimer_id,
const char *fck_source,
const char *property)
@@ -454,6 +513,15 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
res = omap_dm_timer_init_one(&clksrc, fck_source, property,
&clocksource_gpt.name,
OMAP_TIMER_NONPOSTED);
+
+ if (soc_is_am43xx()) {
+ clocksource_gpt.suspend = omap2_gptimer_clksrc_suspend;
+ clocksource_gpt.resume = omap2_gptimer_clksrc_resume;
+
+ clocksource_gpt_hwmod =
+ omap_hwmod_lookup(clocksource_gpt.name);
+ }
+
BUG_ON(res);
__omap_dm_timer_load_start(&clksrc,
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 0adb1bd..4d475f6 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -30,7 +30,7 @@
#include <linux/wm97xx.h>
#include <linux/power_supply.h>
#include <linux/usb/gpio_vbus.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <asm/mach-types.h>
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 4b8a0df..8c64f93b 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -446,6 +446,10 @@ static int __init pxa3xx_init(void)
pxa3xx_init_pm();
+ enable_irq_wake(IRQ_WAKEUP0);
+ if (cpu_is_pxa320())
+ enable_irq_wake(IRQ_WAKEUP1);
+
register_syscore_ops(&pxa_irq_syscore_ops);
register_syscore_ops(&pxa3xx_mfp_syscore_ops);
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index df62bb2..bbea5fa 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -27,11 +27,11 @@
#include <linux/platform_data/i2c-pxa.h>
#include <linux/platform_data/pcf857x.h>
-#include <linux/platform_data/at24.h>
#include <linux/smc91x.h>
#include <linux/gpio/machine.h>
#include <linux/gpio.h>
#include <linux/leds.h>
+#include <linux/property.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -795,9 +795,9 @@ static struct pcf857x_platform_data platform_data_pcf857x = {
.context = NULL,
};
-static struct at24_platform_data pca9500_eeprom_pdata = {
- .byte_len = 256,
- .page_size = 4,
+static const struct property_entry pca9500_eeprom_properties[] = {
+ PROPERTY_ENTRY_U32("pagesize", 4),
+ { }
};
/**
@@ -935,7 +935,7 @@ static struct i2c_board_info __initdata stargate2_i2c_board_info[] = {
}, {
.type = "24c02",
.addr = 0x57,
- .platform_data = &pca9500_eeprom_pdata,
+ .properties = pca9500_eeprom_properties,
}, {
.type = "max1238",
.addr = 0x35,
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index 207dcc2..ab2f892 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -35,7 +35,7 @@
#include <linux/sched.h>
#include <linux/gpio.h>
#include <linux/jiffies.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/platform_data/i2c-pxa.h>
#include <linux/serial_8250.h>
diff --git a/arch/arm/mach-s3c24xx/h1940-bluetooth.c b/arch/arm/mach-s3c24xx/h1940-bluetooth.c
index 46ad20e..186b532 100644
--- a/arch/arm/mach-s3c24xx/h1940-bluetooth.c
+++ b/arch/arm/mach-s3c24xx/h1940-bluetooth.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-1.0
+// SPDX-License-Identifier: GPL-1.0+
//
// Copyright (c) Arnaud Patard <arnaud.patard@rtp-net.org>
//
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index 95753e0..f9fc1f8 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -20,7 +20,7 @@
#include <linux/serial_core.h>
#include <linux/serial_s3c.h>
#include <linux/dm9000.h>
-#include <linux/platform_data/at24.h>
+#include <linux/property.h>
#include <linux/platform_device.h>
#include <linux/gpio_keys.h>
#include <linux/i2c.h>
@@ -481,15 +481,15 @@ static struct platform_device mini2440_audio = {
/*
* I2C devices
*/
-static struct at24_platform_data at24c08 = {
- .byte_len = SZ_8K / 8,
- .page_size = 16,
+static const struct property_entry mini2440_at24_properties[] = {
+ PROPERTY_ENTRY_U32("pagesize", 16),
+ { }
};
static struct i2c_board_info mini2440_i2c_devs[] __initdata = {
{
I2C_BOARD_INFO("24c08", 0x50),
- .platform_data = &at24c08,
+ .properties = mini2440_at24_properties,
},
};
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index f45aed2..406487e 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -37,7 +37,7 @@
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/leds.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
#include "generic.h"
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index fe60cd09..0b67254 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -74,6 +74,10 @@ config ARCH_R8A7745
bool "RZ/G1E (R8A77450)"
select ARCH_RCAR_GEN2
+config ARCH_R8A77470
+ bool "RZ/G1C (R8A77470)"
+ select ARCH_RCAR_GEN2
+
config ARCH_R8A7778
bool "R-Car M1A (R8A77781)"
select ARCH_RCAR_GEN1
@@ -109,6 +113,15 @@ config ARCH_R8A7794
bool "R-Car E2 (R8A77940)"
select ARCH_RCAR_GEN2
+config ARCH_R9A06G032
+ bool "RZ/N1D (R9A06G032)"
+ select ARCH_RZN1
+
+config ARCH_RZN1
+ bool "RZ/N1 (R9A06G0xx) Family"
+ select ARM_AMBA
+ select CPU_V7
+
config ARCH_SH73A0
bool "SH-Mobile AG5 (R8A73A00)"
select ARCH_RMOBILE
diff --git a/arch/arm/mach-shmobile/common.h b/arch/arm/mach-shmobile/common.h
index 43c1ac69..2109f12 100644
--- a/arch/arm/mach-shmobile/common.h
+++ b/arch/arm/mach-shmobile/common.h
@@ -2,7 +2,6 @@
#ifndef __ARCH_MACH_COMMON_H
#define __ARCH_MACH_COMMON_H
-extern void shmobile_init_cntvoff(void);
extern void shmobile_init_delay(void);
extern void shmobile_boot_vector(void);
extern unsigned long shmobile_boot_fn;
diff --git a/arch/arm/mach-shmobile/headsmp-apmu.S b/arch/arm/mach-shmobile/headsmp-apmu.S
index 5672b58..d49ab19 100644
--- a/arch/arm/mach-shmobile/headsmp-apmu.S
+++ b/arch/arm/mach-shmobile/headsmp-apmu.S
@@ -11,29 +11,9 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
-ENTRY(shmobile_init_cntvoff)
- /*
- * CNTVOFF has to be initialized either from non-secure Hypervisor
- * mode or secure Monitor mode with SCR.NS==1. If TrustZone is enabled
- * then it should be handled by the secure code
- */
- cps #MON_MODE
- mrc p15, 0, r1, c1, c1, 0 /* Get Secure Config */
- orr r0, r1, #1
- mcr p15, 0, r0, c1, c1, 0 /* Set Non Secure bit */
- instr_sync
- mov r0, #0
- mcrr p15, 4, r0, r0, c14 /* CNTVOFF = 0 */
- instr_sync
- mcr p15, 0, r1, c1, c1, 0 /* Set Secure bit */
- instr_sync
- cps #SVC_MODE
- ret lr
-ENDPROC(shmobile_init_cntvoff)
-
#ifdef CONFIG_SMP
ENTRY(shmobile_boot_apmu)
- bl shmobile_init_cntvoff
+ bl secure_cntvoff_init
b secondary_startup
ENDPROC(shmobile_boot_apmu)
#endif
diff --git a/arch/arm/mach-shmobile/setup-rcar-gen2.c b/arch/arm/mach-shmobile/setup-rcar-gen2.c
index 5561dbe..88fdc18 100644
--- a/arch/arm/mach-shmobile/setup-rcar-gen2.c
+++ b/arch/arm/mach-shmobile/setup-rcar-gen2.c
@@ -26,6 +26,7 @@
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
+#include <asm/secure_cntvoff.h>
#include "common.h"
#include "rcar-gen2.h"
@@ -70,9 +71,10 @@ void __init rcar_gen2_timer_init(void)
void __iomem *base;
u32 freq;
- shmobile_init_cntvoff();
+ secure_cntvoff_init();
if (of_machine_is_compatible("renesas,r8a7745") ||
+ of_machine_is_compatible("renesas,r8a77470") ||
of_machine_is_compatible("renesas,r8a7792") ||
of_machine_is_compatible("renesas,r8a7794")) {
freq = 260000000 / 8; /* ZS / 8 */
@@ -205,6 +207,7 @@ MACHINE_END
static const char * const rz_g1_boards_compat_dt[] __initconst = {
"renesas,r8a7743",
"renesas,r8a7745",
+ "renesas,r8a77470",
NULL,
};
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index ce53cea..d9c8ecf 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -51,7 +51,7 @@ config MACH_SUN9I
config ARCH_SUNXI_MC_SMP
bool
depends on SMP
- default MACH_SUN9I
+ default MACH_SUN9I || MACH_SUN8I
select ARM_CCI400_PORT_CTRL
select ARM_CPU_SUSPEND
diff --git a/arch/arm/mach-sunxi/Makefile b/arch/arm/mach-sunxi/Makefile
index 7de9cc2..71429aa 100644
--- a/arch/arm/mach-sunxi/Makefile
+++ b/arch/arm/mach-sunxi/Makefile
@@ -1,5 +1,5 @@
CFLAGS_mc_smp.o += -march=armv7-a
obj-$(CONFIG_ARCH_SUNXI) += sunxi.o
-obj-$(CONFIG_ARCH_SUNXI_MC_SMP) += mc_smp.o
+obj-$(CONFIG_ARCH_SUNXI_MC_SMP) += mc_smp.o headsmp.o
obj-$(CONFIG_SMP) += platsmp.o
diff --git a/arch/arm/mach-sunxi/headsmp.S b/arch/arm/mach-sunxi/headsmp.S
new file mode 100644
index 0000000..32d76be
--- /dev/null
+++ b/arch/arm/mach-sunxi/headsmp.S
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (c) 2018 Chen-Yu Tsai
+ * Copyright (c) 2018 Bootlin
+ *
+ * Chen-Yu Tsai <wens@csie.org>
+ * Mylène Josserand <mylene.josserand@bootlin.com>
+ *
+ * SMP support for sunxi based systems with Cortex A7/A15
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/cputype.h>
+
+ENTRY(sunxi_mc_smp_cluster_cache_enable)
+ .arch armv7-a
+ /*
+ * Enable cluster-level coherency, in preparation for turning on the MMU.
+ *
+ * Also enable regional clock gating and L2 data latency settings for
+ * Cortex-A15. These settings are from the vendor kernel.
+ */
+ mrc p15, 0, r1, c0, c0, 0
+ movw r2, #(ARM_CPU_PART_MASK & 0xffff)
+ movt r2, #(ARM_CPU_PART_MASK >> 16)
+ and r1, r1, r2
+ movw r2, #(ARM_CPU_PART_CORTEX_A15 & 0xffff)
+ movt r2, #(ARM_CPU_PART_CORTEX_A15 >> 16)
+ cmp r1, r2
+ bne not_a15
+
+ /* The following is Cortex-A15 specific */
+
+ /* ACTLR2: Enable CPU regional clock gates */
+ mrc p15, 1, r1, c15, c0, 4
+ orr r1, r1, #(0x1 << 31)
+ mcr p15, 1, r1, c15, c0, 4
+
+ /* L2ACTLR */
+ mrc p15, 1, r1, c15, c0, 0
+ /* Enable L2, GIC, and Timer regional clock gates */
+ orr r1, r1, #(0x1 << 26)
+ /* Disable clean/evict from being pushed to external */
+ orr r1, r1, #(0x1<<3)
+ mcr p15, 1, r1, c15, c0, 0
+
+ /* L2CTRL: L2 data RAM latency */
+ mrc p15, 1, r1, c9, c0, 2
+ bic r1, r1, #(0x7 << 0)
+ orr r1, r1, #(0x3 << 0)
+ mcr p15, 1, r1, c9, c0, 2
+
+ /* End of Cortex-A15 specific setup */
+ not_a15:
+
+ /* Get value of sunxi_mc_smp_first_comer */
+ adr r1, first
+ ldr r0, [r1]
+ ldr r0, [r1, r0]
+
+ /* Skip cci_enable_port_for_self if not first comer */
+ cmp r0, #0
+ bxeq lr
+ b cci_enable_port_for_self
+
+ .align 2
+ first: .word sunxi_mc_smp_first_comer - .
+ENDPROC(sunxi_mc_smp_cluster_cache_enable)
+
+ENTRY(sunxi_mc_smp_secondary_startup)
+ bl sunxi_mc_smp_cluster_cache_enable
+ bl secure_cntvoff_init
+ b secondary_startup
+ENDPROC(sunxi_mc_smp_secondary_startup)
+
+ENTRY(sunxi_mc_smp_resume)
+ bl sunxi_mc_smp_cluster_cache_enable
+ b cpu_resume
+ENDPROC(sunxi_mc_smp_resume)
diff --git a/arch/arm/mach-sunxi/mc_smp.c b/arch/arm/mach-sunxi/mc_smp.c
index c0246ec..b4037b6 100644
--- a/arch/arm/mach-sunxi/mc_smp.c
+++ b/arch/arm/mach-sunxi/mc_smp.c
@@ -55,22 +55,35 @@
#define CPUCFG_CX_RST_CTRL_L2_RST BIT(8)
#define CPUCFG_CX_RST_CTRL_CX_RST(n) BIT(4 + (n))
#define CPUCFG_CX_RST_CTRL_CORE_RST(n) BIT(n)
+#define CPUCFG_CX_RST_CTRL_CORE_RST_ALL (0xf << 0)
#define PRCM_CPU_PO_RST_CTRL(c) (0x4 + 0x4 * (c))
#define PRCM_CPU_PO_RST_CTRL_CORE(n) BIT(n)
#define PRCM_CPU_PO_RST_CTRL_CORE_ALL 0xf
#define PRCM_PWROFF_GATING_REG(c) (0x100 + 0x4 * (c))
-#define PRCM_PWROFF_GATING_REG_CLUSTER BIT(4)
+/* The power off register for clusters are different from a80 and a83t */
+#define PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I BIT(0)
+#define PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I BIT(4)
#define PRCM_PWROFF_GATING_REG_CORE(n) BIT(n)
#define PRCM_PWR_SWITCH_REG(c, cpu) (0x140 + 0x10 * (c) + 0x4 * (cpu))
#define PRCM_CPU_SOFT_ENTRY_REG 0x164
+/* R_CPUCFG registers, specific to sun8i-a83t */
+#define R_CPUCFG_CLUSTER_PO_RST_CTRL(c) (0x30 + (c) * 0x4)
+#define R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(n) BIT(n)
+#define R_CPUCFG_CPU_SOFT_ENTRY_REG 0x01a4
+
#define CPU0_SUPPORT_HOTPLUG_MAGIC0 0xFA50392F
#define CPU0_SUPPORT_HOTPLUG_MAGIC1 0x790DCA3A
static void __iomem *cpucfg_base;
static void __iomem *prcm_base;
static void __iomem *sram_b_smp_base;
+static void __iomem *r_cpucfg_base;
+
+extern void sunxi_mc_smp_secondary_startup(void);
+extern void sunxi_mc_smp_resume(void);
+static bool is_a83t;
static bool sunxi_core_is_cortex_a15(unsigned int core, unsigned int cluster)
{
@@ -157,6 +170,16 @@ static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster)
reg &= ~PRCM_CPU_PO_RST_CTRL_CORE(cpu);
writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
+ if (is_a83t) {
+ /* assert cpu power-on reset */
+ reg = readl(r_cpucfg_base +
+ R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster));
+ reg &= ~(R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(cpu));
+ writel(reg, r_cpucfg_base +
+ R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster));
+ udelay(10);
+ }
+
/* Cortex-A7: hold L1 reset disable signal low */
if (!sunxi_core_is_cortex_a15(cpu, cluster)) {
reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG0(cluster));
@@ -180,17 +203,38 @@ static int sunxi_cpu_powerup(unsigned int cpu, unsigned int cluster)
/* open power switch */
sunxi_cpu_power_switch_set(cpu, cluster, true);
+ /* Handle A83T bit swap */
+ if (is_a83t) {
+ if (cpu == 0)
+ cpu = 4;
+ }
+
/* clear processor power gate */
reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster));
reg &= ~PRCM_PWROFF_GATING_REG_CORE(cpu);
writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster));
udelay(20);
+ /* Handle A83T bit swap */
+ if (is_a83t) {
+ if (cpu == 4)
+ cpu = 0;
+ }
+
/* de-assert processor power-on reset */
reg = readl(prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
reg |= PRCM_CPU_PO_RST_CTRL_CORE(cpu);
writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
+ if (is_a83t) {
+ reg = readl(r_cpucfg_base +
+ R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster));
+ reg |= R_CPUCFG_CLUSTER_PO_RST_CTRL_CORE(cpu);
+ writel(reg, r_cpucfg_base +
+ R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster));
+ udelay(10);
+ }
+
/* de-assert all processor resets */
reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
reg |= CPUCFG_CX_RST_CTRL_DBG_RST(cpu);
@@ -212,6 +256,14 @@ static int sunxi_cluster_powerup(unsigned int cluster)
if (cluster >= SUNXI_NR_CLUSTERS)
return -EINVAL;
+ /* For A83T, assert cluster cores resets */
+ if (is_a83t) {
+ reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
+ reg &= ~CPUCFG_CX_RST_CTRL_CORE_RST_ALL; /* Core Reset */
+ writel(reg, cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
+ udelay(10);
+ }
+
/* assert ACINACTM */
reg = readl(cpucfg_base + CPUCFG_CX_CTRL_REG1(cluster));
reg |= CPUCFG_CX_CTRL_REG1_ACINACTM;
@@ -222,6 +274,16 @@ static int sunxi_cluster_powerup(unsigned int cluster)
reg &= ~PRCM_CPU_PO_RST_CTRL_CORE_ALL;
writel(reg, prcm_base + PRCM_CPU_PO_RST_CTRL(cluster));
+ /* assert cluster cores resets */
+ if (is_a83t) {
+ reg = readl(r_cpucfg_base +
+ R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster));
+ reg &= ~CPUCFG_CX_RST_CTRL_CORE_RST_ALL;
+ writel(reg, r_cpucfg_base +
+ R_CPUCFG_CLUSTER_PO_RST_CTRL(cluster));
+ udelay(10);
+ }
+
/* assert cluster resets */
reg = readl(cpucfg_base + CPUCFG_CX_RST_CTRL(cluster));
reg &= ~CPUCFG_CX_RST_CTRL_DBG_SOC_RST;
@@ -252,7 +314,10 @@ static int sunxi_cluster_powerup(unsigned int cluster)
/* clear cluster power gate */
reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster));
- reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER;
+ if (is_a83t)
+ reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I;
+ else
+ reg &= ~PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I;
writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster));
udelay(20);
@@ -300,74 +365,7 @@ static void sunxi_cluster_cache_disable_without_axi(void)
}
static int sunxi_mc_smp_cpu_table[SUNXI_NR_CLUSTERS][SUNXI_CPUS_PER_CLUSTER];
-static int sunxi_mc_smp_first_comer;
-
-/*
- * Enable cluster-level coherency, in preparation for turning on the MMU.
- *
- * Also enable regional clock gating and L2 data latency settings for
- * Cortex-A15. These settings are from the vendor kernel.
- */
-static void __naked sunxi_mc_smp_cluster_cache_enable(void)
-{
- asm volatile (
- "mrc p15, 0, r1, c0, c0, 0\n"
- "movw r2, #" __stringify(ARM_CPU_PART_MASK & 0xffff) "\n"
- "movt r2, #" __stringify(ARM_CPU_PART_MASK >> 16) "\n"
- "and r1, r1, r2\n"
- "movw r2, #" __stringify(ARM_CPU_PART_CORTEX_A15 & 0xffff) "\n"
- "movt r2, #" __stringify(ARM_CPU_PART_CORTEX_A15 >> 16) "\n"
- "cmp r1, r2\n"
- "bne not_a15\n"
-
- /* The following is Cortex-A15 specific */
-
- /* ACTLR2: Enable CPU regional clock gates */
- "mrc p15, 1, r1, c15, c0, 4\n"
- "orr r1, r1, #(0x1<<31)\n"
- "mcr p15, 1, r1, c15, c0, 4\n"
-
- /* L2ACTLR */
- "mrc p15, 1, r1, c15, c0, 0\n"
- /* Enable L2, GIC, and Timer regional clock gates */
- "orr r1, r1, #(0x1<<26)\n"
- /* Disable clean/evict from being pushed to external */
- "orr r1, r1, #(0x1<<3)\n"
- "mcr p15, 1, r1, c15, c0, 0\n"
-
- /* L2CTRL: L2 data RAM latency */
- "mrc p15, 1, r1, c9, c0, 2\n"
- "bic r1, r1, #(0x7<<0)\n"
- "orr r1, r1, #(0x3<<0)\n"
- "mcr p15, 1, r1, c9, c0, 2\n"
-
- /* End of Cortex-A15 specific setup */
- "not_a15:\n"
-
- /* Get value of sunxi_mc_smp_first_comer */
- "adr r1, first\n"
- "ldr r0, [r1]\n"
- "ldr r0, [r1, r0]\n"
-
- /* Skip cci_enable_port_for_self if not first comer */
- "cmp r0, #0\n"
- "bxeq lr\n"
- "b cci_enable_port_for_self\n"
-
- ".align 2\n"
- "first: .word sunxi_mc_smp_first_comer - .\n"
- );
-}
-
-static void __naked sunxi_mc_smp_secondary_startup(void)
-{
- asm volatile(
- "bl sunxi_mc_smp_cluster_cache_enable\n"
- "b secondary_startup"
- /* Let compiler know about sunxi_mc_smp_cluster_cache_enable */
- :: "i" (sunxi_mc_smp_cluster_cache_enable)
- );
-}
+int sunxi_mc_smp_first_comer;
static DEFINE_SPINLOCK(boot_lock);
@@ -516,7 +514,10 @@ static int sunxi_cluster_powerdown(unsigned int cluster)
/* gate cluster power */
pr_debug("%s: gate cluster power\n", __func__);
reg = readl(prcm_base + PRCM_PWROFF_GATING_REG(cluster));
- reg |= PRCM_PWROFF_GATING_REG_CLUSTER;
+ if (is_a83t)
+ reg |= PRCM_PWROFF_GATING_REG_CLUSTER_SUN8I;
+ else
+ reg |= PRCM_PWROFF_GATING_REG_CLUSTER_SUN9I;
writel(reg, prcm_base + PRCM_PWROFF_GATING_REG(cluster));
udelay(20);
@@ -598,8 +599,12 @@ out:
return !ret;
}
-static bool sunxi_mc_smp_cpu_can_disable(unsigned int __unused)
+static bool sunxi_mc_smp_cpu_can_disable(unsigned int cpu)
{
+ /* CPU0 hotplug not handled for sun8i-a83t */
+ if (is_a83t)
+ if (cpu == 0)
+ return false;
return true;
}
#endif
@@ -637,16 +642,6 @@ static bool __init sunxi_mc_smp_cpu_table_init(void)
*/
typedef typeof(cpu_reset) phys_reset_t;
-static void __init __naked sunxi_mc_smp_resume(void)
-{
- asm volatile(
- "bl sunxi_mc_smp_cluster_cache_enable\n"
- "b cpu_resume"
- /* Let compiler know about sunxi_mc_smp_cluster_cache_enable */
- :: "i" (sunxi_mc_smp_cluster_cache_enable)
- );
-}
-
static int __init nocache_trampoline(unsigned long __unused)
{
phys_reset_t phys_reset;
@@ -692,12 +687,14 @@ struct sunxi_mc_smp_nodes {
struct device_node *prcm_node;
struct device_node *cpucfg_node;
struct device_node *sram_node;
+ struct device_node *r_cpucfg_node;
};
/* This structure holds SoC-specific bits tied to an enable-method string. */
struct sunxi_mc_smp_data {
const char *enable_method;
int (*get_smp_nodes)(struct sunxi_mc_smp_nodes *nodes);
+ bool is_a83t;
};
static void __init sunxi_mc_smp_put_nodes(struct sunxi_mc_smp_nodes *nodes)
@@ -705,6 +702,7 @@ static void __init sunxi_mc_smp_put_nodes(struct sunxi_mc_smp_nodes *nodes)
of_node_put(nodes->prcm_node);
of_node_put(nodes->cpucfg_node);
of_node_put(nodes->sram_node);
+ of_node_put(nodes->r_cpucfg_node);
memset(nodes, 0, sizeof(*nodes));
}
@@ -734,11 +732,42 @@ static int __init sun9i_a80_get_smp_nodes(struct sunxi_mc_smp_nodes *nodes)
return 0;
}
+static int __init sun8i_a83t_get_smp_nodes(struct sunxi_mc_smp_nodes *nodes)
+{
+ nodes->prcm_node = of_find_compatible_node(NULL, NULL,
+ "allwinner,sun8i-a83t-r-ccu");
+ if (!nodes->prcm_node) {
+ pr_err("%s: PRCM not available\n", __func__);
+ return -ENODEV;
+ }
+
+ nodes->cpucfg_node = of_find_compatible_node(NULL, NULL,
+ "allwinner,sun8i-a83t-cpucfg");
+ if (!nodes->cpucfg_node) {
+ pr_err("%s: CPUCFG not available\n", __func__);
+ return -ENODEV;
+ }
+
+ nodes->r_cpucfg_node = of_find_compatible_node(NULL, NULL,
+ "allwinner,sun8i-a83t-r-cpucfg");
+ if (!nodes->r_cpucfg_node) {
+ pr_err("%s: RCPUCFG not available\n", __func__);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static const struct sunxi_mc_smp_data sunxi_mc_smp_data[] __initconst = {
{
.enable_method = "allwinner,sun9i-a80-smp",
.get_smp_nodes = sun9i_a80_get_smp_nodes,
},
+ {
+ .enable_method = "allwinner,sun8i-a83t-smp",
+ .get_smp_nodes = sun8i_a83t_get_smp_nodes,
+ .is_a83t = true,
+ },
};
static int __init sunxi_mc_smp_init(void)
@@ -746,6 +775,7 @@ static int __init sunxi_mc_smp_init(void)
struct sunxi_mc_smp_nodes nodes = { 0 };
struct device_node *node;
struct resource res;
+ void __iomem *addr;
int i, ret;
/*
@@ -771,6 +801,8 @@ static int __init sunxi_mc_smp_init(void)
break;
}
+ is_a83t = sunxi_mc_smp_data[i].is_a83t;
+
of_node_put(node);
if (ret)
return -ENODEV;
@@ -808,12 +840,23 @@ static int __init sunxi_mc_smp_init(void)
goto err_unmap_prcm;
}
- sram_b_smp_base = of_io_request_and_map(nodes.sram_node, 0,
- "sunxi-mc-smp");
- if (IS_ERR(sram_b_smp_base)) {
- ret = PTR_ERR(sram_b_smp_base);
- pr_err("%s: failed to map secure SRAM\n", __func__);
- goto err_unmap_release_cpucfg;
+ if (is_a83t) {
+ r_cpucfg_base = of_io_request_and_map(nodes.r_cpucfg_node,
+ 0, "sunxi-mc-smp");
+ if (IS_ERR(r_cpucfg_base)) {
+ ret = PTR_ERR(r_cpucfg_base);
+ pr_err("%s: failed to map R-CPUCFG registers\n",
+ __func__);
+ goto err_unmap_release_cpucfg;
+ }
+ } else {
+ sram_b_smp_base = of_io_request_and_map(nodes.sram_node, 0,
+ "sunxi-mc-smp");
+ if (IS_ERR(sram_b_smp_base)) {
+ ret = PTR_ERR(sram_b_smp_base);
+ pr_err("%s: failed to map secure SRAM\n", __func__);
+ goto err_unmap_release_cpucfg;
+ }
}
/* Configure CCI-400 for boot cluster */
@@ -821,15 +864,18 @@ static int __init sunxi_mc_smp_init(void)
if (ret) {
pr_err("%s: failed to configure boot cluster: %d\n",
__func__, ret);
- goto err_unmap_release_secure_sram;
+ goto err_unmap_release_sram_rcpucfg;
}
/* We don't need the device nodes anymore */
sunxi_mc_smp_put_nodes(&nodes);
/* Set the hardware entry point address */
- writel(__pa_symbol(sunxi_mc_smp_secondary_startup),
- prcm_base + PRCM_CPU_SOFT_ENTRY_REG);
+ if (is_a83t)
+ addr = r_cpucfg_base + R_CPUCFG_CPU_SOFT_ENTRY_REG;
+ else
+ addr = prcm_base + PRCM_CPU_SOFT_ENTRY_REG;
+ writel(__pa_symbol(sunxi_mc_smp_secondary_startup), addr);
/* Actually enable multi cluster SMP */
smp_set_ops(&sunxi_mc_smp_smp_ops);
@@ -838,9 +884,14 @@ static int __init sunxi_mc_smp_init(void)
return 0;
-err_unmap_release_secure_sram:
- iounmap(sram_b_smp_base);
- of_address_to_resource(nodes.sram_node, 0, &res);
+err_unmap_release_sram_rcpucfg:
+ if (is_a83t) {
+ iounmap(r_cpucfg_base);
+ of_address_to_resource(nodes.r_cpucfg_node, 0, &res);
+ } else {
+ iounmap(sram_b_smp_base);
+ of_address_to_resource(nodes.sram_node, 0, &res);
+ }
release_mem_region(res.start, resource_size(&res));
err_unmap_release_cpucfg:
iounmap(cpucfg_base);
diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
index 5e9602c..de4b0e9 100644
--- a/arch/arm/mach-sunxi/sunxi.c
+++ b/arch/arm/mach-sunxi/sunxi.c
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <asm/mach/arch.h>
+#include <asm/secure_cntvoff.h>
static const char * const sunxi_board_dt_compat[] = {
"allwinner,sun4i-a10",
@@ -62,7 +63,6 @@ MACHINE_END
static const char * const sun8i_board_dt_compat[] = {
"allwinner,sun8i-a23",
"allwinner,sun8i-a33",
- "allwinner,sun8i-a83t",
"allwinner,sun8i-h2-plus",
"allwinner,sun8i-h3",
"allwinner,sun8i-r40",
@@ -75,6 +75,24 @@ DT_MACHINE_START(SUN8I_DT, "Allwinner sun8i Family")
.dt_compat = sun8i_board_dt_compat,
MACHINE_END
+static void __init sun8i_a83t_cntvoff_init(void)
+{
+#ifdef CONFIG_SMP
+ secure_cntvoff_init();
+#endif
+}
+
+static const char * const sun8i_a83t_cntvoff_board_dt_compat[] = {
+ "allwinner,sun8i-a83t",
+ NULL,
+};
+
+DT_MACHINE_START(SUN8I_A83T_CNTVOFF_DT, "Allwinner A83t board")
+ .init_early = sun8i_a83t_cntvoff_init,
+ .init_time = sun6i_timer_init,
+ .dt_compat = sun8i_a83t_cntvoff_board_dt_compat,
+MACHINE_END
+
static const char * const sun9i_board_dt_compat[] = {
"allwinner,sun9i-a80",
NULL,
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index 02e712d..f9587be 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -97,6 +97,10 @@ static void __init tegra_dt_init_late(void)
if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
of_machine_is_compatible("compal,paz00"))
tegra_paz00_wifikill_init();
+
+ if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) &&
+ of_machine_is_compatible("nvidia,tegra20"))
+ platform_device_register_simple("tegra20-cpufreq", -1, NULL, 0);
}
static const char * const tegra_dt_board_compat[] = {
diff --git a/arch/arm/mach-ux500/Kconfig b/arch/arm/mach-ux500/Kconfig
index f98332e..c1086eb 100644
--- a/arch/arm/mach-ux500/Kconfig
+++ b/arch/arm/mach-ux500/Kconfig
@@ -9,64 +9,33 @@ menuconfig ARCH_U8500
select ARM_ERRATA_764369 if SMP
select ARM_GIC
select CACHE_L2X0
+ select CLKSRC_DBX500_PRCMU
select CLKSRC_NOMADIK_MTU
select GPIOLIB
select HAVE_ARM_SCU if SMP
select HAVE_ARM_TWD if SMP
+ select I2C
+ select I2C_NOMADIK
+ select MFD_DB8500_PRCMU
select PINCTRL
+ select PINCTRL_AB8500
+ select PINCTRL_AB8505
select PINCTRL_ABX500
+ select PINCTRL_DB8500
select PINCTRL_NOMADIK
select PL310_ERRATA_753970 if CACHE_L2X0
- help
- Support for ST-Ericsson's Ux500 architecture
-
-if ARCH_U8500
-
-config UX500_SOC_DB8500
- bool
- select MFD_DB8500_PRCMU
- select PINCTRL_DB8500
- select PINCTRL_DB8540
- select PINCTRL_AB8500
- select PINCTRL_AB8505
- select PINCTRL_AB9540
- select PINCTRL_AB8540
- select REGULATOR
- select REGULATOR_DB8500_PRCMU
- select CLKSRC_DBX500_PRCMU
select PM_GENERIC_DOMAINS if PM
-
-config MACH_MOP500
- bool "U8500 Development platform, MOP500 versions"
- select I2C
- select I2C_NOMADIK
select REGULATOR
+ select REGULATOR_DB8500_PRCMU
select REGULATOR_FIXED_VOLTAGE
select SOC_BUS
- select UX500_SOC_DB8500
help
- Include support for the MOP500 development platform.
-
-config MACH_HREFV60
- bool "U8500 Development platform, HREFv60 version"
- select MACH_MOP500
- help
- Include support for the HREFv60 new development platform.
- Includes HREFv70, v71 etc.
+ Support for ST-Ericsson's Ux500 architecture
-config MACH_SNOWBALL
- bool "U8500 Snowball platform"
- select MACH_MOP500
- help
- Include support for the snowball development platform.
+if ARCH_U8500
-config UX500_AUTO_PLATFORM
+config UX500_SOC_DB8500
def_bool y
- select MACH_MOP500
- help
- At least one platform needs to be selected in order to build
- a working kernel. If everything else is disabled, this
- automatically enables MACH_MOP500.
config UX500_DEBUG_UART
int "Ux500 UART to use for low-level debug"
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 36cd23c..389ecf6 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -111,11 +111,6 @@ static void ux500_restart(enum reboot_mode mode, const char *cmd)
prcmu_system_reset(0);
}
-static struct of_dev_auxdata u8540_auxdata_lookup[] __initdata = {
- OF_DEV_AUXDATA("stericsson,db8500-prcmu", 0x80157000, "db8500-prcmu", NULL),
- {},
-};
-
static const struct of_device_id u8500_local_bus_nodes[] = {
/* only create devices below soc node */
{ .compatible = "stericsson,db8500", },
@@ -129,20 +124,13 @@ static void __init u8500_init_machine(void)
/* Initialize ux500 power domains */
ux500_pm_domains_init();
- /* automatically probe child nodes of dbx5x0 devices */
- if (of_machine_is_compatible("st-ericsson,u8540"))
- of_platform_populate(NULL, u8500_local_bus_nodes,
- u8540_auxdata_lookup, NULL);
- else
- of_platform_populate(NULL, u8500_local_bus_nodes,
- NULL, NULL);
+ of_platform_populate(NULL, u8500_local_bus_nodes,
+ NULL, NULL);
}
static const char * stericsson_dt_platform_compat[] = {
"st-ericsson,u8500",
- "st-ericsson,u8540",
"st-ericsson,u9500",
- "st-ericsson,u9540",
NULL,
};
diff --git a/arch/arm/mach-ux500/db8500-regs.h b/arch/arm/mach-ux500/db8500-regs.h
index 2739955..3d6e195 100644
--- a/arch/arm/mach-ux500/db8500-regs.h
+++ b/arch/arm/mach-ux500/db8500-regs.h
@@ -41,10 +41,6 @@
/* ASIC ID is at 0xbf4 offset within this region */
#define U8500_ASIC_ID_BASE 0x9001D000
-#define U9540_BOOT_ROM_BASE 0xFFFE0000
-/* ASIC ID is at 0xbf4 offset within this region */
-#define U9540_ASIC_ID_BASE 0xFFFFD000
-
#define U8500_PER6_BASE 0xa03c0000
#define U8500_PER7_BASE 0xa03d0000
#define U8500_PER5_BASE 0xa03e0000
diff --git a/arch/arm/mach-vexpress/spc.c b/arch/arm/mach-vexpress/spc.c
index 21c0642..0f5381d 100644
--- a/arch/arm/mach-vexpress/spc.c
+++ b/arch/arm/mach-vexpress/spc.c
@@ -403,7 +403,7 @@ static int ve_spc_populate_opps(uint32_t cluster)
uint32_t data = 0, off, ret, idx;
struct ve_spc_opp *opps;
- opps = kzalloc(sizeof(*opps) * MAX_OPPS, GFP_KERNEL);
+ opps = kcalloc(MAX_OPPS, sizeof(*opps), GFP_KERNEL);
if (!opps)
return -ENOMEM;
diff --git a/arch/arm/mm/cache-b15-rac.c b/arch/arm/mm/cache-b15-rac.c
index d9586ba..c6ed148 100644
--- a/arch/arm/mm/cache-b15-rac.c
+++ b/arch/arm/mm/cache-b15-rac.c
@@ -33,7 +33,10 @@ extern void v7_flush_kern_cache_all(void);
#define RAC_CPU_SHIFT (8)
#define RACCFG_MASK (0xff)
#define RAC_CONFIG1_REG (0x7c)
-#define RAC_FLUSH_REG (0x80)
+/* Brahma-B15 is a quad-core only design */
+#define B15_RAC_FLUSH_REG (0x80)
+/* Brahma-B53 is an octo-core design */
+#define B53_RAC_FLUSH_REG (0x84)
#define FLUSH_RAC (1 << 0)
/* Bitmask to enable instruction and data prefetching with a 256-bytes stride */
@@ -52,6 +55,7 @@ static void __iomem *b15_rac_base;
static DEFINE_SPINLOCK(rac_lock);
static u32 rac_config0_reg;
+static u32 rac_flush_offset;
/* Initialization flag to avoid checking for b15_rac_base, and to prevent
* multi-platform kernels from crashing here as well.
@@ -70,14 +74,14 @@ static inline void __b15_rac_flush(void)
{
u32 reg;
- __raw_writel(FLUSH_RAC, b15_rac_base + RAC_FLUSH_REG);
+ __raw_writel(FLUSH_RAC, b15_rac_base + rac_flush_offset);
do {
/* This dmb() is required to force the Bus Interface Unit
* to clean oustanding writes, and forces an idle cycle
* to be inserted.
*/
dmb();
- reg = __raw_readl(b15_rac_base + RAC_FLUSH_REG);
+ reg = __raw_readl(b15_rac_base + rac_flush_offset);
} while (reg & FLUSH_RAC);
}
@@ -287,7 +291,7 @@ static struct syscore_ops b15_rac_syscore_ops = {
static int __init b15_rac_init(void)
{
- struct device_node *dn;
+ struct device_node *dn, *cpu_dn;
int ret = 0, cpu;
u32 reg, en_mask = 0;
@@ -305,6 +309,24 @@ static int __init b15_rac_init(void)
goto out;
}
+ cpu_dn = of_get_cpu_node(0, NULL);
+ if (!cpu_dn) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (of_device_is_compatible(cpu_dn, "brcm,brahma-b15"))
+ rac_flush_offset = B15_RAC_FLUSH_REG;
+ else if (of_device_is_compatible(cpu_dn, "brcm,brahma-b53"))
+ rac_flush_offset = B53_RAC_FLUSH_REG;
+ else {
+ pr_err("Unsupported CPU\n");
+ of_node_put(cpu_dn);
+ ret = -EINVAL;
+ goto out;
+ }
+ of_node_put(cpu_dn);
+
ret = register_reboot_notifier(&b15_rac_reboot_nb);
if (ret) {
pr_err("failed to register reboot notifier\n");
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index af27f1c..be0fa7e 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2162,8 +2162,8 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, u64 size)
goto err;
mapping->bitmap_size = bitmap_size;
- mapping->bitmaps = kzalloc(extensions * sizeof(unsigned long *),
- GFP_KERNEL);
+ mapping->bitmaps = kcalloc(extensions, sizeof(unsigned long *),
+ GFP_KERNEL);
if (!mapping->bitmaps)
goto err2;
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c
index 61e281c..a1606d9 100644
--- a/arch/arm/mm/pgd.c
+++ b/arch/arm/mm/pgd.c
@@ -20,7 +20,7 @@
#include "mm.h"
#ifdef CONFIG_ARM_LPAE
-#define __pgd_alloc() kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL)
+#define __pgd_alloc() kmalloc_array(PTRS_PER_PGD, sizeof(pgd_t), GFP_KERNEL)
#define __pgd_free(pgd) kfree(pgd)
#else
#define __pgd_alloc() (pgd_t *)__get_free_pages(GFP_KERNEL, 2)
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index afc1a1d..c0a242c 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -115,16 +115,6 @@ config OMAP_SERIAL_WAKE
to data on the serial RX line. This allows you to wake the
system from serial console.
-choice
- prompt "OMAP PM layer selection"
- depends on ARCH_OMAP
- default OMAP_PM_NOOP
-
-config OMAP_PM_NOOP
- bool "No-op/debug PM layer"
-
-endchoice
-
endmenu
endif
diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c
index 42bac8d..2da3573 100644
--- a/arch/arm/plat-samsung/adc.c
+++ b/arch/arm/plat-samsung/adc.c
@@ -413,8 +413,7 @@ static int s3c_adc_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int s3c_adc_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct adc_device *adc = platform_get_drvdata(pdev);
+ struct adc_device *adc = dev_get_drvdata(dev);
unsigned long flags;
u32 con;
diff --git a/arch/arm/plat-samsung/include/plat/map-s5p.h b/arch/arm/plat-samsung/include/plat/map-s5p.h
index f5769e9..d69a0ca 100644
--- a/arch/arm/plat-samsung/include/plat/map-s5p.h
+++ b/arch/arm/plat-samsung/include/plat/map-s5p.h
@@ -11,10 +11,6 @@
#define S5P_VA_CHIPID S3C_ADDR(0x02000000)
-#define S5P_VA_COREPERI_BASE S3C_ADDR(0x02800000)
-#define S5P_VA_COREPERI(x) (S5P_VA_COREPERI_BASE + (x))
-#define S5P_VA_SCU S5P_VA_COREPERI(0x0)
-
#define VA_VIC(x) (S3C_VA_IRQ + ((x) * 0x10000))
#define VA_VIC0 VA_VIC(0)
#define VA_VIC1 VA_VIC(1)
diff --git a/arch/arm/probes/kprobes/test-core.c b/arch/arm/probes/kprobes/test-core.c
index 9ed0129..14db141 100644
--- a/arch/arm/probes/kprobes/test-core.c
+++ b/arch/arm/probes/kprobes/test-core.c
@@ -766,8 +766,9 @@ static int coverage_start_fn(const struct decode_header *h, void *args)
static int coverage_start(const union decode_item *table)
{
- coverage.base = kmalloc(MAX_COVERAGE_ENTRIES *
- sizeof(struct coverage_entry), GFP_KERNEL);
+ coverage.base = kmalloc_array(MAX_COVERAGE_ENTRIES,
+ sizeof(struct coverage_entry),
+ GFP_KERNEL);
coverage.num_entries = 0;
coverage.nesting = 0;
return table_iter(table, coverage_start_fn, &coverage);
diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile
index bb411821..f4efff9 100644
--- a/arch/arm/vdso/Makefile
+++ b/arch/arm/vdso/Makefile
@@ -30,6 +30,9 @@ CFLAGS_vgettimeofday.o = -O2
# Disable gcov profiling for VDSO code
GCOV_PROFILE := n
+# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
+KCOV_INSTRUMENT := n
+
# Force dependency
$(obj)/vdso.o : $(obj)/vdso.so
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 8073625..07060e5 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -59,6 +59,9 @@ struct xen_memory_region xen_extra_mem[XEN_EXTRA_MEM_MAX_REGIONS] __initdata;
static __read_mostly unsigned int xen_events_irq;
+uint32_t xen_start_flags;
+EXPORT_SYMBOL(xen_start_flags);
+
int xen_remap_domain_gfn_array(struct vm_area_struct *vma,
unsigned long addr,
xen_pfn_t *gfn, int nr,
@@ -293,9 +296,7 @@ void __init xen_early_init(void)
xen_setup_features();
if (xen_feature(XENFEAT_dom0))
- xen_start_info->flags |= SIF_INITDOMAIN|SIF_PRIVILEGED;
- else
- xen_start_info->flags &= ~(SIF_INITDOMAIN|SIF_PRIVILEGED);
+ xen_start_flags |= SIF_INITDOMAIN|SIF_PRIVILEGED;
if (!console_set_on_cmdline && !xen_initial_domain())
add_preferred_console("hvc", 0, NULL);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 9795b59..42c090c 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -46,6 +46,7 @@ config ARM64
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_SUPPORTS_MEMORY_FAILURE
select ARCH_SUPPORTS_ATOMIC_RMW
+ select ARCH_SUPPORTS_INT128 if GCC_VERSION >= 50000 || CC_IS_CLANG
select ARCH_SUPPORTS_NUMA_BALANCING
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
select ARCH_WANT_FRAME_POINTERS
@@ -102,7 +103,6 @@ config ARM64
select HAVE_ARM_SMCCC
select HAVE_EBPF_JIT
select HAVE_C_RECORDMCOUNT
- select HAVE_CC_STACKPROTECTOR
select HAVE_CMPXCHG_DOUBLE
select HAVE_CMPXCHG_LOCAL
select HAVE_CONTEXT_TRACKING
@@ -127,6 +127,7 @@ config ARM64
select HAVE_PERF_USER_STACK_DUMP
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RCU_TABLE_FREE
+ select HAVE_STACKPROTECTOR
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
select HAVE_KRETPROBES
@@ -1128,6 +1129,7 @@ endmenu
config ARM64_SVE
bool "ARM Scalable Vector Extension support"
default y
+ depends on !KVM || ARM64_VHE
help
The Scalable Vector Extension (SVE) is an extension to the AArch64
execution state which complements and extends the SIMD functionality
@@ -1153,6 +1155,12 @@ config ARM64_SVE
booting the kernel. If unsure and you are not observing these
symptoms, you should assume that it is safe to say Y.
+ CPUs that support SVE are architecturally required to support the
+ Virtualization Host Extensions (VHE), so the kernel makes no
+ provision for supporting SVE alongside KVM without VHE enabled.
+ Thus, you will need to enable CONFIG_ARM64_VHE if you want to support
+ KVM in the same kernel image.
+
config ARM64_MODULE_PLTS
bool
select HAVE_MOD_ARCH_SPECIFIC
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 2b1535c..d5aeac3 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -208,6 +208,12 @@ config ARCH_R8A77980
help
This enables support for the Renesas R-Car V3H SoC.
+config ARCH_R8A77990
+ bool "Renesas R-Car E3 SoC Platform"
+ depends on ARCH_RENESAS
+ help
+ This enables support for the Renesas R-Car E3 SoC.
+
config ARCH_R8A77995
bool "Renesas R-Car D3 SoC Platform"
depends on ARCH_RENESAS
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 3c353b4..4527226 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -56,12 +56,6 @@ KBUILD_AFLAGS += $(lseinstr) $(brokengasinst)
KBUILD_CFLAGS += $(call cc-option,-mabi=lp64)
KBUILD_AFLAGS += $(call cc-option,-mabi=lp64)
-ifeq ($(cc-name),clang)
-KBUILD_CFLAGS += -DCONFIG_ARCH_SUPPORTS_INT128
-else
-KBUILD_CFLAGS += $(call cc-ifversion, -ge, 0500, -DCONFIG_ARCH_SUPPORTS_INT128)
-endif
-
ifeq ($(CONFIG_CPU_BIG_ENDIAN), y)
KBUILD_CPPFLAGS += -mbig-endian
CHECKFLAGS += -D__AARCH64EB__
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index 4aa50b9..3543bc3 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -22,5 +22,6 @@ subdir-y += renesas
subdir-y += rockchip
subdir-y += socionext
subdir-y += sprd
+subdir-y += synaptics
subdir-y += xilinx
subdir-y += zte
diff --git a/arch/arm64/boot/dts/allwinner/Makefile b/arch/arm64/boot/dts/allwinner/Makefile
index 8bebe7d..c31f90a 100644
--- a/arch/arm64/boot/dts/allwinner/Makefile
+++ b/arch/arm64/boot/dts/allwinner/Makefile
@@ -6,10 +6,11 @@ dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-orangepi-win.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-sopine-baseboard.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-teres-i.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-libretech-all-h3-cc.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo2.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo-plus2.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-pc2.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-prime.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-zero-plus2.dtb
-dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo2.dtb
-dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-nanopi-neo-plus2.dtb
dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h6-pine-h64.dtb
diff --git a/arch/arm64/boot/dts/allwinner/axp803.dtsi b/arch/arm64/boot/dts/allwinner/axp803.dtsi
index ff8af52..e5eae8b 100644
--- a/arch/arm64/boot/dts/allwinner/axp803.dtsi
+++ b/arch/arm64/boot/dts/allwinner/axp803.dtsi
@@ -146,5 +146,10 @@
regulator-max-microvolt = <3000000>;
regulator-name = "rtc-ldo";
};
+
+ reg_drivevbus: drivevbus {
+ regulator-name = "drivevbus";
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
index 2250dec..0716b14 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-bananapi-m64.dts
@@ -86,6 +86,10 @@
};
};
+&ehci0 {
+ status = "okay";
+};
+
&ehci1 {
status = "okay";
};
@@ -155,6 +159,10 @@
status = "okay";
};
+&ohci0 {
+ status = "okay";
+};
+
&ohci1 {
status = "okay";
};
@@ -167,6 +175,7 @@
reg = <0x3a3>;
interrupt-parent = <&r_intc>;
interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ x-powers,drive-vbus-en; /* set N_VBUSEN as output pin */
};
};
@@ -254,6 +263,11 @@
regulator-name = "vcc-wifi-io";
};
+&reg_drivevbus {
+ regulator-name = "usb0-vbus";
+ status = "okay";
+};
+
&reg_eldo1 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
@@ -294,6 +308,13 @@
status = "okay";
};
+&usb_otg {
+ dr_mode = "otg";
+ status = "okay";
+};
+
&usbphy {
+ usb0_id_det-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */
+ usb0_vbus-supply = <&reg_drivevbus>;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts
new file mode 100644
index 0000000..95e113c
--- /dev/null
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-libretech-all-h3-cc.dts
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (C) 2018 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+/dts-v1/;
+#include "sun50i-h5.dtsi"
+#include <arm/sunxi-libretech-all-h3-cc.dtsi>
+
+/ {
+ model = "Libre Computer Board ALL-H3-CC H5";
+ compatible = "libretech,all-h3-cc-h5", "allwinner,sun50i-h5";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
index e237c05..62d646b 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
@@ -47,7 +47,7 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ cpu0: cpu@0 {
compatible = "arm,cortex-a53", "arm,armv8";
device_type = "cpu";
reg = <0>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
index d36de5e..b6f2d6b 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-pine-h64.dts
@@ -22,6 +22,16 @@
};
};
+&r_i2c {
+ status = "okay";
+
+ pcf8563: rtc@51 {
+ compatible = "nxp,pcf8563";
+ reg = <0x51>;
+ #clock-cells = <0>;
+ };
+};
+
&uart0 {
pinctrl-names = "default";
pinctrl-0 = <&uart0_ph_pins>;
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
index 5656315..c72da8c 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi
@@ -4,6 +4,8 @@
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/sun50i-h6-ccu.h>
+#include <dt-bindings/reset/sun50i-h6-ccu.h>
/ {
interrupt-parent = <&gic>;
@@ -115,7 +117,7 @@
<GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&ccu 26>, <&osc24M>, <&osc32k>;
+ clocks = <&ccu CLK_APB1>, <&osc24M>, <&osc32k>;
clock-names = "apb", "hosc", "losc";
gpio-controller;
#gpio-cells = <3>;
@@ -134,8 +136,8 @@
interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
- clocks = <&ccu 70>;
- resets = <&ccu 21>;
+ clocks = <&ccu CLK_BUS_UART0>;
+ resets = <&ccu RST_BUS_UART0>;
status = "disabled";
};
@@ -145,8 +147,8 @@
interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
- clocks = <&ccu 71>;
- resets = <&ccu 22>;
+ clocks = <&ccu CLK_BUS_UART1>;
+ resets = <&ccu RST_BUS_UART1>;
status = "disabled";
};
@@ -156,8 +158,8 @@
interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
- clocks = <&ccu 72>;
- resets = <&ccu 23>;
+ clocks = <&ccu CLK_BUS_UART2>;
+ resets = <&ccu RST_BUS_UART2>;
status = "disabled";
};
@@ -167,9 +169,59 @@
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
reg-shift = <2>;
reg-io-width = <4>;
- clocks = <&ccu 73>;
- resets = <&ccu 24>;
+ clocks = <&ccu CLK_BUS_UART3>;
+ resets = <&ccu RST_BUS_UART3>;
status = "disabled";
};
+
+ r_ccu: clock@7010000 {
+ compatible = "allwinner,sun50i-h6-r-ccu";
+ reg = <0x07010000 0x400>;
+ clocks = <&osc24M>, <&osc32k>, <&iosc>,
+ <&ccu CLK_PLL_PERIPH0>;
+ clock-names = "hosc", "losc", "iosc", "pll-periph";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ r_intc: interrupt-controller@7021000 {
+ compatible = "allwinner,sun50i-h6-r-intc",
+ "allwinner,sun6i-a31-r-intc";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ reg = <0x07021000 0x400>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ r_pio: pinctrl@7022000 {
+ compatible = "allwinner,sun50i-h6-r-pinctrl";
+ reg = <0x07022000 0x400>;
+ interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu 2>, <&osc24M>, <&osc32k>;
+ clock-names = "apb", "hosc", "losc";
+ gpio-controller;
+ #gpio-cells = <3>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+
+ r_i2c_pins: r-i2c {
+ pins = "PL0", "PL1";
+ function = "s_i2c";
+ };
+ };
+
+ r_i2c: i2c@7081400 {
+ compatible = "allwinner,sun6i-a31-i2c";
+ reg = <0x07081400 0x400>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&r_ccu 8>;
+ resets = <&r_ccu 4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&r_i2c_pins>;
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
index 57eedce..4b3331f 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-axg-s400.dts
@@ -15,6 +15,53 @@
serial0 = &uart_AO;
serial1 = &uart_A;
};
+
+ 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>;
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&gpio GPIOX_7 GPIO_ACTIVE_LOW>;
+ clocks = <&wifi32k>;
+ clock-names = "ext_clock";
+ };
+
+ wifi32k: wifi32k {
+ compatible = "pwm-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ pwms = <&pwm_ab 0 30518 0>; /* PWM_A at 32.768KHz */
+ };
};
&ethmac {
@@ -47,3 +94,62 @@
pinctrl-0 = <&i2c1_z_pins>;
pinctrl-names = "default";
};
+
+&i2c_AO {
+ status = "okay";
+ pinctrl-0 = <&i2c_ao_sck_10_pins>, <&i2c_ao_sda_11_pins>;
+ pinctrl-names = "default";
+};
+
+&pwm_ab {
+ status = "okay";
+ pinctrl-0 = <&pwm_a_x20_pins>;
+ pinctrl-names = "default";
+};
+
+/* emmc storage */
+&sd_emmc_c {
+ status = "okay";
+ pinctrl-0 = <&emmc_pins>;
+ pinctrl-1 = <&emmc_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <8>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ max-frequency = <180000000>;
+ non-removable;
+ disable-wp;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vddio_boot>;
+};
+
+/* wifi module */
+&sd_emmc_b {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pinctrl-0 = <&sdio_pins>;
+ pinctrl-1 = <&sdio_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <4>;
+ cap-sd-highspeed;
+ max-frequency = <100000000>;
+ non-removable;
+ disable-wp;
+
+ mmc-pwrseq = <&sdio_pwrseq>;
+
+ vmmc-supply = <&vddao_3v3>;
+ vqmmc-supply = <&vddio_boot>;
+
+ brcmf: wifi@1 {
+ reg = <1>;
+ compatible = "brcm,bcm4329-fmac";
+ };
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index b58808e..fee8773 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -7,6 +7,9 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/axg-clkc.h>
+#include <dt-bindings/clock/axg-aoclkc.h>
+#include <dt-bindings/gpio/meson-axg-gpio.h>
+#include <dt-bindings/reset/amlogic,meson-axg-reset.h>
/ {
compatible = "amlogic,meson-axg";
@@ -107,12 +110,51 @@
#clock-cells = <0>;
};
+ ao_alt_xtal: ao_alt_xtal-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <32000000>;
+ clock-output-names = "ao_alt_xtal";
+ #clock-cells = <0>;
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ apb: apb@ffe00000 {
+ compatible = "simple-bus";
+ reg = <0x0 0xffe00000 0x0 0x200000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x0 0x0 0x0 0xffe00000 0x0 0x200000>;
+
+ sd_emmc_b: sd@5000 {
+ compatible = "amlogic,meson-axg-mmc";
+ reg = <0x0 0x5000 0x0 0x2000>;
+ interrupts = <GIC_SPI 217 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ clocks = <&clkc CLKID_SD_EMMC_B>,
+ <&clkc CLKID_SD_EMMC_B_CLK0>,
+ <&clkc CLKID_FCLK_DIV2>;
+ clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_B>;
+ };
+
+ sd_emmc_c: mmc@7000 {
+ compatible = "amlogic,meson-axg-mmc";
+ reg = <0x0 0x7000 0x0 0x2000>;
+ interrupts = <GIC_SPI 218 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ clocks = <&clkc CLKID_SD_EMMC_C>,
+ <&clkc CLKID_SD_EMMC_C_CLK0>,
+ <&clkc CLKID_FCLK_DIV2>;
+ clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_C>;
+ };
+ };
+
cbus: bus@ffd00000 {
compatible = "simple-bus";
reg = <0x0 0xffd00000 0x0 0x25000>;
@@ -120,6 +162,15 @@
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xffd00000 0x0 0x25000>;
+ gpio_intc: interrupt-controller@f080 {
+ compatible = "amlogic,meson-gpio-intc";
+ reg = <0x0 0xf080 0x0 0x10>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ amlogic,channel-interrupts = <64 65 66 67 68 69 70 71>;
+ status = "disabled";
+ };
+
pwm_ab: pwm@1b000 {
compatible = "amlogic,meson-axg-ee-pwm";
reg = <0x0 0x1b000 0x0 0x20>;
@@ -164,50 +215,42 @@
i2c0: i2c@1f000 {
compatible = "amlogic,meson-axg-i2c";
- status = "disabled";
reg = <0x0 0x1f000 0x0 0x20>;
- interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 47 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc CLKID_I2C>;
#address-cells = <1>;
#size-cells = <0>;
- clocks = <&clkc CLKID_I2C>;
- clock-names = "clk_i2c";
+ status = "disabled";
};
i2c1: i2c@1e000 {
compatible = "amlogic,meson-axg-i2c";
+ reg = <0x0 0x1e000 0x0 0x20>;
+ interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc CLKID_I2C>;
#address-cells = <1>;
#size-cells = <0>;
- reg = <0x0 0x1e000 0x0 0x20>;
status = "disabled";
- interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 48 IRQ_TYPE_EDGE_RISING>;
- clocks = <&clkc CLKID_I2C>;
- clock-names = "clk_i2c";
};
i2c2: i2c@1d000 {
compatible = "amlogic,meson-axg-i2c";
- status = "disabled";
reg = <0x0 0x1d000 0x0 0x20>;
- interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 49 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc CLKID_I2C>;
#address-cells = <1>;
#size-cells = <0>;
- clocks = <&clkc CLKID_I2C>;
- clock-names = "clk_i2c";
+ status = "disabled";
};
i2c3: i2c@1c000 {
compatible = "amlogic,meson-axg-i2c";
- status = "disabled";
reg = <0x0 0x1c000 0x0 0x20>;
- interrupts = <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 50 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc CLKID_I2C>;
#address-cells = <1>;
#size-cells = <0>;
- clocks = <&clkc CLKID_I2C>;
- clock-names = "clk_i2c";
+ status = "disabled";
};
uart_A: serial@24000 {
@@ -262,10 +305,14 @@
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xff63c000 0x0 0x1c00>;
- clkc: clock-controller@0 {
- compatible = "amlogic,axg-clkc";
- #clock-cells = <1>;
- reg = <0x0 0x0 0x0 0x320>;
+ sysctrl: system-controller@0 {
+ compatible = "amlogic,meson-axg-hhi-sysctrl", "syscon", "simple-mfd";
+ reg = <0 0 0 0x400>;
+
+ clkc: clock-controller {
+ compatible = "amlogic,axg-clkc";
+ #clock-cells = <1>;
+ };
};
};
@@ -309,6 +356,57 @@
gpio-ranges = <&pinctrl_periphs 0 0 86>;
};
+ emmc_pins: emmc {
+ mux {
+ groups = "emmc_nand_d0",
+ "emmc_nand_d1",
+ "emmc_nand_d2",
+ "emmc_nand_d3",
+ "emmc_nand_d4",
+ "emmc_nand_d5",
+ "emmc_nand_d6",
+ "emmc_nand_d7",
+ "emmc_clk",
+ "emmc_cmd",
+ "emmc_ds";
+ function = "emmc";
+ };
+ };
+
+ emmc_clk_gate_pins: emmc_clk_gate {
+ mux {
+ groups = "BOOT_8";
+ function = "gpio_periphs";
+ };
+ cfg-pull-down {
+ pins = "BOOT_8";
+ bias-pull-down;
+ };
+ };
+
+ sdio_pins: sdio {
+ mux {
+ groups = "sdio_d0",
+ "sdio_d1",
+ "sdio_d2",
+ "sdio_d3",
+ "sdio_cmd",
+ "sdio_clk";
+ function = "sdio";
+ };
+ };
+
+ sdio_clk_gate_pins: sdio_clk_gate {
+ mux {
+ groups = "GPIOX_4";
+ function = "gpio_periphs";
+ };
+ cfg-pull-down {
+ pins = "GPIOX_4";
+ bias-pull-down;
+ };
+ };
+
eth_rmii_x_pins: eth-x-rmii {
mux {
groups = "eth_mdio_x",
@@ -660,6 +758,251 @@
function = "uart_ao_b_z";
};
};
+
+ mclk_b_pins: mclk_b {
+ mux {
+ groups = "mclk_b";
+ function = "mclk_b";
+ };
+ };
+
+ mclk_c_pins: mclk_c {
+ mux {
+ groups = "mclk_c";
+ function = "mclk_c";
+ };
+ };
+
+ tdma_sclk_pins: tdma_sclk {
+ mux {
+ groups = "tdma_sclk";
+ function = "tdma";
+ };
+ };
+
+ tdma_sclk_slv_pins: tdma_sclk_slv {
+ mux {
+ groups = "tdma_sclk_slv";
+ function = "tdma";
+ };
+ };
+
+ tdma_fs_pins: tdma_fs {
+ mux {
+ groups = "tdma_fs";
+ function = "tdma";
+ };
+ };
+
+ tdma_fs_slv_pins: tdma_fs_slv {
+ mux {
+ groups = "tdma_fs_slv";
+ function = "tdma";
+ };
+ };
+
+ tdma_din0_pins: tdma_din0 {
+ mux {
+ groups = "tdma_din0";
+ function = "tdma";
+ };
+ };
+
+ tdma_dout0_x14_pins: tdma_dout0_x14 {
+ mux {
+ groups = "tdma_dout0_x14";
+ function = "tdma";
+ };
+ };
+
+ tdma_dout0_x15_pins: tdma_dout0_x15 {
+ mux {
+ groups = "tdma_dout0_x15";
+ function = "tdma";
+ };
+ };
+
+ tdma_dout1_pins: tdma_dout1 {
+ mux {
+ groups = "tdma_dout1";
+ function = "tdma";
+ };
+ };
+
+ tdma_din1_pins: tdma_din1 {
+ mux {
+ groups = "tdma_din1";
+ function = "tdma";
+ };
+ };
+
+ tdmb_sclk_pins: tdmb_sclk {
+ mux {
+ groups = "tdmb_sclk";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_sclk_slv_pins: tdmb_sclk_slv {
+ mux {
+ groups = "tdmb_sclk_slv";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_fs_pins: tdmb_fs {
+ mux {
+ groups = "tdmb_fs";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_fs_slv_pins: tdmb_fs_slv {
+ mux {
+ groups = "tdmb_fs_slv";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_din0_pins: tdmb_din0 {
+ mux {
+ groups = "tdmb_din0";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_dout0_pins: tdmb_dout0 {
+ mux {
+ groups = "tdmb_dout0";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_din1_pins: tdmb_din1 {
+ mux {
+ groups = "tdmb_din1";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_dout1_pins: tdmb_dout1 {
+ mux {
+ groups = "tdmb_dout1";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_din2_pins: tdmb_din2 {
+ mux {
+ groups = "tdmb_din2";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_dout2_pins: tdmb_dout2 {
+ mux {
+ groups = "tdmb_dout2";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_din3_pins: tdmb_din3 {
+ mux {
+ groups = "tdmb_din3";
+ function = "tdmb";
+ };
+ };
+
+ tdmb_dout3_pins: tdmb_dout3 {
+ mux {
+ groups = "tdmb_dout3";
+ function = "tdmb";
+ };
+ };
+
+ tdmc_sclk_pins: tdmc_sclk {
+ mux {
+ groups = "tdmc_sclk";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_sclk_slv_pins: tdmc_sclk_slv {
+ mux {
+ groups = "tdmc_sclk_slv";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_fs_pins: tdmc_fs {
+ mux {
+ groups = "tdmc_fs";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_fs_slv_pins: tdmc_fs_slv {
+ mux {
+ groups = "tdmc_fs_slv";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_din0_pins: tdmc_din0 {
+ mux {
+ groups = "tdmc_din0";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_dout0_pins: tdmc_dout0 {
+ mux {
+ groups = "tdmc_dout0";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_din1_pins: tdmc_din1 {
+ mux {
+ groups = "tdmc_din1";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_dout1_pins: tdmc_dout1 {
+ mux {
+ groups = "tdmc_dout1";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_din2_pins: tdmc_din2 {
+ mux {
+ groups = "tdmc_din2";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_dout2_pins: tdmc_dout2 {
+ mux {
+ groups = "tdmc_dout2";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_din3_pins: tdmc_din3 {
+ mux {
+ groups = "tdmc_din3";
+ function = "tdmc";
+ };
+ };
+
+ tdmc_dout3_pins: tdmc_dout3 {
+ mux {
+ groups = "tdmc_dout3";
+ function = "tdmc";
+ };
+ };
};
};
@@ -688,6 +1031,17 @@
#size-cells = <2>;
ranges = <0x0 0x0 0x0 0xff800000 0x0 0x100000>;
+ sysctrl_AO: sys-ctrl@0 {
+ compatible = "amlogic,meson-axg-ao-sysctrl", "syscon", "simple-mfd";
+ reg = <0x0 0x0 0x0 0x100>;
+
+ clkc_AO: clock-controller {
+ compatible = "amlogic,meson-axg-aoclkc";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+ };
+
pinctrl_aobus: pinctrl@14 {
compatible = "amlogic,meson-axg-aobus-pinctrl";
#address-cells = <2>;
@@ -704,6 +1058,48 @@
gpio-ranges = <&pinctrl_aobus 0 0 15>;
};
+ i2c_ao_sck_4_pins: i2c_ao_sck_4 {
+ mux {
+ groups = "i2c_ao_sck_4";
+ function = "i2c_ao";
+ };
+ };
+
+ i2c_ao_sck_8_pins: i2c_ao_sck_8 {
+ mux {
+ groups = "i2c_ao_sck_8";
+ function = "i2c_ao";
+ };
+ };
+
+ i2c_ao_sck_10_pins: i2c_ao_sck_10 {
+ mux {
+ groups = "i2c_ao_sck_10";
+ function = "i2c_ao";
+ };
+ };
+
+ i2c_ao_sda_5_pins: i2c_ao_sda_5 {
+ mux {
+ groups = "i2c_ao_sda_5";
+ function = "i2c_ao";
+ };
+ };
+
+ i2c_ao_sda_9_pins: i2c_ao_sda_9 {
+ mux {
+ groups = "i2c_ao_sda_9";
+ function = "i2c_ao";
+ };
+ };
+
+ i2c_ao_sda_11_pins: i2c_ao_sda_11 {
+ mux {
+ groups = "i2c_ao_sda_11";
+ function = "i2c_ao";
+ };
+ };
+
remote_input_ao_pins: remote_input_ao {
mux {
groups = "remote_input_ao";
@@ -766,20 +1162,19 @@
i2c_AO: i2c@5000 {
compatible = "amlogic,meson-axg-i2c";
- status = "disabled";
reg = <0x0 0x05000 0x0 0x20>;
interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&clkc CLKID_AO_I2C>;
#address-cells = <1>;
#size-cells = <0>;
- clocks = <&clkc CLKID_I2C>;
- clock-names = "clk_i2c";
+ status = "disabled";
};
uart_AO: serial@3000 {
compatible = "amlogic,meson-gx-uart", "amlogic,meson-ao-uart";
reg = <0x0 0x3000 0x0 0x18>;
interrupts = <GIC_SPI 193 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+ clocks = <&xtal>, <&clkc_AO CLKID_AO_UART1>, <&xtal>;
clock-names = "xtal", "pclk", "baud";
status = "disabled";
};
@@ -788,7 +1183,7 @@
compatible = "amlogic,meson-gx-uart", "amlogic,meson-ao-uart";
reg = <0x0 0x4000 0x0 0x18>;
interrupts = <GIC_SPI 197 IRQ_TYPE_EDGE_RISING>;
- clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+ clocks = <&xtal>, <&clkc_AO CLKID_AO_UART2>, <&xtal>;
clock-names = "xtal", "pclk", "baud";
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 562c26a..98cbba6 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -307,11 +307,10 @@
clock-names = "isfr", "iahb", "venci";
};
-&hiubus {
- clkc: clock-controller@0 {
+&sysctrl {
+ clkc: clock-controller {
compatible = "amlogic,gxbb-clkc";
#clock-cells = <1>;
- reg = <0x0 0x0 0x0 0x3db>;
};
};
@@ -716,6 +715,7 @@
<&clkc CLKID_SD_EMMC_A_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_A>;
};
&sd_emmc_b {
@@ -723,6 +723,7 @@
<&clkc CLKID_SD_EMMC_B_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_B>;
};
&sd_emmc_c {
@@ -730,6 +731,7 @@
<&clkc CLKID_SD_EMMC_C_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_C>;
};
&spicc {
@@ -749,12 +751,12 @@
};
&uart_AO {
- clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+ clocks = <&xtal>, <&clkc_AO CLKID_AO_UART1>, <&xtal>;
clock-names = "xtal", "pclk", "baud";
};
&uart_AO_B {
- clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+ clocks = <&xtal>, <&clkc_AO CLKID_AO_UART2>, <&xtal>;
clock-names = "xtal", "pclk", "baud";
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index dba365e..27538ee 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -267,11 +267,10 @@
clock-names = "isfr", "iahb", "venci";
};
-&hiubus {
- clkc: clock-controller@0 {
- compatible = "amlogic,gxl-clkc", "amlogic,gxbb-clkc";
+&sysctrl {
+ clkc: clock-controller {
+ compatible = "amlogic,gxl-clkc";
#clock-cells = <1>;
- reg = <0x0 0x0 0x0 0x3db>;
};
};
@@ -725,13 +724,15 @@
<&clkc CLKID_SD_EMMC_A_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_A>;
};
&sd_emmc_b {
clocks = <&clkc CLKID_SD_EMMC_B>,
<&clkc CLKID_SD_EMMC_B_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
- clock-names = "core", "clkin0", "clkin1";
+ clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_B>;
};
&sd_emmc_c {
@@ -739,6 +740,7 @@
<&clkc CLKID_SD_EMMC_C_CLK0>,
<&clkc CLKID_FCLK_DIV2>;
clock-names = "core", "clkin0", "clkin1";
+ resets = <&reset RESET_SD_EMMC_C>;
};
&spicc {
@@ -758,12 +760,12 @@
};
&uart_AO {
- clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+ clocks = <&xtal>, <&clkc_AO CLKID_AO_UART1>, <&xtal>;
clock-names = "xtal", "pclk", "baud";
};
&uart_AO_B {
- clocks = <&xtal>, <&clkc CLKID_CLK81>, <&xtal>;
+ clocks = <&xtal>, <&clkc_AO CLKID_AO_UART2>, <&xtal>;
clock-names = "xtal", "pclk", "baud";
};
diff --git a/arch/arm64/boot/dts/arm/juno-base.dtsi b/arch/arm64/boot/dts/arm/juno-base.dtsi
index eb749c5..ce56a4a 100644
--- a/arch/arm64/boot/dts/arm/juno-base.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-base.dtsi
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include "juno-clocks.dtsi"
+#include "juno-motherboard.dtsi"
/ {
/*
@@ -572,14 +573,14 @@
thermal-sensors = <&scpi_sensors0 3>;
};
- big_cluster_thermal_zone: big_cluster {
+ big_cluster_thermal_zone: big-cluster {
polling-delay = <1000>;
polling-delay-passive = <100>;
thermal-sensors = <&scpi_sensors0 21>;
status = "disabled";
};
- little_cluster_thermal_zone: little_cluster {
+ little_cluster_thermal_zone: little-cluster {
polling-delay = <1000>;
polling-delay-passive = <100>;
thermal-sensors = <&scpi_sensors0 22>;
@@ -677,7 +678,7 @@
clock-names = "pxlclk";
port {
- hdlcd1_output: hdlcd1-endpoint {
+ hdlcd1_output: endpoint {
remote-endpoint = <&tda998x_1_input>;
};
};
@@ -692,7 +693,7 @@
clock-names = "pxlclk";
port {
- hdlcd0_output: hdlcd0-endpoint {
+ hdlcd0_output: endpoint {
remote-endpoint = <&tda998x_0_input>;
};
};
@@ -720,7 +721,7 @@
compatible = "nxp,tda998x";
reg = <0x70>;
port {
- tda998x_0_input: tda998x-0-endpoint {
+ tda998x_0_input: endpoint {
remote-endpoint = <&hdlcd0_output>;
};
};
@@ -730,7 +731,7 @@
compatible = "nxp,tda998x";
reg = <0x71>;
port {
- tda998x_1_input: tda998x-1-endpoint {
+ tda998x_1_input: endpoint {
remote-endpoint = <&hdlcd1_output>;
};
};
@@ -795,8 +796,6 @@
<0 0 10 &gic 0 0 0 167 IRQ_TYPE_LEVEL_HIGH>,
<0 0 11 &gic 0 0 0 168 IRQ_TYPE_LEVEL_HIGH>,
<0 0 12 &gic 0 0 0 169 IRQ_TYPE_LEVEL_HIGH>;
-
- /include/ "juno-motherboard.dtsi"
};
site2: tlx@60000000 {
diff --git a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
index 69804c5..1792b07 100644
--- a/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
+++ b/arch/arm64/boot/dts/arm/juno-motherboard.dtsi
@@ -7,6 +7,8 @@
*
*/
+/ {
+ smb@8000000 {
mb_clk24mhz: clk24mhz {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -54,46 +56,46 @@
regulator-always-on;
};
- gpio_keys {
+ gpio-keys {
compatible = "gpio-keys";
power-button {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <116>;
label = "POWER";
gpios = <&iofpga_gpio0 0 0x4>;
};
home-button {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <102>;
label = "HOME";
gpios = <&iofpga_gpio0 1 0x4>;
};
rlock-button {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <152>;
label = "RLOCK";
gpios = <&iofpga_gpio0 2 0x4>;
};
vol-up-button {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <115>;
label = "VOL+";
gpios = <&iofpga_gpio0 3 0x4>;
};
vol-down-button {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <114>;
label = "VOL-";
gpios = <&iofpga_gpio0 4 0x4>;
};
nmi-button {
- debounce_interval = <50>;
+ debounce-interval = <50>;
wakeup-source;
linux,code = <99>;
label = "NMI";
@@ -287,3 +289,5 @@
};
};
};
+ };
+};
diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts
index aed6389..2c5db03 100644
--- a/arch/arm64/boot/dts/arm/juno-r1.dts
+++ b/arch/arm64/boot/dts/arm/juno-r1.dts
@@ -201,7 +201,7 @@
};
};
- pmu_a57 {
+ pmu-a57 {
compatible = "arm,cortex-a57-pmu";
interrupts = <GIC_SPI 02 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 06 IRQ_TYPE_LEVEL_HIGH>;
@@ -209,7 +209,7 @@
<&A57_1>;
};
- pmu_a53 {
+ pmu-a53 {
compatible = "arm,cortex-a53-pmu";
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
@@ -278,6 +278,10 @@
remote-endpoint = <&csys2_funnel_out_port>;
};
+&csys1_funnel_in_port0 {
+ remote-endpoint = <&stm_out_port>;
+};
+
&stm_out_port {
remote-endpoint = <&csys1_funnel_in_port0>;
};
diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts b/arch/arm64/boot/dts/arm/juno-r2.dts
index b39b6d6..c51950f 100644
--- a/arch/arm64/boot/dts/arm/juno-r2.dts
+++ b/arch/arm64/boot/dts/arm/juno-r2.dts
@@ -201,7 +201,7 @@
};
};
- pmu_a72 {
+ pmu-a72 {
compatible = "arm,cortex-a72-pmu";
interrupts = <GIC_SPI 02 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 06 IRQ_TYPE_LEVEL_HIGH>;
@@ -209,7 +209,7 @@
<&A72_1>;
};
- pmu_a53 {
+ pmu-a53 {
compatible = "arm,cortex-a53-pmu";
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
@@ -278,6 +278,10 @@
remote-endpoint = <&csys2_funnel_out_port>;
};
+&csys1_funnel_in_port0 {
+ remote-endpoint = <&stm_out_port>;
+};
+
&stm_out_port {
remote-endpoint = <&csys1_funnel_in_port0>;
};
diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts
index c9236c4..2b2bf39 100644
--- a/arch/arm64/boot/dts/arm/juno.dts
+++ b/arch/arm64/boot/dts/arm/juno.dts
@@ -200,7 +200,7 @@
};
};
- pmu_a57 {
+ pmu-a57 {
compatible = "arm,cortex-a57-pmu";
interrupts = <GIC_SPI 02 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 06 IRQ_TYPE_LEVEL_HIGH>;
@@ -208,7 +208,7 @@
<&A57_1>;
};
- pmu_a53 {
+ pmu-a53 {
compatible = "arm,cortex-a53-pmu";
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
index 06c8117..602f63f 100644
--- a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
+++ b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
@@ -12,6 +12,8 @@
/memreserve/ 0x80000000 0x00010000;
+#include "rtsm_ve-motherboard.dtsi"
+
/ {
model = "RTSM_VE_AEMv8A";
compatible = "arm,rtsm_ve,aemv8a", "arm,vexpress";
@@ -162,7 +164,5 @@
<0 0 40 &gic 0 40 4>,
<0 0 41 &gic 0 41 4>,
<0 0 42 &gic 0 42 4>;
-
- /include/ "rtsm_ve-motherboard.dtsi"
};
};
diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
index 1134e5d..d2dbc3f 100644
--- a/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
+++ b/arch/arm64/boot/dts/arm/rtsm_ve-motherboard.dtsi
@@ -7,270 +7,273 @@
*
* VEMotherBoard.lisa
*/
-
- motherboard {
- arm,v2m-memory-map = "rs1";
- compatible = "arm,vexpress,v2m-p1", "simple-bus";
- #address-cells = <2>; /* SMB chipselect number and offset */
- #size-cells = <1>;
- #interrupt-cells = <1>;
- ranges;
-
- flash@0,00000000 {
- compatible = "arm,vexpress-flash", "cfi-flash";
- reg = <0 0x00000000 0x04000000>,
- <4 0x00000000 0x04000000>;
- bank-width = <4>;
- };
-
- v2m_video_ram: vram@2,00000000 {
- compatible = "arm,vexpress-vram";
- reg = <2 0x00000000 0x00800000>;
- };
-
- ethernet@2,02000000 {
- compatible = "smsc,lan91c111";
- reg = <2 0x02000000 0x10000>;
- interrupts = <15>;
- };
-
- v2m_clk24mhz: clk24mhz {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <24000000>;
- clock-output-names = "v2m:clk24mhz";
- };
-
- v2m_refclk1mhz: refclk1mhz {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <1000000>;
- clock-output-names = "v2m:refclk1mhz";
- };
-
- v2m_refclk32khz: refclk32khz {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- clock-output-names = "v2m:refclk32khz";
- };
-
- iofpga@3,00000000 {
- compatible = "simple-bus";
- #address-cells = <1>;
+/ {
+ smb@8000000 {
+ motherboard {
+ arm,v2m-memory-map = "rs1";
+ compatible = "arm,vexpress,v2m-p1", "simple-bus";
+ #address-cells = <2>; /* SMB chipselect number and offset */
#size-cells = <1>;
- ranges = <0 3 0 0x200000>;
-
- v2m_sysreg: sysreg@10000 {
- compatible = "arm,vexpress-sysreg";
- reg = <0x010000 0x1000>;
- gpio-controller;
- #gpio-cells = <2>;
+ #interrupt-cells = <1>;
+ ranges;
+
+ flash@0,00000000 {
+ compatible = "arm,vexpress-flash", "cfi-flash";
+ reg = <0 0x00000000 0x04000000>,
+ <4 0x00000000 0x04000000>;
+ bank-width = <4>;
};
- v2m_sysctl: sysctl@20000 {
- compatible = "arm,sp810", "arm,primecell";
- reg = <0x020000 0x1000>;
- clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
- clock-names = "refclk", "timclk", "apb_pclk";
- #clock-cells = <1>;
- clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
- assigned-clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_sysctl 3>, <&v2m_sysctl 3>;
- assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
+ v2m_video_ram: vram@2,00000000 {
+ compatible = "arm,vexpress-vram";
+ reg = <2 0x00000000 0x00800000>;
};
- aaci@40000 {
- compatible = "arm,pl041", "arm,primecell";
- reg = <0x040000 0x1000>;
- interrupts = <11>;
- clocks = <&v2m_clk24mhz>;
- clock-names = "apb_pclk";
+ ethernet@2,02000000 {
+ compatible = "smsc,lan91c111";
+ reg = <2 0x02000000 0x10000>;
+ interrupts = <15>;
};
- mmci@50000 {
- compatible = "arm,pl180", "arm,primecell";
- reg = <0x050000 0x1000>;
- interrupts = <9 10>;
- cd-gpios = <&v2m_sysreg 0 0>;
- wp-gpios = <&v2m_sysreg 1 0>;
- max-frequency = <12000000>;
- vmmc-supply = <&v2m_fixed_3v3>;
- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
- clock-names = "mclk", "apb_pclk";
+ v2m_clk24mhz: clk24mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "v2m:clk24mhz";
};
- kmi@60000 {
- compatible = "arm,pl050", "arm,primecell";
- reg = <0x060000 0x1000>;
- interrupts = <12>;
- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
- clock-names = "KMIREFCLK", "apb_pclk";
+ v2m_refclk1mhz: refclk1mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1000000>;
+ clock-output-names = "v2m:refclk1mhz";
};
- kmi@70000 {
- compatible = "arm,pl050", "arm,primecell";
- reg = <0x070000 0x1000>;
- interrupts = <13>;
- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
- clock-names = "KMIREFCLK", "apb_pclk";
+ v2m_refclk32khz: refclk32khz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "v2m:refclk32khz";
};
- v2m_serial0: uart@90000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x090000 0x1000>;
- interrupts = <5>;
- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
- clock-names = "uartclk", "apb_pclk";
- };
+ iofpga@3,00000000 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 3 0 0x200000>;
+
+ v2m_sysreg: sysreg@10000 {
+ compatible = "arm,vexpress-sysreg";
+ reg = <0x010000 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
- v2m_serial1: uart@a0000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x0a0000 0x1000>;
- interrupts = <6>;
- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
- clock-names = "uartclk", "apb_pclk";
- };
+ v2m_sysctl: sysctl@20000 {
+ compatible = "arm,sp810", "arm,primecell";
+ reg = <0x020000 0x1000>;
+ clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>;
+ clock-names = "refclk", "timclk", "apb_pclk";
+ #clock-cells = <1>;
+ clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+ assigned-clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_sysctl 3>, <&v2m_sysctl 3>;
+ assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
+ };
- v2m_serial2: uart@b0000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x0b0000 0x1000>;
- interrupts = <7>;
- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
- clock-names = "uartclk", "apb_pclk";
- };
+ aaci@40000 {
+ compatible = "arm,pl041", "arm,primecell";
+ reg = <0x040000 0x1000>;
+ interrupts = <11>;
+ clocks = <&v2m_clk24mhz>;
+ clock-names = "apb_pclk";
+ };
- v2m_serial3: uart@c0000 {
- compatible = "arm,pl011", "arm,primecell";
- reg = <0x0c0000 0x1000>;
- interrupts = <8>;
- clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
- clock-names = "uartclk", "apb_pclk";
- };
+ mmci@50000 {
+ compatible = "arm,pl180", "arm,primecell";
+ reg = <0x050000 0x1000>;
+ interrupts = <9 10>;
+ cd-gpios = <&v2m_sysreg 0 0>;
+ wp-gpios = <&v2m_sysreg 1 0>;
+ max-frequency = <12000000>;
+ vmmc-supply = <&v2m_fixed_3v3>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "mclk", "apb_pclk";
+ };
- wdt@f0000 {
- compatible = "arm,sp805", "arm,primecell";
- reg = <0x0f0000 0x1000>;
- interrupts = <0>;
- clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>;
- clock-names = "wdogclk", "apb_pclk";
- };
+ kmi@60000 {
+ compatible = "arm,pl050", "arm,primecell";
+ reg = <0x060000 0x1000>;
+ interrupts = <12>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "KMIREFCLK", "apb_pclk";
+ };
- v2m_timer01: timer@110000 {
- compatible = "arm,sp804", "arm,primecell";
- reg = <0x110000 0x1000>;
- interrupts = <2>;
- clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>;
- clock-names = "timclken1", "timclken2", "apb_pclk";
- };
+ kmi@70000 {
+ compatible = "arm,pl050", "arm,primecell";
+ reg = <0x070000 0x1000>;
+ interrupts = <13>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "KMIREFCLK", "apb_pclk";
+ };
- v2m_timer23: timer@120000 {
- compatible = "arm,sp804", "arm,primecell";
- reg = <0x120000 0x1000>;
- interrupts = <3>;
- clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>;
- clock-names = "timclken1", "timclken2", "apb_pclk";
- };
+ v2m_serial0: uart@90000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x090000 0x1000>;
+ interrupts = <5>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "uartclk", "apb_pclk";
+ };
- rtc@170000 {
- compatible = "arm,pl031", "arm,primecell";
- reg = <0x170000 0x1000>;
- interrupts = <4>;
- clocks = <&v2m_clk24mhz>;
- clock-names = "apb_pclk";
- };
+ v2m_serial1: uart@a0000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0a0000 0x1000>;
+ interrupts = <6>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "uartclk", "apb_pclk";
+ };
- clcd@1f0000 {
- compatible = "arm,pl111", "arm,primecell";
- reg = <0x1f0000 0x1000>;
- interrupt-names = "combined";
- interrupts = <14>;
- clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
- clock-names = "clcdclk", "apb_pclk";
- arm,pl11x,framebuffer = <0x18000000 0x00180000>;
- memory-region = <&v2m_video_ram>;
- max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */
-
- port {
- v2m_clcd_pads: endpoint {
- remote-endpoint = <&v2m_clcd_panel>;
- arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
- };
+ v2m_serial2: uart@b0000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0b0000 0x1000>;
+ interrupts = <7>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "uartclk", "apb_pclk";
};
- panel {
- compatible = "panel-dpi";
+ v2m_serial3: uart@c0000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0x0c0000 0x1000>;
+ interrupts = <8>;
+ clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>;
+ clock-names = "uartclk", "apb_pclk";
+ };
+
+ wdt@f0000 {
+ compatible = "arm,sp805", "arm,primecell";
+ reg = <0x0f0000 0x1000>;
+ interrupts = <0>;
+ clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>;
+ clock-names = "wdogclk", "apb_pclk";
+ };
+
+ v2m_timer01: timer@110000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x110000 0x1000>;
+ interrupts = <2>;
+ clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
+ };
+
+ v2m_timer23: timer@120000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0x120000 0x1000>;
+ interrupts = <3>;
+ clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
+ };
+
+ rtc@170000 {
+ compatible = "arm,pl031", "arm,primecell";
+ reg = <0x170000 0x1000>;
+ interrupts = <4>;
+ clocks = <&v2m_clk24mhz>;
+ clock-names = "apb_pclk";
+ };
+
+ clcd@1f0000 {
+ compatible = "arm,pl111", "arm,primecell";
+ reg = <0x1f0000 0x1000>;
+ interrupt-names = "combined";
+ interrupts = <14>;
+ clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>;
+ clock-names = "clcdclk", "apb_pclk";
+ arm,pl11x,framebuffer = <0x18000000 0x00180000>;
+ memory-region = <&v2m_video_ram>;
+ max-memory-bandwidth = <130000000>; /* 16bpp @ 63.5MHz */
port {
- v2m_clcd_panel: endpoint {
- remote-endpoint = <&v2m_clcd_pads>;
+ v2m_clcd_pads: endpoint {
+ remote-endpoint = <&v2m_clcd_panel>;
+ arm,pl11x,tft-r0g0b0-pads = <0 8 16>;
};
};
- panel-timing {
- clock-frequency = <63500127>;
- hactive = <1024>;
- hback-porch = <152>;
- hfront-porch = <48>;
- hsync-len = <104>;
- vactive = <768>;
- vback-porch = <23>;
- vfront-porch = <3>;
- vsync-len = <4>;
+ panel {
+ compatible = "panel-dpi";
+
+ port {
+ v2m_clcd_panel: endpoint {
+ remote-endpoint = <&v2m_clcd_pads>;
+ };
+ };
+
+ panel-timing {
+ clock-frequency = <63500127>;
+ hactive = <1024>;
+ hback-porch = <152>;
+ hfront-porch = <48>;
+ hsync-len = <104>;
+ vactive = <768>;
+ vback-porch = <23>;
+ vfront-porch = <3>;
+ vsync-len = <4>;
+ };
};
};
- };
- virtio-block@130000 {
- compatible = "virtio,mmio";
- reg = <0x130000 0x200>;
- interrupts = <42>;
+ virtio-block@130000 {
+ compatible = "virtio,mmio";
+ reg = <0x130000 0x200>;
+ interrupts = <42>;
+ };
};
- };
-
- v2m_fixed_3v3: v2m-3v3 {
- compatible = "regulator-fixed";
- regulator-name = "3V3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
- mcc {
- compatible = "arm,vexpress,config-bus";
- arm,vexpress,config-bridge = <&v2m_sysreg>;
- v2m_oscclk1: oscclk1 {
- /* CLCD clock */
- compatible = "arm,vexpress-osc";
- arm,vexpress-sysreg,func = <1 1>;
- freq-range = <23750000 63500000>;
- #clock-cells = <0>;
- clock-output-names = "v2m:oscclk1";
+ v2m_fixed_3v3: v2m-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
};
- reset {
- compatible = "arm,vexpress-reset";
- arm,vexpress-sysreg,func = <5 0>;
- };
+ mcc {
+ compatible = "arm,vexpress,config-bus";
+ arm,vexpress,config-bridge = <&v2m_sysreg>;
+
+ v2m_oscclk1: oscclk1 {
+ /* CLCD clock */
+ compatible = "arm,vexpress-osc";
+ arm,vexpress-sysreg,func = <1 1>;
+ freq-range = <23750000 63500000>;
+ #clock-cells = <0>;
+ clock-output-names = "v2m:oscclk1";
+ };
- muxfpga {
- compatible = "arm,vexpress-muxfpga";
- arm,vexpress-sysreg,func = <7 0>;
- };
+ reset {
+ compatible = "arm,vexpress-reset";
+ arm,vexpress-sysreg,func = <5 0>;
+ };
- shutdown {
- compatible = "arm,vexpress-shutdown";
- arm,vexpress-sysreg,func = <8 0>;
- };
+ muxfpga {
+ compatible = "arm,vexpress-muxfpga";
+ arm,vexpress-sysreg,func = <7 0>;
+ };
- reboot {
- compatible = "arm,vexpress-reboot";
- arm,vexpress-sysreg,func = <9 0>;
- };
+ shutdown {
+ compatible = "arm,vexpress-shutdown";
+ arm,vexpress-sysreg,func = <8 0>;
+ };
+
+ reboot {
+ compatible = "arm,vexpress-reboot";
+ arm,vexpress-sysreg,func = <9 0>;
+ };
- dvimode {
- compatible = "arm,vexpress-dvimode";
- arm,vexpress-sysreg,func = <11 0>;
+ dvimode {
+ compatible = "arm,vexpress-dvimode";
+ arm,vexpress-sysreg,func = <11 0>;
+ };
};
};
};
+};
diff --git a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
index 1c9eadc..3888038 100644
--- a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
+++ b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
@@ -13,6 +13,7 @@
/dts-v1/;
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "vexpress-v2m-rs1.dtsi"
/ {
model = "V2F-1XV7 Cortex-A53x2 SMM";
@@ -129,7 +130,7 @@
};
};
- smb@8000000 {
+ smb: smb@8000000 {
compatible = "simple-bus";
#address-cells = <2>;
@@ -186,7 +187,5 @@
<0 0 40 &gic GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
<0 0 41 &gic GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
<0 0 42 &gic GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
-
- /include/ "vexpress-v2m-rs1.dtsi"
};
};
diff --git a/arch/arm64/boot/dts/broadcom/Makefile b/arch/arm64/boot/dts/broadcom/Makefile
index 2a2591e..1193a9e 100644
--- a/arch/arm64/boot/dts/broadcom/Makefile
+++ b/arch/arm64/boot/dts/broadcom/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
-dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb
+dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb \
+ bcm2837-rpi-3-b-plus.dtb
subdir-y += northstar2
subdir-y += stingray
diff --git a/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dts b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dts
new file mode 100644
index 0000000..46ad202
--- /dev/null
+++ b/arch/arm64/boot/dts/broadcom/bcm2837-rpi-3-b-plus.dts
@@ -0,0 +1,2 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "arm/bcm2837-rpi-3-b-plus.dts"
diff --git a/arch/arm64/boot/dts/exynos/exynos5433.dtsi b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
index 1ad8677..038c997 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos5433.dtsi
@@ -18,8 +18,8 @@
/ {
compatible = "samsung,exynos5433";
- #address-cells = <2>;
- #size-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
interrupt-parent = <&gic>;
@@ -231,18 +231,11 @@
cpu_on = <0xC4000003>;
};
- reboot: syscon-reboot {
- compatible = "syscon-reboot";
- regmap = <&pmu_system_controller>;
- offset = <0x400>; /* SWRESET */
- mask = <0x1>;
- };
-
soc: soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0x0 0x0 0x0 0x18000000>;
+ ranges;
arm_a53_pmu {
compatible = "arm,cortex-a53-pmu", "arm,armv8-pmuv3";
@@ -799,6 +792,13 @@
#clock-cells = <1>;
clock-names = "clkout16";
clocks = <&xxti>;
+
+ reboot: syscon-reboot {
+ compatible = "syscon-reboot";
+ regmap = <&pmu_system_controller>;
+ offset = <0x400>; /* SWRESET */
+ mask = <0x1>;
+ };
};
gic: interrupt-controller@11001000 {
@@ -829,11 +829,16 @@
<&cmu_disp CLK_ACLK_SMMU_DECON0X>,
<&cmu_disp CLK_ACLK_XIU_DECON0X>,
<&cmu_disp CLK_PCLK_SMMU_DECON0X>,
+ <&cmu_disp CLK_ACLK_SMMU_DECON1X>,
+ <&cmu_disp CLK_ACLK_XIU_DECON1X>,
+ <&cmu_disp CLK_PCLK_SMMU_DECON1X>,
<&cmu_disp CLK_SCLK_DECON_VCLK>,
<&cmu_disp CLK_SCLK_DECON_ECLK>;
clock-names = "pclk", "aclk_decon", "aclk_smmu_decon0x",
"aclk_xiu_decon0x", "pclk_smmu_decon0x",
- "sclk_decon_vclk", "sclk_decon_eclk";
+ "aclk_smmu_decon1x", "aclk_xiu_decon1x",
+ "pclk_smmu_decon1x", "sclk_decon_vclk",
+ "sclk_decon_eclk";
power-domains = <&pd_disp>;
interrupt-names = "fifo", "vsync", "lcd_sys";
interrupts = <GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH>,
@@ -866,11 +871,16 @@
<&cmu_disp CLK_ACLK_SMMU_TV0X>,
<&cmu_disp CLK_ACLK_XIU_TV0X>,
<&cmu_disp CLK_PCLK_SMMU_TV0X>,
+ <&cmu_disp CLK_ACLK_SMMU_TV1X>,
+ <&cmu_disp CLK_ACLK_XIU_TV1X>,
+ <&cmu_disp CLK_PCLK_SMMU_TV1X>,
<&cmu_disp CLK_SCLK_DECON_TV_VCLK>,
<&cmu_disp CLK_SCLK_DECON_TV_ECLK>;
clock-names = "pclk", "aclk_decon", "aclk_smmu_decon0x",
"aclk_xiu_decon0x", "pclk_smmu_decon0x",
- "sclk_decon_vclk", "sclk_decon_eclk";
+ "aclk_smmu_decon1x", "aclk_xiu_decon1x",
+ "pclk_smmu_decon1x", "sclk_decon_vclk",
+ "sclk_decon_eclk";
samsung,disp-sysreg = <&syscon_disp>;
power-domains = <&pd_disp>;
interrupt-names = "fifo", "vsync", "lcd_sys";
@@ -1034,6 +1044,30 @@
power-domains = <&pd_gscl>;
};
+ scaler_0: scaler@15000000 {
+ compatible = "samsung,exynos5433-scaler";
+ reg = <0x15000000 0x1294>;
+ interrupts = <0 402 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "pclk", "aclk", "aclk_xiu";
+ clocks = <&cmu_mscl CLK_PCLK_M2MSCALER0>,
+ <&cmu_mscl CLK_ACLK_M2MSCALER0>,
+ <&cmu_mscl CLK_ACLK_XIU_MSCLX>;
+ iommus = <&sysmmu_scaler_0>;
+ power-domains = <&pd_mscl>;
+ };
+
+ scaler_1: scaler@15010000 {
+ compatible = "samsung,exynos5433-scaler";
+ reg = <0x15010000 0x1294>;
+ interrupts = <0 403 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "pclk", "aclk", "aclk_xiu";
+ clocks = <&cmu_mscl CLK_PCLK_M2MSCALER1>,
+ <&cmu_mscl CLK_ACLK_M2MSCALER1>,
+ <&cmu_mscl CLK_ACLK_XIU_MSCLX>;
+ iommus = <&sysmmu_scaler_1>;
+ power-domains = <&pd_mscl>;
+ };
+
jpeg: codec@15020000 {
compatible = "samsung,exynos5433-jpeg";
reg = <0x15020000 0x10000>;
@@ -1137,6 +1171,28 @@
power-domains = <&pd_gscl>;
};
+ sysmmu_scaler_0: sysmmu@0x15040000 {
+ compatible = "samsung,exynos-sysmmu";
+ reg = <0x15040000 0x1000>;
+ interrupts = <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "pclk", "aclk";
+ clocks = <&cmu_mscl CLK_PCLK_SMMU_M2MSCALER0>,
+ <&cmu_mscl CLK_ACLK_SMMU_M2MSCALER0>;
+ #iommu-cells = <0>;
+ power-domains = <&pd_mscl>;
+ };
+
+ sysmmu_scaler_1: sysmmu@0x15050000 {
+ compatible = "samsung,exynos-sysmmu";
+ reg = <0x15050000 0x1000>;
+ interrupts = <GIC_SPI 406 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "pclk", "aclk";
+ clocks = <&cmu_mscl CLK_PCLK_SMMU_M2MSCALER1>,
+ <&cmu_mscl CLK_ACLK_SMMU_M2MSCALER1>;
+ #iommu-cells = <0>;
+ power-domains = <&pd_mscl>;
+ };
+
sysmmu_jpeg: sysmmu@15060000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x15060000 0x1000>;
diff --git a/arch/arm64/boot/dts/exynos/exynos7.dtsi b/arch/arm64/boot/dts/exynos/exynos7.dtsi
index ad9dce6..93a8433 100644
--- a/arch/arm64/boot/dts/exynos/exynos7.dtsi
+++ b/arch/arm64/boot/dts/exynos/exynos7.dtsi
@@ -12,8 +12,8 @@
/ {
compatible = "samsung,exynos7";
interrupt-parent = <&gic>;
- #address-cells = <2>;
- #size-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
aliases {
pinctrl0 = &pinctrl_alive;
@@ -70,7 +70,7 @@
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0 0 0 0x18000000>;
+ ranges;
chipid@10000000 {
compatible = "samsung,exynos4210-chipid";
@@ -494,13 +494,13 @@
pmu_system_controller: system-controller@105c0000 {
compatible = "samsung,exynos7-pmu", "syscon";
reg = <0x105c0000 0x5000>;
- };
- reboot: syscon-reboot {
- compatible = "syscon-reboot";
- regmap = <&pmu_system_controller>;
- offset = <0x0400>;
- mask = <0x1>;
+ reboot: syscon-reboot {
+ compatible = "syscon-reboot";
+ regmap = <&pmu_system_controller>;
+ offset = <0x0400>;
+ mask = <0x1>;
+ };
};
rtc: rtc@10590000 {
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
index bb788ed..205f0f4 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
@@ -53,11 +53,11 @@
aliases {
crypto = &crypto;
- rtic_a = &rtic_a;
- rtic_b = &rtic_b;
- rtic_c = &rtic_c;
- rtic_d = &rtic_d;
- sec_mon = &sec_mon;
+ rtic-a = &rtic_a;
+ rtic-b = &rtic_b;
+ rtic-c = &rtic_c;
+ rtic-d = &rtic_d;
+ sec-mon = &sec_mon;
};
cpus {
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
index 5498c70..061647b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
@@ -134,7 +134,7 @@
&dspi {
status = "okay";
- dflash0: n25q512a {
+ dflash0: n25q512a@0 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "st,m25p80";
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index ec3eb8e..8d477dc 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/hi3660-clock.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
compatible = "hisilicon,hi3660";
@@ -62,6 +63,10 @@
next-level-cache = <&A53_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <592>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
+ operating-points-v2 = <&cluster0_opp>;
+ #cooling-cells = <2>;
+ dynamic-power-coefficient = <110>;
};
cpu1: cpu@1 {
@@ -72,6 +77,8 @@
next-level-cache = <&A53_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <592>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu2: cpu@2 {
@@ -82,6 +89,8 @@
next-level-cache = <&A53_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <592>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu3: cpu@3 {
@@ -92,6 +101,8 @@
next-level-cache = <&A53_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
capacity-dmips-mhz = <592>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER0>;
+ operating-points-v2 = <&cluster0_opp>;
};
cpu4: cpu@100 {
@@ -102,6 +113,10 @@
next-level-cache = <&A73_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
capacity-dmips-mhz = <1024>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
+ operating-points-v2 = <&cluster1_opp>;
+ #cooling-cells = <2>;
+ dynamic-power-coefficient = <550>;
};
cpu5: cpu@101 {
@@ -112,6 +127,8 @@
next-level-cache = <&A73_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
capacity-dmips-mhz = <1024>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
+ operating-points-v2 = <&cluster1_opp>;
};
cpu6: cpu@102 {
@@ -122,6 +139,8 @@
next-level-cache = <&A73_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
capacity-dmips-mhz = <1024>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
+ operating-points-v2 = <&cluster1_opp>;
};
cpu7: cpu@103 {
@@ -132,6 +151,8 @@
next-level-cache = <&A73_L2>;
cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_1>;
capacity-dmips-mhz = <1024>;
+ clocks = <&stub_clock HI3660_CLK_STUB_CLUSTER1>;
+ operating-points-v2 = <&cluster1_opp>;
};
idle-states {
@@ -174,6 +195,76 @@
};
};
+ cluster0_opp: opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp00 {
+ opp-hz = /bits/ 64 <533000000>;
+ opp-microvolt = <700000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp01 {
+ opp-hz = /bits/ 64 <999000000>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp02 {
+ opp-hz = /bits/ 64 <1402000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp03 {
+ opp-hz = /bits/ 64 <1709000000>;
+ opp-microvolt = <1000000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp04 {
+ opp-hz = /bits/ 64 <1844000000>;
+ opp-microvolt = <1100000>;
+ clock-latency-ns = <300000>;
+ };
+ };
+
+ cluster1_opp: opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp10 {
+ opp-hz = /bits/ 64 <903000000>;
+ opp-microvolt = <700000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp11 {
+ opp-hz = /bits/ 64 <1421000000>;
+ opp-microvolt = <800000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp12 {
+ opp-hz = /bits/ 64 <1805000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp13 {
+ opp-hz = /bits/ 64 <2112000000>;
+ opp-microvolt = <1000000>;
+ clock-latency-ns = <300000>;
+ };
+
+ opp14 {
+ opp-hz = /bits/ 64 <2362000000>;
+ opp-microvolt = <1100000>;
+ clock-latency-ns = <300000>;
+ };
+ };
+
gic: interrupt-controller@e82b0000 {
compatible = "arm,gic-400";
reg = <0x0 0xe82b1000 0 0x1000>, /* GICD */
@@ -274,6 +365,21 @@
#reset-cells = <2>;
};
+ mailbox: mailbox@e896b000 {
+ compatible = "hisilicon,hi3660-mbox";
+ reg = <0x0 0xe896b000 0x0 0x1000>;
+ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+ #mbox-cells = <3>;
+ };
+
+ stub_clock: stub_clock@e896b500 {
+ compatible = "hisilicon,hi3660-stub-clk";
+ reg = <0x0 0xe896b500 0x0 0x0100>;
+ #clock-cells = <1>;
+ mboxes = <&mailbox 13 3 0>;
+ };
+
dual_timer0: timer@fff14000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x0 0xfff14000 0x0 0x1000>;
@@ -872,6 +978,8 @@
0x0 0x02000000>;
num-lanes = <1>;
#interrupt-cells = <1>;
+ interrupts = <0 283 4>;
+ interrupt-names = "msi";
interrupt-map-mask = <0xf800 0 0 7>;
interrupt-map = <0x0 0 0 1
&gic GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
@@ -972,5 +1080,44 @@
interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
#thermal-sensor-cells = <1>;
};
+
+ thermal-zones {
+
+ cls0: cls0 {
+ polling-delay = <1000>;
+ polling-delay-passive = <100>;
+ sustainable-power = <4500>;
+
+ /* sensor ID */
+ thermal-sensors = <&tsensor 1>;
+
+ trips {
+ threshold: trip-point@0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ target: trip-point@1 {
+ temperature = <75000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&target>;
+ contribution = <1024>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ map1 {
+ trip = <&target>;
+ contribution = <512>;
+ cooling-device = <&cpu4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
};
};
diff --git a/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts b/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts
index 4d5d644..d30f6eb 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts
+++ b/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts
@@ -11,6 +11,7 @@
#include <dt-bindings/gpio/gpio.h>
#include "hi3798cv200.dtsi"
+#include "poplar-pinctrl.dtsi"
/ {
model = "HiSilicon Poplar Development Board";
@@ -61,6 +62,33 @@
default-state = "off";
};
};
+
+ reg_pcie: regulator-pcie {
+ compatible = "regulator-fixed";
+ regulator-name = "3V3_PCIE0";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio6 7 0>;
+ enable-active-high;
+ };
+};
+
+&ehci {
+ status = "okay";
+};
+
+&emmc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_pins_1 &emmc_pins_2
+ &emmc_pins_3 &emmc_pins_4>;
+ fifo-depth = <256>;
+ clock-frequency = <200000000>;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ non-removable;
+ bus-width = <8>;
+ status = "okay";
};
&gmac1 {
@@ -146,6 +174,16 @@
status = "okay";
};
+&ohci {
+ status = "okay";
+};
+
+&pcie {
+ reset-gpios = <&gpio4 4 GPIO_ACTIVE_HIGH>;
+ vpcie-supply = <&reg_pcie>;
+ status = "okay";
+};
+
&sd0 {
bus-width = <4>;
cap-sd-highspeed;
diff --git a/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi b/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi
index 962bd79..7c0fddd 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi
@@ -8,7 +8,9 @@
*/
#include <dt-bindings/clock/histb-clock.h>
+#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy.h>
#include <dt-bindings/reset/ti-syscon.h>
/ {
@@ -106,6 +108,113 @@
#reset-cells = <2>;
};
+ perictrl: peripheral-controller@8a20000 {
+ compatible = "hisilicon,hi3798cv200-perictrl", "syscon",
+ "simple-mfd";
+ reg = <0x8a20000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x8a20000 0x1000>;
+
+ usb2_phy1: usb2-phy@120 {
+ compatible = "hisilicon,hi3798cv200-usb2-phy";
+ reg = <0x120 0x4>;
+ clocks = <&crg HISTB_USB2_PHY1_REF_CLK>;
+ resets = <&crg 0xbc 4>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb2_phy1_port0: phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ resets = <&crg 0xbc 8>;
+ };
+
+ usb2_phy1_port1: phy@1 {
+ reg = <1>;
+ #phy-cells = <0>;
+ resets = <&crg 0xbc 9>;
+ };
+ };
+
+ usb2_phy2: usb2-phy@124 {
+ compatible = "hisilicon,hi3798cv200-usb2-phy";
+ reg = <0x124 0x4>;
+ clocks = <&crg HISTB_USB2_PHY2_REF_CLK>;
+ resets = <&crg 0xbc 6>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usb2_phy2_port0: phy@0 {
+ reg = <0>;
+ #phy-cells = <0>;
+ resets = <&crg 0xbc 10>;
+ };
+ };
+
+ combphy0: phy@850 {
+ compatible = "hisilicon,hi3798cv200-combphy";
+ reg = <0x850 0x8>;
+ #phy-cells = <1>;
+ clocks = <&crg HISTB_COMBPHY0_CLK>;
+ resets = <&crg 0x188 4>;
+ assigned-clocks = <&crg HISTB_COMBPHY0_CLK>;
+ assigned-clock-rates = <100000000>;
+ hisilicon,fixed-mode = <PHY_TYPE_USB3>;
+ };
+
+ combphy1: phy@858 {
+ compatible = "hisilicon,hi3798cv200-combphy";
+ reg = <0x858 0x8>;
+ #phy-cells = <1>;
+ clocks = <&crg HISTB_COMBPHY1_CLK>;
+ resets = <&crg 0x188 12>;
+ assigned-clocks = <&crg HISTB_COMBPHY1_CLK>;
+ assigned-clock-rates = <100000000>;
+ hisilicon,mode-select-bits = <0x0008 11 (0x3 << 11)>;
+ };
+ };
+
+ pmx0: pinconf@8a21000 {
+ compatible = "pinconf-single";
+ reg = <0x8a21000 0x180>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <7>;
+ pinctrl-single,gpio-range = <
+ &range 0 8 2 /* GPIO 0 */
+ &range 8 1 0 /* GPIO 1 */
+ &range 9 4 2
+ &range 13 1 0
+ &range 14 1 1
+ &range 15 1 0
+ &range 16 5 0 /* GPIO 2 */
+ &range 21 3 1
+ &range 24 4 1 /* GPIO 3 */
+ &range 28 2 2
+ &range 86 1 1
+ &range 87 1 0
+ &range 30 4 2 /* GPIO 4 */
+ &range 34 3 0
+ &range 37 1 2
+ &range 38 3 2 /* GPIO 6 */
+ &range 41 5 0
+ &range 46 8 1 /* GPIO 7 */
+ &range 54 8 1 /* GPIO 8 */
+ &range 64 7 1 /* GPIO 9 */
+ &range 71 1 0
+ &range 72 6 1 /* GPIO 10 */
+ &range 78 1 0
+ &range 79 1 1
+ &range 80 6 1 /* GPIO 11 */
+ &range 70 2 1
+ &range 88 8 0 /* GPIO 12 */
+ >;
+
+ range: gpio-range {
+ #pinctrl-single,gpio-range-cells = <3>;
+ };
+ };
+
uart0: serial@8b00000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0x8b00000 0x1000>;
@@ -205,12 +314,17 @@
};
emmc: mmc@9830000 {
- compatible = "snps,dw-mshc";
+ compatible = "hisilicon,hi3798cv200-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";
+ <&crg HISTB_MMC_BIU_CLK>,
+ <&crg HISTB_MMC_SAMPLE_CLK>,
+ <&crg HISTB_MMC_DRV_CLK>;
+ clock-names = "ciu", "biu", "ciu-sample", "ciu-drive";
+ resets = <&crg 0xa0 4>;
+ reset-names = "reset";
+ status = "disabled";
};
gpio0: gpio@8b20000 {
@@ -221,6 +335,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx0 0 0 8>;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -234,6 +349,13 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <
+ &pmx0 0 8 1
+ &pmx0 1 9 4
+ &pmx0 5 13 1
+ &pmx0 6 14 1
+ &pmx0 7 15 1
+ >;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -247,6 +369,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx0 0 16 5 &pmx0 5 21 3>;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -260,6 +383,12 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <
+ &pmx0 0 24 4
+ &pmx0 4 28 2
+ &pmx0 6 86 1
+ &pmx0 7 87 1
+ >;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -273,6 +402,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx0 0 30 4 &pmx0 4 34 3 &pmx0 7 37 1>;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -299,6 +429,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx0 0 38 3 &pmx0 0 41 5>;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -312,6 +443,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx0 0 46 8>;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -325,6 +457,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx0 0 54 8>;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -338,6 +471,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx0 0 64 7 &pmx0 71 1>;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -351,6 +485,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx0 0 72 6 &pmx0 6 78 1 &pmx0 7 79 1>;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -364,6 +499,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx0 0 80 6 &pmx0 6 70 2>;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -377,6 +513,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&pmx0 0 88 8>;
clocks = <&crg HISTB_APB_CLK>;
clock-names = "apb_pclk";
status = "disabled";
@@ -419,5 +556,67 @@
clocks = <&sysctrl HISTB_IR_CLK>;
status = "disabled";
};
+
+ pcie: pcie@9860000 {
+ compatible = "hisilicon,hi3798cv200-pcie";
+ reg = <0x9860000 0x1000>,
+ <0x0 0x2000>,
+ <0x2000000 0x01000000>;
+ reg-names = "control", "rc-dbi", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ bus-range = <0 15>;
+ num-lanes = <1>;
+ ranges = <0x81000000 0x0 0x00000000 0x4f00000 0x0 0x100000
+ 0x82000000 0x0 0x3000000 0x3000000 0x0 0x01f00000>;
+ interrupts = <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic 0 131 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_PCIE_AUX_CLK>,
+ <&crg HISTB_PCIE_PIPE_CLK>,
+ <&crg HISTB_PCIE_SYS_CLK>,
+ <&crg HISTB_PCIE_BUS_CLK>;
+ clock-names = "aux", "pipe", "sys", "bus";
+ resets = <&crg 0x18c 6>, <&crg 0x18c 5>, <&crg 0x18c 4>;
+ reset-names = "soft", "sys", "bus";
+ phys = <&combphy1 PHY_TYPE_PCIE>;
+ phy-names = "phy";
+ status = "disabled";
+ };
+
+ ohci: ohci@9880000 {
+ compatible = "generic-ohci";
+ reg = <0x9880000 0x10000>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_USB2_BUS_CLK>,
+ <&crg HISTB_USB2_12M_CLK>,
+ <&crg HISTB_USB2_48M_CLK>;
+ clock-names = "bus", "clk12", "clk48";
+ resets = <&crg 0xb8 12>;
+ reset-names = "bus";
+ phys = <&usb2_phy1_port0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci: ehci@9890000 {
+ compatible = "generic-ehci";
+ reg = <0x9890000 0x10000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&crg HISTB_USB2_BUS_CLK>,
+ <&crg HISTB_USB2_PHY_CLK>,
+ <&crg HISTB_USB2_UTMI_CLK>;
+ clock-names = "bus", "phy", "utmi";
+ resets = <&crg 0xb8 12>,
+ <&crg 0xb8 16>,
+ <&crg 0xb8 13>;
+ reset-names = "bus", "phy", "utmi";
+ phys = <&usb2_phy1_port0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm64/boot/dts/hisilicon/hip06-d03.dts b/arch/arm64/boot/dts/hisilicon/hip06-d03.dts
index 9af6330..a95c6f5 100644
--- a/arch/arm64/boot/dts/hisilicon/hip06-d03.dts
+++ b/arch/arm64/boot/dts/hisilicon/hip06-d03.dts
@@ -25,6 +25,14 @@
chosen { };
};
+&ipmi0 {
+ status = "ok";
+};
+
+&uart0 {
+ status = "ok";
+};
+
&eth0 {
status = "ok";
};
diff --git a/arch/arm64/boot/dts/hisilicon/hip06.dtsi b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
index 35202eb..d78a6a7 100644
--- a/arch/arm64/boot/dts/hisilicon/hip06.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
@@ -350,6 +350,27 @@
#size-cells = <2>;
ranges;
+ isa@a01b0000 {
+ compatible = "hisilicon,hip06-lpc";
+ #size-cells = <1>;
+ #address-cells = <2>;
+ reg = <0x0 0xa01b0000 0x0 0x1000>;
+
+ ipmi0: bt@e4 {
+ compatible = "ipmi-bt";
+ device_type = "ipmi";
+ reg = <0x01 0xe4 0x04>;
+ status = "disabled";
+ };
+
+ uart0: lpc-uart@2f8 {
+ compatible = "ns16550a";
+ clock-frequency = <1843200>;
+ reg = <0x01 0x2f8 0x08>;
+ status = "disabled";
+ };
+ };
+
refclk: refclk {
compatible = "fixed-clock";
clock-frequency = <50000000>;
diff --git a/arch/arm64/boot/dts/hisilicon/hip07-d05.dts b/arch/arm64/boot/dts/hisilicon/hip07-d05.dts
index fe7c16c..21147e8 100644
--- a/arch/arm64/boot/dts/hisilicon/hip07-d05.dts
+++ b/arch/arm64/boot/dts/hisilicon/hip07-d05.dts
@@ -57,6 +57,10 @@
status = "ok";
};
+&ipmi0 {
+ status = "ok";
+};
+
&usb_ohci {
status = "ok";
};
diff --git a/arch/arm64/boot/dts/hisilicon/hip07.dtsi b/arch/arm64/boot/dts/hisilicon/hip07.dtsi
index 0600a6a..9c10030a 100644
--- a/arch/arm64/boot/dts/hisilicon/hip07.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip07.dtsi
@@ -1114,6 +1114,20 @@
#size-cells = <2>;
ranges;
+ isa@a01b0000 {
+ compatible = "hisilicon,hip07-lpc";
+ #size-cells = <1>;
+ #address-cells = <2>;
+ reg = <0x0 0xa01b0000 0x0 0x1000>;
+
+ ipmi0: bt@e4 {
+ compatible = "ipmi-bt";
+ device_type = "ipmi";
+ reg = <0x01 0xe4 0x04>;
+ status = "disabled";
+ };
+ };
+
uart0: uart@602b0000 {
compatible = "arm,sbsa-uart";
reg = <0x0 0x602b0000 0x0 0x1000>;
diff --git a/arch/arm64/boot/dts/hisilicon/poplar-pinctrl.dtsi b/arch/arm64/boot/dts/hisilicon/poplar-pinctrl.dtsi
new file mode 100644
index 0000000..7bb19e4
--- /dev/null
+++ b/arch/arm64/boot/dts/hisilicon/poplar-pinctrl.dtsi
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Pinctrl dts file for HiSilicon Poplar board
+ *
+ * Copyright (c) 2016-2018 HiSilicon Technologies Co., Ltd.
+ */
+
+#include <dt-bindings/pinctrl/hisi.h>
+
+/* value, enable bits, disable bits, mask */
+#define PINCTRL_PULLDOWN(value, enable, disable, mask) \
+ (value << 13) (enable << 13) (disable << 13) (mask << 13)
+#define PINCTRL_PULLUP(value, enable, disable, mask) \
+ (value << 12) (enable << 12) (disable << 12) (mask << 12)
+#define PINCTRL_SLEW_RATE(value, mask) (value << 8) (mask << 8)
+#define PINCTRL_DRV_STRENGTH(value, mask) (value << 4) (mask << 4)
+
+&pmx0 {
+ emmc_pins_1: emmc-pins-1 {
+ pinctrl-single,pins = <
+ 0x000 MUX_M2
+ 0x004 MUX_M2
+ 0x008 MUX_M2
+ 0x00c MUX_M2
+ 0x010 MUX_M2
+ 0x014 MUX_M2
+ 0x018 MUX_M2
+ 0x01c MUX_M2
+ 0x024 MUX_M2
+ >;
+ pinctrl-single,bias-pulldown = <
+ PINCTRL_PULLDOWN(0, 1, 0, 1)
+ >;
+ pinctrl-single,bias-pullup = <
+ PINCTRL_PULLUP(0, 1, 0, 1)
+ >;
+ pinctrl-single,slew-rate = <
+ PINCTRL_SLEW_RATE(1, 1)
+ >;
+ pinctrl-single,drive-strength = <
+ PINCTRL_DRV_STRENGTH(0xb, 0xf)
+ >;
+ };
+
+ emmc_pins_2: emmc-pins-2 {
+ pinctrl-single,pins = <
+ 0x028 MUX_M2
+ >;
+ pinctrl-single,bias-pulldown = <
+ PINCTRL_PULLDOWN(0, 1, 0, 1)
+ >;
+ pinctrl-single,bias-pullup = <
+ PINCTRL_PULLUP(0, 1, 0, 1)
+ >;
+ pinctrl-single,slew-rate = <
+ PINCTRL_SLEW_RATE(1, 1)
+ >;
+ pinctrl-single,drive-strength = <
+ PINCTRL_DRV_STRENGTH(0x9, 0xf)
+ >;
+ };
+
+ emmc_pins_3: emmc-pins-3 {
+ pinctrl-single,pins = <
+ 0x02c MUX_M2
+ >;
+ pinctrl-single,bias-pulldown = <
+ PINCTRL_PULLDOWN(0, 1, 0, 1)
+ >;
+ pinctrl-single,bias-pullup = <
+ PINCTRL_PULLUP(0, 1, 0, 1)
+ >;
+ pinctrl-single,slew-rate = <
+ PINCTRL_SLEW_RATE(1, 1)
+ >;
+ pinctrl-single,drive-strength = <
+ PINCTRL_DRV_STRENGTH(3, 3)
+ >;
+ };
+
+ emmc_pins_4: emmc-pins-4 {
+ pinctrl-single,pins = <
+ 0x030 MUX_M2
+ >;
+ pinctrl-single,bias-pulldown = <
+ PINCTRL_PULLDOWN(1, 1, 0, 1)
+ >;
+ pinctrl-single,bias-pullup = <
+ PINCTRL_PULLUP(0, 1, 0, 1)
+ >;
+ pinctrl-single,slew-rate = <
+ PINCTRL_SLEW_RATE(1, 1)
+ >;
+ pinctrl-single,drive-strength = <
+ PINCTRL_DRV_STRENGTH(3, 3)
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/marvell/Makefile b/arch/arm64/boot/dts/marvell/Makefile
index cb454be..ea9d49f 100644
--- a/arch/arm64/boot/dts/marvell/Makefile
+++ b/arch/arm64/boot/dts/marvell/Makefile
@@ -1,8 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-# Berlin SoC Family
-dtb-$(CONFIG_ARCH_BERLIN) += berlin4ct-dmp.dtb
-dtb-$(CONFIG_ARCH_BERLIN) += berlin4ct-stb.dtb
-
# Mvebu SoC Family
dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-db.dtb
dtb-$(CONFIG_ARCH_MVEBU) += armada-3720-espressobin.dtb
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
index ef7fd2c..3ab25ad 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-espressobin.dts
@@ -63,6 +63,33 @@
status = "okay";
};
+&spi0 {
+ status = "okay";
+
+ flash@0 {
+ reg = <0>;
+ compatible = "winbond,w25q32dw", "jedec,spi-flash";
+ spi-max-frequency = <104000000>;
+ m25p,fast-read;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "uboot";
+ reg = <0 0x180000>;
+ };
+
+ partition@180000 {
+ label = "ubootenv";
+ reg = <0x180000 0x10000>;
+ };
+ };
+ };
+};
+
/* Exported on the micro USB connector J5 through an FTDI */
&uart0 {
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index 97207a6..3353252 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -148,10 +148,13 @@
compatible = "marvell,armada3710-nb-pinctrl",
"syscon", "simple-mfd";
reg = <0x13800 0x100>, <0x13C00 0x20>;
+ /* MPP1[19:0] */
gpionb: gpio {
#gpio-cells = <2>;
gpio-ranges = <&pinctrl_nb 0 0 36>;
gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
interrupts =
<GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
@@ -209,10 +212,13 @@
compatible = "marvell,armada3710-sb-pinctrl",
"syscon", "simple-mfd";
reg = <0x18800 0x100>, <0x18C00 0x20>;
+ /* MPP2[23:0] */
gpiosb: gpio {
#gpio-cells = <2>;
gpio-ranges = <&pinctrl_sb 0 0 30>;
gpio-controller;
+ interrupt-controller;
+ #interrupt-cells = <2>;
interrupts =
<GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm64/boot/dts/marvell/armada-7040-db.dts b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
index d6bec05..412efdb 100644
--- a/arch/arm64/boot/dts/marvell/armada-7040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-7040-db.dts
@@ -242,6 +242,11 @@
phy-mode = "10gbase-kr";
/* Generic PHY, providing serdes lanes */
phys = <&cp0_comphy2 0>;
+
+ fixed-link {
+ speed = <10000>;
+ full-duplex;
+ };
};
&cp0_eth1 {
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-db.dts b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
index 5689fb2..1bac437 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-db.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-db.dts
@@ -177,6 +177,11 @@
&cp0_eth0 {
status = "okay";
phy-mode = "10gbase-kr";
+
+ fixed-link {
+ speed = <10000>;
+ full-duplex;
+ };
};
&cp0_eth2 {
@@ -303,6 +308,11 @@
&cp1_eth0 {
status = "okay";
phy-mode = "10gbase-kr";
+
+ fixed-link {
+ speed = <10000>;
+ full-duplex;
+ };
};
&cp1_eth1 {
diff --git a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
index 81de03e..a66958ff 100644
--- a/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
+++ b/arch/arm64/boot/dts/marvell/armada-8040-mcbin.dts
@@ -27,6 +27,7 @@
ethernet0 = &cp0_eth0;
ethernet1 = &cp1_eth0;
ethernet2 = &cp1_eth1;
+ ethernet3 = &cp1_eth2;
};
/* Regulator labels correspond with schematics */
@@ -64,6 +65,42 @@
compatible = "usb-nop-xceiv";
vcc-supply = <&v_5v0_usb3_hst_vbus>;
};
+
+ sfp_eth0: sfp-eth0 {
+ /* CON15,16 - CPM lane 4 */
+ compatible = "sff,sfp";
+ i2c-bus = <&sfpp0_i2c>;
+ los-gpio = <&cp1_gpio1 28 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpio = <&cp1_gpio1 27 GPIO_ACTIVE_LOW>;
+ tx-disable-gpio = <&cp1_gpio1 29 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpio = <&cp1_gpio1 26 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_sfpp0_pins>;
+ };
+
+ sfp_eth1: sfp-eth1 {
+ /* CON17,18 - CPS lane 4 */
+ compatible = "sff,sfp";
+ i2c-bus = <&sfpp1_i2c>;
+ los-gpio = <&cp1_gpio1 8 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpio = <&cp1_gpio1 11 GPIO_ACTIVE_LOW>;
+ tx-disable-gpio = <&cp1_gpio1 10 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpio = <&cp0_gpio2 30 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp1_sfpp1_pins &cp0_sfpp1_pins>;
+ };
+
+ sfp_eth3: sfp-eth3 {
+ /* CON3,4 - CPS lane 5 */
+ compatible = "sff,sfp";
+ i2c-bus = <&sfp_1g_i2c>;
+ los-gpio = <&cp0_gpio2 22 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpio = <&cp0_gpio2 21 GPIO_ACTIVE_LOW>;
+ tx-disable-gpio = <&cp1_gpio1 24 GPIO_ACTIVE_HIGH>;
+ tx-fault-gpio = <&cp0_gpio2 19 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cp0_sfp_1g_pins &cp1_sfp_1g_pins>;
+ };
};
&uart0 {
@@ -171,6 +208,10 @@
marvell,pins = "mpp47";
marvell,function = "gpio";
};
+ cp0_sfp_1g_pins: sfp-1g-pins {
+ marvell,pins = "mpp51", "mpp53", "mpp54";
+ marvell,function = "gpio";
+ };
cp0_pcie_pins: pcie-pins {
marvell,pins = "mpp52";
marvell,function = "gpio";
@@ -180,6 +221,10 @@
"mpp60", "mpp61";
marvell,function = "sdio";
};
+ cp0_sfpp1_pins: sfpp1-pins {
+ marvell,pins = "mpp62";
+ marvell,function = "gpio";
+ };
};
&cp0_xmdio {
@@ -188,11 +233,13 @@
phy0: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c45";
reg = <0>;
+ sfp = <&sfp_eth0>;
};
phy8: ethernet-phy@8 {
compatible = "ethernet-phy-ieee802.3-c45";
reg = <8>;
+ sfp = <&sfp_eth1>;
};
};
@@ -257,7 +304,22 @@
phys = <&cp1_comphy0 1>;
};
+&cp1_eth2 {
+ /* CPS Lane 5 */
+ status = "okay";
+ /* Network PHY */
+ phy-mode = "2500base-x";
+ managed = "in-band-status";
+ /* Generic PHY, providing serdes lanes */
+ phys = <&cp1_comphy5 2>;
+ sfp = <&sfp_eth3>;
+};
+
&cp1_pinctrl {
+ cp1_sfpp1_pins: sfpp1-pins {
+ marvell,pins = "mpp8", "mpp10", "mpp11";
+ marvell,function = "gpio";
+ };
cp1_spi1_pins: spi1-pins {
marvell,pins = "mpp12", "mpp13", "mpp14", "mpp15", "mpp16";
marvell,function = "spi1";
@@ -266,6 +328,14 @@
marvell,pins = "mpp6", "mpp7";
marvell,function = "uart0";
};
+ cp1_sfp_1g_pins: sfp-1g-pins {
+ marvell,pins = "mpp24";
+ marvell,function = "gpio";
+ };
+ cp1_sfpp0_pins: sfpp0-pins {
+ marvell,pins = "mpp26", "mpp27", "mpp28", "mpp29";
+ marvell,function = "gpio";
+ };
};
/* J27 UART header */
diff --git a/arch/arm64/boot/dts/marvell/armada-cp110.dtsi b/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
index ed2f123..7dabe25 100644
--- a/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-cp110.dtsi
@@ -236,6 +236,7 @@
compatible = "marvell,armada-8k-ahci",
"generic-ahci";
reg = <0x540000 0x30000>;
+ dma-coherent;
interrupts = <ICU_GRP_NSR 107 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&CP110_LABEL(clk) 1 15>,
<&CP110_LABEL(clk) 1 16>;
diff --git a/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts b/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts
deleted file mode 100644
index fae6c69..0000000
--- a/arch/arm64/boot/dts/marvell/berlin4ct-dmp.dts
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2015 Marvell Technology Group Ltd.
- *
- * Author: Jisheng Zhang <jszhang@marvell.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 "berlin4ct.dtsi"
-
-/ {
- model = "Marvell BG4CT DMP board";
- compatible = "marvell,berlin4ct-dmp", "marvell,berlin4ct", "marvell,berlin";
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- memory@1000000 {
- device_type = "memory";
- /* the first 16MB is for firmwares' usage */
- reg = <0 0x01000000 0 0x7f000000>;
- };
-};
-
-&uart0 {
- status = "okay";
-};
diff --git a/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts b/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts
deleted file mode 100644
index d47edad..0000000
--- a/arch/arm64/boot/dts/marvell/berlin4ct-stb.dts
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2015 Marvell Technology Group Ltd.
- *
- * Author: Jisheng Zhang <jszhang@marvell.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 "berlin4ct.dtsi"
-
-/ {
- model = "Marvell BG4CT STB board";
- compatible = "marvell,berlin4ct-stb", "marvell,berlin4ct", "marvell,berlin";
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- memory@1000000 {
- device_type = "memory";
- /* the first 16MB is for firmwares' usage */
- reg = <0 0x01000000 0 0x7f000000>;
- };
-};
-
-&uart0 {
- status = "okay";
-};
diff --git a/arch/arm64/boot/dts/mediatek/mt2712-pinfunc.h b/arch/arm64/boot/dts/mediatek/mt2712-pinfunc.h
new file mode 100644
index 0000000..1b4cb0c
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt2712-pinfunc.h
@@ -0,0 +1,1123 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ * Author: Zhiyong Tao <zhiyong.tao@mediatek.com>
+ *
+ */
+#ifndef __DTS_MT2712_PINFUNC_H
+#define __DTS_MT2712_PINFUNC_H
+
+#include <dt-bindings/pinctrl/mt65xx.h>
+
+#define MT2712_PIN_0_EINT0__FUNC_GPIO0 (MTK_PIN_NO(0) | 0)
+#define MT2712_PIN_0_EINT0__FUNC_EINT0 (MTK_PIN_NO(0) | 1)
+#define MT2712_PIN_0_EINT0__FUNC_MBIST_DIAG_SCANOUT (MTK_PIN_NO(0) | 2)
+#define MT2712_PIN_0_EINT0__FUNC_DSIA_TE (MTK_PIN_NO(0) | 3)
+#define MT2712_PIN_0_EINT0__FUNC_DSIC_TE (MTK_PIN_NO(0) | 4)
+#define MT2712_PIN_0_EINT0__FUNC_DIN_D3 (MTK_PIN_NO(0) | 5)
+#define MT2712_PIN_0_EINT0__FUNC_PURE_HW_PROTECT (MTK_PIN_NO(0) | 6)
+
+#define MT2712_PIN_1_EINT1__FUNC_GPIO1 (MTK_PIN_NO(1) | 0)
+#define MT2712_PIN_1_EINT1__FUNC_EINT1 (MTK_PIN_NO(1) | 1)
+#define MT2712_PIN_1_EINT1__FUNC_IR_IN (MTK_PIN_NO(1) | 2)
+#define MT2712_PIN_1_EINT1__FUNC_DSIB_TE (MTK_PIN_NO(1) | 3)
+#define MT2712_PIN_1_EINT1__FUNC_DSID_TE (MTK_PIN_NO(1) | 4)
+#define MT2712_PIN_1_EINT1__FUNC_DIN_D4 (MTK_PIN_NO(1) | 5)
+
+#define MT2712_PIN_2_EINT2__FUNC_GPIO2 (MTK_PIN_NO(2) | 0)
+#define MT2712_PIN_2_EINT2__FUNC_EINT2 (MTK_PIN_NO(2) | 1)
+#define MT2712_PIN_2_EINT2__FUNC_IR_IN (MTK_PIN_NO(2) | 2)
+#define MT2712_PIN_2_EINT2__FUNC_LCM_RST1 (MTK_PIN_NO(2) | 3)
+#define MT2712_PIN_2_EINT2__FUNC_DIN_D5 (MTK_PIN_NO(2) | 5)
+
+#define MT2712_PIN_3_EINT3__FUNC_GPIO3 (MTK_PIN_NO(3) | 0)
+#define MT2712_PIN_3_EINT3__FUNC_EINT3 (MTK_PIN_NO(3) | 1)
+#define MT2712_PIN_3_EINT3__FUNC_IR_IN (MTK_PIN_NO(3) | 2)
+#define MT2712_PIN_3_EINT3__FUNC_LCM_RST0 (MTK_PIN_NO(3) | 3)
+#define MT2712_PIN_3_EINT3__FUNC_DIN_D6 (MTK_PIN_NO(3) | 5)
+
+#define MT2712_PIN_4_PWM0__FUNC_GPIO4 (MTK_PIN_NO(4) | 0)
+#define MT2712_PIN_4_PWM0__FUNC_PWM0 (MTK_PIN_NO(4) | 1)
+#define MT2712_PIN_4_PWM0__FUNC_DISP0_PWM (MTK_PIN_NO(4) | 2)
+#define MT2712_PIN_4_PWM0__FUNC_DISP1_PWM (MTK_PIN_NO(4) | 3)
+#define MT2712_PIN_4_PWM0__FUNC_DIN_CLK (MTK_PIN_NO(4) | 5)
+
+#define MT2712_PIN_5_PWM1__FUNC_GPIO5 (MTK_PIN_NO(5) | 0)
+#define MT2712_PIN_5_PWM1__FUNC_PWM1 (MTK_PIN_NO(5) | 1)
+#define MT2712_PIN_5_PWM1__FUNC_DISP1_PWM (MTK_PIN_NO(5) | 2)
+#define MT2712_PIN_5_PWM1__FUNC_DISP0_PWM (MTK_PIN_NO(5) | 3)
+#define MT2712_PIN_5_PWM1__FUNC_DIN_VSYNC (MTK_PIN_NO(5) | 5)
+
+#define MT2712_PIN_6_PWM2__FUNC_GPIO6 (MTK_PIN_NO(6) | 0)
+#define MT2712_PIN_6_PWM2__FUNC_PWM2 (MTK_PIN_NO(6) | 1)
+#define MT2712_PIN_6_PWM2__FUNC_DISP0_PWM (MTK_PIN_NO(6) | 2)
+#define MT2712_PIN_6_PWM2__FUNC_DISP1_PWM (MTK_PIN_NO(6) | 3)
+#define MT2712_PIN_6_PWM2__FUNC_DISP2_PWM (MTK_PIN_NO(6) | 4)
+#define MT2712_PIN_6_PWM2__FUNC_DIN_HSYNC (MTK_PIN_NO(6) | 5)
+
+#define MT2712_PIN_7_PWM3__FUNC_GPIO7 (MTK_PIN_NO(7) | 0)
+#define MT2712_PIN_7_PWM3__FUNC_PWM3 (MTK_PIN_NO(7) | 1)
+#define MT2712_PIN_7_PWM3__FUNC_DISP1_PWM (MTK_PIN_NO(7) | 2)
+#define MT2712_PIN_7_PWM3__FUNC_DISP0_PWM (MTK_PIN_NO(7) | 3)
+#define MT2712_PIN_7_PWM3__FUNC_LCM_RST2 (MTK_PIN_NO(7) | 4)
+#define MT2712_PIN_7_PWM3__FUNC_DIN_D0 (MTK_PIN_NO(7) | 5)
+
+#define MT2712_PIN_8_PWM4__FUNC_GPIO8 (MTK_PIN_NO(8) | 0)
+#define MT2712_PIN_8_PWM4__FUNC_PWM4 (MTK_PIN_NO(8) | 1)
+#define MT2712_PIN_8_PWM4__FUNC_DISP0_PWM (MTK_PIN_NO(8) | 2)
+#define MT2712_PIN_8_PWM4__FUNC_DISP1_PWM (MTK_PIN_NO(8) | 3)
+#define MT2712_PIN_8_PWM4__FUNC_DSIA_TE (MTK_PIN_NO(8) | 4)
+#define MT2712_PIN_8_PWM4__FUNC_DIN_D1 (MTK_PIN_NO(8) | 5)
+
+#define MT2712_PIN_9_PWM5__FUNC_GPIO9 (MTK_PIN_NO(9) | 0)
+#define MT2712_PIN_9_PWM5__FUNC_PWM5 (MTK_PIN_NO(9) | 1)
+#define MT2712_PIN_9_PWM5__FUNC_DISP1_PWM (MTK_PIN_NO(9) | 2)
+#define MT2712_PIN_9_PWM5__FUNC_DISP0_PWM (MTK_PIN_NO(9) | 3)
+#define MT2712_PIN_9_PWM5__FUNC_DSIB_TE (MTK_PIN_NO(9) | 4)
+#define MT2712_PIN_9_PWM5__FUNC_DIN_D2 (MTK_PIN_NO(9) | 5)
+
+#define MT2712_PIN_10_PWM6__FUNC_GPIO10 (MTK_PIN_NO(10) | 0)
+#define MT2712_PIN_10_PWM6__FUNC_PWM6 (MTK_PIN_NO(10) | 1)
+#define MT2712_PIN_10_PWM6__FUNC_DISP0_PWM (MTK_PIN_NO(10) | 2)
+#define MT2712_PIN_10_PWM6__FUNC_DISP1_PWM (MTK_PIN_NO(10) | 3)
+#define MT2712_PIN_10_PWM6__FUNC_LCM_RST0 (MTK_PIN_NO(10) | 4)
+
+#define MT2712_PIN_11_PWM7__FUNC_GPIO11 (MTK_PIN_NO(11) | 0)
+#define MT2712_PIN_11_PWM7__FUNC_PWM7 (MTK_PIN_NO(11) | 1)
+#define MT2712_PIN_11_PWM7__FUNC_DISP1_PWM (MTK_PIN_NO(11) | 2)
+#define MT2712_PIN_11_PWM7__FUNC_DISP0_PWM (MTK_PIN_NO(11) | 3)
+#define MT2712_PIN_11_PWM7__FUNC_LCM_RST1 (MTK_PIN_NO(11) | 4)
+
+#define MT2712_PIN_12_IDDIG_P0__FUNC_GPIO12 (MTK_PIN_NO(12) | 0)
+#define MT2712_PIN_12_IDDIG_P0__FUNC_IDDIG_A (MTK_PIN_NO(12) | 1)
+#define MT2712_PIN_12_IDDIG_P0__FUNC_DIN_D7 (MTK_PIN_NO(12) | 5)
+
+#define MT2712_PIN_13_DRV_VBUS_P0__FUNC_GPIO13 (MTK_PIN_NO(13) | 0)
+#define MT2712_PIN_13_DRV_VBUS_P0__FUNC_DRV_VBUS_A (MTK_PIN_NO(13) | 1)
+
+#define MT2712_PIN_14_IDDIG_P1__FUNC_GPIO14 (MTK_PIN_NO(14) | 0)
+#define MT2712_PIN_14_IDDIG_P1__FUNC_IDDIG_B (MTK_PIN_NO(14) | 1)
+
+#define MT2712_PIN_15_DRV_VBUS_P1__FUNC_GPIO15 (MTK_PIN_NO(15) | 0)
+#define MT2712_PIN_15_DRV_VBUS_P1__FUNC_DRV_VBUS_B (MTK_PIN_NO(15) | 1)
+
+#define MT2712_PIN_16_DRV_VBUS_P2__FUNC_GPIO16 (MTK_PIN_NO(16) | 0)
+#define MT2712_PIN_16_DRV_VBUS_P2__FUNC_DRV_VBUS_C (MTK_PIN_NO(16) | 1)
+
+#define MT2712_PIN_17_DRV_VBUS_P3__FUNC_GPIO17 (MTK_PIN_NO(17) | 0)
+#define MT2712_PIN_17_DRV_VBUS_P3__FUNC_DRV_VBUS_D (MTK_PIN_NO(17) | 1)
+
+#define MT2712_PIN_18_KPROW0__FUNC_GPIO18 (MTK_PIN_NO(18) | 0)
+#define MT2712_PIN_18_KPROW0__FUNC_KROW0 (MTK_PIN_NO(18) | 1)
+
+#define MT2712_PIN_19_KPCOL0__FUNC_GPIO19 (MTK_PIN_NO(19) | 0)
+#define MT2712_PIN_19_KPCOL0__FUNC_KCOL0 (MTK_PIN_NO(19) | 1)
+
+#define MT2712_PIN_20_KPROW1__FUNC_GPIO20 (MTK_PIN_NO(20) | 0)
+#define MT2712_PIN_20_KPROW1__FUNC_KROW1 (MTK_PIN_NO(20) | 1)
+
+#define MT2712_PIN_21_KPCOL1__FUNC_GPIO21 (MTK_PIN_NO(21) | 0)
+#define MT2712_PIN_21_KPCOL1__FUNC_KCOL1 (MTK_PIN_NO(21) | 1)
+
+#define MT2712_PIN_22_KPROW2__FUNC_GPIO22 (MTK_PIN_NO(22) | 0)
+#define MT2712_PIN_22_KPROW2__FUNC_KROW2 (MTK_PIN_NO(22) | 1)
+#define MT2712_PIN_22_KPROW2__FUNC_DISP1_PWM (MTK_PIN_NO(22) | 2)
+
+#define MT2712_PIN_23_KPCOL2__FUNC_GPIO23 (MTK_PIN_NO(23) | 0)
+#define MT2712_PIN_23_KPCOL2__FUNC_KCOL2 (MTK_PIN_NO(23) | 1)
+#define MT2712_PIN_23_KPCOL2__FUNC_DISP0_PWM (MTK_PIN_NO(23) | 2)
+
+#define MT2712_PIN_24_CMMCLK__FUNC_GPIO24 (MTK_PIN_NO(24) | 0)
+#define MT2712_PIN_24_CMMCLK__FUNC_CMMCLK (MTK_PIN_NO(24) | 1)
+#define MT2712_PIN_24_CMMCLK__FUNC_DBG_MON_A_1_ (MTK_PIN_NO(24) | 7)
+
+#define MT2712_PIN_25_CM2MCLK__FUNC_GPIO25 (MTK_PIN_NO(25) | 0)
+#define MT2712_PIN_25_CM2MCLK__FUNC_CM2MCLK (MTK_PIN_NO(25) | 1)
+#define MT2712_PIN_25_CM2MCLK__FUNC_DBG_MON_A_2_ (MTK_PIN_NO(25) | 7)
+
+#define MT2712_PIN_26_PCM_TX__FUNC_GPIO26 (MTK_PIN_NO(26) | 0)
+#define MT2712_PIN_26_PCM_TX__FUNC_PCM1_DO (MTK_PIN_NO(26) | 1)
+#define MT2712_PIN_26_PCM_TX__FUNC_MRG_TX (MTK_PIN_NO(26) | 2)
+#define MT2712_PIN_26_PCM_TX__FUNC_DAI_TX (MTK_PIN_NO(26) | 3)
+#define MT2712_PIN_26_PCM_TX__FUNC_MRG_RX (MTK_PIN_NO(26) | 4)
+#define MT2712_PIN_26_PCM_TX__FUNC_DAI_RX (MTK_PIN_NO(26) | 5)
+#define MT2712_PIN_26_PCM_TX__FUNC_PCM1_DI (MTK_PIN_NO(26) | 6)
+#define MT2712_PIN_26_PCM_TX__FUNC_DBG_MON_A_3_ (MTK_PIN_NO(26) | 7)
+
+#define MT2712_PIN_27_PCM_CLK__FUNC_GPIO27 (MTK_PIN_NO(27) | 0)
+#define MT2712_PIN_27_PCM_CLK__FUNC_PCM1_CLK (MTK_PIN_NO(27) | 1)
+#define MT2712_PIN_27_PCM_CLK__FUNC_MRG_CLK (MTK_PIN_NO(27) | 2)
+#define MT2712_PIN_27_PCM_CLK__FUNC_DAI_CLK (MTK_PIN_NO(27) | 3)
+#define MT2712_PIN_27_PCM_CLK__FUNC_DBG_MON_A_4_ (MTK_PIN_NO(27) | 7)
+
+#define MT2712_PIN_28_PCM_RX__FUNC_GPIO28 (MTK_PIN_NO(28) | 0)
+#define MT2712_PIN_28_PCM_RX__FUNC_PCM1_DI (MTK_PIN_NO(28) | 1)
+#define MT2712_PIN_28_PCM_RX__FUNC_MRG_RX (MTK_PIN_NO(28) | 2)
+#define MT2712_PIN_28_PCM_RX__FUNC_DAI_RX (MTK_PIN_NO(28) | 3)
+#define MT2712_PIN_28_PCM_RX__FUNC_MRG_TX (MTK_PIN_NO(28) | 4)
+#define MT2712_PIN_28_PCM_RX__FUNC_DAI_TX (MTK_PIN_NO(28) | 5)
+#define MT2712_PIN_28_PCM_RX__FUNC_PCM1_DO (MTK_PIN_NO(28) | 6)
+#define MT2712_PIN_28_PCM_RX__FUNC_DBG_MON_A_5_ (MTK_PIN_NO(28) | 7)
+
+#define MT2712_PIN_29_PCM_SYNC__FUNC_GPIO29 (MTK_PIN_NO(29) | 0)
+#define MT2712_PIN_29_PCM_SYNC__FUNC_PCM1_SYNC (MTK_PIN_NO(29) | 1)
+#define MT2712_PIN_29_PCM_SYNC__FUNC_MRG_SYNC (MTK_PIN_NO(29) | 2)
+#define MT2712_PIN_29_PCM_SYNC__FUNC_DAI_SYNC (MTK_PIN_NO(29) | 3)
+#define MT2712_PIN_29_PCM_SYNC__FUNC_DBG_MON_A_6_ (MTK_PIN_NO(29) | 7)
+
+#define MT2712_PIN_30_NCEB0__FUNC_GPIO30 (MTK_PIN_NO(30) | 0)
+#define MT2712_PIN_30_NCEB0__FUNC_NCEB0 (MTK_PIN_NO(30) | 1)
+#define MT2712_PIN_30_NCEB0__FUNC_USB0_FT_SDA (MTK_PIN_NO(30) | 2)
+#define MT2712_PIN_30_NCEB0__FUNC_DBG_MON_A_7_ (MTK_PIN_NO(30) | 7)
+
+#define MT2712_PIN_31_NCEB1__FUNC_GPIO31 (MTK_PIN_NO(31) | 0)
+#define MT2712_PIN_31_NCEB1__FUNC_NCEB1 (MTK_PIN_NO(31) | 1)
+#define MT2712_PIN_31_NCEB1__FUNC_USB1_FT_SCL (MTK_PIN_NO(31) | 2)
+#define MT2712_PIN_31_NCEB1__FUNC_DBG_MON_A_8_ (MTK_PIN_NO(31) | 7)
+
+#define MT2712_PIN_32_NF_DQS__FUNC_GPIO32 (MTK_PIN_NO(32) | 0)
+#define MT2712_PIN_32_NF_DQS__FUNC_NF_DQS (MTK_PIN_NO(32) | 1)
+#define MT2712_PIN_32_NF_DQS__FUNC_USB1_FT_SDA (MTK_PIN_NO(32) | 2)
+#define MT2712_PIN_32_NF_DQS__FUNC_DBG_MON_A_9_ (MTK_PIN_NO(32) | 7)
+
+#define MT2712_PIN_33_NWEB__FUNC_GPIO33 (MTK_PIN_NO(33) | 0)
+#define MT2712_PIN_33_NWEB__FUNC_NWEB (MTK_PIN_NO(33) | 1)
+#define MT2712_PIN_33_NWEB__FUNC_USB2_FT_SCL (MTK_PIN_NO(33) | 2)
+#define MT2712_PIN_33_NWEB__FUNC_DBG_MON_A_10_ (MTK_PIN_NO(33) | 7)
+
+#define MT2712_PIN_34_NREB__FUNC_GPIO34 (MTK_PIN_NO(34) | 0)
+#define MT2712_PIN_34_NREB__FUNC_NREB (MTK_PIN_NO(34) | 1)
+#define MT2712_PIN_34_NREB__FUNC_USB2_FT_SDA (MTK_PIN_NO(34) | 2)
+#define MT2712_PIN_34_NREB__FUNC_DBG_MON_A_11_ (MTK_PIN_NO(34) | 7)
+
+#define MT2712_PIN_35_NCLE__FUNC_GPIO35 (MTK_PIN_NO(35) | 0)
+#define MT2712_PIN_35_NCLE__FUNC_NCLE (MTK_PIN_NO(35) | 1)
+#define MT2712_PIN_35_NCLE__FUNC_USB3_FT_SCL (MTK_PIN_NO(35) | 2)
+#define MT2712_PIN_35_NCLE__FUNC_DBG_MON_A_12_ (MTK_PIN_NO(35) | 7)
+
+#define MT2712_PIN_36_NALE__FUNC_GPIO36 (MTK_PIN_NO(36) | 0)
+#define MT2712_PIN_36_NALE__FUNC_NALE (MTK_PIN_NO(36) | 1)
+#define MT2712_PIN_36_NALE__FUNC_USB3_FT_SDA (MTK_PIN_NO(36) | 2)
+#define MT2712_PIN_36_NALE__FUNC_DBG_MON_A_13_ (MTK_PIN_NO(36) | 7)
+
+#define MT2712_PIN_37_MSDC0E_CLK__FUNC_GPIO37 (MTK_PIN_NO(37) | 0)
+#define MT2712_PIN_37_MSDC0E_CLK__FUNC_MSDC0_CLK (MTK_PIN_NO(37) | 1)
+#define MT2712_PIN_37_MSDC0E_CLK__FUNC_USB0_FT_SCL (MTK_PIN_NO(37) | 2)
+#define MT2712_PIN_37_MSDC0E_CLK__FUNC_DBG_MON_A_0_ (MTK_PIN_NO(37) | 7)
+
+#define MT2712_PIN_38_MSDC0E_DAT7__FUNC_GPIO38 (MTK_PIN_NO(38) | 0)
+#define MT2712_PIN_38_MSDC0E_DAT7__FUNC_MSDC0_DAT7 (MTK_PIN_NO(38) | 1)
+#define MT2712_PIN_38_MSDC0E_DAT7__FUNC_NAND_ND7 (MTK_PIN_NO(38) | 2)
+#define MT2712_PIN_38_MSDC0E_DAT7__FUNC_DBG_MON_A_14_ (MTK_PIN_NO(38) | 7)
+
+#define MT2712_PIN_39_MSDC0E_DAT6__FUNC_GPIO39 (MTK_PIN_NO(39) | 0)
+#define MT2712_PIN_39_MSDC0E_DAT6__FUNC_MSDC0_DAT6 (MTK_PIN_NO(39) | 1)
+#define MT2712_PIN_39_MSDC0E_DAT6__FUNC_NAND_ND6 (MTK_PIN_NO(39) | 2)
+#define MT2712_PIN_39_MSDC0E_DAT6__FUNC_DBG_MON_A_15_ (MTK_PIN_NO(39) | 7)
+
+#define MT2712_PIN_40_MSDC0E_DAT5__FUNC_GPIO40 (MTK_PIN_NO(40) | 0)
+#define MT2712_PIN_40_MSDC0E_DAT5__FUNC_MSDC0_DAT5 (MTK_PIN_NO(40) | 1)
+#define MT2712_PIN_40_MSDC0E_DAT5__FUNC_NAND_ND5 (MTK_PIN_NO(40) | 2)
+#define MT2712_PIN_40_MSDC0E_DAT5__FUNC_DBG_MON_A_16_ (MTK_PIN_NO(40) | 7)
+
+#define MT2712_PIN_41_MSDC0E_DAT4__FUNC_GPIO41 (MTK_PIN_NO(41) | 0)
+#define MT2712_PIN_41_MSDC0E_DAT4__FUNC_MSDC0_DAT4 (MTK_PIN_NO(41) | 1)
+#define MT2712_PIN_41_MSDC0E_DAT4__FUNC_NAND_ND4 (MTK_PIN_NO(41) | 2)
+#define MT2712_PIN_41_MSDC0E_DAT4__FUNC_DBG_MON_A_17_ (MTK_PIN_NO(41) | 7)
+
+#define MT2712_PIN_42_MSDC0E_DAT3__FUNC_GPIO42 (MTK_PIN_NO(42) | 0)
+#define MT2712_PIN_42_MSDC0E_DAT3__FUNC_MSDC0_DAT3 (MTK_PIN_NO(42) | 1)
+#define MT2712_PIN_42_MSDC0E_DAT3__FUNC_NAND_ND3 (MTK_PIN_NO(42) | 2)
+#define MT2712_PIN_42_MSDC0E_DAT3__FUNC_DBG_MON_A_18_ (MTK_PIN_NO(42) | 7)
+
+#define MT2712_PIN_43_MSDC0E_DAT2__FUNC_GPIO43 (MTK_PIN_NO(43) | 0)
+#define MT2712_PIN_43_MSDC0E_DAT2__FUNC_MSDC0_DAT2 (MTK_PIN_NO(43) | 1)
+#define MT2712_PIN_43_MSDC0E_DAT2__FUNC_NAND_ND2 (MTK_PIN_NO(43) | 2)
+#define MT2712_PIN_43_MSDC0E_DAT2__FUNC_DBG_MON_A_19_ (MTK_PIN_NO(43) | 7)
+
+#define MT2712_PIN_44_MSDC0E_DAT1__FUNC_GPIO44 (MTK_PIN_NO(44) | 0)
+#define MT2712_PIN_44_MSDC0E_DAT1__FUNC_MSDC0_DAT1 (MTK_PIN_NO(44) | 1)
+#define MT2712_PIN_44_MSDC0E_DAT1__FUNC_NAND_ND1 (MTK_PIN_NO(44) | 2)
+#define MT2712_PIN_44_MSDC0E_DAT1__FUNC_DBG_MON_A_20_ (MTK_PIN_NO(44) | 7)
+
+#define MT2712_PIN_45_MSDC0E_DAT0__FUNC_GPIO45 (MTK_PIN_NO(45) | 0)
+#define MT2712_PIN_45_MSDC0E_DAT0__FUNC_MSDC0_DAT0 (MTK_PIN_NO(45) | 1)
+#define MT2712_PIN_45_MSDC0E_DAT0__FUNC_NAND_ND0 (MTK_PIN_NO(45) | 2)
+#define MT2712_PIN_45_MSDC0E_DAT0__FUNC_DBG_MON_A_21_ (MTK_PIN_NO(45) | 7)
+
+#define MT2712_PIN_46_MSDC0E_CMD__FUNC_GPIO46 (MTK_PIN_NO(46) | 0)
+#define MT2712_PIN_46_MSDC0E_CMD__FUNC_MSDC0_CMD (MTK_PIN_NO(46) | 1)
+#define MT2712_PIN_46_MSDC0E_CMD__FUNC_NAND_NRNB (MTK_PIN_NO(46) | 2)
+#define MT2712_PIN_46_MSDC0E_CMD__FUNC_DBG_MON_A_22_ (MTK_PIN_NO(46) | 7)
+
+#define MT2712_PIN_47_MSDC0E_DSL__FUNC_GPIO47 (MTK_PIN_NO(47) | 0)
+#define MT2712_PIN_47_MSDC0E_DSL__FUNC_MSDC0_DSL (MTK_PIN_NO(47) | 1)
+#define MT2712_PIN_47_MSDC0E_DSL__FUNC_DBG_MON_A_23_ (MTK_PIN_NO(47) | 7)
+
+#define MT2712_PIN_48_MSDC0E_RSTB__FUNC_GPIO48 (MTK_PIN_NO(48) | 0)
+#define MT2712_PIN_48_MSDC0E_RSTB__FUNC_MSDC0_RSTB (MTK_PIN_NO(48) | 1)
+#define MT2712_PIN_48_MSDC0E_RSTB__FUNC_DBG_MON_A_24_ (MTK_PIN_NO(48) | 7)
+
+#define MT2712_PIN_49_MSDC3_DAT3__FUNC_GPIO49 (MTK_PIN_NO(49) | 0)
+#define MT2712_PIN_49_MSDC3_DAT3__FUNC_MSDC3_DAT3 (MTK_PIN_NO(49) | 1)
+#define MT2712_PIN_49_MSDC3_DAT3__FUNC_DBG_MON_A_25_ (MTK_PIN_NO(49) | 7)
+
+#define MT2712_PIN_50_MSDC3_DAT2__FUNC_GPIO50 (MTK_PIN_NO(50) | 0)
+#define MT2712_PIN_50_MSDC3_DAT2__FUNC_MSDC3_DAT2 (MTK_PIN_NO(50) | 1)
+#define MT2712_PIN_50_MSDC3_DAT2__FUNC_DBG_MON_A_26_ (MTK_PIN_NO(50) | 7)
+
+#define MT2712_PIN_51_MSDC3_DAT1__FUNC_GPIO51 (MTK_PIN_NO(51) | 0)
+#define MT2712_PIN_51_MSDC3_DAT1__FUNC_MSDC3_DAT1 (MTK_PIN_NO(51) | 1)
+#define MT2712_PIN_51_MSDC3_DAT1__FUNC_DBG_MON_A_27_ (MTK_PIN_NO(51) | 7)
+
+#define MT2712_PIN_52_MSDC3_DAT0__FUNC_GPIO52 (MTK_PIN_NO(52) | 0)
+#define MT2712_PIN_52_MSDC3_DAT0__FUNC_MSDC3_DAT0 (MTK_PIN_NO(52) | 1)
+#define MT2712_PIN_52_MSDC3_DAT0__FUNC_DBG_MON_A_28_ (MTK_PIN_NO(52) | 7)
+
+#define MT2712_PIN_53_MSDC3_CMD__FUNC_GPIO53 (MTK_PIN_NO(53) | 0)
+#define MT2712_PIN_53_MSDC3_CMD__FUNC_MSDC3_CMD (MTK_PIN_NO(53) | 1)
+#define MT2712_PIN_53_MSDC3_CMD__FUNC_DBG_MON_A_29_ (MTK_PIN_NO(53) | 7)
+
+#define MT2712_PIN_54_MSDC3_INS__FUNC_GPIO54 (MTK_PIN_NO(54) | 0)
+#define MT2712_PIN_54_MSDC3_INS__FUNC_MSDC3_INS (MTK_PIN_NO(54) | 1)
+#define MT2712_PIN_54_MSDC3_INS__FUNC_DBG_MON_A_30_ (MTK_PIN_NO(54) | 7)
+
+#define MT2712_PIN_55_MSDC3_DSL__FUNC_GPIO55 (MTK_PIN_NO(55) | 0)
+#define MT2712_PIN_55_MSDC3_DSL__FUNC_MSDC3_DSL (MTK_PIN_NO(55) | 1)
+#define MT2712_PIN_55_MSDC3_DSL__FUNC_DBG_MON_A_31_ (MTK_PIN_NO(55) | 7)
+
+#define MT2712_PIN_56_MSDC3_CLK__FUNC_GPIO56 (MTK_PIN_NO(56) | 0)
+#define MT2712_PIN_56_MSDC3_CLK__FUNC_MSDC3_CLK (MTK_PIN_NO(56) | 1)
+#define MT2712_PIN_56_MSDC3_CLK__FUNC_DBG_MON_A_32_ (MTK_PIN_NO(56) | 7)
+
+#define MT2712_PIN_57_NOR_CS__FUNC_GPIO57 (MTK_PIN_NO(57) | 0)
+#define MT2712_PIN_57_NOR_CS__FUNC_NOR_CS (MTK_PIN_NO(57) | 1)
+
+#define MT2712_PIN_58_NOR_CK__FUNC_GPIO58 (MTK_PIN_NO(58) | 0)
+#define MT2712_PIN_58_NOR_CK__FUNC_NOR_CK (MTK_PIN_NO(58) | 1)
+
+#define MT2712_PIN_59_NOR_IO0__FUNC_GPIO59 (MTK_PIN_NO(59) | 0)
+#define MT2712_PIN_59_NOR_IO0__FUNC_NOR_IO0 (MTK_PIN_NO(59) | 1)
+
+#define MT2712_PIN_60_NOR_IO1__FUNC_GPIO60 (MTK_PIN_NO(60) | 0)
+#define MT2712_PIN_60_NOR_IO1__FUNC_NOR_IO1 (MTK_PIN_NO(60) | 1)
+
+#define MT2712_PIN_61_NOR_IO2__FUNC_GPIO61 (MTK_PIN_NO(61) | 0)
+#define MT2712_PIN_61_NOR_IO2__FUNC_NOR_IO2 (MTK_PIN_NO(61) | 1)
+
+#define MT2712_PIN_62_NOR_IO3__FUNC_GPIO62 (MTK_PIN_NO(62) | 0)
+#define MT2712_PIN_62_NOR_IO3__FUNC_NOR_IO3 (MTK_PIN_NO(62) | 1)
+
+#define MT2712_PIN_63_MSDC1_CLK__FUNC_GPIO63 (MTK_PIN_NO(63) | 0)
+#define MT2712_PIN_63_MSDC1_CLK__FUNC_MSDC1_CLK (MTK_PIN_NO(63) | 1)
+#define MT2712_PIN_63_MSDC1_CLK__FUNC_UDI_TCK (MTK_PIN_NO(63) | 2)
+
+#define MT2712_PIN_64_MSDC1_DAT3__FUNC_GPIO64 (MTK_PIN_NO(64) | 0)
+#define MT2712_PIN_64_MSDC1_DAT3__FUNC_MSDC1_DAT3 (MTK_PIN_NO(64) | 1)
+#define MT2712_PIN_64_MSDC1_DAT3__FUNC_UDI_TDI (MTK_PIN_NO(64) | 2)
+
+#define MT2712_PIN_65_MSDC1_DAT1__FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
+#define MT2712_PIN_65_MSDC1_DAT1__FUNC_MSDC1_DAT1 (MTK_PIN_NO(65) | 1)
+#define MT2712_PIN_65_MSDC1_DAT1__FUNC_UDI_TMS (MTK_PIN_NO(65) | 2)
+
+#define MT2712_PIN_66_MSDC1_DAT2__FUNC_GPIO66 (MTK_PIN_NO(66) | 0)
+#define MT2712_PIN_66_MSDC1_DAT2__FUNC_MSDC1_DAT2 (MTK_PIN_NO(66) | 1)
+#define MT2712_PIN_66_MSDC1_DAT2__FUNC_UDI_TDO (MTK_PIN_NO(66) | 2)
+
+#define MT2712_PIN_67_MSDC1_PSW__FUNC_GPIO67 (MTK_PIN_NO(67) | 0)
+#define MT2712_PIN_67_MSDC1_PSW__FUNC_UDI_NTRST (MTK_PIN_NO(67) | 2)
+
+#define MT2712_PIN_68_MSDC1_DAT0__FUNC_GPIO68 (MTK_PIN_NO(68) | 0)
+#define MT2712_PIN_68_MSDC1_DAT0__FUNC_MSDC1_DAT0 (MTK_PIN_NO(68) | 1)
+
+#define MT2712_PIN_69_MSDC1_CMD__FUNC_GPIO69 (MTK_PIN_NO(69) | 0)
+#define MT2712_PIN_69_MSDC1_CMD__FUNC_MSDC1_CMD (MTK_PIN_NO(69) | 1)
+
+#define MT2712_PIN_70_MSDC1_INS__FUNC_GPIO70 (MTK_PIN_NO(70) | 0)
+
+#define MT2712_PIN_71_GBE_TXD3__FUNC_GPIO71 (MTK_PIN_NO(71) | 0)
+#define MT2712_PIN_71_GBE_TXD3__FUNC_GBE_TXD3 (MTK_PIN_NO(71) | 1)
+#define MT2712_PIN_71_GBE_TXD3__FUNC_DBG_MON_B_0_ (MTK_PIN_NO(71) | 7)
+
+#define MT2712_PIN_72_GBE_TXD2__FUNC_GPIO72 (MTK_PIN_NO(72) | 0)
+#define MT2712_PIN_72_GBE_TXD2__FUNC_GBE_TXD2 (MTK_PIN_NO(72) | 1)
+#define MT2712_PIN_72_GBE_TXD2__FUNC_DBG_MON_B_1_ (MTK_PIN_NO(72) | 7)
+
+#define MT2712_PIN_73_GBE_TXD1__FUNC_GPIO73 (MTK_PIN_NO(73) | 0)
+#define MT2712_PIN_73_GBE_TXD1__FUNC_GBE_TXD1 (MTK_PIN_NO(73) | 1)
+#define MT2712_PIN_73_GBE_TXD1__FUNC_DBG_MON_B_2_ (MTK_PIN_NO(73) | 7)
+
+#define MT2712_PIN_74_GBE_TXD0__FUNC_GPIO74 (MTK_PIN_NO(74) | 0)
+#define MT2712_PIN_74_GBE_TXD0__FUNC_GBE_TXD0 (MTK_PIN_NO(74) | 1)
+#define MT2712_PIN_74_GBE_TXD0__FUNC_DBG_MON_B_3_ (MTK_PIN_NO(74) | 7)
+
+#define MT2712_PIN_75_GBE_TXC__FUNC_GPIO75 (MTK_PIN_NO(75) | 0)
+#define MT2712_PIN_75_GBE_TXC__FUNC_GBE_TXC (MTK_PIN_NO(75) | 1)
+#define MT2712_PIN_75_GBE_TXC__FUNC_DBG_MON_B_4_ (MTK_PIN_NO(75) | 7)
+
+#define MT2712_PIN_76_GBE_TXEN__FUNC_GPIO76 (MTK_PIN_NO(76) | 0)
+#define MT2712_PIN_76_GBE_TXEN__FUNC_GBE_TXEN (MTK_PIN_NO(76) | 1)
+#define MT2712_PIN_76_GBE_TXEN__FUNC_DBG_MON_B_5_ (MTK_PIN_NO(76) | 7)
+
+#define MT2712_PIN_77_GBE_TXER__FUNC_GPIO77 (MTK_PIN_NO(77) | 0)
+#define MT2712_PIN_77_GBE_TXER__FUNC_GBE_TXER (MTK_PIN_NO(77) | 1)
+#define MT2712_PIN_77_GBE_TXER__FUNC_DBG_MON_B_6_ (MTK_PIN_NO(77) | 7)
+
+#define MT2712_PIN_78_GBE_RXD3__FUNC_GPIO78 (MTK_PIN_NO(78) | 0)
+#define MT2712_PIN_78_GBE_RXD3__FUNC_GBE_RXD3 (MTK_PIN_NO(78) | 1)
+#define MT2712_PIN_78_GBE_RXD3__FUNC_DBG_MON_B_7_ (MTK_PIN_NO(78) | 7)
+
+#define MT2712_PIN_79_GBE_RXD2__FUNC_GPIO79 (MTK_PIN_NO(79) | 0)
+#define MT2712_PIN_79_GBE_RXD2__FUNC_GBE_RXD2 (MTK_PIN_NO(79) | 1)
+#define MT2712_PIN_79_GBE_RXD2__FUNC_DBG_MON_B_8_ (MTK_PIN_NO(79) | 7)
+
+#define MT2712_PIN_80_GBE_RXD1__FUNC_GPIO80 (MTK_PIN_NO(80) | 0)
+#define MT2712_PIN_80_GBE_RXD1__FUNC_GBE_RXD1 (MTK_PIN_NO(80) | 1)
+#define MT2712_PIN_80_GBE_RXD1__FUNC_DBG_MON_B_9_ (MTK_PIN_NO(80) | 7)
+
+#define MT2712_PIN_81_GBE_RXD0__FUNC_GPIO81 (MTK_PIN_NO(81) | 0)
+#define MT2712_PIN_81_GBE_RXD0__FUNC_GBE_RXD0 (MTK_PIN_NO(81) | 1)
+#define MT2712_PIN_81_GBE_RXD0__FUNC_DBG_MON_B_10_ (MTK_PIN_NO(81) | 7)
+
+#define MT2712_PIN_82_GBE_RXDV__FUNC_GPIO82 (MTK_PIN_NO(82) | 0)
+#define MT2712_PIN_82_GBE_RXDV__FUNC_GBE_RXDV (MTK_PIN_NO(82) | 1)
+#define MT2712_PIN_82_GBE_RXDV__FUNC_DBG_MON_B_11_ (MTK_PIN_NO(82) | 7)
+
+#define MT2712_PIN_83_GBE_RXER__FUNC_GPIO83 (MTK_PIN_NO(83) | 0)
+#define MT2712_PIN_83_GBE_RXER__FUNC_GBE_RXER (MTK_PIN_NO(83) | 1)
+#define MT2712_PIN_83_GBE_RXER__FUNC_DBG_MON_B_12_ (MTK_PIN_NO(83) | 7)
+
+#define MT2712_PIN_84_GBE_RXC__FUNC_GPIO84 (MTK_PIN_NO(84) | 0)
+#define MT2712_PIN_84_GBE_RXC__FUNC_GBE_RXC (MTK_PIN_NO(84) | 1)
+#define MT2712_PIN_84_GBE_RXC__FUNC_DBG_MON_B_13_ (MTK_PIN_NO(84) | 7)
+
+#define MT2712_PIN_85_GBE_MDC__FUNC_GPIO85 (MTK_PIN_NO(85) | 0)
+#define MT2712_PIN_85_GBE_MDC__FUNC_GBE_MDC (MTK_PIN_NO(85) | 1)
+#define MT2712_PIN_85_GBE_MDC__FUNC_DBG_MON_B_14_ (MTK_PIN_NO(85) | 7)
+
+#define MT2712_PIN_86_GBE_MDIO__FUNC_GPIO86 (MTK_PIN_NO(86) | 0)
+#define MT2712_PIN_86_GBE_MDIO__FUNC_GBE_MDIO (MTK_PIN_NO(86) | 1)
+#define MT2712_PIN_86_GBE_MDIO__FUNC_DBG_MON_B_15_ (MTK_PIN_NO(86) | 7)
+
+#define MT2712_PIN_87_GBE_COL__FUNC_GPIO87 (MTK_PIN_NO(87) | 0)
+#define MT2712_PIN_87_GBE_COL__FUNC_GBE_COL (MTK_PIN_NO(87) | 1)
+#define MT2712_PIN_87_GBE_COL__FUNC_DBG_MON_B_16_ (MTK_PIN_NO(87) | 7)
+
+#define MT2712_PIN_88_GBE_INTR__FUNC_GPIO88 (MTK_PIN_NO(88) | 0)
+#define MT2712_PIN_88_GBE_INTR__FUNC_GBE_INTR (MTK_PIN_NO(88) | 1)
+#define MT2712_PIN_88_GBE_INTR__FUNC_GBE_CRS (MTK_PIN_NO(88) | 2)
+#define MT2712_PIN_88_GBE_INTR__FUNC_DBG_MON_B_17_ (MTK_PIN_NO(88) | 7)
+
+#define MT2712_PIN_89_MSDC2_CLK__FUNC_GPIO89 (MTK_PIN_NO(89) | 0)
+#define MT2712_PIN_89_MSDC2_CLK__FUNC_MSDC2_CLK (MTK_PIN_NO(89) | 1)
+#define MT2712_PIN_89_MSDC2_CLK__FUNC_DBG_MON_B_18_ (MTK_PIN_NO(89) | 7)
+
+#define MT2712_PIN_90_MSDC2_DAT3__FUNC_GPIO90 (MTK_PIN_NO(90) | 0)
+#define MT2712_PIN_90_MSDC2_DAT3__FUNC_MSDC2_DAT3 (MTK_PIN_NO(90) | 1)
+#define MT2712_PIN_90_MSDC2_DAT3__FUNC_DBG_MON_B_19_ (MTK_PIN_NO(90) | 7)
+
+#define MT2712_PIN_91_MSDC2_DAT2__FUNC_GPIO91 (MTK_PIN_NO(91) | 0)
+#define MT2712_PIN_91_MSDC2_DAT2__FUNC_MSDC2_DAT2 (MTK_PIN_NO(91) | 1)
+#define MT2712_PIN_91_MSDC2_DAT2__FUNC_DBG_MON_B_20_ (MTK_PIN_NO(91) | 7)
+
+#define MT2712_PIN_92_MSDC2_DAT1__FUNC_GPIO92 (MTK_PIN_NO(92) | 0)
+#define MT2712_PIN_92_MSDC2_DAT1__FUNC_MSDC2_DAT1 (MTK_PIN_NO(92) | 1)
+#define MT2712_PIN_92_MSDC2_DAT1__FUNC_DBG_MON_B_21_ (MTK_PIN_NO(92) | 7)
+
+#define MT2712_PIN_93_MSDC2_DAT0__FUNC_GPIO93 (MTK_PIN_NO(93) | 0)
+#define MT2712_PIN_93_MSDC2_DAT0__FUNC_MSDC2_DAT0 (MTK_PIN_NO(93) | 1)
+#define MT2712_PIN_93_MSDC2_DAT0__FUNC_DBG_MON_B_22_ (MTK_PIN_NO(93) | 7)
+
+#define MT2712_PIN_94_MSDC2_INS__FUNC_GPIO94 (MTK_PIN_NO(94) | 0)
+#define MT2712_PIN_94_MSDC2_INS__FUNC_DBG_MON_B_23_ (MTK_PIN_NO(94) | 7)
+
+#define MT2712_PIN_95_MSDC2_CMD__FUNC_GPIO95 (MTK_PIN_NO(95) | 0)
+#define MT2712_PIN_95_MSDC2_CMD__FUNC_MSDC2_CMD (MTK_PIN_NO(95) | 1)
+#define MT2712_PIN_95_MSDC2_CMD__FUNC_DBG_MON_B_24_ (MTK_PIN_NO(95) | 7)
+
+#define MT2712_PIN_96_MSDC2_PSW__FUNC_GPIO96 (MTK_PIN_NO(96) | 0)
+#define MT2712_PIN_96_MSDC2_PSW__FUNC_DBG_MON_B_25_ (MTK_PIN_NO(96) | 7)
+
+#define MT2712_PIN_97_URXD4__FUNC_GPIO97 (MTK_PIN_NO(97) | 0)
+#define MT2712_PIN_97_URXD4__FUNC_URXD4 (MTK_PIN_NO(97) | 1)
+#define MT2712_PIN_97_URXD4__FUNC_UTXD4 (MTK_PIN_NO(97) | 2)
+#define MT2712_PIN_97_URXD4__FUNC_MRG_CLK (MTK_PIN_NO(97) | 3)
+#define MT2712_PIN_97_URXD4__FUNC_PCM1_CLK (MTK_PIN_NO(97) | 4)
+#define MT2712_PIN_97_URXD4__FUNC_I2S_IQ2_SDQB (MTK_PIN_NO(97) | 5)
+#define MT2712_PIN_97_URXD4__FUNC_I2SO1_WS (MTK_PIN_NO(97) | 6)
+#define MT2712_PIN_97_URXD4__FUNC_DBG_MON_B_26_ (MTK_PIN_NO(97) | 7)
+
+#define MT2712_PIN_98_URTS4__FUNC_GPIO98 (MTK_PIN_NO(98) | 0)
+#define MT2712_PIN_98_URTS4__FUNC_URTS4 (MTK_PIN_NO(98) | 1)
+#define MT2712_PIN_98_URTS4__FUNC_UCTS4 (MTK_PIN_NO(98) | 2)
+#define MT2712_PIN_98_URTS4__FUNC_MRG_RX (MTK_PIN_NO(98) | 3)
+#define MT2712_PIN_98_URTS4__FUNC_PCM1_DI (MTK_PIN_NO(98) | 4)
+#define MT2712_PIN_98_URTS4__FUNC_I2S_IQ1_SDIB (MTK_PIN_NO(98) | 5)
+#define MT2712_PIN_98_URTS4__FUNC_I2SO1_MCK (MTK_PIN_NO(98) | 6)
+#define MT2712_PIN_98_URTS4__FUNC_DBG_MON_B_27_ (MTK_PIN_NO(98) | 7)
+
+#define MT2712_PIN_99_UTXD4__FUNC_GPIO99 (MTK_PIN_NO(99) | 0)
+#define MT2712_PIN_99_UTXD4__FUNC_UTXD4 (MTK_PIN_NO(99) | 1)
+#define MT2712_PIN_99_UTXD4__FUNC_URXD4 (MTK_PIN_NO(99) | 2)
+#define MT2712_PIN_99_UTXD4__FUNC_MRG_SYNC (MTK_PIN_NO(99) | 3)
+#define MT2712_PIN_99_UTXD4__FUNC_PCM1_SYNC (MTK_PIN_NO(99) | 4)
+#define MT2712_PIN_99_UTXD4__FUNC_I2S_IQ0_SDQB (MTK_PIN_NO(99) | 5)
+#define MT2712_PIN_99_UTXD4__FUNC_I2SO1_BCK (MTK_PIN_NO(99) | 6)
+#define MT2712_PIN_99_UTXD4__FUNC_DBG_MON_B_28_ (MTK_PIN_NO(99) | 7)
+
+#define MT2712_PIN_100_UCTS4__FUNC_GPIO100 (MTK_PIN_NO(100) | 0)
+#define MT2712_PIN_100_UCTS4__FUNC_UCTS4 (MTK_PIN_NO(100) | 1)
+#define MT2712_PIN_100_UCTS4__FUNC_URTS4 (MTK_PIN_NO(100) | 2)
+#define MT2712_PIN_100_UCTS4__FUNC_MRG_TX (MTK_PIN_NO(100) | 3)
+#define MT2712_PIN_100_UCTS4__FUNC_PCM1_DO (MTK_PIN_NO(100) | 4)
+#define MT2712_PIN_100_UCTS4__FUNC_I2S_IQ0_SDIB (MTK_PIN_NO(100) | 5)
+#define MT2712_PIN_100_UCTS4__FUNC_I2SO1_DO (MTK_PIN_NO(100) | 6)
+#define MT2712_PIN_100_UCTS4__FUNC_DBG_MON_B_29_ (MTK_PIN_NO(100) | 7)
+
+#define MT2712_PIN_101_URXD5__FUNC_GPIO101 (MTK_PIN_NO(101) | 0)
+#define MT2712_PIN_101_URXD5__FUNC_URXD5 (MTK_PIN_NO(101) | 1)
+#define MT2712_PIN_101_URXD5__FUNC_UTXD5 (MTK_PIN_NO(101) | 2)
+#define MT2712_PIN_101_URXD5__FUNC_I2SO3_WS (MTK_PIN_NO(101) | 3)
+#define MT2712_PIN_101_URXD5__FUNC_TDMIN_LRCK (MTK_PIN_NO(101) | 4)
+#define MT2712_PIN_101_URXD5__FUNC_I2SO0_WS (MTK_PIN_NO(101) | 6)
+#define MT2712_PIN_101_URXD5__FUNC_DBG_MON_B_30_ (MTK_PIN_NO(101) | 7)
+
+#define MT2712_PIN_102_URTS5__FUNC_GPIO102 (MTK_PIN_NO(102) | 0)
+#define MT2712_PIN_102_URTS5__FUNC_URTS5 (MTK_PIN_NO(102) | 1)
+#define MT2712_PIN_102_URTS5__FUNC_UCTS5 (MTK_PIN_NO(102) | 2)
+#define MT2712_PIN_102_URTS5__FUNC_I2SO3_MCK (MTK_PIN_NO(102) | 3)
+#define MT2712_PIN_102_URTS5__FUNC_TDMIN_MCLK (MTK_PIN_NO(102) | 4)
+#define MT2712_PIN_102_URTS5__FUNC_IR_IN (MTK_PIN_NO(102) | 5)
+#define MT2712_PIN_102_URTS5__FUNC_I2SO0_MCK (MTK_PIN_NO(102) | 6)
+#define MT2712_PIN_102_URTS5__FUNC_DBG_MON_B_31_ (MTK_PIN_NO(102) | 7)
+
+#define MT2712_PIN_103_UTXD5__FUNC_GPIO103 (MTK_PIN_NO(103) | 0)
+#define MT2712_PIN_103_UTXD5__FUNC_UTXD5 (MTK_PIN_NO(103) | 1)
+#define MT2712_PIN_103_UTXD5__FUNC_URXD5 (MTK_PIN_NO(103) | 2)
+#define MT2712_PIN_103_UTXD5__FUNC_I2SO3_BCK (MTK_PIN_NO(103) | 3)
+#define MT2712_PIN_103_UTXD5__FUNC_TDMIN_BCK (MTK_PIN_NO(103) | 4)
+#define MT2712_PIN_103_UTXD5__FUNC_I2SO0_BCK (MTK_PIN_NO(103) | 6)
+#define MT2712_PIN_103_UTXD5__FUNC_DBG_MON_B_32_ (MTK_PIN_NO(103) | 7)
+
+#define MT2712_PIN_104_UCTS5__FUNC_GPIO104 (MTK_PIN_NO(104) | 0)
+#define MT2712_PIN_104_UCTS5__FUNC_UCTS5 (MTK_PIN_NO(104) | 1)
+#define MT2712_PIN_104_UCTS5__FUNC_URTS5 (MTK_PIN_NO(104) | 2)
+#define MT2712_PIN_104_UCTS5__FUNC_I2SO0_DO1 (MTK_PIN_NO(104) | 3)
+#define MT2712_PIN_104_UCTS5__FUNC_TDMIN_DI (MTK_PIN_NO(104) | 4)
+#define MT2712_PIN_104_UCTS5__FUNC_IR_IN (MTK_PIN_NO(104) | 5)
+#define MT2712_PIN_104_UCTS5__FUNC_I2SO0_DO0 (MTK_PIN_NO(104) | 6)
+
+#define MT2712_PIN_105_I2C_SDA0__FUNC_GPIO105 (MTK_PIN_NO(105) | 0)
+#define MT2712_PIN_105_I2C_SDA0__FUNC_SDA0 (MTK_PIN_NO(105) | 1)
+
+#define MT2712_PIN_106_I2C_SDA1__FUNC_GPIO106 (MTK_PIN_NO(106) | 0)
+#define MT2712_PIN_106_I2C_SDA1__FUNC_SDA1 (MTK_PIN_NO(106) | 1)
+
+#define MT2712_PIN_107_I2C_SDA2__FUNC_GPIO107 (MTK_PIN_NO(107) | 0)
+#define MT2712_PIN_107_I2C_SDA2__FUNC_SDA2 (MTK_PIN_NO(107) | 1)
+
+#define MT2712_PIN_108_I2C_SDA3__FUNC_GPIO108 (MTK_PIN_NO(108) | 0)
+#define MT2712_PIN_108_I2C_SDA3__FUNC_SDA3 (MTK_PIN_NO(108) | 1)
+
+#define MT2712_PIN_109_I2C_SDA4__FUNC_GPIO109 (MTK_PIN_NO(109) | 0)
+#define MT2712_PIN_109_I2C_SDA4__FUNC_SDA4 (MTK_PIN_NO(109) | 1)
+
+#define MT2712_PIN_110_I2C_SDA5__FUNC_GPIO110 (MTK_PIN_NO(110) | 0)
+#define MT2712_PIN_110_I2C_SDA5__FUNC_SDA5 (MTK_PIN_NO(110) | 1)
+
+#define MT2712_PIN_111_I2C_SCL0__FUNC_GPIO111 (MTK_PIN_NO(111) | 0)
+#define MT2712_PIN_111_I2C_SCL0__FUNC_SCL0 (MTK_PIN_NO(111) | 1)
+
+#define MT2712_PIN_112_I2C_SCL1__FUNC_GPIO112 (MTK_PIN_NO(112) | 0)
+#define MT2712_PIN_112_I2C_SCL1__FUNC_SCL1 (MTK_PIN_NO(112) | 1)
+
+#define MT2712_PIN_113_I2C_SCL2__FUNC_GPIO113 (MTK_PIN_NO(113) | 0)
+#define MT2712_PIN_113_I2C_SCL2__FUNC_SCL2 (MTK_PIN_NO(113) | 1)
+
+#define MT2712_PIN_114_I2C_SCL3__FUNC_GPIO114 (MTK_PIN_NO(114) | 0)
+#define MT2712_PIN_114_I2C_SCL3__FUNC_SCL3 (MTK_PIN_NO(114) | 1)
+
+#define MT2712_PIN_115_I2C_SCL4__FUNC_GPIO115 (MTK_PIN_NO(115) | 0)
+#define MT2712_PIN_115_I2C_SCL4__FUNC_SCL4 (MTK_PIN_NO(115) | 1)
+
+#define MT2712_PIN_116_I2C_SCL5__FUNC_GPIO116 (MTK_PIN_NO(116) | 0)
+#define MT2712_PIN_116_I2C_SCL5__FUNC_SCL5 (MTK_PIN_NO(116) | 1)
+
+#define MT2712_PIN_117_URXD0__FUNC_GPIO117 (MTK_PIN_NO(117) | 0)
+#define MT2712_PIN_117_URXD0__FUNC_URXD0 (MTK_PIN_NO(117) | 1)
+#define MT2712_PIN_117_URXD0__FUNC_UTXD0 (MTK_PIN_NO(117) | 2)
+
+#define MT2712_PIN_118_URXD1__FUNC_GPIO118 (MTK_PIN_NO(118) | 0)
+#define MT2712_PIN_118_URXD1__FUNC_URXD1 (MTK_PIN_NO(118) | 1)
+#define MT2712_PIN_118_URXD1__FUNC_UTXD1 (MTK_PIN_NO(118) | 2)
+
+#define MT2712_PIN_119_URXD2__FUNC_GPIO119 (MTK_PIN_NO(119) | 0)
+#define MT2712_PIN_119_URXD2__FUNC_URXD2 (MTK_PIN_NO(119) | 1)
+#define MT2712_PIN_119_URXD2__FUNC_UTXD2 (MTK_PIN_NO(119) | 2)
+
+#define MT2712_PIN_120_UTXD0__FUNC_GPIO120 (MTK_PIN_NO(120) | 0)
+#define MT2712_PIN_120_UTXD0__FUNC_UTXD0 (MTK_PIN_NO(120) | 1)
+#define MT2712_PIN_120_UTXD0__FUNC_URXD0 (MTK_PIN_NO(120) | 2)
+
+#define MT2712_PIN_121_UTXD1__FUNC_GPIO121 (MTK_PIN_NO(121) | 0)
+#define MT2712_PIN_121_UTXD1__FUNC_UTXD1 (MTK_PIN_NO(121) | 1)
+#define MT2712_PIN_121_UTXD1__FUNC_URXD1 (MTK_PIN_NO(121) | 2)
+
+#define MT2712_PIN_122_UTXD2__FUNC_GPIO122 (MTK_PIN_NO(122) | 0)
+#define MT2712_PIN_122_UTXD2__FUNC_UTXD2 (MTK_PIN_NO(122) | 1)
+#define MT2712_PIN_122_UTXD2__FUNC_URXD2 (MTK_PIN_NO(122) | 2)
+
+#define MT2712_PIN_123_URXD3__FUNC_GPIO123 (MTK_PIN_NO(123) | 0)
+#define MT2712_PIN_123_URXD3__FUNC_URXD3 (MTK_PIN_NO(123) | 1)
+#define MT2712_PIN_123_URXD3__FUNC_UTXD3 (MTK_PIN_NO(123) | 2)
+#define MT2712_PIN_123_URXD3__FUNC_PURE_HW_PROTECT (MTK_PIN_NO(123) | 3)
+
+#define MT2712_PIN_124_UTXD3__FUNC_GPIO124 (MTK_PIN_NO(124) | 0)
+#define MT2712_PIN_124_UTXD3__FUNC_UTXD3 (MTK_PIN_NO(124) | 1)
+#define MT2712_PIN_124_UTXD3__FUNC_URXD3 (MTK_PIN_NO(124) | 2)
+#define MT2712_PIN_124_UTXD3__FUNC_PURE_HW_PROTECT (MTK_PIN_NO(124) | 3)
+
+#define MT2712_PIN_125_URTS3__FUNC_GPIO125 (MTK_PIN_NO(125) | 0)
+#define MT2712_PIN_125_URTS3__FUNC_URTS3 (MTK_PIN_NO(125) | 1)
+#define MT2712_PIN_125_URTS3__FUNC_UCTS3 (MTK_PIN_NO(125) | 2)
+#define MT2712_PIN_125_URTS3__FUNC_WATCH_DOG (MTK_PIN_NO(125) | 3)
+
+#define MT2712_PIN_126_UCTS3__FUNC_GPIO126 (MTK_PIN_NO(126) | 0)
+#define MT2712_PIN_126_UCTS3__FUNC_UCTS3 (MTK_PIN_NO(126) | 1)
+#define MT2712_PIN_126_UCTS3__FUNC_URTS3 (MTK_PIN_NO(126) | 2)
+#define MT2712_PIN_126_UCTS3__FUNC_SRCLKENA0 (MTK_PIN_NO(126) | 3)
+
+#define MT2712_PIN_127_SPI2_CSN__FUNC_GPIO127 (MTK_PIN_NO(127) | 0)
+#define MT2712_PIN_127_SPI2_CSN__FUNC_SPI_CS_2_ (MTK_PIN_NO(127) | 1)
+#define MT2712_PIN_127_SPI2_CSN__FUNC_SPI_CS_1_ (MTK_PIN_NO(127) | 2)
+
+#define MT2712_PIN_128_SPI2_MO__FUNC_GPIO128 (MTK_PIN_NO(128) | 0)
+#define MT2712_PIN_128_SPI2_MO__FUNC_SPI_MO_2_ (MTK_PIN_NO(128) | 1)
+#define MT2712_PIN_128_SPI2_MO__FUNC_SPI_SO_1_ (MTK_PIN_NO(128) | 2)
+
+#define MT2712_PIN_129_SPI2_MI__FUNC_GPIO129 (MTK_PIN_NO(129) | 0)
+#define MT2712_PIN_129_SPI2_MI__FUNC_SPI_MI_2_ (MTK_PIN_NO(129) | 1)
+#define MT2712_PIN_129_SPI2_MI__FUNC_SPI_SI_1_ (MTK_PIN_NO(129) | 2)
+
+#define MT2712_PIN_130_SPI2_CK__FUNC_GPIO130 (MTK_PIN_NO(130) | 0)
+#define MT2712_PIN_130_SPI2_CK__FUNC_SPI_CK_2_ (MTK_PIN_NO(130) | 1)
+#define MT2712_PIN_130_SPI2_CK__FUNC_SPI_CK_1_ (MTK_PIN_NO(130) | 2)
+
+#define MT2712_PIN_131_SPI3_CSN__FUNC_GPIO131 (MTK_PIN_NO(131) | 0)
+#define MT2712_PIN_131_SPI3_CSN__FUNC_SPI_CS_3_ (MTK_PIN_NO(131) | 1)
+
+#define MT2712_PIN_132_SPI3_MO__FUNC_GPIO132 (MTK_PIN_NO(132) | 0)
+#define MT2712_PIN_132_SPI3_MO__FUNC_SPI_MO_3_ (MTK_PIN_NO(132) | 1)
+
+#define MT2712_PIN_133_SPI3_MI__FUNC_GPIO133 (MTK_PIN_NO(133) | 0)
+#define MT2712_PIN_133_SPI3_MI__FUNC_SPI_MI_3_ (MTK_PIN_NO(133) | 1)
+
+#define MT2712_PIN_134_SPI3_CK__FUNC_GPIO134 (MTK_PIN_NO(134) | 0)
+#define MT2712_PIN_134_SPI3_CK__FUNC_SPI_CK_3_ (MTK_PIN_NO(134) | 1)
+
+#define MT2712_PIN_135_KPROW3__FUNC_GPIO135 (MTK_PIN_NO(135) | 0)
+#define MT2712_PIN_135_KPROW3__FUNC_KROW3 (MTK_PIN_NO(135) | 1)
+#define MT2712_PIN_135_KPROW3__FUNC_DSIC_TE (MTK_PIN_NO(135) | 2)
+
+#define MT2712_PIN_136_KPROW4__FUNC_GPIO136 (MTK_PIN_NO(136) | 0)
+#define MT2712_PIN_136_KPROW4__FUNC_KROW4 (MTK_PIN_NO(136) | 1)
+#define MT2712_PIN_136_KPROW4__FUNC_DSID_TE (MTK_PIN_NO(136) | 2)
+
+#define MT2712_PIN_137_KPCOL3__FUNC_GPIO137 (MTK_PIN_NO(137) | 0)
+#define MT2712_PIN_137_KPCOL3__FUNC_KCOL3 (MTK_PIN_NO(137) | 1)
+#define MT2712_PIN_137_KPCOL3__FUNC_DISP2_PWM (MTK_PIN_NO(137) | 2)
+
+#define MT2712_PIN_138_KPCOL4__FUNC_GPIO138 (MTK_PIN_NO(138) | 0)
+#define MT2712_PIN_138_KPCOL4__FUNC_KCOL4 (MTK_PIN_NO(138) | 1)
+#define MT2712_PIN_138_KPCOL4__FUNC_LCM_RST2 (MTK_PIN_NO(138) | 2)
+
+#define MT2712_PIN_139_KPCOL5__FUNC_GPIO139 (MTK_PIN_NO(139) | 0)
+#define MT2712_PIN_139_KPCOL5__FUNC_KCOL5 (MTK_PIN_NO(139) | 1)
+#define MT2712_PIN_139_KPCOL5__FUNC_DSIA_TE (MTK_PIN_NO(139) | 3)
+#define MT2712_PIN_139_KPCOL5__FUNC_PURE_HW_PROTECT (MTK_PIN_NO(139) | 4)
+
+#define MT2712_PIN_140_KPCOL6__FUNC_GPIO140 (MTK_PIN_NO(140) | 0)
+#define MT2712_PIN_140_KPCOL6__FUNC_KCOL6 (MTK_PIN_NO(140) | 1)
+#define MT2712_PIN_140_KPCOL6__FUNC_WATCH_DOG (MTK_PIN_NO(140) | 2)
+#define MT2712_PIN_140_KPCOL6__FUNC_LCM_RST1 (MTK_PIN_NO(140) | 3)
+
+#define MT2712_PIN_141_KPROW5__FUNC_GPIO141 (MTK_PIN_NO(141) | 0)
+#define MT2712_PIN_141_KPROW5__FUNC_KROW5 (MTK_PIN_NO(141) | 1)
+#define MT2712_PIN_141_KPROW5__FUNC_LCM_RST0 (MTK_PIN_NO(141) | 3)
+#define MT2712_PIN_141_KPROW5__FUNC_PURE_HW_PROTECT (MTK_PIN_NO(141) | 4)
+
+#define MT2712_PIN_142_KPROW6__FUNC_GPIO142 (MTK_PIN_NO(142) | 0)
+#define MT2712_PIN_142_KPROW6__FUNC_KROW6 (MTK_PIN_NO(142) | 1)
+#define MT2712_PIN_142_KPROW6__FUNC_SRCLKENA0 (MTK_PIN_NO(142) | 2)
+#define MT2712_PIN_142_KPROW6__FUNC_DSIB_TE (MTK_PIN_NO(142) | 3)
+
+#define MT2712_PIN_143_JTDO_ICE__FUNC_GPIO143 (MTK_PIN_NO(143) | 0)
+#define MT2712_PIN_143_JTDO_ICE__FUNC_JTDO_ICE (MTK_PIN_NO(143) | 1)
+#define MT2712_PIN_143_JTDO_ICE__FUNC_DFD_TDO (MTK_PIN_NO(143) | 3)
+
+#define MT2712_PIN_144_JTCK_ICE__FUNC_GPIO144 (MTK_PIN_NO(144) | 0)
+#define MT2712_PIN_144_JTCK_ICE__FUNC_JTCK_ICE (MTK_PIN_NO(144) | 1)
+#define MT2712_PIN_144_JTCK_ICE__FUNC_DFD_TCK (MTK_PIN_NO(144) | 3)
+
+#define MT2712_PIN_145_JTDI_ICE__FUNC_GPIO145 (MTK_PIN_NO(145) | 0)
+#define MT2712_PIN_145_JTDI_ICE__FUNC_JTDI_ICE (MTK_PIN_NO(145) | 1)
+#define MT2712_PIN_145_JTDI_ICE__FUNC_DFD_TDI (MTK_PIN_NO(145) | 3)
+
+#define MT2712_PIN_146_JTMS_ICE__FUNC_GPIO146 (MTK_PIN_NO(146) | 0)
+#define MT2712_PIN_146_JTMS_ICE__FUNC_JTMS_ICE (MTK_PIN_NO(146) | 1)
+#define MT2712_PIN_146_JTMS_ICE__FUNC_DFD_TMS (MTK_PIN_NO(146) | 3)
+
+#define MT2712_PIN_147_JTRSTB_ICE__FUNC_GPIO147 (MTK_PIN_NO(147) | 0)
+#define MT2712_PIN_147_JTRSTB_ICE__FUNC_JTRST_B_ICE (MTK_PIN_NO(147) | 1)
+#define MT2712_PIN_147_JTRSTB_ICE__FUNC_DFD_NTRST (MTK_PIN_NO(147) | 3)
+
+#define MT2712_PIN_148_GPIO148__FUNC_GPIO148 (MTK_PIN_NO(148) | 0)
+#define MT2712_PIN_148_GPIO148__FUNC_JTRSTB_CM4 (MTK_PIN_NO(148) | 1)
+#define MT2712_PIN_148_GPIO148__FUNC_DFD_NTRST (MTK_PIN_NO(148) | 3)
+
+#define MT2712_PIN_149_GPIO149__FUNC_GPIO149 (MTK_PIN_NO(149) | 0)
+#define MT2712_PIN_149_GPIO149__FUNC_JTCK_CM4 (MTK_PIN_NO(149) | 1)
+#define MT2712_PIN_149_GPIO149__FUNC_DFD_TCK (MTK_PIN_NO(149) | 3)
+
+#define MT2712_PIN_150_GPIO150__FUNC_GPIO150 (MTK_PIN_NO(150) | 0)
+#define MT2712_PIN_150_GPIO150__FUNC_JTMS_CM4 (MTK_PIN_NO(150) | 1)
+#define MT2712_PIN_150_GPIO150__FUNC_DFD_TMS (MTK_PIN_NO(150) | 3)
+
+#define MT2712_PIN_151_GPIO151__FUNC_GPIO151 (MTK_PIN_NO(151) | 0)
+#define MT2712_PIN_151_GPIO151__FUNC_JTDI_CM4 (MTK_PIN_NO(151) | 1)
+#define MT2712_PIN_151_GPIO151__FUNC_DFD_TDI (MTK_PIN_NO(151) | 3)
+
+#define MT2712_PIN_152_GPIO152__FUNC_GPIO152 (MTK_PIN_NO(152) | 0)
+#define MT2712_PIN_152_GPIO152__FUNC_JTDO_CM4 (MTK_PIN_NO(152) | 1)
+#define MT2712_PIN_152_GPIO152__FUNC_DFD_TDO (MTK_PIN_NO(152) | 3)
+
+#define MT2712_PIN_153_SPI0_CSN__FUNC_GPIO153 (MTK_PIN_NO(153) | 0)
+#define MT2712_PIN_153_SPI0_CSN__FUNC_SPI_CS_0_ (MTK_PIN_NO(153) | 1)
+#define MT2712_PIN_153_SPI0_CSN__FUNC_SRCLKENA0 (MTK_PIN_NO(153) | 2)
+#define MT2712_PIN_153_SPI0_CSN__FUNC_UTXD0 (MTK_PIN_NO(153) | 3)
+#define MT2712_PIN_153_SPI0_CSN__FUNC_I2SO0_DO1 (MTK_PIN_NO(153) | 4)
+#define MT2712_PIN_153_SPI0_CSN__FUNC_TDMO0_DATA1 (MTK_PIN_NO(153) | 6)
+#define MT2712_PIN_153_SPI0_CSN__FUNC_I2S_IQ2_SDQB (MTK_PIN_NO(153) | 7)
+
+#define MT2712_PIN_154_SPI0_MI__FUNC_GPIO154 (MTK_PIN_NO(154) | 0)
+#define MT2712_PIN_154_SPI0_MI__FUNC_SPI_MI_0_ (MTK_PIN_NO(154) | 1)
+#define MT2712_PIN_154_SPI0_MI__FUNC_SRCLKENA0 (MTK_PIN_NO(154) | 2)
+#define MT2712_PIN_154_SPI0_MI__FUNC_URXD0 (MTK_PIN_NO(154) | 3)
+#define MT2712_PIN_154_SPI0_MI__FUNC_I2SO0_DO0 (MTK_PIN_NO(154) | 4)
+#define MT2712_PIN_154_SPI0_MI__FUNC_I2SO1_DO (MTK_PIN_NO(154) | 5)
+#define MT2712_PIN_154_SPI0_MI__FUNC_TDMO0_DATA (MTK_PIN_NO(154) | 6)
+#define MT2712_PIN_154_SPI0_MI__FUNC_I2S_IQ1_SDIB (MTK_PIN_NO(154) | 7)
+
+#define MT2712_PIN_155_SPI0_CK__FUNC_GPIO155 (MTK_PIN_NO(155) | 0)
+#define MT2712_PIN_155_SPI0_CK__FUNC_SPI_CK_0_ (MTK_PIN_NO(155) | 1)
+#define MT2712_PIN_155_SPI0_CK__FUNC_SC_APBIAS_OFF (MTK_PIN_NO(155) | 2)
+#define MT2712_PIN_155_SPI0_CK__FUNC_UTXD1 (MTK_PIN_NO(155) | 3)
+#define MT2712_PIN_155_SPI0_CK__FUNC_I2SO0_BCK (MTK_PIN_NO(155) | 4)
+#define MT2712_PIN_155_SPI0_CK__FUNC_I2SO1_BCK (MTK_PIN_NO(155) | 5)
+#define MT2712_PIN_155_SPI0_CK__FUNC_TDMO0_BCK (MTK_PIN_NO(155) | 6)
+#define MT2712_PIN_155_SPI0_CK__FUNC_I2S_IQ0_SDQB (MTK_PIN_NO(155) | 7)
+
+#define MT2712_PIN_156_SPI0_MO__FUNC_GPIO156 (MTK_PIN_NO(156) | 0)
+#define MT2712_PIN_156_SPI0_MO__FUNC_SPI_MO_0_ (MTK_PIN_NO(156) | 1)
+#define MT2712_PIN_156_SPI0_MO__FUNC_SC_APBIAS_OFF (MTK_PIN_NO(156) | 2)
+#define MT2712_PIN_156_SPI0_MO__FUNC_URXD1 (MTK_PIN_NO(156) | 3)
+#define MT2712_PIN_156_SPI0_MO__FUNC_I2SO0_WS (MTK_PIN_NO(156) | 4)
+#define MT2712_PIN_156_SPI0_MO__FUNC_I2SO1_WS (MTK_PIN_NO(156) | 5)
+#define MT2712_PIN_156_SPI0_MO__FUNC_TDMO0_LRCK (MTK_PIN_NO(156) | 6)
+#define MT2712_PIN_156_SPI0_MO__FUNC_I2S_IQ0_SDIB (MTK_PIN_NO(156) | 7)
+
+#define MT2712_PIN_157_SPI5_CSN__FUNC_GPIO157 (MTK_PIN_NO(157) | 0)
+#define MT2712_PIN_157_SPI5_CSN__FUNC_SPI_CS_5_ (MTK_PIN_NO(157) | 1)
+#define MT2712_PIN_157_SPI5_CSN__FUNC_LCM_RST0 (MTK_PIN_NO(157) | 2)
+#define MT2712_PIN_157_SPI5_CSN__FUNC_UTXD2 (MTK_PIN_NO(157) | 3)
+#define MT2712_PIN_157_SPI5_CSN__FUNC_I2SO0_MCK (MTK_PIN_NO(157) | 4)
+#define MT2712_PIN_157_SPI5_CSN__FUNC_I2SO1_MCK (MTK_PIN_NO(157) | 5)
+#define MT2712_PIN_157_SPI5_CSN__FUNC_TDMO0_MCLK (MTK_PIN_NO(157) | 6)
+
+#define MT2712_PIN_158_SPI5_MI__FUNC_GPIO158 (MTK_PIN_NO(158) | 0)
+#define MT2712_PIN_158_SPI5_MI__FUNC_SPI_MI_5_ (MTK_PIN_NO(158) | 1)
+#define MT2712_PIN_158_SPI5_MI__FUNC_DSIA_TE (MTK_PIN_NO(158) | 2)
+#define MT2712_PIN_158_SPI5_MI__FUNC_URXD2 (MTK_PIN_NO(158) | 3)
+
+#define MT2712_PIN_159_SPI5_MO__FUNC_GPIO159 (MTK_PIN_NO(159) | 0)
+#define MT2712_PIN_159_SPI5_MO__FUNC_SPI_MO_5_ (MTK_PIN_NO(159) | 1)
+#define MT2712_PIN_159_SPI5_MO__FUNC_DSIB_TE (MTK_PIN_NO(159) | 2)
+#define MT2712_PIN_159_SPI5_MO__FUNC_UTXD3 (MTK_PIN_NO(159) | 3)
+
+#define MT2712_PIN_160_SPI5_CK__FUNC_GPIO160 (MTK_PIN_NO(160) | 0)
+#define MT2712_PIN_160_SPI5_CK__FUNC_SPI_CK_5_ (MTK_PIN_NO(160) | 1)
+#define MT2712_PIN_160_SPI5_CK__FUNC_LCM_RST1 (MTK_PIN_NO(160) | 2)
+#define MT2712_PIN_160_SPI5_CK__FUNC_URXD3 (MTK_PIN_NO(160) | 3)
+
+#define MT2712_PIN_161_SPI1_CSN__FUNC_GPIO161 (MTK_PIN_NO(161) | 0)
+#define MT2712_PIN_161_SPI1_CSN__FUNC_SPI_CS_1_ (MTK_PIN_NO(161) | 1)
+#define MT2712_PIN_161_SPI1_CSN__FUNC_SPI_CS_4_ (MTK_PIN_NO(161) | 2)
+#define MT2712_PIN_161_SPI1_CSN__FUNC_I2S_IQ2_SDQB (MTK_PIN_NO(161) | 4)
+#define MT2712_PIN_161_SPI1_CSN__FUNC_I2SO2_DO (MTK_PIN_NO(161) | 5)
+#define MT2712_PIN_161_SPI1_CSN__FUNC_TDMO0_DATA1 (MTK_PIN_NO(161) | 6)
+#define MT2712_PIN_161_SPI1_CSN__FUNC_I2SO0_DO1 (MTK_PIN_NO(161) | 7)
+
+#define MT2712_PIN_162_SPI1_SI__FUNC_GPIO162 (MTK_PIN_NO(162) | 0)
+#define MT2712_PIN_162_SPI1_SI__FUNC_SPI_SI_1_ (MTK_PIN_NO(162) | 1)
+#define MT2712_PIN_162_SPI1_SI__FUNC_SPI_MI_4_ (MTK_PIN_NO(162) | 2)
+#define MT2712_PIN_162_SPI1_SI__FUNC_I2S_IQ1_SDIB (MTK_PIN_NO(162) | 4)
+#define MT2712_PIN_162_SPI1_SI__FUNC_I2SO2_BCK (MTK_PIN_NO(162) | 5)
+#define MT2712_PIN_162_SPI1_SI__FUNC_TDMO0_DATA (MTK_PIN_NO(162) | 6)
+#define MT2712_PIN_162_SPI1_SI__FUNC_I2SO0_DO0 (MTK_PIN_NO(162) | 7)
+
+#define MT2712_PIN_163_SPI1_CK__FUNC_GPIO163 (MTK_PIN_NO(163) | 0)
+#define MT2712_PIN_163_SPI1_CK__FUNC_SPI_CK_1_ (MTK_PIN_NO(163) | 1)
+#define MT2712_PIN_163_SPI1_CK__FUNC_SPI_CK_4_ (MTK_PIN_NO(163) | 2)
+#define MT2712_PIN_163_SPI1_CK__FUNC_I2S_IQ0_SDQB (MTK_PIN_NO(163) | 4)
+#define MT2712_PIN_163_SPI1_CK__FUNC_I2SO2_WS (MTK_PIN_NO(163) | 5)
+#define MT2712_PIN_163_SPI1_CK__FUNC_TDMO0_BCK (MTK_PIN_NO(163) | 6)
+#define MT2712_PIN_163_SPI1_CK__FUNC_I2SO0_BCK (MTK_PIN_NO(163) | 7)
+
+#define MT2712_PIN_164_SPI1_SO__FUNC_GPIO164 (MTK_PIN_NO(164) | 0)
+#define MT2712_PIN_164_SPI1_SO__FUNC_SPI_SO_1_ (MTK_PIN_NO(164) | 1)
+#define MT2712_PIN_164_SPI1_SO__FUNC_SPI_MO_4_ (MTK_PIN_NO(164) | 2)
+#define MT2712_PIN_164_SPI1_SO__FUNC_I2S_IQ0_SDIB (MTK_PIN_NO(164) | 4)
+#define MT2712_PIN_164_SPI1_SO__FUNC_I2SO2_MCK (MTK_PIN_NO(164) | 5)
+#define MT2712_PIN_164_SPI1_SO__FUNC_TDMO0_LRCK (MTK_PIN_NO(164) | 6)
+#define MT2712_PIN_164_SPI1_SO__FUNC_I2SO0_WS (MTK_PIN_NO(164) | 7)
+
+#define MT2712_PIN_165_SPI4_CSN__FUNC_GPIO165 (MTK_PIN_NO(165) | 0)
+#define MT2712_PIN_165_SPI4_CSN__FUNC_SPI_CS_4_ (MTK_PIN_NO(165) | 1)
+#define MT2712_PIN_165_SPI4_CSN__FUNC_LCM_RST0 (MTK_PIN_NO(165) | 2)
+#define MT2712_PIN_165_SPI4_CSN__FUNC_SPI_CS_1_ (MTK_PIN_NO(165) | 3)
+#define MT2712_PIN_165_SPI4_CSN__FUNC_UTXD4 (MTK_PIN_NO(165) | 4)
+#define MT2712_PIN_165_SPI4_CSN__FUNC_I2SO1_DO (MTK_PIN_NO(165) | 5)
+#define MT2712_PIN_165_SPI4_CSN__FUNC_TDMO0_MCLK (MTK_PIN_NO(165) | 6)
+#define MT2712_PIN_165_SPI4_CSN__FUNC_I2SO0_MCK (MTK_PIN_NO(165) | 7)
+
+#define MT2712_PIN_166_SPI4_MI__FUNC_GPIO166 (MTK_PIN_NO(166) | 0)
+#define MT2712_PIN_166_SPI4_MI__FUNC_SPI_MI_4_ (MTK_PIN_NO(166) | 1)
+#define MT2712_PIN_166_SPI4_MI__FUNC_DSIA_TE (MTK_PIN_NO(166) | 2)
+#define MT2712_PIN_166_SPI4_MI__FUNC_SPI_SI_1_ (MTK_PIN_NO(166) | 3)
+#define MT2712_PIN_166_SPI4_MI__FUNC_URXD4 (MTK_PIN_NO(166) | 4)
+#define MT2712_PIN_166_SPI4_MI__FUNC_I2SO1_BCK (MTK_PIN_NO(166) | 5)
+
+#define MT2712_PIN_167_SPI4_MO__FUNC_GPIO167 (MTK_PIN_NO(167) | 0)
+#define MT2712_PIN_167_SPI4_MO__FUNC_SPI_MO_4_ (MTK_PIN_NO(167) | 1)
+#define MT2712_PIN_167_SPI4_MO__FUNC_DSIB_TE (MTK_PIN_NO(167) | 2)
+#define MT2712_PIN_167_SPI4_MO__FUNC_SPI_SO_1_ (MTK_PIN_NO(167) | 3)
+#define MT2712_PIN_167_SPI4_MO__FUNC_UTXD5 (MTK_PIN_NO(167) | 4)
+#define MT2712_PIN_167_SPI4_MO__FUNC_I2SO1_WS (MTK_PIN_NO(167) | 5)
+
+#define MT2712_PIN_168_SPI4_CK__FUNC_GPIO168 (MTK_PIN_NO(168) | 0)
+#define MT2712_PIN_168_SPI4_CK__FUNC_SPI_CK_4_ (MTK_PIN_NO(168) | 1)
+#define MT2712_PIN_168_SPI4_CK__FUNC_LCM_RST1 (MTK_PIN_NO(168) | 2)
+#define MT2712_PIN_168_SPI4_CK__FUNC_SPI_CK_1_ (MTK_PIN_NO(168) | 3)
+#define MT2712_PIN_168_SPI4_CK__FUNC_URXD5 (MTK_PIN_NO(168) | 4)
+#define MT2712_PIN_168_SPI4_CK__FUNC_I2SO1_MCK (MTK_PIN_NO(168) | 5)
+
+#define MT2712_PIN_169_I2SI0_DATA__FUNC_GPIO169 (MTK_PIN_NO(169) | 0)
+#define MT2712_PIN_169_I2SI0_DATA__FUNC_I2SI0_DI (MTK_PIN_NO(169) | 1)
+#define MT2712_PIN_169_I2SI0_DATA__FUNC_I2SI1_DI (MTK_PIN_NO(169) | 2)
+#define MT2712_PIN_169_I2SI0_DATA__FUNC_I2SI2_DI (MTK_PIN_NO(169) | 3)
+#define MT2712_PIN_169_I2SI0_DATA__FUNC_TDMIN_DI (MTK_PIN_NO(169) | 4)
+
+#define MT2712_PIN_170_I2SI0_LRCK__FUNC_GPIO170 (MTK_PIN_NO(170) | 0)
+#define MT2712_PIN_170_I2SI0_LRCK__FUNC_I2SI0_WS (MTK_PIN_NO(170) | 1)
+#define MT2712_PIN_170_I2SI0_LRCK__FUNC_I2SI1_WS (MTK_PIN_NO(170) | 2)
+#define MT2712_PIN_170_I2SI0_LRCK__FUNC_I2SI2_WS (MTK_PIN_NO(170) | 3)
+#define MT2712_PIN_170_I2SI0_LRCK__FUNC_TDMIN_LRCK (MTK_PIN_NO(170) | 4)
+#define MT2712_PIN_170_I2SI0_LRCK__FUNC_TDMO0_DATA3 (MTK_PIN_NO(170) | 5)
+#define MT2712_PIN_170_I2SI0_LRCK__FUNC_TDMO1_DATA3 (MTK_PIN_NO(170) | 6)
+
+#define MT2712_PIN_171_I2SI0_MCLK__FUNC_GPIO171 (MTK_PIN_NO(171) | 0)
+#define MT2712_PIN_171_I2SI0_MCLK__FUNC_I2SI0_MCK (MTK_PIN_NO(171) | 1)
+#define MT2712_PIN_171_I2SI0_MCLK__FUNC_I2SI1_MCK (MTK_PIN_NO(171) | 2)
+#define MT2712_PIN_171_I2SI0_MCLK__FUNC_I2SI2_MCK (MTK_PIN_NO(171) | 3)
+#define MT2712_PIN_171_I2SI0_MCLK__FUNC_TDMIN_MCLK (MTK_PIN_NO(171) | 4)
+#define MT2712_PIN_171_I2SI0_MCLK__FUNC_TDMO0_DATA2 (MTK_PIN_NO(171) | 5)
+#define MT2712_PIN_171_I2SI0_MCLK__FUNC_TDMO1_DATA2 (MTK_PIN_NO(171) | 6)
+
+#define MT2712_PIN_172_I2SI0_BCK__FUNC_GPIO172 (MTK_PIN_NO(172) | 0)
+#define MT2712_PIN_172_I2SI0_BCK__FUNC_I2SI0_BCK (MTK_PIN_NO(172) | 1)
+#define MT2712_PIN_172_I2SI0_BCK__FUNC_I2SI1_BCK (MTK_PIN_NO(172) | 2)
+#define MT2712_PIN_172_I2SI0_BCK__FUNC_I2SI2_BCK (MTK_PIN_NO(172) | 3)
+#define MT2712_PIN_172_I2SI0_BCK__FUNC_TDMIN_BCK (MTK_PIN_NO(172) | 4)
+#define MT2712_PIN_172_I2SI0_BCK__FUNC_TDMO0_DATA1 (MTK_PIN_NO(172) | 5)
+#define MT2712_PIN_172_I2SI0_BCK__FUNC_TDMO1_DATA1 (MTK_PIN_NO(172) | 6)
+
+#define MT2712_PIN_173_I2SI2_DATA__FUNC_GPIO173 (MTK_PIN_NO(173) | 0)
+#define MT2712_PIN_173_I2SI2_DATA__FUNC_I2SI2_DI (MTK_PIN_NO(173) | 1)
+#define MT2712_PIN_173_I2SI2_DATA__FUNC_I2SI0_DI (MTK_PIN_NO(173) | 2)
+#define MT2712_PIN_173_I2SI2_DATA__FUNC_I2SI1_DI (MTK_PIN_NO(173) | 3)
+#define MT2712_PIN_173_I2SI2_DATA__FUNC_PCM1_DI (MTK_PIN_NO(173) | 4)
+#define MT2712_PIN_173_I2SI2_DATA__FUNC_TDMIN_DI (MTK_PIN_NO(173) | 5)
+#define MT2712_PIN_173_I2SI2_DATA__FUNC_PCM1_DO (MTK_PIN_NO(173) | 6)
+
+#define MT2712_PIN_174_I2SI2_MCLK__FUNC_GPIO174 (MTK_PIN_NO(174) | 0)
+#define MT2712_PIN_174_I2SI2_MCLK__FUNC_I2SI2_MCK (MTK_PIN_NO(174) | 1)
+#define MT2712_PIN_174_I2SI2_MCLK__FUNC_I2SI0_MCK (MTK_PIN_NO(174) | 2)
+#define MT2712_PIN_174_I2SI2_MCLK__FUNC_I2SI1_MCK (MTK_PIN_NO(174) | 3)
+#define MT2712_PIN_174_I2SI2_MCLK__FUNC_PCM1_DO (MTK_PIN_NO(174) | 4)
+#define MT2712_PIN_174_I2SI2_MCLK__FUNC_TDMIN_MCLK (MTK_PIN_NO(174) | 5)
+#define MT2712_PIN_174_I2SI2_MCLK__FUNC_PCM1_DI (MTK_PIN_NO(174) | 6)
+#define MT2712_PIN_174_I2SI2_MCLK__FUNC_I2S_IQ2_SDQB (MTK_PIN_NO(174) | 7)
+
+#define MT2712_PIN_175_I2SI2_BCK__FUNC_GPIO175 (MTK_PIN_NO(175) | 0)
+#define MT2712_PIN_175_I2SI2_BCK__FUNC_I2SI2_BCK (MTK_PIN_NO(175) | 1)
+#define MT2712_PIN_175_I2SI2_BCK__FUNC_I2SI0_BCK (MTK_PIN_NO(175) | 2)
+#define MT2712_PIN_175_I2SI2_BCK__FUNC_I2SI1_BCK (MTK_PIN_NO(175) | 3)
+#define MT2712_PIN_175_I2SI2_BCK__FUNC_PCM1_CLK (MTK_PIN_NO(175) | 4)
+#define MT2712_PIN_175_I2SI2_BCK__FUNC_TDMIN_BCK (MTK_PIN_NO(175) | 5)
+
+#define MT2712_PIN_176_I2SI2_LRCK__FUNC_GPIO176 (MTK_PIN_NO(176) | 0)
+#define MT2712_PIN_176_I2SI2_LRCK__FUNC_I2SI2_WS (MTK_PIN_NO(176) | 1)
+#define MT2712_PIN_176_I2SI2_LRCK__FUNC_I2SI0_WS (MTK_PIN_NO(176) | 2)
+#define MT2712_PIN_176_I2SI2_LRCK__FUNC_I2SI1_WS (MTK_PIN_NO(176) | 3)
+#define MT2712_PIN_176_I2SI2_LRCK__FUNC_PCM1_SYNC (MTK_PIN_NO(176) | 4)
+#define MT2712_PIN_176_I2SI2_LRCK__FUNC_TDMIN_LRCK (MTK_PIN_NO(176) | 5)
+
+#define MT2712_PIN_177_I2SI1_DATA__FUNC_GPIO177 (MTK_PIN_NO(177) | 0)
+#define MT2712_PIN_177_I2SI1_DATA__FUNC_I2SI1_DI (MTK_PIN_NO(177) | 1)
+#define MT2712_PIN_177_I2SI1_DATA__FUNC_I2SI0_DI (MTK_PIN_NO(177) | 2)
+#define MT2712_PIN_177_I2SI1_DATA__FUNC_I2SI2_DI (MTK_PIN_NO(177) | 3)
+#define MT2712_PIN_177_I2SI1_DATA__FUNC_TDMIN_DI (MTK_PIN_NO(177) | 4)
+
+#define MT2712_PIN_178_I2SI1_BCK__FUNC_GPIO178 (MTK_PIN_NO(178) | 0)
+#define MT2712_PIN_178_I2SI1_BCK__FUNC_I2SI1_BCK (MTK_PIN_NO(178) | 1)
+#define MT2712_PIN_178_I2SI1_BCK__FUNC_I2SI0_BCK (MTK_PIN_NO(178) | 2)
+#define MT2712_PIN_178_I2SI1_BCK__FUNC_I2SI2_BCK (MTK_PIN_NO(178) | 3)
+#define MT2712_PIN_178_I2SI1_BCK__FUNC_TDMIN_BCK (MTK_PIN_NO(178) | 4)
+#define MT2712_PIN_178_I2SI1_BCK__FUNC_TDMO0_DATA3 (MTK_PIN_NO(178) | 5)
+#define MT2712_PIN_178_I2SI1_BCK__FUNC_TDMO1_DATA3 (MTK_PIN_NO(178) | 6)
+
+#define MT2712_PIN_179_I2SI1_LRCK__FUNC_GPIO179 (MTK_PIN_NO(179) | 0)
+#define MT2712_PIN_179_I2SI1_LRCK__FUNC_I2SI1_WS (MTK_PIN_NO(179) | 1)
+#define MT2712_PIN_179_I2SI1_LRCK__FUNC_I2SI0_WS (MTK_PIN_NO(179) | 2)
+#define MT2712_PIN_179_I2SI1_LRCK__FUNC_I2SI2_WS (MTK_PIN_NO(179) | 3)
+#define MT2712_PIN_179_I2SI1_LRCK__FUNC_TDMIN_LRCK (MTK_PIN_NO(179) | 4)
+#define MT2712_PIN_179_I2SI1_LRCK__FUNC_TDMO0_DATA2 (MTK_PIN_NO(179) | 5)
+#define MT2712_PIN_179_I2SI1_LRCK__FUNC_TDMO1_DATA2 (MTK_PIN_NO(179) | 6)
+
+#define MT2712_PIN_180_I2SI1_MCLK__FUNC_GPIO180 (MTK_PIN_NO(180) | 0)
+#define MT2712_PIN_180_I2SI1_MCLK__FUNC_I2SI1_MCK (MTK_PIN_NO(180) | 1)
+#define MT2712_PIN_180_I2SI1_MCLK__FUNC_I2SI0_MCK (MTK_PIN_NO(180) | 2)
+#define MT2712_PIN_180_I2SI1_MCLK__FUNC_I2SI2_MCK (MTK_PIN_NO(180) | 3)
+#define MT2712_PIN_180_I2SI1_MCLK__FUNC_TDMIN_MCLK (MTK_PIN_NO(180) | 4)
+#define MT2712_PIN_180_I2SI1_MCLK__FUNC_TDMO0_DATA1 (MTK_PIN_NO(180) | 5)
+#define MT2712_PIN_180_I2SI1_MCLK__FUNC_TDMO1_DATA1 (MTK_PIN_NO(180) | 6)
+#define MT2712_PIN_180_I2SI1_MCLK__FUNC_I2S_IQ2_SDIB (MTK_PIN_NO(180) | 7)
+
+#define MT2712_PIN_181_I2SO1_DATA0__FUNC_GPIO181 (MTK_PIN_NO(181) | 0)
+#define MT2712_PIN_181_I2SO1_DATA0__FUNC_I2SO1_DO (MTK_PIN_NO(181) | 1)
+#define MT2712_PIN_181_I2SO1_DATA0__FUNC_I2SO0_DO0 (MTK_PIN_NO(181) | 2)
+#define MT2712_PIN_181_I2SO1_DATA0__FUNC_I2SO2_DO (MTK_PIN_NO(181) | 3)
+#define MT2712_PIN_181_I2SO1_DATA0__FUNC_DAI_TX (MTK_PIN_NO(181) | 4)
+#define MT2712_PIN_181_I2SO1_DATA0__FUNC_TDMIN_MCLK (MTK_PIN_NO(181) | 5)
+#define MT2712_PIN_181_I2SO1_DATA0__FUNC_I2S_IQ2_SDIA (MTK_PIN_NO(181) | 7)
+
+#define MT2712_PIN_182_I2SO1_BCK__FUNC_GPIO182 (MTK_PIN_NO(182) | 0)
+#define MT2712_PIN_182_I2SO1_BCK__FUNC_I2SO1_BCK (MTK_PIN_NO(182) | 1)
+#define MT2712_PIN_182_I2SO1_BCK__FUNC_I2SO0_BCK (MTK_PIN_NO(182) | 2)
+#define MT2712_PIN_182_I2SO1_BCK__FUNC_I2SO2_BCK (MTK_PIN_NO(182) | 3)
+#define MT2712_PIN_182_I2SO1_BCK__FUNC_DAI_SYNC (MTK_PIN_NO(182) | 4)
+#define MT2712_PIN_182_I2SO1_BCK__FUNC_TDMIN_BCK (MTK_PIN_NO(182) | 5)
+#define MT2712_PIN_182_I2SO1_BCK__FUNC_TDMO0_DATA3 (MTK_PIN_NO(182) | 6)
+#define MT2712_PIN_182_I2SO1_BCK__FUNC_I2S_IQ2_BCK (MTK_PIN_NO(182) | 7)
+
+#define MT2712_PIN_183_I2SO1_LRCK__FUNC_GPIO183 (MTK_PIN_NO(183) | 0)
+#define MT2712_PIN_183_I2SO1_LRCK__FUNC_I2SO1_WS (MTK_PIN_NO(183) | 1)
+#define MT2712_PIN_183_I2SO1_LRCK__FUNC_I2SO0_WS (MTK_PIN_NO(183) | 2)
+#define MT2712_PIN_183_I2SO1_LRCK__FUNC_I2SO2_WS (MTK_PIN_NO(183) | 3)
+#define MT2712_PIN_183_I2SO1_LRCK__FUNC_DAI_CLK (MTK_PIN_NO(183) | 4)
+#define MT2712_PIN_183_I2SO1_LRCK__FUNC_TDMIN_DI (MTK_PIN_NO(183) | 5)
+#define MT2712_PIN_183_I2SO1_LRCK__FUNC_TDMO0_DATA2 (MTK_PIN_NO(183) | 6)
+#define MT2712_PIN_183_I2SO1_LRCK__FUNC_I2S_IQ2_WS (MTK_PIN_NO(183) | 7)
+
+#define MT2712_PIN_184_I2SO1_MCLK__FUNC_GPIO184 (MTK_PIN_NO(184) | 0)
+#define MT2712_PIN_184_I2SO1_MCLK__FUNC_I2SO1_MCK (MTK_PIN_NO(184) | 1)
+#define MT2712_PIN_184_I2SO1_MCLK__FUNC_I2SO0_MCK (MTK_PIN_NO(184) | 2)
+#define MT2712_PIN_184_I2SO1_MCLK__FUNC_I2SO2_MCK (MTK_PIN_NO(184) | 3)
+#define MT2712_PIN_184_I2SO1_MCLK__FUNC_DAI_RX (MTK_PIN_NO(184) | 4)
+#define MT2712_PIN_184_I2SO1_MCLK__FUNC_TDMIN_LRCK (MTK_PIN_NO(184) | 5)
+#define MT2712_PIN_184_I2SO1_MCLK__FUNC_TDMO0_DATA1 (MTK_PIN_NO(184) | 6)
+#define MT2712_PIN_184_I2SO1_MCLK__FUNC_I2S_IQ2_SDQA (MTK_PIN_NO(184) | 7)
+
+#define MT2712_PIN_185_AUD_EXT_CK2__FUNC_GPIO185 (MTK_PIN_NO(185) | 0)
+#define MT2712_PIN_185_AUD_EXT_CK2__FUNC_AUD_EXT_CK2 (MTK_PIN_NO(185) | 1)
+#define MT2712_PIN_185_AUD_EXT_CK2__FUNC_AUD_EXT_CK1 (MTK_PIN_NO(185) | 2)
+#define MT2712_PIN_185_AUD_EXT_CK2__FUNC_I2SO1_DO (MTK_PIN_NO(185) | 3)
+#define MT2712_PIN_185_AUD_EXT_CK2__FUNC_I2SI2_DI (MTK_PIN_NO(185) | 4)
+#define MT2712_PIN_185_AUD_EXT_CK2__FUNC_MRG_RX (MTK_PIN_NO(185) | 5)
+#define MT2712_PIN_185_AUD_EXT_CK2__FUNC_PCM1_DI (MTK_PIN_NO(185) | 6)
+#define MT2712_PIN_185_AUD_EXT_CK2__FUNC_I2S_IQ0_SDQB (MTK_PIN_NO(185) | 7)
+
+#define MT2712_PIN_186_AUD_EXT_CK1__FUNC_GPIO186 (MTK_PIN_NO(186) | 0)
+#define MT2712_PIN_186_AUD_EXT_CK1__FUNC_AUD_EXT_CK1 (MTK_PIN_NO(186) | 1)
+#define MT2712_PIN_186_AUD_EXT_CK1__FUNC_AUD_EXT_CK2 (MTK_PIN_NO(186) | 2)
+#define MT2712_PIN_186_AUD_EXT_CK1__FUNC_I2SO0_DO1 (MTK_PIN_NO(186) | 3)
+#define MT2712_PIN_186_AUD_EXT_CK1__FUNC_I2SI1_DI (MTK_PIN_NO(186) | 4)
+#define MT2712_PIN_186_AUD_EXT_CK1__FUNC_MRG_TX (MTK_PIN_NO(186) | 5)
+#define MT2712_PIN_186_AUD_EXT_CK1__FUNC_PCM1_DO (MTK_PIN_NO(186) | 6)
+#define MT2712_PIN_186_AUD_EXT_CK1__FUNC_I2S_IQ0_SDIB (MTK_PIN_NO(186) | 7)
+
+#define MT2712_PIN_187_I2SO2_BCK__FUNC_GPIO187 (MTK_PIN_NO(187) | 0)
+#define MT2712_PIN_187_I2SO2_BCK__FUNC_I2SO2_BCK (MTK_PIN_NO(187) | 1)
+#define MT2712_PIN_187_I2SO2_BCK__FUNC_I2SO0_BCK (MTK_PIN_NO(187) | 2)
+#define MT2712_PIN_187_I2SO2_BCK__FUNC_I2SO1_BCK (MTK_PIN_NO(187) | 3)
+#define MT2712_PIN_187_I2SO2_BCK__FUNC_PCM1_CLK (MTK_PIN_NO(187) | 4)
+#define MT2712_PIN_187_I2SO2_BCK__FUNC_MRG_SYNC (MTK_PIN_NO(187) | 5)
+#define MT2712_PIN_187_I2SO2_BCK__FUNC_TDMO1_DATA3 (MTK_PIN_NO(187) | 6)
+#define MT2712_PIN_187_I2SO2_BCK__FUNC_I2S_IQ0_BCK (MTK_PIN_NO(187) | 7)
+
+#define MT2712_PIN_188_I2SO2_LRCK__FUNC_GPIO188 (MTK_PIN_NO(188) | 0)
+#define MT2712_PIN_188_I2SO2_LRCK__FUNC_I2SO2_WS (MTK_PIN_NO(188) | 1)
+#define MT2712_PIN_188_I2SO2_LRCK__FUNC_I2SO0_WS (MTK_PIN_NO(188) | 2)
+#define MT2712_PIN_188_I2SO2_LRCK__FUNC_I2SO1_WS (MTK_PIN_NO(188) | 3)
+#define MT2712_PIN_188_I2SO2_LRCK__FUNC_PCM1_SYNC (MTK_PIN_NO(188) | 4)
+#define MT2712_PIN_188_I2SO2_LRCK__FUNC_MRG_CLK (MTK_PIN_NO(188) | 5)
+#define MT2712_PIN_188_I2SO2_LRCK__FUNC_TDMO1_DATA2 (MTK_PIN_NO(188) | 6)
+#define MT2712_PIN_188_I2SO2_LRCK__FUNC_I2S_IQ0_WS (MTK_PIN_NO(188) | 7)
+
+#define MT2712_PIN_189_I2SO2_MCLK__FUNC_GPIO189 (MTK_PIN_NO(189) | 0)
+#define MT2712_PIN_189_I2SO2_MCLK__FUNC_I2SO2_MCK (MTK_PIN_NO(189) | 1)
+#define MT2712_PIN_189_I2SO2_MCLK__FUNC_I2SO0_MCK (MTK_PIN_NO(189) | 2)
+#define MT2712_PIN_189_I2SO2_MCLK__FUNC_I2SO1_MCK (MTK_PIN_NO(189) | 3)
+#define MT2712_PIN_189_I2SO2_MCLK__FUNC_PCM1_DO (MTK_PIN_NO(189) | 4)
+#define MT2712_PIN_189_I2SO2_MCLK__FUNC_MRG_RX (MTK_PIN_NO(189) | 5)
+#define MT2712_PIN_189_I2SO2_MCLK__FUNC_TDMO1_DATA1 (MTK_PIN_NO(189) | 6)
+#define MT2712_PIN_189_I2SO2_MCLK__FUNC_I2S_IQ0_SDQA (MTK_PIN_NO(189) | 7)
+
+#define MT2712_PIN_190_I2SO2_DATA0__FUNC_GPIO190 (MTK_PIN_NO(190) | 0)
+#define MT2712_PIN_190_I2SO2_DATA0__FUNC_I2SO2_DO (MTK_PIN_NO(190) | 1)
+#define MT2712_PIN_190_I2SO2_DATA0__FUNC_I2SO0_DO0 (MTK_PIN_NO(190) | 2)
+#define MT2712_PIN_190_I2SO2_DATA0__FUNC_I2SO1_DO (MTK_PIN_NO(190) | 3)
+#define MT2712_PIN_190_I2SO2_DATA0__FUNC_PCM1_DI (MTK_PIN_NO(190) | 4)
+#define MT2712_PIN_190_I2SO2_DATA0__FUNC_MRG_TX (MTK_PIN_NO(190) | 5)
+#define MT2712_PIN_190_I2SO2_DATA0__FUNC_PCM1_DO (MTK_PIN_NO(190) | 6)
+#define MT2712_PIN_190_I2SO2_DATA0__FUNC_I2S_IQ0_SDIA (MTK_PIN_NO(190) | 7)
+
+#define MT2712_PIN_191_I2SO0_DATA1__FUNC_GPIO191 (MTK_PIN_NO(191) | 0)
+#define MT2712_PIN_191_I2SO0_DATA1__FUNC_I2SO0_DO1 (MTK_PIN_NO(191) | 1)
+#define MT2712_PIN_191_I2SO0_DATA1__FUNC_I2SI0_DI (MTK_PIN_NO(191) | 2)
+#define MT2712_PIN_191_I2SO0_DATA1__FUNC_I2SI1_DI (MTK_PIN_NO(191) | 3)
+#define MT2712_PIN_191_I2SO0_DATA1__FUNC_I2SI2_DI (MTK_PIN_NO(191) | 4)
+#define MT2712_PIN_191_I2SO0_DATA1__FUNC_DAI_TX (MTK_PIN_NO(191) | 5)
+#define MT2712_PIN_191_I2SO0_DATA1__FUNC_I2S_IQ0_SDQB (MTK_PIN_NO(191) | 6)
+#define MT2712_PIN_191_I2SO0_DATA1__FUNC_I2S_IQ1_SDQB (MTK_PIN_NO(191) | 7)
+
+#define MT2712_PIN_192_I2SO0_MCLK__FUNC_GPIO192 (MTK_PIN_NO(192) | 0)
+#define MT2712_PIN_192_I2SO0_MCLK__FUNC_I2SO0_MCK (MTK_PIN_NO(192) | 1)
+#define MT2712_PIN_192_I2SO0_MCLK__FUNC_I2SO1_MCK (MTK_PIN_NO(192) | 2)
+#define MT2712_PIN_192_I2SO0_MCLK__FUNC_I2SO2_MCK (MTK_PIN_NO(192) | 3)
+#define MT2712_PIN_192_I2SO0_MCLK__FUNC_USB4_FT_SCL (MTK_PIN_NO(192) | 4)
+#define MT2712_PIN_192_I2SO0_MCLK__FUNC_TDMO1_DATA3 (MTK_PIN_NO(192) | 5)
+#define MT2712_PIN_192_I2SO0_MCLK__FUNC_I2S_IQ0_SDIB (MTK_PIN_NO(192) | 6)
+#define MT2712_PIN_192_I2SO0_MCLK__FUNC_I2S_IQ1_SDQA (MTK_PIN_NO(192) | 7)
+
+#define MT2712_PIN_193_I2SO0_DATA0__FUNC_GPIO193 (MTK_PIN_NO(193) | 0)
+#define MT2712_PIN_193_I2SO0_DATA0__FUNC_I2SO0_DO0 (MTK_PIN_NO(193) | 1)
+#define MT2712_PIN_193_I2SO0_DATA0__FUNC_I2SO1_DO (MTK_PIN_NO(193) | 2)
+#define MT2712_PIN_193_I2SO0_DATA0__FUNC_I2SO2_DO (MTK_PIN_NO(193) | 3)
+#define MT2712_PIN_193_I2SO0_DATA0__FUNC_USB4_FT_SDA (MTK_PIN_NO(193) | 4)
+#define MT2712_PIN_193_I2SO0_DATA0__FUNC_I2S_IQ1_SDIA (MTK_PIN_NO(193) | 7)
+
+#define MT2712_PIN_194_I2SO0_LRCK__FUNC_GPIO194 (MTK_PIN_NO(194) | 0)
+#define MT2712_PIN_194_I2SO0_LRCK__FUNC_I2SO0_WS (MTK_PIN_NO(194) | 1)
+#define MT2712_PIN_194_I2SO0_LRCK__FUNC_I2SO1_WS (MTK_PIN_NO(194) | 2)
+#define MT2712_PIN_194_I2SO0_LRCK__FUNC_I2SO2_WS (MTK_PIN_NO(194) | 3)
+#define MT2712_PIN_194_I2SO0_LRCK__FUNC_USB5_FT_SCL (MTK_PIN_NO(194) | 4)
+#define MT2712_PIN_194_I2SO0_LRCK__FUNC_TDMO1_DATA2 (MTK_PIN_NO(194) | 5)
+#define MT2712_PIN_194_I2SO0_LRCK__FUNC_I2S_IQ1_WS (MTK_PIN_NO(194) | 7)
+
+#define MT2712_PIN_195_I2SO0_BCK__FUNC_GPIO195 (MTK_PIN_NO(195) | 0)
+#define MT2712_PIN_195_I2SO0_BCK__FUNC_I2SO0_BCK (MTK_PIN_NO(195) | 1)
+#define MT2712_PIN_195_I2SO0_BCK__FUNC_I2SO1_BCK (MTK_PIN_NO(195) | 2)
+#define MT2712_PIN_195_I2SO0_BCK__FUNC_I2SO2_BCK (MTK_PIN_NO(195) | 3)
+#define MT2712_PIN_195_I2SO0_BCK__FUNC_USB5_FT_SDA (MTK_PIN_NO(195) | 4)
+#define MT2712_PIN_195_I2SO0_BCK__FUNC_TDMO1_DATA1 (MTK_PIN_NO(195) | 5)
+#define MT2712_PIN_195_I2SO0_BCK__FUNC_I2S_IQ1_BCK (MTK_PIN_NO(195) | 7)
+
+#define MT2712_PIN_196_TDMO1_MCLK__FUNC_GPIO196 (MTK_PIN_NO(196) | 0)
+#define MT2712_PIN_196_TDMO1_MCLK__FUNC_TDMO1_MCLK (MTK_PIN_NO(196) | 1)
+#define MT2712_PIN_196_TDMO1_MCLK__FUNC_TDMO0_MCLK (MTK_PIN_NO(196) | 2)
+#define MT2712_PIN_196_TDMO1_MCLK__FUNC_TDMIN_MCLK (MTK_PIN_NO(196) | 3)
+#define MT2712_PIN_196_TDMO1_MCLK__FUNC_I2SO0_DO1 (MTK_PIN_NO(196) | 6)
+#define MT2712_PIN_196_TDMO1_MCLK__FUNC_I2S_IQ1_SDIB (MTK_PIN_NO(196) | 7)
+
+#define MT2712_PIN_197_TDMO1_LRCK__FUNC_GPIO197 (MTK_PIN_NO(197) | 0)
+#define MT2712_PIN_197_TDMO1_LRCK__FUNC_TDMO1_LRCK (MTK_PIN_NO(197) | 1)
+#define MT2712_PIN_197_TDMO1_LRCK__FUNC_TDMO0_LRCK (MTK_PIN_NO(197) | 2)
+#define MT2712_PIN_197_TDMO1_LRCK__FUNC_TDMIN_LRCK (MTK_PIN_NO(197) | 3)
+#define MT2712_PIN_197_TDMO1_LRCK__FUNC_TDMO0_DATA3 (MTK_PIN_NO(197) | 4)
+#define MT2712_PIN_197_TDMO1_LRCK__FUNC_TDMO1_DATA3 (MTK_PIN_NO(197) | 5)
+#define MT2712_PIN_197_TDMO1_LRCK__FUNC_I2SO3_MCK (MTK_PIN_NO(197) | 6)
+#define MT2712_PIN_197_TDMO1_LRCK__FUNC_TDMO1_DATA2 (MTK_PIN_NO(197) | 7)
+
+#define MT2712_PIN_198_TDMO1_BCK__FUNC_GPIO198 (MTK_PIN_NO(198) | 0)
+#define MT2712_PIN_198_TDMO1_BCK__FUNC_TDMO1_BCK (MTK_PIN_NO(198) | 1)
+#define MT2712_PIN_198_TDMO1_BCK__FUNC_TDMO0_BCK (MTK_PIN_NO(198) | 2)
+#define MT2712_PIN_198_TDMO1_BCK__FUNC_TDMIN_BCK (MTK_PIN_NO(198) | 3)
+#define MT2712_PIN_198_TDMO1_BCK__FUNC_TDMO0_DATA2 (MTK_PIN_NO(198) | 4)
+#define MT2712_PIN_198_TDMO1_BCK__FUNC_TDMO1_DATA2 (MTK_PIN_NO(198) | 5)
+#define MT2712_PIN_198_TDMO1_BCK__FUNC_I2SO3_BCK (MTK_PIN_NO(198) | 6)
+#define MT2712_PIN_198_TDMO1_BCK__FUNC_TDMO1_DATA1 (MTK_PIN_NO(198) | 7)
+
+#define MT2712_PIN_199_TDMO1_DATA__FUNC_GPIO199 (MTK_PIN_NO(199) | 0)
+#define MT2712_PIN_199_TDMO1_DATA__FUNC_TDMO1_DATA (MTK_PIN_NO(199) | 1)
+#define MT2712_PIN_199_TDMO1_DATA__FUNC_TDMO0_DATA (MTK_PIN_NO(199) | 2)
+#define MT2712_PIN_199_TDMO1_DATA__FUNC_TDMIN_DI (MTK_PIN_NO(199) | 3)
+#define MT2712_PIN_199_TDMO1_DATA__FUNC_TDMO0_DATA1 (MTK_PIN_NO(199) | 4)
+#define MT2712_PIN_199_TDMO1_DATA__FUNC_TDMO1_DATA1 (MTK_PIN_NO(199) | 5)
+#define MT2712_PIN_199_TDMO1_DATA__FUNC_I2SO3_WS (MTK_PIN_NO(199) | 6)
+
+#define MT2712_PIN_200_TDMO0_MCLK__FUNC_GPIO200 (MTK_PIN_NO(200) | 0)
+#define MT2712_PIN_200_TDMO0_MCLK__FUNC_TDMO0_MCLK0 (MTK_PIN_NO(200) | 1)
+#define MT2712_PIN_200_TDMO0_MCLK__FUNC_TDMO1_MCLK0 (MTK_PIN_NO(200) | 2)
+#define MT2712_PIN_200_TDMO0_MCLK__FUNC_PCM1_DI (MTK_PIN_NO(200) | 3)
+#define MT2712_PIN_200_TDMO0_MCLK__FUNC_TDMO0_MCLK1 (MTK_PIN_NO(200) | 4)
+#define MT2712_PIN_200_TDMO0_MCLK__FUNC_TDMO1_MCLK1 (MTK_PIN_NO(200) | 5)
+#define MT2712_PIN_200_TDMO0_MCLK__FUNC_MRG_TX (MTK_PIN_NO(200) | 6)
+#define MT2712_PIN_200_TDMO0_MCLK__FUNC_I2SO2_MCK (MTK_PIN_NO(200) | 7)
+
+#define MT2712_PIN_201_TDMO0_LRCK__FUNC_GPIO201 (MTK_PIN_NO(201) | 0)
+#define MT2712_PIN_201_TDMO0_LRCK__FUNC_TDMO0_LRCK0 (MTK_PIN_NO(201) | 1)
+#define MT2712_PIN_201_TDMO0_LRCK__FUNC_TDMO1_LRCK0 (MTK_PIN_NO(201) | 2)
+#define MT2712_PIN_201_TDMO0_LRCK__FUNC_PCM1_SYNC (MTK_PIN_NO(201) | 3)
+#define MT2712_PIN_201_TDMO0_LRCK__FUNC_TDMO0_LRCK1 (MTK_PIN_NO(201) | 4)
+#define MT2712_PIN_201_TDMO0_LRCK__FUNC_TDMO1_LRCK1 (MTK_PIN_NO(201) | 5)
+#define MT2712_PIN_201_TDMO0_LRCK__FUNC_MRG_RX (MTK_PIN_NO(201) | 6)
+#define MT2712_PIN_201_TDMO0_LRCK__FUNC_I2SO2_WS (MTK_PIN_NO(201) | 7)
+
+#define MT2712_PIN_202_TDMO0_BCK__FUNC_GPIO202 (MTK_PIN_NO(202) | 0)
+#define MT2712_PIN_202_TDMO0_BCK__FUNC_TDMO0_BCK0 (MTK_PIN_NO(202) | 1)
+#define MT2712_PIN_202_TDMO0_BCK__FUNC_TDMO1_BCK0 (MTK_PIN_NO(202) | 2)
+#define MT2712_PIN_202_TDMO0_BCK__FUNC_PCM1_CLK (MTK_PIN_NO(202) | 3)
+#define MT2712_PIN_202_TDMO0_BCK__FUNC_TDMO0_BCK1 (MTK_PIN_NO(202) | 4)
+#define MT2712_PIN_202_TDMO0_BCK__FUNC_TDMO1_BCK1 (MTK_PIN_NO(202) | 5)
+#define MT2712_PIN_202_TDMO0_BCK__FUNC_MRG_SYNC (MTK_PIN_NO(202) | 6)
+#define MT2712_PIN_202_TDMO0_BCK__FUNC_I2SO2_BCK (MTK_PIN_NO(202) | 7)
+
+#define MT2712_PIN_203_TDMO0_DATA__FUNC_GPIO203 (MTK_PIN_NO(203) | 0)
+#define MT2712_PIN_203_TDMO0_DATA__FUNC_TDMO0_DATA0 (MTK_PIN_NO(203) | 1)
+#define MT2712_PIN_203_TDMO0_DATA__FUNC_TDMO1_DATA0 (MTK_PIN_NO(203) | 2)
+#define MT2712_PIN_203_TDMO0_DATA__FUNC_PCM1_DO (MTK_PIN_NO(203) | 3)
+#define MT2712_PIN_203_TDMO0_DATA__FUNC_TDMO0_DATA1 (MTK_PIN_NO(203) | 4)
+#define MT2712_PIN_203_TDMO0_DATA__FUNC_TDMO1_DATA1 (MTK_PIN_NO(203) | 5)
+#define MT2712_PIN_203_TDMO0_DATA__FUNC_MRG_CLK (MTK_PIN_NO(203) | 6)
+#define MT2712_PIN_203_TDMO0_DATA__FUNC_I2SO2_DO (MTK_PIN_NO(203) | 7)
+
+#define MT2712_PIN_204_PERSTB_P0__FUNC_GPIO204 (MTK_PIN_NO(204) | 0)
+#define MT2712_PIN_204_PERSTB_P0__FUNC_PERST_B_P0 (MTK_PIN_NO(204) | 1)
+
+#define MT2712_PIN_205_CLKREQN_P0__FUNC_GPIO205 (MTK_PIN_NO(205) | 0)
+#define MT2712_PIN_205_CLKREQN_P0__FUNC_CLKREQ_N_P0 (MTK_PIN_NO(205) | 1)
+
+#define MT2712_PIN_206_WAKEEN_P0__FUNC_GPIO206 (MTK_PIN_NO(206) | 0)
+#define MT2712_PIN_206_WAKEEN_P0__FUNC_WAKE_EN_P0 (MTK_PIN_NO(206) | 1)
+
+#define MT2712_PIN_207_PERSTB_P1__FUNC_GPIO207 (MTK_PIN_NO(207) | 0)
+#define MT2712_PIN_207_PERSTB_P1__FUNC_PERST_B_P1 (MTK_PIN_NO(207) | 1)
+
+#define MT2712_PIN_208_CLKREQN_P1__FUNC_GPIO208 (MTK_PIN_NO(208) | 0)
+#define MT2712_PIN_208_CLKREQN_P1__FUNC_CLKREQ_N_P1 (MTK_PIN_NO(208) | 1)
+
+#define MT2712_PIN_209_WAKEEN_P1__FUNC_GPIO209 (MTK_PIN_NO(209) | 0)
+#define MT2712_PIN_209_WAKEEN_P1__FUNC_WAKE_EN_P1 (MTK_PIN_NO(209) | 1)
+
+#endif /* __DTS_MT2712_PINFUNC_H */
diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
index 9d88f41..6d8532a 100644
--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
@@ -9,6 +9,7 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/mt2712-power.h>
+#include "mt2712-pinfunc.h"
/ {
compatible = "mediatek,mt2712";
@@ -199,6 +200,34 @@
clock-output-names = "clkaud_ext_i_2";
};
+ clki2si0_mck_i: oscillator@6 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <30000000>;
+ clock-output-names = "clki2si0_mck_i";
+ };
+
+ clki2si1_mck_i: oscillator@7 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <30000000>;
+ clock-output-names = "clki2si1_mck_i";
+ };
+
+ clki2si2_mck_i: oscillator@8 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <30000000>;
+ clock-output-names = "clki2si2_mck_i";
+ };
+
+ clktdmin_mclk_i: oscillator@9 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <30000000>;
+ clock-output-names = "clktdmin_mclk_i";
+ };
+
timer {
compatible = "arm,armv8-timer";
interrupt-parent = <&gic>;
@@ -230,6 +259,23 @@
#clock-cells = <1>;
};
+ syscfg_pctl_a: syscfg_pctl_a@10005000 {
+ compatible = "mediatek,mt2712-pctl-a-syscfg", "syscon";
+ reg = <0 0x10005000 0 0x1000>;
+ };
+
+ pio: pinctrl@10005000 {
+ compatible = "mediatek,mt2712-pinctrl";
+ reg = <0 0x1000b000 0 0x1000>;
+ mediatek,pctl-regmap = <&syscfg_pctl_a>;
+ pins-are-numbered;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
scpsys: scpsys@10006000 {
compatible = "mediatek,mt2712-scpsys", "syscon";
#power-domain-cells = <1>;
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
index 45d8655..b783764 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
@@ -18,7 +18,7 @@
compatible = "mediatek,mt7622-rfb1", "mediatek,mt7622";
chosen {
- bootargs = "console=ttyS0,115200n1";
+ bootargs = "console=ttyS0,115200n1 swiotlb=512";
};
cpus {
@@ -163,10 +163,17 @@
i2s1_pins: i2s1-pins {
mux {
function = "i2s";
- groups = "i2s_out_bclk_ws_mclk",
+ groups = "i2s_out_mclk_bclk_ws",
"i2s1_in_data",
"i2s1_out_data";
};
+
+ conf {
+ pins = "I2S1_IN", "I2S1_OUT", "I2S_BCLK",
+ "I2S_WS", "I2S_MCLK";
+ drive-strength = <12>;
+ bias-pull-down;
+ };
};
irrx_pins: irrx-pins {
diff --git a/arch/arm64/boot/dts/mediatek/mt7622.dtsi b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
index e9d5130..9213c96 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7622.dtsi
@@ -527,6 +527,95 @@
status = "disabled";
};
+ audsys: clock-controller@11220000 {
+ compatible = "mediatek,mt7622-audsys", "syscon";
+ reg = <0 0x11220000 0 0x2000>;
+ #clock-cells = <1>;
+
+ afe: audio-controller {
+ compatible = "mediatek,mt7622-audio";
+ interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 145 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "afe", "asys";
+
+ clocks = <&infracfg CLK_INFRA_AUDIO_PD>,
+ <&topckgen CLK_TOP_AUD1_SEL>,
+ <&topckgen CLK_TOP_AUD2_SEL>,
+ <&topckgen CLK_TOP_A1SYS_HP_DIV_PD>,
+ <&topckgen CLK_TOP_A2SYS_HP_DIV_PD>,
+ <&topckgen CLK_TOP_I2S0_MCK_SEL>,
+ <&topckgen CLK_TOP_I2S1_MCK_SEL>,
+ <&topckgen CLK_TOP_I2S2_MCK_SEL>,
+ <&topckgen CLK_TOP_I2S3_MCK_SEL>,
+ <&topckgen CLK_TOP_I2S0_MCK_DIV>,
+ <&topckgen CLK_TOP_I2S1_MCK_DIV>,
+ <&topckgen CLK_TOP_I2S2_MCK_DIV>,
+ <&topckgen CLK_TOP_I2S3_MCK_DIV>,
+ <&topckgen CLK_TOP_I2S0_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_I2S1_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_I2S2_MCK_DIV_PD>,
+ <&topckgen CLK_TOP_I2S3_MCK_DIV_PD>,
+ <&audsys CLK_AUDIO_I2SO1>,
+ <&audsys CLK_AUDIO_I2SO2>,
+ <&audsys CLK_AUDIO_I2SO3>,
+ <&audsys CLK_AUDIO_I2SO4>,
+ <&audsys CLK_AUDIO_I2SIN1>,
+ <&audsys CLK_AUDIO_I2SIN2>,
+ <&audsys CLK_AUDIO_I2SIN3>,
+ <&audsys CLK_AUDIO_I2SIN4>,
+ <&audsys CLK_AUDIO_ASRCO1>,
+ <&audsys CLK_AUDIO_ASRCO2>,
+ <&audsys CLK_AUDIO_ASRCO3>,
+ <&audsys CLK_AUDIO_ASRCO4>,
+ <&audsys CLK_AUDIO_AFE>,
+ <&audsys CLK_AUDIO_AFE_CONN>,
+ <&audsys CLK_AUDIO_A1SYS>,
+ <&audsys CLK_AUDIO_A2SYS>;
+
+ clock-names = "infra_sys_audio_clk",
+ "top_audio_mux1_sel",
+ "top_audio_mux2_sel",
+ "top_audio_a1sys_hp",
+ "top_audio_a2sys_hp",
+ "i2s0_src_sel",
+ "i2s1_src_sel",
+ "i2s2_src_sel",
+ "i2s3_src_sel",
+ "i2s0_src_div",
+ "i2s1_src_div",
+ "i2s2_src_div",
+ "i2s3_src_div",
+ "i2s0_mclk_en",
+ "i2s1_mclk_en",
+ "i2s2_mclk_en",
+ "i2s3_mclk_en",
+ "i2so0_hop_ck",
+ "i2so1_hop_ck",
+ "i2so2_hop_ck",
+ "i2so3_hop_ck",
+ "i2si0_hop_ck",
+ "i2si1_hop_ck",
+ "i2si2_hop_ck",
+ "i2si3_hop_ck",
+ "asrc0_out_ck",
+ "asrc1_out_ck",
+ "asrc2_out_ck",
+ "asrc3_out_ck",
+ "audio_afe_pd",
+ "audio_afe_conn_pd",
+ "audio_a1sys_pd",
+ "audio_a2sys_pd";
+
+ assigned-clocks = <&topckgen CLK_TOP_A1SYS_HP_SEL>,
+ <&topckgen CLK_TOP_A2SYS_HP_SEL>,
+ <&topckgen CLK_TOP_A1SYS_HP_DIV>,
+ <&topckgen CLK_TOP_A2SYS_HP_DIV>;
+ assigned-clock-parents = <&topckgen CLK_TOP_AUD1PLL>,
+ <&topckgen CLK_TOP_AUD2PLL>;
+ assigned-clock-rates = <0>, <0>, <49152000>, <45158400>;
+ };
+ };
+
mmc0: mmc@11230000 {
compatible = "mediatek,mt7622-mmc";
reg = <0 0x11230000 0 0x1000>;
@@ -735,6 +824,16 @@
#reset-cells = <1>;
};
+ hsdma: dma-controller@1b007000 {
+ compatible = "mediatek,mt7622-hsdma";
+ reg = <0 0x1b007000 0 0x1000>;
+ interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&ethsys CLK_ETH_HSDMA_EN>;
+ clock-names = "hsdma";
+ power-domains = <&scpsys MT7622_POWER_DOMAIN_ETHSYS>;
+ #dma-cells = <1>;
+ };
+
eth: ethernet@1b100000 {
compatible = "mediatek,mt7622-eth",
"mediatek,mt2701-eth",
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 55ec5ee..9319e74 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -6,3 +6,4 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8992-bullhead-rev-101.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8994-angler-rev-101.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sdm845-mtp.dtb
diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi
index 6167af9..a6ad3d7 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c-pmic-pins.dtsi
@@ -4,7 +4,7 @@
&pm8994_gpios {
pinctrl-names = "default";
- pinctrl-0 = <&ls_exp_gpio_f>;
+ pinctrl-0 = <&ls_exp_gpio_f &bt_en_gpios>;
ls_exp_gpio_f: pm8994_gpio5 {
pinconf {
diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
index 4b8bb02..0f829db 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dtsi
@@ -117,6 +117,16 @@
pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
cd-gpios = <&msmgpio 38 0x1>;
+ vmmc-supply = <&pm8994_l21>;
+ vqmmc-supply = <&pm8994_l13>;
+ status = "okay";
+ };
+
+ phy@627000 {
+ status = "okay";
+ };
+
+ ufshc@624000 {
status = "okay";
};
@@ -169,19 +179,6 @@
pinctrl-0 = <&usb2_vbus_det_gpio>;
};
- bt_en: bt-en-1-8v {
- pinctrl-names = "default";
- pinctrl-0 = <&bt_en_gpios>;
- compatible = "regulator-fixed";
- regulator-name = "bt-en-regulator";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
-
- /* WLAN card specific delay */
- startup-delay-us = <70000>;
- enable-active-high;
- };
-
wlan_en: wlan-en-1-8v {
pinctrl-names = "default";
pinctrl-0 = <&wlan_en_gpios>;
@@ -198,19 +195,18 @@
};
agnoc@0 {
- qcom,pcie@600000 {
+ pcie@600000 {
status = "okay";
perst-gpio = <&msmgpio 35 GPIO_ACTIVE_LOW>;
- vddpe-supply = <&wlan_en>;
- vddpe1-supply = <&bt_en>;
+ vddpe-3v3-supply = <&wlan_en>;
};
- qcom,pcie@608000 {
+ pcie@608000 {
status = "okay";
perst-gpio = <&msmgpio 130 GPIO_ACTIVE_LOW>;
};
- qcom,pcie@610000 {
+ pcie@610000 {
status = "okay";
perst-gpio = <&msmgpio 114 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
index 6a838b5..c13ddee 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
@@ -21,6 +21,7 @@
aliases {
serial0 = &blsp1_uart5;
+ serial1 = &blsp1_uart3;
};
chosen {
@@ -33,20 +34,61 @@
};
soc {
- pinctrl@1000000 {
- serial_4_pins: serial4_pinmux {
- mux {
- pins = "gpio23", "gpio24";
- function = "blsp4_uart1";
- bias-disable;
- };
+ serial@78b3000 {
+ status = "ok";
+ };
+
+ spi@78b5000 {
+ status = "ok";
+
+ m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
};
};
- serial@78b3000 {
- pinctrl-0 = <&serial_4_pins>;
- pinctrl-names = "default";
+ serial@78b1000 {
+ status = "ok";
+ };
+
+ i2c@78b6000 {
+ status = "ok";
+ };
+
+ dma@7984000 {
+ status = "ok";
+ };
+
+ nand@79b0000 {
+ status = "ok";
+
+ nand@0 {
+ reg = <0>;
+ nand-ecc-strength = <4>;
+ nand-ecc-step-size = <512>;
+ nand-bus-width = <8>;
+ };
+ };
+
+ phy@86000 {
+ status = "ok";
+ };
+
+ phy@8e000 {
+ status = "ok";
+ };
+
+ pci@20000000 {
+ status = "ok";
+ perst-gpio = <&tlmm 58 0x1>;
+ };
+
+ pci@10000000 {
status = "ok";
+ perst-gpio = <&tlmm 61 0x1>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
index 2bc5dec..1822698 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -24,7 +24,7 @@
ranges = <0 0 0 0xffffffff>;
compatible = "simple-bus";
- pinctrl@1000000 {
+ tlmm: pinctrl@1000000 {
compatible = "qcom,ipq8074-pinctrl";
reg = <0x1000000 0x300000>;
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
@@ -32,6 +32,45 @@
#gpio-cells = <0x2>;
interrupt-controller;
#interrupt-cells = <0x2>;
+
+ serial_4_pins: serial4-pinmux {
+ pins = "gpio23", "gpio24";
+ function = "blsp4_uart1";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ i2c_0_pins: i2c-0-pinmux {
+ pins = "gpio42", "gpio43";
+ function = "blsp1_i2c";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ spi_0_pins: spi-0-pins {
+ pins = "gpio38", "gpio39", "gpio40", "gpio41";
+ function = "blsp0_spi";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ hsuart_pins: hsuart-pins {
+ pins = "gpio46", "gpio47", "gpio48", "gpio49";
+ function = "blsp2_uart";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ qpic_pins: qpic-pins {
+ pins = "gpio1", "gpio3", "gpio4",
+ "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio10", "gpio11",
+ "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17";
+ function = "qpic";
+ drive-strength = <8>;
+ bias-disable;
+ };
};
intc: interrupt-controller@b000000 {
@@ -122,6 +161,276 @@
clocks = <&gcc GCC_BLSP1_UART5_APPS_CLK>,
<&gcc GCC_BLSP1_AHB_CLK>;
clock-names = "core", "iface";
+ pinctrl-0 = <&serial_4_pins>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ blsp_dma: dma@7884000 {
+ compatible = "qcom,bam-v1.7.0";
+ reg = <0x7884000 0x2b000>;
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "bam_clk";
+ #dma-cells = <1>;
+ qcom,ee = <0>;
+ };
+
+ blsp1_uart1: serial@78af000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x78af000 0x200>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>,
+ <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ status = "disabled";
+ };
+
+ blsp1_uart3: serial@78b1000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x78b1000 0x200>;
+ interrupts = <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_UART3_APPS_CLK>,
+ <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ dmas = <&blsp_dma 4>,
+ <&blsp_dma 5>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&hsuart_pins>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ blsp1_spi1: spi@78b5000 {
+ compatible = "qcom,spi-qup-v2.2.1";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x78b5000 0x600>;
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+ spi-max-frequency = <50000000>;
+ clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>,
+ <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ dmas = <&blsp_dma 12>, <&blsp_dma 13>;
+ dma-names = "tx", "rx";
+ pinctrl-0 = <&spi_0_pins>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ blsp1_i2c2: i2c@78b6000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x78b6000 0x600>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>,
+ <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>;
+ clock-names = "iface", "core";
+ clock-frequency = <400000>;
+ dmas = <&blsp_dma 15>, <&blsp_dma 14>;
+ dma-names = "rx", "tx";
+ pinctrl-0 = <&i2c_0_pins>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ blsp1_i2c3: i2c@78b7000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x78b7000 0x600>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>,
+ <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>;
+ clock-names = "iface", "core";
+ clock-frequency = <100000>;
+ dmas = <&blsp_dma 17>, <&blsp_dma 16>;
+ dma-names = "rx", "tx";
+ status = "disabled";
+ };
+
+ qpic_bam: dma@7984000 {
+ compatible = "qcom,bam-v1.7.0";
+ reg = <0x7984000 0x1a000>;
+ interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_QPIC_AHB_CLK>;
+ clock-names = "bam_clk";
+ #dma-cells = <1>;
+ qcom,ee = <0>;
+ status = "disabled";
+ };
+
+ qpic_nand: nand@79b0000 {
+ compatible = "qcom,ipq8074-nand";
+ reg = <0x79b0000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ clocks = <&gcc GCC_QPIC_CLK>,
+ <&gcc GCC_QPIC_AHB_CLK>;
+ clock-names = "core", "aon";
+
+ dmas = <&qpic_bam 0>,
+ <&qpic_bam 1>,
+ <&qpic_bam 2>;
+ dma-names = "tx", "rx", "cmd";
+ pinctrl-0 = <&qpic_pins>;
+ pinctrl-names = "default";
+ status = "disabled";
+ };
+
+ pcie_phy0: phy@86000 {
+ compatible = "qcom,ipq8074-qmp-pcie-phy";
+ reg = <0x86000 0x1000>;
+ #phy-cells = <0>;
+ clocks = <&gcc GCC_PCIE0_PIPE_CLK>;
+ clock-names = "pipe_clk";
+ clock-output-names = "pcie20_phy0_pipe_clk";
+
+ resets = <&gcc GCC_PCIE0_PHY_BCR>,
+ <&gcc GCC_PCIE0PHY_PHY_BCR>;
+ reset-names = "phy",
+ "common";
+ status = "disabled";
+ };
+
+ pcie0: pci@20000000 {
+ compatible = "qcom,pcie-ipq8074";
+ reg = <0x20000000 0xf1d
+ 0x20000f20 0xa8
+ 0x80000 0x2000
+ 0x20100000 0x1000>;
+ reg-names = "dbi", "elbi", "parf", "config";
+ device_type = "pci";
+ linux,pci-domain = <0>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ phys = <&pcie_phy0>;
+ phy-names = "pciephy";
+
+ ranges = <0x81000000 0 0x20200000 0x20200000
+ 0 0x100000 /* downstream I/O */
+ 0x82000000 0 0x20300000 0x20300000
+ 0 0xd00000>; /* non-prefetchable memory */
+
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 75
+ IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+ <0 0 0 2 &intc 0 78
+ IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+ <0 0 0 3 &intc 0 79
+ IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+ <0 0 0 4 &intc 0 83
+ IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+ clocks = <&gcc GCC_SYS_NOC_PCIE0_AXI_CLK>,
+ <&gcc GCC_PCIE0_AXI_M_CLK>,
+ <&gcc GCC_PCIE0_AXI_S_CLK>,
+ <&gcc GCC_PCIE0_AHB_CLK>,
+ <&gcc GCC_PCIE0_AUX_CLK>;
+
+ clock-names = "iface",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "aux";
+ resets = <&gcc GCC_PCIE0_PIPE_ARES>,
+ <&gcc GCC_PCIE0_SLEEP_ARES>,
+ <&gcc GCC_PCIE0_CORE_STICKY_ARES>,
+ <&gcc GCC_PCIE0_AXI_MASTER_ARES>,
+ <&gcc GCC_PCIE0_AXI_SLAVE_ARES>,
+ <&gcc GCC_PCIE0_AHB_ARES>,
+ <&gcc GCC_PCIE0_AXI_MASTER_STICKY_ARES>;
+ reset-names = "pipe",
+ "sleep",
+ "sticky",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "axi_m_sticky";
+ status = "disabled";
+ };
+
+ pcie_phy1: phy@8e000 {
+ compatible = "qcom,ipq8074-qmp-pcie-phy";
+ reg = <0x8e000 0x1000>;
+ #phy-cells = <0>;
+ clocks = <&gcc GCC_PCIE1_PIPE_CLK>;
+ clock-names = "pipe_clk";
+ clock-output-names = "pcie20_phy1_pipe_clk";
+
+ resets = <&gcc GCC_PCIE1_PHY_BCR>,
+ <&gcc GCC_PCIE1PHY_PHY_BCR>;
+ reset-names = "phy",
+ "common";
+ status = "disabled";
+ };
+
+ pcie1: pci@10000000 {
+ compatible = "qcom,pcie-ipq8074";
+ reg = <0x10000000 0xf1d
+ 0x10000f20 0xa8
+ 0x88000 0x2000
+ 0x10100000 0x1000>;
+ reg-names = "dbi", "elbi", "parf", "config";
+ device_type = "pci";
+ linux,pci-domain = <1>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ phys = <&pcie_phy1>;
+ phy-names = "pciephy";
+
+ ranges = <0x81000000 0 0x10200000 0x10200000
+ 0 0x100000 /* downstream I/O */
+ 0x82000000 0 0x10300000 0x10300000
+ 0 0xd00000>; /* non-prefetchable memory */
+
+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 142
+ IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+ <0 0 0 2 &intc 0 143
+ IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+ <0 0 0 3 &intc 0 144
+ IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+ <0 0 0 4 &intc 0 145
+ IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+ clocks = <&gcc GCC_SYS_NOC_PCIE1_AXI_CLK>,
+ <&gcc GCC_PCIE1_AXI_M_CLK>,
+ <&gcc GCC_PCIE1_AXI_S_CLK>,
+ <&gcc GCC_PCIE1_AHB_CLK>,
+ <&gcc GCC_PCIE1_AUX_CLK>;
+ clock-names = "iface",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "aux";
+ resets = <&gcc GCC_PCIE1_PIPE_ARES>,
+ <&gcc GCC_PCIE1_SLEEP_ARES>,
+ <&gcc GCC_PCIE1_CORE_STICKY_ARES>,
+ <&gcc GCC_PCIE1_AXI_MASTER_ARES>,
+ <&gcc GCC_PCIE1_AXI_SLAVE_ARES>,
+ <&gcc GCC_PCIE1_AHB_ARES>,
+ <&gcc GCC_PCIE1_AXI_MASTER_STICKY_ARES>;
+ reset-names = "pipe",
+ "sleep",
+ "sticky",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "axi_m_sticky";
status = "disabled";
};
};
@@ -175,7 +484,7 @@
pmu {
compatible = "arm,armv8-pmuv3";
- interrupts = <GIC_PPI 7 GIC_CPU_MASK_SIMPLE(4)>;
+ interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
clocks {
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index 66b318e..650f356 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -179,7 +179,7 @@
pmu {
compatible = "arm,cortex-a53-pmu";
- interrupts = <GIC_PPI 7 GIC_CPU_MASK_SIMPLE(4)>;
+ interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(4)| IRQ_TYPE_LEVEL_HIGH)>;
};
thermal-zones {
@@ -512,7 +512,7 @@
blsp_i2c2: i2c@78b6000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x078b6000 0x500>;
- interrupts = <GIC_SPI 96 0>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_BLSP1_AHB_CLK>,
<&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>;
clock-names = "iface", "core";
@@ -527,7 +527,7 @@
blsp_i2c4: i2c@78b8000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x078b8000 0x500>;
- interrupts = <GIC_SPI 98 0>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_BLSP1_AHB_CLK>,
<&gcc GCC_BLSP1_QUP4_I2C_APPS_CLK>;
clock-names = "iface", "core";
@@ -542,7 +542,7 @@
blsp_i2c6: i2c@78ba000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x078ba000 0x500>;
- interrupts = <GIC_SPI 100 0>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_BLSP1_AHB_CLK>,
<&gcc GCC_BLSP1_QUP6_I2C_APPS_CLK>;
clock-names = "iface", "core";
@@ -574,7 +574,7 @@
"mi2s-bit-clk3";
#sound-dai-cells = <1>;
- interrupts = <0 160 0>;
+ interrupts = <0 160 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "lpass-irq-lpaif";
reg = <0x07708000 0x10000>;
reg-names = "lpass-lpaif";
@@ -594,7 +594,7 @@
reg = <0x07824900 0x11c>, <0x07824000 0x800>;
reg-names = "hc_mem", "core_mem";
- interrupts = <0 123 0>, <0 138 0>;
+ interrupts = <0 123 IRQ_TYPE_LEVEL_HIGH>, <0 138 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hc_irq", "pwr_irq";
clocks = <&gcc GCC_SDCC1_APPS_CLK>,
<&gcc GCC_SDCC1_AHB_CLK>,
@@ -611,7 +611,7 @@
reg = <0x07864900 0x11c>, <0x07864000 0x800>;
reg-names = "hc_mem", "core_mem";
- interrupts = <0 125 0>, <0 221 0>;
+ interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>, <0 221 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hc_irq", "pwr_irq";
clocks = <&gcc GCC_SDCC2_APPS_CLK>,
<&gcc GCC_SDCC2_AHB_CLK>,
@@ -818,7 +818,7 @@
iommu-ctx@2000 {
compatible = "qcom,msm-iommu-v1-ns";
reg = <0x2000 0x1000>;
- interrupts = <GIC_SPI 242 0>;
+ interrupts = <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>;
};
};
@@ -862,7 +862,7 @@
"bus_clk",
"vsync_clk";
- interrupts = <0 72 0>;
+ interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts b/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts
index 4542133..8c69516 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts
+++ b/arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts
@@ -38,4 +38,21 @@
pinctrl-1 = <&blsp1_uart2_sleep>;
};
};
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ramoops@1ff00000 {
+ compatible = "ramoops";
+ reg = <0x0 0x1ff00000 0x0 0x40000>;
+ console-size = <0x10000>;
+ record-size = <0x10000>;
+ ftrace-size = <0x10000>;
+ pmsg-size = <0x20000>;
+ };
+ };
};
+
+#include "msm8994-smd-rpm.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi b/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi
index d2a26f0..31bc9d9 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8992-pins.dtsi
@@ -35,4 +35,64 @@
bias-pull-down;
};
};
+
+ /* 0-3 for sdc1 4-6 for sdc2 */
+ /* Order of pins */
+ /* SDC1: CLK -> 0, CMD -> 1, DATA -> 2, RCLK -> 3 */
+ /* SDC2: CLK -> 4, CMD -> 5, DATA -> 6 */
+ sdc1_clk_on: clk-on {
+ pinconf {
+ pins = "sdc1_clk";
+ bias-disable = <0>; /* No pull */
+ drive-strength = <16>; /* 16mA */
+ };
+ };
+
+ sdc1_clk_off: clk-off {
+ pinconf {
+ pins = "sdc1_clk";
+ bias-disable = <0>; /* No pull */
+ drive-strength = <2>; /* 2mA */
+ };
+ };
+
+ sdc1_cmd_on: cmd-on {
+ pinconf {
+ pins = "sdc1_cmd";
+ bias-pull-up;
+ drive-strength = <8>;
+ };
+ };
+
+ sdc1_cmd_off: cmd-off {
+ pinconf {
+ pins = "sdc1_cmd";
+ bias-pull-up = <0x3>; /* same as 3.10 ?? */
+ drive-strength = <2>; /* 2mA */
+ };
+ };
+
+ sdc1_data_on: data-on {
+ pinconf {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <8>; /* 8mA */
+ };
+ };
+
+ sdc1_data_off: data-off {
+ pinconf {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
+
+ sdc1_rclk_on: rclk-on {
+ bias-pull-down; /* pull down */
+ };
+
+ sdc1_rclk_off: rclk-off {
+ bias-pull-down; /* pull down */
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/msm8992.dtsi b/arch/arm64/boot/dts/qcom/msm8992.dtsi
index 1715787..cf5cacd 100644
--- a/arch/arm64/boot/dts/qcom/msm8992.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8992.dtsi
@@ -202,6 +202,31 @@
reg = <0xfc400000 0x2000>;
};
+ sdhci1: mmc@f9824900 {
+ compatible = "qcom,sdhci-msm-v4";
+ reg = <0xf9824900 0x1a0>, <0xf9824000 0x800>;
+ reg-names = "hc_mem", "core_mem";
+
+ interrupts = <GIC_SPI 123 IRQ_TYPE_NONE>,
+ <GIC_SPI 138 IRQ_TYPE_NONE>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&clock_gcc GCC_SDCC1_APPS_CLK>,
+ <&clock_gcc GCC_SDCC1_AHB_CLK>;
+ clock-names = "core", "iface";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on
+ &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off
+ &sdc1_rclk_off>;
+
+ regulator-always-on;
+ bus-width = <8>;
+ mmc-hs400-1_8v;
+ status = "okay";
+ };
+
rpm_msg_ram: memory@fc428000 {
compatible = "qcom,rpm-msg-ram";
reg = <0xfc428000 0x4000>;
@@ -231,7 +256,67 @@
};
};
+ smd_rpm: smd {
+ compatible = "qcom,smd";
+ rpm {
+ interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
+ qcom,ipc = <&apcs 8 0>;
+ qcom,smd-edge = <15>;
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <6>;
+
+ rpm-requests {
+ compatible = "qcom,rpm-msm8994";
+ qcom,smd-channels = "rpm_requests";
+
+ pm8994-regulators {
+ compatible = "qcom,rpm-pm8994-regulators";
+
+ pm8994_s1: s1 {};
+ pm8994_s2: s2 {};
+ pm8994_s3: s3 {};
+ pm8994_s4: s4 {};
+ pm8994_s5: s5 {};
+ pm8994_s6: s6 {};
+ pm8994_s7: s7 {};
+
+ pm8994_l1: l1 {};
+ pm8994_l2: l2 {};
+ pm8994_l3: l3 {};
+ pm8994_l4: l4 {};
+ pm8994_l6: l6 {};
+ pm8994_l8: l8 {};
+ pm8994_l9: l9 {};
+ pm8994_l10: l10 {};
+ pm8994_l11: l11 {};
+ pm8994_l12: l12 {};
+ pm8994_l13: l13 {};
+ pm8994_l14: l14 {};
+ pm8994_l15: l15 {};
+ pm8994_l16: l16 {};
+ pm8994_l17: l17 {};
+ pm8994_l18: l18 {};
+ pm8994_l19: l19 {};
+ pm8994_l20: l20 {};
+ pm8994_l21: l21 {};
+ pm8994_l22: l22 {};
+ pm8994_l23: l23 {};
+ pm8994_l24: l24 {};
+ pm8994_l25: l25 {};
+ pm8994_l26: l26 {};
+ pm8994_l27: l27 {};
+ pm8994_l28: l28 {};
+ pm8994_l29: l29 {};
+ pm8994_l30: l30 {};
+ pm8994_l31: l31 {};
+ pm8994_l32: l32 {};
+
+ pm8994_lvs1: lvs1 {};
+ pm8994_lvs2: lvs2 {};
+ };
+ };
+ };
+ };
};
-
#include "msm8992-pins.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8994-smd-rpm.dtsi b/arch/arm64/boot/dts/qcom/msm8994-smd-rpm.dtsi
new file mode 100644
index 0000000..47ebd16
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8994-smd-rpm.dtsi
@@ -0,0 +1,276 @@
+/* Copyright (c) 2015, LGE Inc. All rights reserved.
+ * Copyright (c) 2016, The Linux Foundation. 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 and
+ * only 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.
+ */
+
+&smd_rpm {
+ rpm {
+ rpm_requests {
+ pm8994-regulators {
+
+ vdd_l1-supply = <&pm8994_s1>;
+ vdd_l2_26_28-supply = <&pm8994_s3>;
+ vdd_l3_11-supply = <&pm8994_s3>;
+ vdd_l4_27_31-supply = <&pm8994_s3>;
+ vdd_l5_7-supply = <&pm8994_s3>;
+ vdd_l6_12_32-supply = <&pm8994_s5>;
+ vdd_l8_16_30-supply = <&vreg_vph_pwr>;
+ vdd_l9_10_18_22-supply = <&vreg_vph_pwr>;
+ vdd_l13_19_23_24-supply = <&vreg_vph_pwr>;
+ vdd_l14_15-supply = <&pm8994_s5>;
+ vdd_l17_29-supply = <&vreg_vph_pwr>;
+ vdd_l20_21-supply = <&vreg_vph_pwr>;
+ vdd_l25-supply = <&pm8994_s5>;
+ vdd_lvs1_2 = <&pm8994_s4>;
+
+ s1 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ };
+
+ s2 {
+ /* TODO */
+ };
+
+ s3 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allow-set-load;
+ regulator-system-load = <325000>;
+ };
+
+ s5 {
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ };
+
+ s7 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ l1 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ l2 {
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <1250000>;
+ };
+
+ l3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ l4 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ l5 {
+ /* TODO */
+ };
+
+ l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l7 {
+ /* TODO */
+ };
+
+ l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ };
+
+ l11 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ qcom,init-voltage = <1200000>;
+ };
+
+ l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ proxy-supply = <&pm8994_l12>;
+ qcom,proxy-consumer-enable;
+ qcom,proxy-consumer-current = <10000>;
+ status = "okay";
+ };
+
+ l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+
+ l14 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ qcom,init-voltage = <1200000>;
+ proxy-supply = <&pm8994_l14>;
+ qcom,proxy-consumer-enable;
+ qcom,proxy-consumer-current = <10000>;
+ status = "okay";
+ };
+
+ l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+
+ l16 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ qcom,init-voltage = <2700000>;
+ status = "okay";
+ };
+
+ l17 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ qcom,init-voltage = <2700000>;
+ status = "okay";
+ };
+
+ l18 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ qcom,init-voltage = <3000000>;
+ qcom,init-ldo-mode = <1>;
+ };
+
+ l19 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+
+ l20 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-allow-set-load;
+ regulator-system-load = <570000>;
+ };
+
+ l21 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ qcom,init-voltage = <1800000>;
+ };
+
+ l22 {
+ regulator-min-microvolt = <3100000>;
+ regulator-max-microvolt = <3100000>;
+ qcom,init-voltage = <3100000>;
+ };
+
+ l23 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ qcom,init-voltage = <2800000>;
+ };
+
+ l24 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3150000>;
+ qcom,init-voltage = <3075000>;
+ };
+
+ l25 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ };
+
+ l26 {
+ /* TODO: value from downstream
+ regulator-min-microvolt = <987500>;
+ fails to apply */
+ };
+
+ l27 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ qcom,init-voltage = <1050000>;
+ };
+
+ l28 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ qcom,init-voltage = <1000000>;
+ proxy-supply = <&pm8994_l28>;
+ qcom,proxy-consumer-enable;
+ qcom,proxy-consumer-current = <10000>;
+ };
+
+ l29 {
+ /* TODO: Unsupported voltage range.
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ qcom,init-voltage = <2800000>;
+ */
+ };
+
+ l30 {
+ /* TODO: get this verified
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ */
+ };
+
+ l31 {
+ regulator-min-microvolt = <1262500>;
+ regulator-max-microvolt = <1262500>;
+ qcom,init-voltage = <1262500>;
+ };
+
+ l32 {
+ /* TODO: get this verified
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ */
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index f8e49d0..8c7f9ca 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -447,7 +447,7 @@
blsp2_i2c0: i2c@75b5000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x075b5000 0x1000>;
- interrupts = <GIC_SPI 101 0>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_BLSP2_AHB_CLK>,
<&gcc GCC_BLSP2_QUP1_I2C_APPS_CLK>;
clock-names = "iface", "core";
@@ -478,7 +478,7 @@
blsp2_i2c1: i2c@75b6000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x075b6000 0x1000>;
- interrupts = <GIC_SPI 102 0>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_BLSP2_AHB_CLK>,
<&gcc GCC_BLSP2_QUP2_I2C_APPS_CLK>;
clock-names = "iface", "core";
@@ -503,7 +503,7 @@
blsp1_i2c2: i2c@7577000 {
compatible = "qcom,i2c-qup-v2.2.1";
reg = <0x07577000 0x1000>;
- interrupts = <GIC_SPI 97 0>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_BLSP1_AHB_CLK>,
<&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>;
clock-names = "iface", "core";
@@ -536,7 +536,8 @@
reg = <0x74a4900 0x314>, <0x74a4000 0x800>;
reg-names = "hc_mem", "core_mem";
- interrupts = <0 125 0>, <0 221 0>;
+ interrupts = <0 125 IRQ_TYPE_LEVEL_HIGH>,
+ <0 221 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hc_irq", "pwr_irq";
clock-names = "iface", "core", "xo";
@@ -633,6 +634,91 @@
#interrupt-cells = <4>;
};
+ ufsphy: phy@627000 {
+ compatible = "qcom,msm8996-ufs-phy-qmp-14nm";
+ reg = <0x627000 0xda8>;
+ reg-names = "phy_mem";
+ #phy-cells = <0>;
+
+ vdda-phy-supply = <&pm8994_l28>;
+ vdda-pll-supply = <&pm8994_l12>;
+
+ vdda-phy-max-microamp = <18380>;
+ vdda-pll-max-microamp = <9440>;
+
+ vddp-ref-clk-supply = <&pm8994_l25>;
+ vddp-ref-clk-max-microamp = <100>;
+ vddp-ref-clk-always-on;
+
+ clock-names = "ref_clk_src", "ref_clk";
+ clocks = <&rpmcc RPM_SMD_LN_BB_CLK>,
+ <&gcc GCC_UFS_CLKREF_CLK>;
+ status = "disabled";
+ };
+
+ ufshc@624000 {
+ compatible = "qcom,ufshc";
+ reg = <0x624000 0x2500>;
+ interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
+
+ phys = <&ufsphy>;
+ phy-names = "ufsphy";
+
+ vcc-supply = <&pm8994_l20>;
+ vccq-supply = <&pm8994_l25>;
+ vccq2-supply = <&pm8994_s4>;
+
+ vcc-max-microamp = <600000>;
+ vccq-max-microamp = <450000>;
+ vccq2-max-microamp = <450000>;
+
+ power-domains = <&gcc UFS_GDSC>;
+
+ clock-names =
+ "core_clk_src",
+ "core_clk",
+ "bus_clk",
+ "bus_aggr_clk",
+ "iface_clk",
+ "core_clk_unipro_src",
+ "core_clk_unipro",
+ "core_clk_ice",
+ "ref_clk",
+ "tx_lane0_sync_clk",
+ "rx_lane0_sync_clk";
+ clocks =
+ <&gcc UFS_AXI_CLK_SRC>,
+ <&gcc GCC_UFS_AXI_CLK>,
+ <&gcc GCC_SYS_NOC_UFS_AXI_CLK>,
+ <&gcc GCC_AGGRE2_UFS_AXI_CLK>,
+ <&gcc GCC_UFS_AHB_CLK>,
+ <&gcc UFS_ICE_CORE_CLK_SRC>,
+ <&gcc GCC_UFS_UNIPRO_CORE_CLK>,
+ <&gcc GCC_UFS_ICE_CORE_CLK>,
+ <&rpmcc RPM_SMD_LN_BB_CLK>,
+ <&gcc GCC_UFS_TX_SYMBOL_0_CLK>,
+ <&gcc GCC_UFS_RX_SYMBOL_0_CLK>;
+ freq-table-hz =
+ <100000000 200000000>,
+ <0 0>,
+ <0 0>,
+ <0 0>,
+ <0 0>,
+ <150000000 300000000>,
+ <0 0>,
+ <0 0>,
+ <0 0>,
+ <0 0>,
+ <0 0>;
+
+ lanes-per-direction = <1>;
+ status = "disabled";
+
+ ufs_variant {
+ compatible = "qcom,ufs_variant";
+ };
+ };
+
mmcc: clock-controller@8c0000 {
compatible = "qcom,mmcc-msm8996";
#clock-cells = <1>;
@@ -819,7 +905,7 @@
dwc3@7600000 {
compatible = "snps,dwc3";
reg = <0x7600000 0xcc00>;
- interrupts = <0 138 0>;
+ interrupts = <0 138 IRQ_TYPE_LEVEL_HIGH>;
phys = <&hsusb_phy2>;
phy-names = "usb2-phy";
};
@@ -848,7 +934,7 @@
dwc3@6a00000 {
compatible = "snps,dwc3";
reg = <0x6a00000 0xcc00>;
- interrupts = <0 131 0>;
+ interrupts = <0 131 IRQ_TYPE_LEVEL_HIGH>;
phys = <&hsusb_phy1>, <&ssusb_phy_0>;
phy-names = "usb2-phy", "usb3-phy";
};
@@ -861,7 +947,7 @@
#size-cells = <1>;
ranges;
- pcie0: qcom,pcie@600000 {
+ pcie0: pcie@600000 {
compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
status = "disabled";
power-domains = <&gcc PCIE0_GDSC>;
@@ -882,7 +968,7 @@
ranges = <0x01000000 0x0 0x0c200000 0x0c200000 0x0 0x100000>,
<0x02000000 0x0 0x0c300000 0x0c300000 0x0 0xd00000>;
- interrupts = <GIC_SPI 405 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
@@ -914,7 +1000,7 @@
};
- pcie1: qcom,pcie@608000 {
+ pcie1: pcie@608000 {
compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
power-domains = <&gcc PCIE1_GDSC>;
bus-range = <0x00 0xff>;
@@ -937,7 +1023,7 @@
ranges = <0x01000000 0x0 0x0d200000 0x0d200000 0x0 0x100000>,
<0x02000000 0x0 0x0d300000 0x0d300000 0x0 0xd00000>;
- interrupts = <GIC_SPI 413 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 413 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
@@ -967,7 +1053,7 @@
"bus_slave";
};
- pcie2: qcom,pcie@610000 {
+ pcie2: pcie@610000 {
compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
power-domains = <&gcc PCIE2_GDSC>;
bus-range = <0x00 0xff>;
@@ -990,7 +1076,7 @@
device_type = "pci";
- interrupts = <GIC_SPI 421 IRQ_TYPE_NONE>;
+ interrupts = <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
new file mode 100644
index 0000000..979ab49
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SDM845 MTP board device tree source
+ *
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include "sdm845.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM845 MTP";
+ compatible = "qcom,sdm845-mtp";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
new file mode 100644
index 0000000..cdaabeb
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SDM845 SoC device tree source
+ *
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ interrupt-parent = <&intc>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ chosen { };
+
+ memory@80000000 {
+ device_type = "memory";
+ /* We expect the bootloader to fill in the size */
+ reg = <0 0x80000000 0 0>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ memory@85fc0000 {
+ reg = <0 0x85fc0000 0 0x20000>;
+ no-map;
+ };
+
+ memory@85fe0000 {
+ compatible = "qcom,cmd-db";
+ reg = <0x0 0x85fe0000 0x0 0x20000>;
+ no-map;
+ };
+
+ smem_mem: memory@86000000 {
+ reg = <0x0 0x86000000 0x0 0x200000>;
+ no-map;
+ };
+
+ memory@86200000 {
+ reg = <0 0x86200000 0 0x2d00000>;
+ no-map;
+ };
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "qcom,kryo385";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ L3_0: l3-cache {
+ compatible = "cache";
+ };
+ };
+ };
+
+ CPU1: cpu@100 {
+ device_type = "cpu";
+ compatible = "qcom,kryo385";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ next-level-cache = <&L2_100>;
+ L2_100: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU2: cpu@200 {
+ device_type = "cpu";
+ compatible = "qcom,kryo385";
+ reg = <0x0 0x200>;
+ enable-method = "psci";
+ next-level-cache = <&L2_200>;
+ L2_200: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU3: cpu@300 {
+ device_type = "cpu";
+ compatible = "qcom,kryo385";
+ reg = <0x0 0x300>;
+ enable-method = "psci";
+ next-level-cache = <&L2_300>;
+ L2_300: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU4: cpu@400 {
+ device_type = "cpu";
+ compatible = "qcom,kryo385";
+ reg = <0x0 0x400>;
+ enable-method = "psci";
+ next-level-cache = <&L2_400>;
+ L2_400: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU5: cpu@500 {
+ device_type = "cpu";
+ compatible = "qcom,kryo385";
+ reg = <0x0 0x500>;
+ enable-method = "psci";
+ next-level-cache = <&L2_500>;
+ L2_500: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU6: cpu@600 {
+ device_type = "cpu";
+ compatible = "qcom,kryo385";
+ reg = <0x0 0x600>;
+ enable-method = "psci";
+ next-level-cache = <&L2_600>;
+ L2_600: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU7: cpu@700 {
+ device_type = "cpu";
+ compatible = "qcom,kryo385";
+ reg = <0x0 0x700>;
+ enable-method = "psci";
+ next-level-cache = <&L2_700>;
+ L2_700: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 1 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 2 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 3 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 0 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ clocks {
+ xo_board: xo-board {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <38400000>;
+ clock-output-names = "xo_board";
+ };
+
+ sleep_clk: sleep-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32764>;
+ };
+ };
+
+ tcsr_mutex: hwlock {
+ compatible = "qcom,tcsr-mutex";
+ syscon = <&tcsr_mutex_regs 0 0x1000>;
+ #hwlock-cells = <1>;
+ };
+
+ smem {
+ compatible = "qcom,smem";
+ memory-region = <&smem_mem>;
+ hwlocks = <&tcsr_mutex 3>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ soc: soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+ compatible = "simple-bus";
+
+ gcc: clock-controller@100000 {
+ compatible = "qcom,gcc-sdm845";
+ reg = <0x100000 0x1f0000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ tcsr_mutex_regs: syscon@1f40000 {
+ compatible = "syscon";
+ reg = <0x1f40000 0x40000>;
+ };
+
+ tlmm: pinctrl@3400000 {
+ compatible = "qcom,sdm845-pinctrl";
+ reg = <0x03400000 0xc00000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ spmi_bus: spmi@c440000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0xc440000 0x1100>,
+ <0xc600000 0x2000000>,
+ <0xe600000 0x100000>,
+ <0xe700000 0xa0000>,
+ <0xc40a000 0x26000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 481 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ cell-index = <0>;
+ };
+
+ apss_shared: mailbox@17990000 {
+ compatible = "qcom,sdm845-apss-shared";
+ reg = <0x17990000 0x1000>;
+ #mbox-cells = <1>;
+ };
+
+ intc: interrupt-controller@17a00000 {
+ compatible = "arm,gic-v3";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0x17a00000 0x10000>, /* GICD */
+ <0x17a60000 0x100000>; /* GICR * 8 */
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+
+ gic-its@17a40000 {
+ compatible = "arm,gic-v3-its";
+ msi-controller;
+ #msi-cells = <1>;
+ reg = <0x17a40000 0x20000>;
+ status = "disabled";
+ };
+ };
+
+ timer@17c90000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ compatible = "arm,armv7-timer-mem";
+ reg = <0x17c90000 0x1000>;
+
+ frame@17ca0000 {
+ frame-number = <0>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x17ca0000 0x1000>,
+ <0x17cb0000 0x1000>;
+ };
+
+ frame@17cc0000 {
+ frame-number = <1>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x17cc0000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17cd0000 {
+ frame-number = <2>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x17cd0000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17ce0000 {
+ frame-number = <3>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x17ce0000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17cf0000 {
+ frame-number = <4>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x17cf0000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17d00000 {
+ frame-number = <5>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x17d00000 0x1000>;
+ status = "disabled";
+ };
+
+ frame@17d10000 {
+ frame-number = <6>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ reg = <0x17d10000 0x1000>;
+ status = "disabled";
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/renesas/Makefile b/arch/arm64/boot/dts/renesas/Makefile
index 5ede060..9e2394b 100644
--- a/arch/arm64/boot/dts/renesas/Makefile
+++ b/arch/arm64/boot/dts/renesas/Makefile
@@ -9,5 +9,6 @@ dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-m3ulcb-kf.dtb
dtb-$(CONFIG_ARCH_R8A7796) += r8a7796-salvator-xs.dtb
dtb-$(CONFIG_ARCH_R8A77965) += r8a77965-salvator-x.dtb r8a77965-salvator-xs.dtb
dtb-$(CONFIG_ARCH_R8A77970) += r8a77970-eagle.dtb r8a77970-v3msk.dtb
-dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-condor.dtb
+dtb-$(CONFIG_ARCH_R8A77980) += r8a77980-condor.dtb r8a77980-v3hsk.dtb
+dtb-$(CONFIG_ARCH_R8A77990) += r8a77990-ebisu.dtb
dtb-$(CONFIG_ARCH_R8A77995) += r8a77995-draak.dtb
diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts
index 7f2a3d9..3f46345 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7795-es1-salvator-x.dts
@@ -56,6 +56,12 @@
status = "okay";
};
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1 /* HDMI0 */
+ &rsnd_port2>; /* HDMI1 */
+};
+
&hdmi0 {
status = "okay";
@@ -66,6 +72,12 @@
remote-endpoint = <&hdmi0_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi0_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint1>;
+ };
+ };
};
};
@@ -83,6 +95,12 @@
remote-endpoint = <&hdmi1_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi1_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint2>;
+ };
+ };
};
};
@@ -94,6 +112,34 @@
status = "okay";
};
+&rcar_sound {
+ ports {
+ /* rsnd_port0 is on salvator-common */
+ rsnd_port1: port@1 {
+ rsnd_endpoint1: endpoint {
+ remote-endpoint = <&dw_hdmi0_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint1>;
+ frame-master = <&rsnd_endpoint1>;
+
+ playback = <&ssi2>;
+ };
+ };
+ rsnd_port2: port@2 {
+ rsnd_endpoint2: endpoint {
+ remote-endpoint = <&dw_hdmi1_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint2>;
+ frame-master = <&rsnd_endpoint2>;
+
+ playback = <&ssi3>;
+ };
+ };
+ };
+};
+
&pfc {
usb2_pins: usb2 {
groups = "usb2";
diff --git a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
index f9acd12..e19dcd6 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7795-es1.dtsi
@@ -39,7 +39,6 @@
reg = <0 0xe7730000 0 0x1000>;
renesas,ipmmu-main = <&ipmmu_mm 8>;
#iommu-cells = <1>;
- status = "disabled";
};
/delete-node/ usb-phy@ee0e0200;
@@ -108,6 +107,61 @@
resets = <&cpg 117>;
renesas,fcp = <&fcpf2>;
};
+
+ csi21: csi2@fea90000 {
+ compatible = "renesas,r8a7795-csi2";
+ reg = <0 0xfea90000 0 0x10000>;
+ interrupts = <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 713>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 713>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ csi21vin0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vin0csi21>;
+ };
+ csi21vin1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&vin1csi21>;
+ };
+ csi21vin2: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&vin2csi21>;
+ };
+ csi21vin3: endpoint@3 {
+ reg = <3>;
+ remote-endpoint = <&vin3csi21>;
+ };
+ csi21vin4: endpoint@4 {
+ reg = <4>;
+ remote-endpoint = <&vin4csi21>;
+ };
+ csi21vin5: endpoint@5 {
+ reg = <5>;
+ remote-endpoint = <&vin5csi21>;
+ };
+ csi21vin6: endpoint@6 {
+ reg = <6>;
+ remote-endpoint = <&vin6csi21>;
+ };
+ csi21vin7: endpoint@7 {
+ reg = <7>;
+ remote-endpoint = <&vin7csi21>;
+ };
+ };
+ };
+ };
};
&gpio1 {
@@ -175,3 +229,91 @@
&du {
vsps = <&vspd0 &vspd1 &vspd2 &vspd3>;
};
+
+&vin0 {
+ ports {
+ port@1 {
+ vin0csi21: endpoint@1 {
+ reg = <1>;
+ remote-endpoint= <&csi21vin0>;
+ };
+ };
+ };
+};
+
+&vin1 {
+ ports {
+ port@1 {
+ vin1csi21: endpoint@1 {
+ reg = <1>;
+ remote-endpoint= <&csi21vin1>;
+ };
+ };
+ };
+};
+
+&vin2 {
+ ports {
+ port@1 {
+ vin2csi21: endpoint@1 {
+ reg = <1>;
+ remote-endpoint= <&csi21vin2>;
+ };
+ };
+ };
+};
+
+&vin3 {
+ ports {
+ port@1 {
+ vin3csi21: endpoint@1 {
+ reg = <1>;
+ remote-endpoint= <&csi21vin3>;
+ };
+ };
+ };
+};
+
+&vin4 {
+ ports {
+ port@1 {
+ vin4csi21: endpoint@1 {
+ reg = <1>;
+ remote-endpoint= <&csi21vin4>;
+ };
+ };
+ };
+};
+
+&vin5 {
+ ports {
+ port@1 {
+ vin5csi21: endpoint@1 {
+ reg = <1>;
+ remote-endpoint= <&csi21vin5>;
+ };
+ };
+ };
+};
+
+&vin6 {
+ ports {
+ port@1 {
+ vin6csi21: endpoint@1 {
+ reg = <1>;
+ remote-endpoint= <&csi21vin6>;
+ };
+ };
+ };
+};
+
+&vin7 {
+ ports {
+ port@1 {
+ vin7csi21: endpoint@1 {
+ reg = <1>;
+ remote-endpoint= <&csi21vin7>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
index af46741..0efbef5 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
@@ -56,6 +56,12 @@
status = "okay";
};
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1 /* HDMI0 */
+ &rsnd_port2>; /* HDMI1 */
+};
+
&hdmi0 {
status = "okay";
@@ -66,6 +72,12 @@
remote-endpoint = <&hdmi0_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi0_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint1>;
+ };
+ };
};
};
@@ -83,6 +95,12 @@
remote-endpoint = <&hdmi1_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi1_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint2>;
+ };
+ };
};
};
@@ -94,6 +112,34 @@
status = "okay";
};
+&rcar_sound {
+ ports {
+ /* rsnd_port0 is on salvator-common */
+ rsnd_port1: port@1 {
+ rsnd_endpoint1: endpoint {
+ remote-endpoint = <&dw_hdmi0_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint1>;
+ frame-master = <&rsnd_endpoint1>;
+
+ playback = <&ssi2>;
+ };
+ };
+ rsnd_port2: port@2 {
+ rsnd_endpoint2: endpoint {
+ remote-endpoint = <&dw_hdmi1_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint2>;
+ frame-master = <&rsnd_endpoint2>;
+
+ playback = <&ssi3>;
+ };
+ };
+ };
+};
+
&pfc {
usb2_pins: usb2 {
groups = "usb2";
diff --git a/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts
index 8b50ceb..e231b5a 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7795-salvator-xs.dts
@@ -56,6 +56,22 @@
status = "okay";
};
+&ehci3 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&hsusb3 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1 /* HDMI0 */
+ &rsnd_port2>; /* HDMI1 */
+};
+
&hdmi0 {
status = "okay";
@@ -66,6 +82,12 @@
remote-endpoint = <&hdmi0_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi0_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint1>;
+ };
+ };
};
};
@@ -83,6 +105,12 @@
remote-endpoint = <&hdmi1_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi1_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint2>;
+ };
+ };
};
};
@@ -94,11 +122,61 @@
status = "okay";
};
+&ohci3 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&rcar_sound {
+ ports {
+ /* rsnd_port0 is on salvator-common */
+ rsnd_port1: port@1 {
+ rsnd_endpoint1: endpoint {
+ remote-endpoint = <&dw_hdmi0_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint1>;
+ frame-master = <&rsnd_endpoint1>;
+
+ playback = <&ssi2>;
+ };
+ };
+ rsnd_port2: port@2 {
+ rsnd_endpoint2: endpoint {
+ remote-endpoint = <&dw_hdmi1_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint2>;
+ frame-master = <&rsnd_endpoint2>;
+
+ playback = <&ssi3>;
+ };
+ };
+ };
+};
+
&pfc {
usb2_pins: usb2 {
groups = "usb2";
function = "usb2";
};
+
+ /*
+ * - On Salvator-X[S], GP6_3[01] are connected to ADV7482 as irq pins
+ * (when SW31 is the default setting on Salvator-XS).
+ * - If SW31 is the default setting, you cannot use USB2.0 ch3 on
+ * r8a7795 with Salvator-XS.
+ * Hence the SW31 setting must be changed like 2) below.
+ * 1) Default setting of SW31: ON-ON-OFF-OFF-OFF-OFF:
+ * - Connect GP6_3[01] to ADV7842.
+ * 2) Changed setting of SW31: OFF-OFF-ON-ON-ON-ON:
+ * - Connect GP6_3[01] to BD082065 (USB2.0 ch3's host power).
+ * - Connect GP6_{04,21} to ADV7842.
+ */
+ usb2_ch3_pins: usb2_ch3 {
+ groups = "usb2_ch3";
+ function = "usb2_ch3";
+ };
};
&usb2_phy2 {
@@ -107,3 +185,10 @@
status = "okay";
};
+
+&usb2_phy3 {
+ pinctrl-0 = <&usb2_ch3_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a7795.dtsi b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
index 1d5e3ac..d842940 100644
--- a/arch/arm64/boot/dts/renesas/r8a7795.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7795.dtsi
@@ -30,6 +30,91 @@
i2c7 = &i2c_dvfs;
};
+ /*
+ * The external audio clocks are configured as 0 Hz fixed frequency
+ * clocks by default.
+ * Boards that provide audio clocks should override them.
+ */
+ audio_clk_a: audio_clk_a {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ audio_clk_b: audio_clk_b {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ audio_clk_c: audio_clk_c {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ /* External CAN clock - to be overridden by boards that provide it */
+ can_clk: can {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ cluster0_opp: opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <830000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <830000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-1500000000 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <830000>;
+ clock-latency-ns = <300000>;
+ opp-suspend;
+ };
+ opp-1600000000 {
+ opp-hz = /bits/ 64 <1600000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <300000>;
+ turbo-mode;
+ };
+ opp-1700000000 {
+ opp-hz = /bits/ 64 <1700000000>;
+ opp-microvolt = <960000>;
+ clock-latency-ns = <300000>;
+ turbo-mode;
+ };
+ };
+
+ cluster1_opp: opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <820000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <820000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <820000>;
+ clock-latency-ns = <300000>;
+ };
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -47,7 +132,7 @@
};
a57_1: cpu@1 {
- compatible = "arm,cortex-a57","arm,armv8";
+ compatible = "arm,cortex-a57", "arm,armv8";
reg = <0x1>;
device_type = "cpu";
power-domains = <&sysc R8A7795_PD_CA57_CPU1>;
@@ -59,7 +144,7 @@
};
a57_2: cpu@2 {
- compatible = "arm,cortex-a57","arm,armv8";
+ compatible = "arm,cortex-a57", "arm,armv8";
reg = <0x2>;
device_type = "cpu";
power-domains = <&sysc R8A7795_PD_CA57_CPU2>;
@@ -71,7 +156,7 @@
};
a57_3: cpu@3 {
- compatible = "arm,cortex-a57","arm,armv8";
+ compatible = "arm,cortex-a57", "arm,armv8";
reg = <0x3>;
device_type = "cpu";
power-domains = <&sysc R8A7795_PD_CA57_CPU3>;
@@ -94,7 +179,7 @@
};
a53_1: cpu@101 {
- compatible = "arm,cortex-a53","arm,armv8";
+ compatible = "arm,cortex-a53", "arm,armv8";
reg = <0x101>;
device_type = "cpu";
power-domains = <&sysc R8A7795_PD_CA53_CPU1>;
@@ -105,7 +190,7 @@
};
a53_2: cpu@102 {
- compatible = "arm,cortex-a53","arm,armv8";
+ compatible = "arm,cortex-a53", "arm,armv8";
reg = <0x102>;
device_type = "cpu";
power-domains = <&sysc R8A7795_PD_CA53_CPU2>;
@@ -116,7 +201,7 @@
};
a53_3: cpu@103 {
- compatible = "arm,cortex-a53","arm,armv8";
+ compatible = "arm,cortex-a53", "arm,armv8";
reg = <0x103>;
device_type = "cpu";
power-domains = <&sysc R8A7795_PD_CA53_CPU3>;
@@ -155,91 +240,6 @@
clock-frequency = <0>;
};
- /*
- * The external audio clocks are configured as 0 Hz fixed frequency
- * clocks by default.
- * Boards that provide audio clocks should override them.
- */
- audio_clk_a: audio_clk_a {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- audio_clk_b: audio_clk_b {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- audio_clk_c: audio_clk_c {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- /* External CAN clock - to be overridden by boards that provide it */
- can_clk: can {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- cluster0_opp: opp_table0 {
- compatible = "operating-points-v2";
- opp-shared;
-
- opp-500000000 {
- opp-hz = /bits/ 64 <500000000>;
- opp-microvolt = <830000>;
- clock-latency-ns = <300000>;
- };
- opp-1000000000 {
- opp-hz = /bits/ 64 <1000000000>;
- opp-microvolt = <830000>;
- clock-latency-ns = <300000>;
- };
- opp-1500000000 {
- opp-hz = /bits/ 64 <1500000000>;
- opp-microvolt = <830000>;
- clock-latency-ns = <300000>;
- opp-suspend;
- };
- opp-1600000000 {
- opp-hz = /bits/ 64 <1600000000>;
- opp-microvolt = <900000>;
- clock-latency-ns = <300000>;
- turbo-mode;
- };
- opp-1700000000 {
- opp-hz = /bits/ 64 <1700000000>;
- opp-microvolt = <960000>;
- clock-latency-ns = <300000>;
- turbo-mode;
- };
- };
-
- cluster1_opp: opp_table1 {
- compatible = "operating-points-v2";
- opp-shared;
-
- opp-800000000 {
- opp-hz = /bits/ 64 <800000000>;
- opp-microvolt = <820000>;
- clock-latency-ns = <300000>;
- };
- opp-1000000000 {
- opp-hz = /bits/ 64 <1000000000>;
- opp-microvolt = <820000>;
- clock-latency-ns = <300000>;
- };
- opp-1200000000 {
- opp-hz = /bits/ 64 <1200000000>;
- opp-microvolt = <820000>;
- clock-latency-ns = <300000>;
- };
- };
-
/* External PCIe clock - can be overridden by the board */
pcie_bus_clk: pcie_bus {
compatible = "fixed-clock";
@@ -247,18 +247,6 @@
clock-frequency = <0>;
};
- pmu_a57 {
- compatible = "arm,cortex-a57-pmu";
- interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
- <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
- <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
- <&gic GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-affinity = <&a57_0>,
- <&a57_1>,
- <&a57_2>,
- <&a57_3>;
- };
-
pmu_a53 {
compatible = "arm,cortex-a53-pmu";
interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
@@ -271,6 +259,18 @@
<&a53_3>;
};
+ pmu_a57 {
+ compatible = "arm,cortex-a57-pmu";
+ interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&a57_0>,
+ <&a57_1>,
+ <&a57_2>,
+ <&a57_3>;
+ };
+
psci {
compatible = "arm,psci-1.0", "arm,psci-0.2";
method = "smc";
@@ -291,23 +291,6 @@
#size-cells = <2>;
ranges;
- gic: interrupt-controller@f1010000 {
- compatible = "arm,gic-400";
- #interrupt-cells = <3>;
- #address-cells = <0>;
- interrupt-controller;
- reg = <0x0 0xf1010000 0 0x1000>,
- <0x0 0xf1020000 0 0x20000>,
- <0x0 0xf1040000 0 0x20000>,
- <0x0 0xf1060000 0 0x20000>;
- interrupts = <GIC_PPI 9
- (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 {
compatible = "renesas,r8a7795-wdt", "renesas,rcar-gen3-wdt";
reg = <0 0xe6020000 0 0x0c>;
@@ -437,6 +420,11 @@
resets = <&cpg 905>;
};
+ pfc: pin-controller@e6060000 {
+ compatible = "renesas,pfc-r8a7795";
+ reg = <0 0xe6060000 0 0x50c>;
+ };
+
cpg: clock-controller@e6150000 {
compatible = "renesas,r8a7795-cpg-mssr";
reg = <0 0xe6150000 0 0x1000>;
@@ -452,20 +440,25 @@
reg = <0 0xe6160000 0 0x0200>;
};
- prr: chipid@fff00044 {
- compatible = "renesas,prr";
- reg = <0 0xfff00044 0 4>;
- };
-
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7795-sysc";
reg = <0 0xe6180000 0 0x0400>;
#power-domain-cells = <1>;
};
- pfc: pin-controller@e6060000 {
- compatible = "renesas,pfc-r8a7795";
- reg = <0 0xe6060000 0 0x50c>;
+ tsc: thermal@e6198000 {
+ compatible = "renesas,r8a7795-thermal";
+ reg = <0 0xe6198000 0 0x100>,
+ <0 0xe61a0000 0 0x100>,
+ <0 0xe61a8000 0 0x100>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <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";
};
intc_ex: interrupt-controller@e61c0000 {
@@ -484,153 +477,326 @@
resets = <&cpg 407>;
};
- ipmmu_vi0: mmu@febd0000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xfebd0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 14>;
+ i2c0: i2c@e6500000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a7795",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe6500000 0 0x40>;
+ interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 931>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 931>;
+ dmas = <&dmac1 0x91>, <&dmac1 0x90>,
+ <&dmac2 0x91>, <&dmac2 0x90>;
+ dma-names = "tx", "rx", "tx", "rx";
+ i2c-scl-internal-delay-ns = <110>;
+ status = "disabled";
};
- ipmmu_vi1: mmu@febe0000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xfebe0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 15>;
+ i2c1: i2c@e6508000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a7795",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe6508000 0 0x40>;
+ interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 930>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 930>;
+ dmas = <&dmac1 0x93>, <&dmac1 0x92>,
+ <&dmac2 0x93>, <&dmac2 0x92>;
+ dma-names = "tx", "rx", "tx", "rx";
+ i2c-scl-internal-delay-ns = <6>;
status = "disabled";
};
- ipmmu_vp0: mmu@fe990000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xfe990000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 16>;
- power-domains = <&sysc R8A7795_PD_A3VP>;
- #iommu-cells = <1>;
+ i2c2: i2c@e6510000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a7795",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe6510000 0 0x40>;
+ 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>,
+ <&dmac2 0x95>, <&dmac2 0x94>;
+ dma-names = "tx", "rx", "tx", "rx";
+ i2c-scl-internal-delay-ns = <6>;
status = "disabled";
};
- ipmmu_vp1: mmu@fe980000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xfe980000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 17>;
- power-domains = <&sysc R8A7795_PD_A3VP>;
- #iommu-cells = <1>;
+ i2c3: i2c@e66d0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a7795",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe66d0000 0 0x40>;
+ 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>;
+ status = "disabled";
};
- ipmmu_vc0: mmu@fe6b0000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xfe6b0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 12>;
- power-domains = <&sysc R8A7795_PD_A3VC>;
- #iommu-cells = <1>;
+ i2c4: i2c@e66d8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a7795",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe66d8000 0 0x40>;
+ 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>;
status = "disabled";
};
- ipmmu_vc1: mmu@fe6f0000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xfe6f0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 13>;
- power-domains = <&sysc R8A7795_PD_A3VC>;
- #iommu-cells = <1>;
+ i2c5: i2c@e66e0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a7795",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe66e0000 0 0x40>;
+ 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>;
status = "disabled";
};
- ipmmu_pv0: mmu@fd800000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xfd800000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 6>;
+ i2c6: i2c@e66e8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a7795",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe66e8000 0 0x40>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 918>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 918>;
+ dmas = <&dmac0 0x9d>, <&dmac0 0x9c>;
+ dma-names = "tx", "rx";
+ i2c-scl-internal-delay-ns = <6>;
status = "disabled";
};
- ipmmu_pv1: mmu@fd950000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xfd950000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 7>;
+ 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>;
- #iommu-cells = <1>;
+ resets = <&cpg 926>;
+ dmas = <&dmac0 0x11>, <&dmac0 0x10>;
+ dma-names = "tx", "rx";
status = "disabled";
};
- ipmmu_pv2: mmu@fd960000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xfd960000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 8>;
+ hscif0: serial@e6540000 {
+ compatible = "renesas,hscif-r8a7795",
+ "renesas,rcar-gen3-hscif",
+ "renesas,hscif";
+ reg = <0 0xe6540000 0 96>;
+ interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 520>,
+ <&cpg CPG_CORE R8A7795_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 R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 520>;
status = "disabled";
};
- ipmmu_pv3: mmu@fd970000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xfd970000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 9>;
+ hscif1: serial@e6550000 {
+ compatible = "renesas,hscif-r8a7795",
+ "renesas,rcar-gen3-hscif",
+ "renesas,hscif";
+ reg = <0 0xe6550000 0 96>;
+ interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 519>,
+ <&cpg CPG_CORE R8A7795_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 R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 519>;
status = "disabled";
};
- ipmmu_ir: mmu@ff8b0000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xff8b0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 3>;
- power-domains = <&sysc R8A7795_PD_A3IR>;
- #iommu-cells = <1>;
+ hscif2: serial@e6560000 {
+ compatible = "renesas,hscif-r8a7795",
+ "renesas,rcar-gen3-hscif",
+ "renesas,hscif";
+ reg = <0 0xe6560000 0 96>;
+ interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 518>,
+ <&cpg CPG_CORE R8A7795_CLK_S3D1>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac1 0x35>, <&dmac1 0x34>,
+ <&dmac2 0x35>, <&dmac2 0x34>;
+ dma-names = "tx", "rx";
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 518>;
status = "disabled";
};
- ipmmu_hc: mmu@e6570000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xe6570000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 2>;
+ hscif3: serial@e66a0000 {
+ compatible = "renesas,hscif-r8a7795",
+ "renesas,rcar-gen3-hscif",
+ "renesas,hscif";
+ reg = <0 0xe66a0000 0 96>;
+ interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 517>,
+ <&cpg CPG_CORE R8A7795_CLK_S3D1>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x37>, <&dmac0 0x36>;
+ dma-names = "tx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 517>;
status = "disabled";
};
- ipmmu_rt: mmu@ffc80000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xffc80000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 10>;
+ hscif4: serial@e66b0000 {
+ compatible = "renesas,hscif-r8a7795",
+ "renesas,rcar-gen3-hscif",
+ "renesas,hscif";
+ reg = <0 0xe66b0000 0 96>;
+ interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 516>,
+ <&cpg CPG_CORE R8A7795_CLK_S3D1>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x39>, <&dmac0 0x38>;
+ dma-names = "tx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 516>;
status = "disabled";
};
- ipmmu_mp0: mmu@ec670000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xec670000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 4>;
+ hsusb: usb@e6590000 {
+ compatible = "renesas,usbhs-r8a7795",
+ "renesas,rcar-gen3-usbhs";
+ reg = <0 0xe6590000 0 0x100>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 704>;
+ dmas = <&usb_dmac0 0>, <&usb_dmac0 1>,
+ <&usb_dmac1 0>, <&usb_dmac1 1>;
+ dma-names = "ch0", "ch1", "ch2", "ch3";
+ renesas,buswait = <11>;
+ phys = <&usb2_phy0>;
+ phy-names = "usb";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 704>;
status = "disabled";
};
- ipmmu_ds0: mmu@e6740000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xe6740000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 0>;
+ hsusb3: usb@e659c000 {
+ compatible = "renesas,usbhs-r8a7795",
+ "renesas,rcar-gen3-usbhs";
+ reg = <0 0xe659c000 0 0x100>;
+ interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 705>;
+ dmas = <&usb_dmac2 0>, <&usb_dmac2 1>,
+ <&usb_dmac3 0>, <&usb_dmac3 1>;
+ dma-names = "ch0", "ch1", "ch2", "ch3";
+ renesas,buswait = <11>;
+ phys = <&usb2_phy3>;
+ phy-names = "usb";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 705>;
+ status = "disabled";
};
- ipmmu_ds1: mmu@e7740000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xe7740000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 1>;
+ usb_dmac0: dma-controller@e65a0000 {
+ compatible = "renesas,r8a7795-usb-dmac",
+ "renesas,usb-dmac";
+ reg = <0 0xe65a0000 0 0x100>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1";
+ clocks = <&cpg CPG_MOD 330>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 330>;
+ #dma-cells = <1>;
+ dma-channels = <2>;
};
- ipmmu_mm: mmu@e67b0000 {
- compatible = "renesas,ipmmu-r8a7795";
- reg = <0 0xe67b0000 0 0x1000>;
- interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ usb_dmac1: dma-controller@e65b0000 {
+ compatible = "renesas,r8a7795-usb-dmac",
+ "renesas,usb-dmac";
+ reg = <0 0xe65b0000 0 0x100>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1";
+ clocks = <&cpg CPG_MOD 331>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
+ resets = <&cpg 331>;
+ #dma-cells = <1>;
+ dma-channels = <2>;
+ };
+
+ usb_dmac2: dma-controller@e6460000 {
+ compatible = "renesas,r8a7795-usb-dmac",
+ "renesas,usb-dmac";
+ reg = <0 0xe6460000 0 0x100>;
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1";
+ clocks = <&cpg CPG_MOD 326>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 326>;
+ #dma-cells = <1>;
+ dma-channels = <2>;
+ };
+
+ usb_dmac3: dma-controller@e6470000 {
+ compatible = "renesas,r8a7795-usb-dmac",
+ "renesas,usb-dmac";
+ reg = <0 0xe6470000 0 0x100>;
+ interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1";
+ clocks = <&cpg CPG_MOD 329>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 329>;
+ #dma-cells = <1>;
+ dma-channels = <2>;
+ };
+
+ usb3_phy0: usb-phy@e65ee000 {
+ compatible = "renesas,r8a7795-usb3-phy",
+ "renesas,rcar-gen3-usb3-phy";
+ reg = <0 0xe65ee000 0 0x90>;
+ clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>,
+ <&usb_extal_clk>;
+ clock-names = "usb3-if", "usb3s_clk", "usb_extal";
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 328>;
+ #phy-cells = <0>;
+ status = "disabled";
};
dmac0: dma-controller@e6700000 {
@@ -759,88 +925,141 @@
<&ipmmu_ds1 30>, <&ipmmu_ds1 31>;
};
- audma0: dma-controller@ec700000 {
- compatible = "renesas,dmac-r8a7795",
- "renesas,rcar-dmac";
- reg = <0 0xec700000 0 0x10000>;
- interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14", "ch15";
- clocks = <&cpg CPG_MOD 502>;
- clock-names = "fck";
+ ipmmu_ds0: mmu@e6740000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xe6740000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 0>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 502>;
- #dma-cells = <1>;
- dma-channels = <16>;
- iommus = <&ipmmu_mp0 0>, <&ipmmu_mp0 1>,
- <&ipmmu_mp0 2>, <&ipmmu_mp0 3>,
- <&ipmmu_mp0 4>, <&ipmmu_mp0 5>,
- <&ipmmu_mp0 6>, <&ipmmu_mp0 7>,
- <&ipmmu_mp0 8>, <&ipmmu_mp0 9>,
- <&ipmmu_mp0 10>, <&ipmmu_mp0 11>,
- <&ipmmu_mp0 12>, <&ipmmu_mp0 13>,
- <&ipmmu_mp0 14>, <&ipmmu_mp0 15>;
+ #iommu-cells = <1>;
};
- audma1: dma-controller@ec720000 {
- compatible = "renesas,dmac-r8a7795",
- "renesas,rcar-dmac";
- reg = <0 0xec720000 0 0x10000>;
- interrupts = <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14", "ch15";
- clocks = <&cpg CPG_MOD 501>;
- clock-names = "fck";
+ ipmmu_ds1: mmu@e7740000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xe7740000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 1>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 501>;
- #dma-cells = <1>;
- dma-channels = <16>;
- iommus = <&ipmmu_mp0 16>, <&ipmmu_mp0 17>,
- <&ipmmu_mp0 18>, <&ipmmu_mp0 19>,
- <&ipmmu_mp0 20>, <&ipmmu_mp0 21>,
- <&ipmmu_mp0 22>, <&ipmmu_mp0 23>,
- <&ipmmu_mp0 24>, <&ipmmu_mp0 25>,
- <&ipmmu_mp0 26>, <&ipmmu_mp0 27>,
- <&ipmmu_mp0 28>, <&ipmmu_mp0 29>,
- <&ipmmu_mp0 30>, <&ipmmu_mp0 31>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_hc: mmu@e6570000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xe6570000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 2>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_ir: mmu@ff8b0000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xff8b0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 3>;
+ power-domains = <&sysc R8A7795_PD_A3IR>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_mm: mmu@e67b0000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xe67b0000 0 0x1000>;
+ interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_mp0: mmu@ec670000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xec670000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 4>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_pv0: mmu@fd800000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xfd800000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 6>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_pv1: mmu@fd950000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xfd950000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 7>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_pv2: mmu@fd960000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xfd960000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 8>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_pv3: mmu@fd970000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xfd970000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 9>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_rt: mmu@ffc80000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xffc80000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 10>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vc0: mmu@fe6b0000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xfe6b0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 12>;
+ power-domains = <&sysc R8A7795_PD_A3VC>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vc1: mmu@fe6f0000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xfe6f0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 13>;
+ power-domains = <&sysc R8A7795_PD_A3VC>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vi0: mmu@febd0000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xfebd0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 14>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vi1: mmu@febe0000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xfebe0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 15>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vp0: mmu@fe990000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xfe990000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 16>;
+ power-domains = <&sysc R8A7795_PD_A3VP>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vp1: mmu@fe980000 {
+ compatible = "renesas,ipmmu-r8a7795";
+ reg = <0 0xfe980000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 17>;
+ power-domains = <&sysc R8A7795_PD_A3VP>;
+ #iommu-cells = <1>;
};
avb: ethernet@e6800000 {
@@ -946,211 +1165,173 @@
};
};
- drif00: rif@e6f40000 {
- compatible = "renesas,r8a7795-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f40000 0 0x64>;
- interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 515>;
- clock-names = "fck";
- dmas = <&dmac1 0x20>, <&dmac2 0x20>;
- dma-names = "rx", "rx";
+ pwm0: pwm@e6e30000 {
+ compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
+ reg = <0 0xe6e30000 0 0x8>;
+ clocks = <&cpg CPG_MOD 523>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 515>;
- renesas,bonding = <&drif01>;
+ resets = <&cpg 523>;
+ #pwm-cells = <2>;
status = "disabled";
};
- drif01: rif@e6f50000 {
- compatible = "renesas,r8a7795-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f50000 0 0x64>;
- interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 514>;
- clock-names = "fck";
- dmas = <&dmac1 0x22>, <&dmac2 0x22>;
- dma-names = "rx", "rx";
+ pwm1: pwm@e6e31000 {
+ compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
+ reg = <0 0xe6e31000 0 0x8>;
+ clocks = <&cpg CPG_MOD 523>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 514>;
- renesas,bonding = <&drif00>;
+ resets = <&cpg 523>;
+ #pwm-cells = <2>;
status = "disabled";
};
- drif10: rif@e6f60000 {
- compatible = "renesas,r8a7795-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f60000 0 0x64>;
- interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 513>;
- clock-names = "fck";
- dmas = <&dmac1 0x24>, <&dmac2 0x24>;
- dma-names = "rx", "rx";
+ pwm2: pwm@e6e32000 {
+ compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
+ reg = <0 0xe6e32000 0 0x8>;
+ clocks = <&cpg CPG_MOD 523>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 513>;
- renesas,bonding = <&drif11>;
+ resets = <&cpg 523>;
+ #pwm-cells = <2>;
status = "disabled";
};
- drif11: rif@e6f70000 {
- compatible = "renesas,r8a7795-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f70000 0 0x64>;
- interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 512>;
- clock-names = "fck";
- dmas = <&dmac1 0x26>, <&dmac2 0x26>;
- dma-names = "rx", "rx";
+ pwm3: pwm@e6e33000 {
+ compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
+ reg = <0 0xe6e33000 0 0x8>;
+ clocks = <&cpg CPG_MOD 523>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 512>;
- renesas,bonding = <&drif10>;
+ resets = <&cpg 523>;
+ #pwm-cells = <2>;
status = "disabled";
};
- drif20: rif@e6f80000 {
- compatible = "renesas,r8a7795-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f80000 0 0x64>;
- interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 511>;
- clock-names = "fck";
- dmas = <&dmac1 0x28>, <&dmac2 0x28>;
- dma-names = "rx", "rx";
+ pwm4: pwm@e6e34000 {
+ compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
+ reg = <0 0xe6e34000 0 0x8>;
+ clocks = <&cpg CPG_MOD 523>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 511>;
- renesas,bonding = <&drif21>;
+ resets = <&cpg 523>;
+ #pwm-cells = <2>;
status = "disabled";
};
- drif21: rif@e6f90000 {
- compatible = "renesas,r8a7795-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f90000 0 0x64>;
- interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 510>;
- clock-names = "fck";
- dmas = <&dmac1 0x2a>, <&dmac2 0x2a>;
- dma-names = "rx", "rx";
+ pwm5: pwm@e6e35000 {
+ compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
+ reg = <0 0xe6e35000 0 0x8>;
+ clocks = <&cpg CPG_MOD 523>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 510>;
- renesas,bonding = <&drif20>;
+ resets = <&cpg 523>;
+ #pwm-cells = <2>;
status = "disabled";
};
- drif30: rif@e6fa0000 {
- compatible = "renesas,r8a7795-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6fa0000 0 0x64>;
- interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 509>;
- clock-names = "fck";
- dmas = <&dmac1 0x2c>, <&dmac2 0x2c>;
- dma-names = "rx", "rx";
+ pwm6: pwm@e6e36000 {
+ compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
+ reg = <0 0xe6e36000 0 0x8>;
+ clocks = <&cpg CPG_MOD 523>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 509>;
- renesas,bonding = <&drif31>;
+ resets = <&cpg 523>;
+ #pwm-cells = <2>;
status = "disabled";
};
- drif31: rif@e6fb0000 {
- compatible = "renesas,r8a7795-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6fb0000 0 0x64>;
- interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 508>;
- clock-names = "fck";
- dmas = <&dmac1 0x2e>, <&dmac2 0x2e>;
- dma-names = "rx", "rx";
+ scif0: serial@e6e60000 {
+ compatible = "renesas,scif-r8a7795",
+ "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 R8A7795_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 R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 508>;
- renesas,bonding = <&drif30>;
+ resets = <&cpg 207>;
status = "disabled";
};
- hscif0: serial@e6540000 {
- compatible = "renesas,hscif-r8a7795",
- "renesas,rcar-gen3-hscif",
- "renesas,hscif";
- reg = <0 0xe6540000 0 96>;
- interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 520>,
+ scif1: serial@e6e68000 {
+ compatible = "renesas,scif-r8a7795",
+ "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 R8A7795_CLK_S3D1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
- dmas = <&dmac1 0x31>, <&dmac1 0x30>,
- <&dmac2 0x31>, <&dmac2 0x30>;
+ dmas = <&dmac1 0x53>, <&dmac1 0x52>,
+ <&dmac2 0x53>, <&dmac2 0x52>;
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 520>;
+ resets = <&cpg 206>;
status = "disabled";
};
- hscif1: serial@e6550000 {
- compatible = "renesas,hscif-r8a7795",
- "renesas,rcar-gen3-hscif",
- "renesas,hscif";
- reg = <0 0xe6550000 0 96>;
- interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 519>,
+ scif2: serial@e6e88000 {
+ compatible = "renesas,scif-r8a7795",
+ "renesas,rcar-gen3-scif", "renesas,scif";
+ reg = <0 0xe6e88000 0 64>;
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 310>,
<&cpg CPG_CORE R8A7795_CLK_S3D1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
- dmas = <&dmac1 0x33>, <&dmac1 0x32>,
- <&dmac2 0x33>, <&dmac2 0x32>;
+ dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+ <&dmac2 0x13>, <&dmac2 0x12>;
dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 519>;
+ resets = <&cpg 310>;
status = "disabled";
};
- hscif2: serial@e6560000 {
- compatible = "renesas,hscif-r8a7795",
- "renesas,rcar-gen3-hscif",
- "renesas,hscif";
- reg = <0 0xe6560000 0 96>;
- interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 518>,
+ scif3: serial@e6c50000 {
+ compatible = "renesas,scif-r8a7795",
+ "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 R8A7795_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";
+ dmas = <&dmac0 0x57>, <&dmac0 0x56>;
+ dma-names = "tx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 518>;
+ resets = <&cpg 204>;
status = "disabled";
};
- hscif3: serial@e66a0000 {
- compatible = "renesas,hscif-r8a7795",
- "renesas,rcar-gen3-hscif",
- "renesas,hscif";
- reg = <0 0xe66a0000 0 96>;
- interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 517>,
+ scif4: serial@e6c40000 {
+ compatible = "renesas,scif-r8a7795",
+ "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 R8A7795_CLK_S3D1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
- dmas = <&dmac0 0x37>, <&dmac0 0x36>;
+ dmas = <&dmac0 0x59>, <&dmac0 0x58>;
dma-names = "tx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 517>;
+ resets = <&cpg 203>;
status = "disabled";
};
- hscif4: serial@e66b0000 {
- compatible = "renesas,hscif-r8a7795",
- "renesas,rcar-gen3-hscif",
- "renesas,hscif";
- reg = <0 0xe66b0000 0 96>;
- interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 516>,
+ scif5: serial@e6f30000 {
+ compatible = "renesas,scif-r8a7795",
+ "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 R8A7795_CLK_S3D1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
- dmas = <&dmac0 0x39>, <&dmac0 0x38>;
- dma-names = "tx", "rx";
+ dmas = <&dmac1 0x5b>, <&dmac1 0x5a>,
+ <&dmac2 0x5b>, <&dmac2 0x5a>;
+ dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 516>;
+ resets = <&cpg 202>;
status = "disabled";
};
@@ -1216,304 +1397,379 @@
status = "disabled";
};
- scif0: serial@e6e60000 {
- compatible = "renesas,scif-r8a7795",
- "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 R8A7795_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";
+ vin0: video@e6ef0000 {
+ compatible = "renesas,vin-r8a7795";
+ reg = <0 0xe6ef0000 0 0x1000>;
+ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 811>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 207>;
+ resets = <&cpg 811>;
+ renesas,id = <0>;
status = "disabled";
- };
- scif1: serial@e6e68000 {
- compatible = "renesas,scif-r8a7795",
- "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 R8A7795_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 R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 206>;
- status = "disabled";
- };
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
- scif2: serial@e6e88000 {
- compatible = "renesas,scif-r8a7795",
- "renesas,rcar-gen3-scif", "renesas,scif";
- reg = <0 0xe6e88000 0 64>;
- interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 310>,
- <&cpg CPG_CORE R8A7795_CLK_S3D1>,
- <&scif_clk>;
- clock-names = "fck", "brg_int", "scif_clk";
- dmas = <&dmac1 0x13>, <&dmac1 0x12>,
- <&dmac2 0x13>, <&dmac2 0x12>;
- dma-names = "tx", "rx", "tx", "rx";
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 310>;
- status = "disabled";
- };
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
- scif3: serial@e6c50000 {
- compatible = "renesas,scif-r8a7795",
- "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 R8A7795_CLK_S3D1>,
- <&scif_clk>;
- clock-names = "fck", "brg_int", "scif_clk";
- dmas = <&dmac0 0x57>, <&dmac0 0x56>;
- dma-names = "tx", "rx";
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 204>;
- status = "disabled";
- };
+ reg = <1>;
- scif4: serial@e6c40000 {
- compatible = "renesas,scif-r8a7795",
- "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 R8A7795_CLK_S3D1>,
- <&scif_clk>;
- clock-names = "fck", "brg_int", "scif_clk";
- dmas = <&dmac0 0x59>, <&dmac0 0x58>;
- dma-names = "tx", "rx";
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 203>;
- status = "disabled";
+ vin0csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin0>;
+ };
+ vin0csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin0>;
+ };
+ };
+ };
};
- scif5: serial@e6f30000 {
- compatible = "renesas,scif-r8a7795",
- "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 R8A7795_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";
+ vin1: video@e6ef1000 {
+ compatible = "renesas,vin-r8a7795";
+ reg = <0 0xe6ef1000 0 0x1000>;
+ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 810>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 202>;
+ resets = <&cpg 810>;
+ renesas,id = <1>;
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>;
- dmas = <&dmac0 0x11>, <&dmac0 0x10>;
- dma-names = "tx", "rx";
- status = "disabled";
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin1csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin1>;
+ };
+ vin1csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin1>;
+ };
+ };
+ };
};
- i2c0: i2c@e6500000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a7795",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe6500000 0 0x40>;
- interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 931>;
+ vin2: video@e6ef2000 {
+ compatible = "renesas,vin-r8a7795";
+ reg = <0 0xe6ef2000 0 0x1000>;
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 809>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 931>;
- dmas = <&dmac1 0x91>, <&dmac1 0x90>,
- <&dmac2 0x91>, <&dmac2 0x90>;
- dma-names = "tx", "rx", "tx", "rx";
- i2c-scl-internal-delay-ns = <110>;
+ resets = <&cpg 809>;
+ renesas,id = <2>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin2csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin2>;
+ };
+ vin2csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin2>;
+ };
+ };
+ };
};
- i2c1: i2c@e6508000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a7795",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe6508000 0 0x40>;
- interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 930>;
+ vin3: video@e6ef3000 {
+ compatible = "renesas,vin-r8a7795";
+ reg = <0 0xe6ef3000 0 0x1000>;
+ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 808>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 930>;
- dmas = <&dmac1 0x93>, <&dmac1 0x92>,
- <&dmac2 0x93>, <&dmac2 0x92>;
- dma-names = "tx", "rx", "tx", "rx";
- i2c-scl-internal-delay-ns = <6>;
+ resets = <&cpg 808>;
+ renesas,id = <3>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin3csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin3>;
+ };
+ vin3csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin3>;
+ };
+ };
+ };
};
- i2c2: i2c@e6510000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a7795",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe6510000 0 0x40>;
- interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 929>;
+ vin4: video@e6ef4000 {
+ compatible = "renesas,vin-r8a7795";
+ reg = <0 0xe6ef4000 0 0x1000>;
+ interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 807>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 929>;
- dmas = <&dmac1 0x95>, <&dmac1 0x94>,
- <&dmac2 0x95>, <&dmac2 0x94>;
- dma-names = "tx", "rx", "tx", "rx";
- i2c-scl-internal-delay-ns = <6>;
+ resets = <&cpg 807>;
+ renesas,id = <4>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin4csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin4>;
+ };
+ vin4csi41: endpoint@3 {
+ reg = <3>;
+ remote-endpoint= <&csi41vin4>;
+ };
+ };
+ };
};
- i2c3: i2c@e66d0000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a7795",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe66d0000 0 0x40>;
- interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 928>;
+ vin5: video@e6ef5000 {
+ compatible = "renesas,vin-r8a7795";
+ reg = <0 0xe6ef5000 0 0x1000>;
+ interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 806>;
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>;
+ resets = <&cpg 806>;
+ renesas,id = <5>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin5csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin5>;
+ };
+ vin5csi41: endpoint@3 {
+ reg = <3>;
+ remote-endpoint= <&csi41vin5>;
+ };
+ };
+ };
};
- i2c4: i2c@e66d8000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a7795",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe66d8000 0 0x40>;
- interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 927>;
+ vin6: video@e6ef6000 {
+ compatible = "renesas,vin-r8a7795";
+ reg = <0 0xe6ef6000 0 0x1000>;
+ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 805>;
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>;
+ resets = <&cpg 805>;
+ renesas,id = <6>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin6csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin6>;
+ };
+ vin6csi41: endpoint@3 {
+ reg = <3>;
+ remote-endpoint= <&csi41vin6>;
+ };
+ };
+ };
};
- i2c5: i2c@e66e0000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a7795",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe66e0000 0 0x40>;
- interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 919>;
+ vin7: video@e6ef7000 {
+ compatible = "renesas,vin-r8a7795";
+ reg = <0 0xe6ef7000 0 0x1000>;
+ interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 804>;
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>;
+ resets = <&cpg 804>;
+ renesas,id = <7>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin7csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin7>;
+ };
+ vin7csi41: endpoint@3 {
+ reg = <3>;
+ remote-endpoint= <&csi41vin7>;
+ };
+ };
+ };
};
- i2c6: i2c@e66e8000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a7795",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe66e8000 0 0x40>;
- interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 918>;
+ drif00: rif@e6f40000 {
+ compatible = "renesas,r8a7795-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f40000 0 0x64>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 515>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x20>, <&dmac2 0x20>;
+ dma-names = "rx", "rx";
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>;
+ resets = <&cpg 515>;
+ renesas,bonding = <&drif01>;
status = "disabled";
};
- pwm0: pwm@e6e30000 {
- compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
- reg = <0 0xe6e30000 0 0x8>;
- clocks = <&cpg CPG_MOD 523>;
+ drif01: rif@e6f50000 {
+ compatible = "renesas,r8a7795-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f50000 0 0x64>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 514>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x22>, <&dmac2 0x22>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 523>;
- #pwm-cells = <2>;
+ resets = <&cpg 514>;
+ renesas,bonding = <&drif00>;
status = "disabled";
};
- pwm1: pwm@e6e31000 {
- compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
- reg = <0 0xe6e31000 0 0x8>;
- clocks = <&cpg CPG_MOD 523>;
+ drif10: rif@e6f60000 {
+ compatible = "renesas,r8a7795-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f60000 0 0x64>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 513>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x24>, <&dmac2 0x24>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 523>;
- #pwm-cells = <2>;
+ resets = <&cpg 513>;
+ renesas,bonding = <&drif11>;
status = "disabled";
};
- pwm2: pwm@e6e32000 {
- compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
- reg = <0 0xe6e32000 0 0x8>;
- clocks = <&cpg CPG_MOD 523>;
+ drif11: rif@e6f70000 {
+ compatible = "renesas,r8a7795-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f70000 0 0x64>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 512>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x26>, <&dmac2 0x26>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 523>;
- #pwm-cells = <2>;
+ resets = <&cpg 512>;
+ renesas,bonding = <&drif10>;
status = "disabled";
};
- pwm3: pwm@e6e33000 {
- compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
- reg = <0 0xe6e33000 0 0x8>;
- clocks = <&cpg CPG_MOD 523>;
+ drif20: rif@e6f80000 {
+ compatible = "renesas,r8a7795-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f80000 0 0x64>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 511>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x28>, <&dmac2 0x28>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 523>;
- #pwm-cells = <2>;
+ resets = <&cpg 511>;
+ renesas,bonding = <&drif21>;
status = "disabled";
};
- pwm4: pwm@e6e34000 {
- compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
- reg = <0 0xe6e34000 0 0x8>;
- clocks = <&cpg CPG_MOD 523>;
+ drif21: rif@e6f90000 {
+ compatible = "renesas,r8a7795-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f90000 0 0x64>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 510>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x2a>, <&dmac2 0x2a>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 523>;
- #pwm-cells = <2>;
+ resets = <&cpg 510>;
+ renesas,bonding = <&drif20>;
status = "disabled";
};
- pwm5: pwm@e6e35000 {
- compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
- reg = <0 0xe6e35000 0 0x8>;
- clocks = <&cpg CPG_MOD 523>;
+ drif30: rif@e6fa0000 {
+ compatible = "renesas,r8a7795-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6fa0000 0 0x64>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 509>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x2c>, <&dmac2 0x2c>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 523>;
- #pwm-cells = <2>;
+ resets = <&cpg 509>;
+ renesas,bonding = <&drif31>;
status = "disabled";
};
- pwm6: pwm@e6e36000 {
- compatible = "renesas,pwm-r8a7795", "renesas,pwm-rcar";
- reg = <0 0xe6e36000 0 0x8>;
- clocks = <&cpg CPG_MOD 523>;
+ drif31: rif@e6fb0000 {
+ compatible = "renesas,r8a7795-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6fb0000 0 0x64>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 508>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x2e>, <&dmac2 0x2e>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 523>;
- #pwm-cells = <2>;
+ resets = <&cpg 508>;
+ renesas,bonding = <&drif30>;
status = "disabled";
};
@@ -1711,31 +1967,104 @@
dma-names = "rx", "tx", "rxu", "txu";
};
};
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ };
+ port@1 {
+ reg = <1>;
+ };
+ port@2 {
+ reg = <2>;
+ };
+ };
};
- sata: sata@ee300000 {
- compatible = "renesas,sata-r8a7795",
- "renesas,rcar-gen3-sata";
- reg = <0 0xee300000 0 0x200000>;
- interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 815>;
+ audma0: dma-controller@ec700000 {
+ compatible = "renesas,dmac-r8a7795",
+ "renesas,rcar-dmac";
+ reg = <0 0xec700000 0 0x10000>;
+ interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15";
+ clocks = <&cpg CPG_MOD 502>;
+ clock-names = "fck";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 815>;
- status = "disabled";
- iommus = <&ipmmu_hc 2>;
+ resets = <&cpg 502>;
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ iommus = <&ipmmu_mp0 0>, <&ipmmu_mp0 1>,
+ <&ipmmu_mp0 2>, <&ipmmu_mp0 3>,
+ <&ipmmu_mp0 4>, <&ipmmu_mp0 5>,
+ <&ipmmu_mp0 6>, <&ipmmu_mp0 7>,
+ <&ipmmu_mp0 8>, <&ipmmu_mp0 9>,
+ <&ipmmu_mp0 10>, <&ipmmu_mp0 11>,
+ <&ipmmu_mp0 12>, <&ipmmu_mp0 13>,
+ <&ipmmu_mp0 14>, <&ipmmu_mp0 15>;
};
- usb3_phy0: usb-phy@e65ee000 {
- compatible = "renesas,r8a7795-usb3-phy",
- "renesas,rcar-gen3-usb3-phy";
- reg = <0 0xe65ee000 0 0x90>;
- clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>,
- <&usb_extal_clk>;
- clock-names = "usb3-if", "usb3s_clk", "usb_extal";
+ audma1: dma-controller@ec720000 {
+ compatible = "renesas,dmac-r8a7795",
+ "renesas,rcar-dmac";
+ reg = <0 0xec720000 0 0x10000>;
+ interrupts = <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15";
+ clocks = <&cpg CPG_MOD 501>;
+ clock-names = "fck";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 328>;
- #phy-cells = <0>;
- status = "disabled";
+ resets = <&cpg 501>;
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ iommus = <&ipmmu_mp0 16>, <&ipmmu_mp0 17>,
+ <&ipmmu_mp0 18>, <&ipmmu_mp0 19>,
+ <&ipmmu_mp0 20>, <&ipmmu_mp0 21>,
+ <&ipmmu_mp0 22>, <&ipmmu_mp0 23>,
+ <&ipmmu_mp0 24>, <&ipmmu_mp0 25>,
+ <&ipmmu_mp0 26>, <&ipmmu_mp0 27>,
+ <&ipmmu_mp0 28>, <&ipmmu_mp0 29>,
+ <&ipmmu_mp0 30>, <&ipmmu_mp0 31>;
};
xhci0: usb@ee000000 {
@@ -1759,153 +2088,51 @@
status = "disabled";
};
- usb_dmac0: dma-controller@e65a0000 {
- compatible = "renesas,r8a7795-usb-dmac",
- "renesas,usb-dmac";
- reg = <0 0xe65a0000 0 0x100>;
- interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
- 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>;
- };
-
- usb_dmac1: dma-controller@e65b0000 {
- compatible = "renesas,r8a7795-usb-dmac",
- "renesas,usb-dmac";
- reg = <0 0xe65b0000 0 0x100>;
- interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
- 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>;
- };
-
- usb_dmac2: dma-controller@e6460000 {
- compatible = "renesas,r8a7795-usb-dmac",
- "renesas,usb-dmac";
- reg = <0 0xe6460000 0 0x100>;
- interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ch0", "ch1";
- clocks = <&cpg CPG_MOD 326>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 326>;
- #dma-cells = <1>;
- dma-channels = <2>;
- };
-
- usb_dmac3: dma-controller@e6470000 {
- compatible = "renesas,r8a7795-usb-dmac",
- "renesas,usb-dmac";
- reg = <0 0xe6470000 0 0x100>;
- interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ch0", "ch1";
- clocks = <&cpg CPG_MOD 329>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 329>;
- #dma-cells = <1>;
- dma-channels = <2>;
- };
-
- sdhi0: sd@ee100000 {
- compatible = "renesas,sdhi-r8a7795",
- "renesas,rcar-gen3-sdhi";
- reg = <0 0xee100000 0 0x2000>;
- interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 314>;
- max-frequency = <200000000>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 314>;
- status = "disabled";
- };
-
- sdhi1: sd@ee120000 {
- compatible = "renesas,sdhi-r8a7795",
- "renesas,rcar-gen3-sdhi";
- reg = <0 0xee120000 0 0x2000>;
- interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 313>;
- max-frequency = <200000000>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 313>;
- status = "disabled";
- };
-
- sdhi2: sd@ee140000 {
- compatible = "renesas,sdhi-r8a7795",
- "renesas,rcar-gen3-sdhi";
- reg = <0 0xee140000 0 0x2000>;
- interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 312>;
- max-frequency = <200000000>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 312>;
- status = "disabled";
- };
-
- sdhi3: sd@ee160000 {
- compatible = "renesas,sdhi-r8a7795",
- "renesas,rcar-gen3-sdhi";
- reg = <0 0xee160000 0 0x2000>;
- interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 311>;
- max-frequency = <200000000>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 311>;
- status = "disabled";
- };
-
- usb2_phy0: usb-phy@ee080200 {
- compatible = "renesas,usb2-phy-r8a7795",
- "renesas,rcar-gen3-usb2-phy";
- reg = <0 0xee080200 0 0x700>;
+ ohci0: usb@ee080000 {
+ compatible = "generic-ohci";
+ reg = <0 0xee080000 0 0x100>;
interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 703>;
+ phys = <&usb2_phy0>;
+ phy-names = "usb";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 703>;
- #phy-cells = <0>;
status = "disabled";
};
- usb2_phy1: usb-phy@ee0a0200 {
- compatible = "renesas,usb2-phy-r8a7795",
- "renesas,rcar-gen3-usb2-phy";
- reg = <0 0xee0a0200 0 0x700>;
+ ohci1: usb@ee0a0000 {
+ compatible = "generic-ohci";
+ reg = <0 0xee0a0000 0 0x100>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 702>;
+ phys = <&usb2_phy1>;
+ phy-names = "usb";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 702>;
- #phy-cells = <0>;
status = "disabled";
};
- usb2_phy2: usb-phy@ee0c0200 {
- compatible = "renesas,usb2-phy-r8a7795",
- "renesas,rcar-gen3-usb2-phy";
- reg = <0 0xee0c0200 0 0x700>;
+ ohci2: usb@ee0c0000 {
+ compatible = "generic-ohci";
+ reg = <0 0xee0c0000 0 0x100>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 701>;
+ phys = <&usb2_phy2>;
+ phy-names = "usb";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 701>;
- #phy-cells = <0>;
status = "disabled";
};
- usb2_phy3: usb-phy@ee0e0200 {
- compatible = "renesas,usb2-phy-r8a7795",
- "renesas,rcar-gen3-usb2-phy";
- reg = <0 0xee0e0200 0 0x700>;
+ ohci3: usb@ee0e0000 {
+ compatible = "generic-ohci";
+ reg = <0 0xee0e0000 0 0x100>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 700>;
+ phys = <&usb2_phy3>;
+ phy-names = "usb";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 700>;
- #phy-cells = <0>;
status = "disabled";
};
@@ -1961,88 +2188,129 @@
status = "disabled";
};
- ohci0: usb@ee080000 {
- compatible = "generic-ohci";
- reg = <0 0xee080000 0 0x100>;
+ usb2_phy0: usb-phy@ee080200 {
+ compatible = "renesas,usb2-phy-r8a7795",
+ "renesas,rcar-gen3-usb2-phy";
+ reg = <0 0xee080200 0 0x700>;
interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 703>;
- phys = <&usb2_phy0>;
- phy-names = "usb";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 703>;
+ #phy-cells = <0>;
status = "disabled";
};
- ohci1: usb@ee0a0000 {
- compatible = "generic-ohci";
- reg = <0 0xee0a0000 0 0x100>;
- interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ usb2_phy1: usb-phy@ee0a0200 {
+ compatible = "renesas,usb2-phy-r8a7795",
+ "renesas,rcar-gen3-usb2-phy";
+ reg = <0 0xee0a0200 0 0x700>;
clocks = <&cpg CPG_MOD 702>;
- phys = <&usb2_phy1>;
- phy-names = "usb";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 702>;
+ #phy-cells = <0>;
status = "disabled";
};
- ohci2: usb@ee0c0000 {
- compatible = "generic-ohci";
- reg = <0 0xee0c0000 0 0x100>;
- interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+ usb2_phy2: usb-phy@ee0c0200 {
+ compatible = "renesas,usb2-phy-r8a7795",
+ "renesas,rcar-gen3-usb2-phy";
+ reg = <0 0xee0c0200 0 0x700>;
clocks = <&cpg CPG_MOD 701>;
- phys = <&usb2_phy2>;
- phy-names = "usb";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 701>;
+ #phy-cells = <0>;
status = "disabled";
};
- ohci3: usb@ee0e0000 {
- compatible = "generic-ohci";
- reg = <0 0xee0e0000 0 0x100>;
+ usb2_phy3: usb-phy@ee0e0200 {
+ compatible = "renesas,usb2-phy-r8a7795",
+ "renesas,rcar-gen3-usb2-phy";
+ reg = <0 0xee0e0200 0 0x700>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 700>;
- phys = <&usb2_phy3>;
- phy-names = "usb";
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
resets = <&cpg 700>;
+ #phy-cells = <0>;
status = "disabled";
};
- hsusb: usb@e6590000 {
- compatible = "renesas,usbhs-r8a7795",
- "renesas,rcar-gen3-usbhs";
- reg = <0 0xe6590000 0 0x100>;
- interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 704>;
- dmas = <&usb_dmac0 0>, <&usb_dmac0 1>,
- <&usb_dmac1 0>, <&usb_dmac1 1>;
- dma-names = "ch0", "ch1", "ch2", "ch3";
- renesas,buswait = <11>;
- phys = <&usb2_phy0>;
- phy-names = "usb";
+ sdhi0: sd@ee100000 {
+ compatible = "renesas,sdhi-r8a7795",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee100000 0 0x2000>;
+ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 314>;
+ max-frequency = <200000000>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 704>;
+ resets = <&cpg 314>;
status = "disabled";
};
- hsusb3: usb@e659c000 {
- compatible = "renesas,usbhs-r8a7795",
- "renesas,rcar-gen3-usbhs";
- reg = <0 0xe659c000 0 0x100>;
- interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 705>;
- dmas = <&usb_dmac2 0>, <&usb_dmac2 1>,
- <&usb_dmac3 0>, <&usb_dmac3 1>;
- dma-names = "ch0", "ch1", "ch2", "ch3";
- renesas,buswait = <11>;
- phys = <&usb2_phy3>;
- phy-names = "usb";
+ sdhi1: sd@ee120000 {
+ compatible = "renesas,sdhi-r8a7795",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee120000 0 0x2000>;
+ interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 313>;
+ max-frequency = <200000000>;
power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 705>;
+ resets = <&cpg 313>;
+ status = "disabled";
+ };
+
+ sdhi2: sd@ee140000 {
+ compatible = "renesas,sdhi-r8a7795",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee140000 0 0x2000>;
+ interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 312>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 312>;
+ status = "disabled";
+ };
+
+ sdhi3: sd@ee160000 {
+ compatible = "renesas,sdhi-r8a7795",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee160000 0 0x2000>;
+ interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 311>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 311>;
status = "disabled";
};
+ sata: sata@ee300000 {
+ compatible = "renesas,sata-r8a7795",
+ "renesas,rcar-gen3-sata";
+ 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";
+ iommus = <&ipmmu_hc 2>;
+ };
+
+ gic: interrupt-controller@f1010000 {
+ compatible = "arm,gic-400";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x0 0xf1010000 0 0x1000>,
+ <0x0 0xf1020000 0 0x20000>,
+ <0x0 0xf1040000 0 0x20000>,
+ <0x0 0xf1060000 0 0x20000>;
+ interrupts = <GIC_PPI 9
+ (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>;
+ };
+
pciec0: pcie@fe000000 {
compatible = "renesas,pcie-r8a7795",
"renesas,pcie-rcar-gen3";
@@ -2137,24 +2405,24 @@
resets = <&cpg 820>;
};
- vspbc: vsp@fe920000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe920000 0 0x8000>;
- interrupts = <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 624>;
+ fdp1@fe940000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe940000 0 0x2400>;
+ interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 119>;
power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 624>;
-
- renesas,fcp = <&fcpvb1>;
+ resets = <&cpg 119>;
+ renesas,fcp = <&fcpf0>;
};
- fcpvb1: fcp@fe92f000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfe92f000 0 0x200>;
- clocks = <&cpg CPG_MOD 606>;
+ fdp1@fe944000 {
+ compatible = "renesas,fdp1";
+ reg = <0 0xfe944000 0 0x2400>;
+ interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 118>;
power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 606>;
- iommus = <&ipmmu_vp1 7>;
+ resets = <&cpg 118>;
+ renesas,fcp = <&fcpf1>;
};
fcpf0: fcp@fe950000 {
@@ -2175,17 +2443,6 @@
iommus = <&ipmmu_vp1 1>;
};
- vspbd: vsp@fe960000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe960000 0 0x8000>;
- interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 626>;
- power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 626>;
-
- renesas,fcp = <&fcpvb0>;
- };
-
fcpvb0: fcp@fe96f000 {
compatible = "renesas,fcpv";
reg = <0 0xfe96f000 0 0x200>;
@@ -2195,15 +2452,13 @@
iommus = <&ipmmu_vp0 5>;
};
- vspi0: vsp@fe9a0000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe9a0000 0 0x8000>;
- interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 631>;
+ fcpvb1: fcp@fe92f000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfe92f000 0 0x200>;
+ clocks = <&cpg CPG_MOD 606>;
power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 631>;
-
- renesas,fcp = <&fcpvi0>;
+ resets = <&cpg 606>;
+ iommus = <&ipmmu_vp1 7>;
};
fcpvi0: fcp@fe9af000 {
@@ -2215,17 +2470,6 @@
iommus = <&ipmmu_vp0 8>;
};
- vspi1: vsp@fe9b0000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe9b0000 0 0x8000>;
- interrupts = <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 630>;
- power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 630>;
-
- renesas,fcp = <&fcpvi1>;
- };
-
fcpvi1: fcp@fe9bf000 {
compatible = "renesas,fcpv";
reg = <0 0xfe9bf000 0 0x200>;
@@ -2235,6 +2479,55 @@
iommus = <&ipmmu_vp1 9>;
};
+ fcpvd0: fcp@fea27000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea27000 0 0x200>;
+ clocks = <&cpg CPG_MOD 603>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 603>;
+ iommus = <&ipmmu_vi0 8>;
+ };
+
+ fcpvd1: fcp@fea2f000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea2f000 0 0x200>;
+ clocks = <&cpg CPG_MOD 602>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 602>;
+ iommus = <&ipmmu_vi0 9>;
+ };
+
+ fcpvd2: fcp@fea37000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea37000 0 0x200>;
+ clocks = <&cpg CPG_MOD 601>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 601>;
+ iommus = <&ipmmu_vi1 10>;
+ };
+
+ vspbd: vsp@fe960000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe960000 0 0x8000>;
+ interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 626>;
+ power-domains = <&sysc R8A7795_PD_A3VP>;
+ resets = <&cpg 626>;
+
+ renesas,fcp = <&fcpvb0>;
+ };
+
+ vspbc: vsp@fe920000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe920000 0 0x8000>;
+ interrupts = <GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 624>;
+ power-domains = <&sysc R8A7795_PD_A3VP>;
+ resets = <&cpg 624>;
+
+ renesas,fcp = <&fcpvb1>;
+ };
+
vspd0: vsp@fea20000 {
compatible = "renesas,vsp2";
reg = <0 0xfea20000 0 0x8000>;
@@ -2246,15 +2539,6 @@
renesas,fcp = <&fcpvd0>;
};
- fcpvd0: fcp@fea27000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfea27000 0 0x200>;
- clocks = <&cpg CPG_MOD 603>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 603>;
- iommus = <&ipmmu_vi0 8>;
- };
-
vspd1: vsp@fea28000 {
compatible = "renesas,vsp2";
reg = <0 0xfea28000 0 0x8000>;
@@ -2266,15 +2550,6 @@
renesas,fcp = <&fcpvd1>;
};
- fcpvd1: fcp@fea2f000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfea2f000 0 0x200>;
- clocks = <&cpg CPG_MOD 602>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 602>;
- iommus = <&ipmmu_vi0 9>;
- };
-
vspd2: vsp@fea30000 {
compatible = "renesas,vsp2";
reg = <0 0xfea30000 0 0x8000>;
@@ -2286,33 +2561,159 @@
renesas,fcp = <&fcpvd2>;
};
- fcpvd2: fcp@fea37000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfea37000 0 0x200>;
- clocks = <&cpg CPG_MOD 601>;
- power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
- resets = <&cpg 601>;
- iommus = <&ipmmu_vi1 10>;
+ vspi0: vsp@fe9a0000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe9a0000 0 0x8000>;
+ interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 631>;
+ power-domains = <&sysc R8A7795_PD_A3VP>;
+ resets = <&cpg 631>;
+
+ renesas,fcp = <&fcpvi0>;
};
- fdp1@fe940000 {
- compatible = "renesas,fdp1";
- reg = <0 0xfe940000 0 0x2400>;
- interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 119>;
+ vspi1: vsp@fe9b0000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe9b0000 0 0x8000>;
+ interrupts = <GIC_SPI 445 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 630>;
power-domains = <&sysc R8A7795_PD_A3VP>;
- resets = <&cpg 119>;
- renesas,fcp = <&fcpf0>;
+ resets = <&cpg 630>;
+
+ renesas,fcp = <&fcpvi1>;
};
- fdp1@fe944000 {
- compatible = "renesas,fdp1";
- reg = <0 0xfe944000 0 0x2400>;
- 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>;
+ csi20: csi2@fea80000 {
+ compatible = "renesas,r8a7795-csi2";
+ reg = <0 0xfea80000 0 0x10000>;
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 714>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 714>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ csi20vin0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vin0csi20>;
+ };
+ csi20vin1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&vin1csi20>;
+ };
+ csi20vin2: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&vin2csi20>;
+ };
+ csi20vin3: endpoint@3 {
+ reg = <3>;
+ remote-endpoint = <&vin3csi20>;
+ };
+ csi20vin4: endpoint@4 {
+ reg = <4>;
+ remote-endpoint = <&vin4csi20>;
+ };
+ csi20vin5: endpoint@5 {
+ reg = <5>;
+ remote-endpoint = <&vin5csi20>;
+ };
+ csi20vin6: endpoint@6 {
+ reg = <6>;
+ remote-endpoint = <&vin6csi20>;
+ };
+ csi20vin7: endpoint@7 {
+ reg = <7>;
+ remote-endpoint = <&vin7csi20>;
+ };
+ };
+ };
+ };
+
+ csi40: csi2@feaa0000 {
+ compatible = "renesas,r8a7795-csi2";
+ reg = <0 0xfeaa0000 0 0x10000>;
+ interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 716>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 716>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ csi40vin0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vin0csi40>;
+ };
+ csi40vin1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&vin1csi40>;
+ };
+ csi40vin2: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&vin2csi40>;
+ };
+ csi40vin3: endpoint@3 {
+ reg = <3>;
+ remote-endpoint = <&vin3csi40>;
+ };
+ };
+ };
+ };
+
+ csi41: csi2@feab0000 {
+ compatible = "renesas,r8a7795-csi2";
+ reg = <0 0xfeab0000 0 0x10000>;
+ interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 715>;
+ power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+ resets = <&cpg 715>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ csi41vin4: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vin4csi41>;
+ };
+ csi41vin5: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&vin5csi41>;
+ };
+ csi41vin6: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&vin6csi41>;
+ };
+ csi41vin7: endpoint@3 {
+ reg = <3>;
+ remote-endpoint = <&vin7csi41>;
+ };
+ };
+ };
};
hdmi0: hdmi@fead0000 {
@@ -2337,6 +2738,10 @@
port@1 {
reg = <1>;
};
+ port@2 {
+ /* HDMI sound */
+ reg = <2>;
+ };
};
};
@@ -2362,6 +2767,10 @@
port@1 {
reg = <1>;
};
+ port@2 {
+ /* HDMI sound */
+ reg = <2>;
+ };
};
};
@@ -2412,38 +2821,12 @@
};
};
- tsc: thermal@e6198000 {
- compatible = "renesas,r8a7795-thermal";
- reg = <0 0xe6198000 0 0x100>,
- <0 0xe61a0000 0 0x100>,
- <0 0xe61a8000 0 0x100>;
- interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
- <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";
+ prr: chipid@fff00044 {
+ compatible = "renesas,prr";
+ reg = <0 0xfff00044 0 4>;
};
};
- timer {
- compatible = "arm,armv8-timer";
- interrupts-extended = <&gic GIC_PPI 13
- (GIC_CPU_MASK_SIMPLE(8) |
- IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 14
- (GIC_CPU_MASK_SIMPLE(8) |
- IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 11
- (GIC_CPU_MASK_SIMPLE(8) |
- IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 10
- (GIC_CPU_MASK_SIMPLE(8) |
- IRQ_TYPE_LEVEL_LOW)>;
- };
-
thermal-zones {
sensor_thermal1: sensor-thermal1 {
polling-delay-passive = <250>;
@@ -2453,12 +2836,12 @@
trips {
sensor1_passive: sensor1-passive {
temperature = <95000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "passive";
};
sensor1_crit: sensor1-crit {
temperature = <120000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -2479,12 +2862,12 @@
trips {
sensor2_passive: sensor2-passive {
temperature = <95000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "passive";
};
sensor2_crit: sensor2-crit {
temperature = <120000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -2505,12 +2888,12 @@
trips {
sensor3_passive: sensor3-passive {
temperature = <95000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "passive";
};
sensor3_crit: sensor3-crit {
temperature = <120000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -2524,6 +2907,14 @@
};
};
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
/* External USB clocks - can be overridden by the board */
usb3s0_clk: usb3s0 {
compatible = "fixed-clock";
diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
index 498c9e8..90cca09 100644
--- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
@@ -40,6 +40,11 @@
"dclkin.0", "dclkin.1", "dclkin.2";
};
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1>; /* HDMI0 */
+};
+
&hdmi0 {
status = "okay";
@@ -50,9 +55,32 @@
remote-endpoint = <&hdmi0_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi0_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint1>;
+ };
+ };
};
};
&hdmi0_con {
remote-endpoint = <&rcar_dw_hdmi0_out>;
};
+
+&rcar_sound {
+ ports {
+ /* rsnd_port0 is on salvator-common */
+ rsnd_port1: port@1 {
+ rsnd_endpoint1: endpoint {
+ remote-endpoint = <&dw_hdmi0_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint1>;
+ frame-master = <&rsnd_endpoint1>;
+
+ playback = <&ssi2>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts
index 2c37055..ddf35d4 100644
--- a/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts
+++ b/arch/arm64/boot/dts/renesas/r8a7796-salvator-xs.dts
@@ -40,6 +40,11 @@
"dclkin.0", "dclkin.1", "dclkin.2";
};
+&sound_card {
+ dais = <&rsnd_port0 /* ak4613 */
+ &rsnd_port1>; /* HDMI0 */
+};
+
&hdmi0 {
status = "okay";
@@ -50,9 +55,32 @@
remote-endpoint = <&hdmi0_con>;
};
};
+ port@2 {
+ reg = <2>;
+ dw_hdmi0_snd_in: endpoint {
+ remote-endpoint = <&rsnd_endpoint1>;
+ };
+ };
};
};
&hdmi0_con {
remote-endpoint = <&rcar_dw_hdmi0_out>;
};
+
+&rcar_sound {
+ ports {
+ /* rsnd_port0 is on salvator-common */
+ rsnd_port1: port@1 {
+ rsnd_endpoint1: endpoint {
+ remote-endpoint = <&dw_hdmi0_snd_in>;
+
+ dai-format = "i2s";
+ bitclock-master = <&rsnd_endpoint1>;
+ frame-master = <&rsnd_endpoint1>;
+
+ playback = <&ssi2>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a7796.dtsi b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
index 556eb8e..7c25be6 100644
--- a/arch/arm64/boot/dts/renesas/r8a7796.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a7796.dtsi
@@ -60,6 +60,72 @@
clock-frequency = <0>;
};
+ cluster0_opp: opp_table0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <820000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <820000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-1500000000 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <820000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-1600000000 {
+ opp-hz = /bits/ 64 <1600000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <300000>;
+ turbo-mode;
+ };
+ opp-1700000000 {
+ opp-hz = /bits/ 64 <1700000000>;
+ opp-microvolt = <900000>;
+ clock-latency-ns = <300000>;
+ turbo-mode;
+ };
+ opp-1800000000 {
+ opp-hz = /bits/ 64 <1800000000>;
+ opp-microvolt = <960000>;
+ clock-latency-ns = <300000>;
+ turbo-mode;
+ };
+ };
+
+ cluster1_opp: opp_table1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <820000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <820000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <820000>;
+ clock-latency-ns = <300000>;
+ };
+ opp-1300000000 {
+ opp-hz = /bits/ 64 <1300000000>;
+ opp-microvolt = <820000>;
+ clock-latency-ns = <300000>;
+ turbo-mode;
+ };
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
@@ -77,7 +143,7 @@
};
a57_1: cpu@1 {
- compatible = "arm,cortex-a57","arm,armv8";
+ compatible = "arm,cortex-a57", "arm,armv8";
reg = <0x1>;
device_type = "cpu";
power-domains = <&sysc R8A7796_PD_CA57_CPU1>;
@@ -100,7 +166,7 @@
};
a53_1: cpu@101 {
- compatible = "arm,cortex-a53","arm,armv8";
+ compatible = "arm,cortex-a53", "arm,armv8";
reg = <0x101>;
device_type = "cpu";
power-domains = <&sysc R8A7796_PD_CA53_CPU1>;
@@ -111,7 +177,7 @@
};
a53_2: cpu@102 {
- compatible = "arm,cortex-a53","arm,armv8";
+ compatible = "arm,cortex-a53", "arm,armv8";
reg = <0x102>;
device_type = "cpu";
power-domains = <&sysc R8A7796_PD_CA53_CPU2>;
@@ -122,7 +188,7 @@
};
a53_3: cpu@103 {
- compatible = "arm,cortex-a53","arm,armv8";
+ compatible = "arm,cortex-a53", "arm,armv8";
reg = <0x103>;
device_type = "cpu";
power-domains = <&sysc R8A7796_PD_CA53_CPU3>;
@@ -161,72 +227,6 @@
clock-frequency = <0>;
};
- cluster0_opp: opp_table0 {
- compatible = "operating-points-v2";
- opp-shared;
-
- opp-500000000 {
- opp-hz = /bits/ 64 <500000000>;
- opp-microvolt = <820000>;
- clock-latency-ns = <300000>;
- };
- opp-1000000000 {
- opp-hz = /bits/ 64 <1000000000>;
- opp-microvolt = <820000>;
- clock-latency-ns = <300000>;
- };
- opp-1500000000 {
- opp-hz = /bits/ 64 <1500000000>;
- opp-microvolt = <820000>;
- clock-latency-ns = <300000>;
- };
- opp-1600000000 {
- opp-hz = /bits/ 64 <1600000000>;
- opp-microvolt = <900000>;
- clock-latency-ns = <300000>;
- turbo-mode;
- };
- opp-1700000000 {
- opp-hz = /bits/ 64 <1700000000>;
- opp-microvolt = <900000>;
- clock-latency-ns = <300000>;
- turbo-mode;
- };
- opp-1800000000 {
- opp-hz = /bits/ 64 <1800000000>;
- opp-microvolt = <960000>;
- clock-latency-ns = <300000>;
- turbo-mode;
- };
- };
-
- cluster1_opp: opp_table1 {
- compatible = "operating-points-v2";
- opp-shared;
-
- opp-800000000 {
- opp-hz = /bits/ 64 <800000000>;
- opp-microvolt = <820000>;
- clock-latency-ns = <300000>;
- };
- opp-1000000000 {
- opp-hz = /bits/ 64 <1000000000>;
- opp-microvolt = <820000>;
- clock-latency-ns = <300000>;
- };
- opp-1200000000 {
- opp-hz = /bits/ 64 <1200000000>;
- opp-microvolt = <820000>;
- clock-latency-ns = <300000>;
- };
- opp-1300000000 {
- opp-hz = /bits/ 64 <1300000000>;
- opp-microvolt = <820000>;
- clock-latency-ns = <300000>;
- turbo-mode;
- };
- };
-
/* External PCIe clock - can be overridden by the board */
pcie_bus_clk: pcie_bus {
compatible = "fixed-clock";
@@ -234,13 +234,6 @@
clock-frequency = <0>;
};
- pmu_a57 {
- compatible = "arm,cortex-a57-pmu";
- interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
- <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-affinity = <&a57_0>, <&a57_1>;
- };
-
pmu_a53 {
compatible = "arm,cortex-a53-pmu";
interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
@@ -250,6 +243,13 @@
interrupt-affinity = <&a53_0>, <&a53_1>, <&a53_2>, <&a53_3>;
};
+ pmu_a57 {
+ compatible = "arm,cortex-a57-pmu";
+ interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&a57_0>, <&a57_1>;
+ };
+
psci {
compatible = "arm,psci-1.0", "arm,psci-0.2";
method = "smc";
@@ -269,23 +269,6 @@
#size-cells = <2>;
ranges;
- gic: interrupt-controller@f1010000 {
- compatible = "arm,gic-400";
- #interrupt-cells = <3>;
- #address-cells = <0>;
- interrupt-controller;
- reg = <0x0 0xf1010000 0 0x1000>,
- <0x0 0xf1020000 0 0x20000>,
- <0x0 0xf1040000 0 0x20000>,
- <0x0 0xf1060000 0 0x20000>;
- interrupts = <GIC_PPI 9
- (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>;
- };
-
wdt0: watchdog@e6020000 {
compatible = "renesas,r8a7796-wdt",
"renesas,rcar-gen3-wdt";
@@ -421,100 +404,6 @@
reg = <0 0xe6060000 0 0x50c>;
};
- ipmmu_vi0: mmu@febd0000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xfebd0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 9>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- };
-
- ipmmu_vc0: mmu@fe6b0000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xfe6b0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 8>;
- power-domains = <&sysc R8A7796_PD_A3VC>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_pv0: mmu@fd800000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xfd800000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 5>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- };
-
- ipmmu_pv1: mmu@fd950000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xfd950000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 6>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_ir: mmu@ff8b0000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xff8b0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 3>;
- power-domains = <&sysc R8A7796_PD_A3IR>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_hc: mmu@e6570000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xe6570000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 2>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_rt: mmu@ffc80000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xffc80000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 7>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_mp: mmu@ec670000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xec670000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 4>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- };
-
- ipmmu_ds0: mmu@e6740000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xe6740000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 0>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- };
-
- ipmmu_ds1: mmu@e7740000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xe7740000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 1>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- };
-
- ipmmu_mm: mmu@e67b0000 {
- compatible = "renesas,ipmmu-r8a7796";
- reg = <0 0xe67b0000 0 0x1000>;
- interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- };
-
cpg: clock-controller@e6150000 {
compatible = "renesas,r8a7796-cpg-mssr";
reg = <0 0xe6150000 0 0x1000>;
@@ -530,17 +419,27 @@
reg = <0 0xe6160000 0 0x0200>;
};
- prr: chipid@fff00044 {
- compatible = "renesas,prr";
- reg = <0 0xfff00044 0 4>;
- };
-
sysc: system-controller@e6180000 {
compatible = "renesas,r8a7796-sysc";
reg = <0 0xe6180000 0 0x0400>;
#power-domain-cells = <1>;
};
+ tsc: thermal@e6198000 {
+ compatible = "renesas,r8a7796-thermal";
+ reg = <0 0xe6198000 0 0x100>,
+ <0 0xe61a0000 0 0x100>,
+ <0 0xe61a8000 0 0x100>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <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";
+ };
+
intc_ex: interrupt-controller@e61c0000 {
compatible = "renesas,intc-ex-r8a7796", "renesas,irqc";
#interrupt-cells = <2>;
@@ -557,92 +456,6 @@
resets = <&cpg 407>;
};
- 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>;
- dmas = <&dmac0 0x11>, <&dmac0 0x10>;
- dma-names = "tx", "rx";
- status = "disabled";
- };
-
- pwm0: pwm@e6e30000 {
- compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
- reg = <0 0xe6e30000 0 8>;
- #pwm-cells = <2>;
- clocks = <&cpg CPG_MOD 523>;
- resets = <&cpg 523>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- status = "disabled";
- };
-
- pwm1: pwm@e6e31000 {
- compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
- reg = <0 0xe6e31000 0 8>;
- #pwm-cells = <2>;
- clocks = <&cpg CPG_MOD 523>;
- resets = <&cpg 523>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- status = "disabled";
- };
-
- pwm2: pwm@e6e32000 {
- compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
- reg = <0 0xe6e32000 0 8>;
- #pwm-cells = <2>;
- clocks = <&cpg CPG_MOD 523>;
- resets = <&cpg 523>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- status = "disabled";
- };
-
- pwm3: pwm@e6e33000 {
- compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
- reg = <0 0xe6e33000 0 8>;
- #pwm-cells = <2>;
- clocks = <&cpg CPG_MOD 523>;
- resets = <&cpg 523>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- status = "disabled";
- };
-
- pwm4: pwm@e6e34000 {
- compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
- reg = <0 0xe6e34000 0 8>;
- #pwm-cells = <2>;
- clocks = <&cpg CPG_MOD 523>;
- resets = <&cpg 523>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- status = "disabled";
- };
-
- pwm5: pwm@e6e35000 {
- compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
- reg = <0 0xe6e35000 0 8>;
- #pwm-cells = <2>;
- clocks = <&cpg CPG_MOD 523>;
- resets = <&cpg 523>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- status = "disabled";
- };
-
- pwm6: pwm@e6e36000 {
- compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
- reg = <0 0xe6e36000 0 8>;
- #pwm-cells = <2>;
- clocks = <&cpg CPG_MOD 523>;
- resets = <&cpg 523>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- status = "disabled";
- };
-
i2c0: i2c@e6500000 {
#address-cells = <1>;
#size-cells = <0>;
@@ -758,181 +571,381 @@
status = "disabled";
};
- can0: can@e6c30000 {
- compatible = "renesas,can-r8a7796",
- "renesas,rcar-gen3-can";
- reg = <0 0xe6c30000 0 0x1000>;
- interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 916>,
- <&cpg CPG_CORE R8A7796_CLK_CANFD>,
- <&can_clk>;
- clock-names = "clkp1", "clkp2", "can_clk";
- assigned-clocks = <&cpg CPG_CORE R8A7796_CLK_CANFD>;
- assigned-clock-rates = <40000000>;
+ 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 916>;
+ resets = <&cpg 926>;
+ dmas = <&dmac0 0x11>, <&dmac0 0x10>;
+ dma-names = "tx", "rx";
status = "disabled";
};
- can1: can@e6c38000 {
- compatible = "renesas,can-r8a7796",
- "renesas,rcar-gen3-can";
- reg = <0 0xe6c38000 0 0x1000>;
- interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 915>,
- <&cpg CPG_CORE R8A7796_CLK_CANFD>,
- <&can_clk>;
- clock-names = "clkp1", "clkp2", "can_clk";
- assigned-clocks = <&cpg CPG_CORE R8A7796_CLK_CANFD>;
- assigned-clock-rates = <40000000>;
+ 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 915>;
+ resets = <&cpg 520>;
status = "disabled";
};
- canfd: can@e66c0000 {
- compatible = "renesas,r8a7796-canfd",
- "renesas,rcar-gen3-canfd";
- reg = <0 0xe66c0000 0 0x8000>;
- interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 914>,
- <&cpg CPG_CORE R8A7796_CLK_CANFD>,
- <&can_clk>;
- clock-names = "fck", "canfd", "can_clk";
- assigned-clocks = <&cpg CPG_CORE R8A7796_CLK_CANFD>;
- assigned-clock-rates = <40000000>;
+ 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 914>;
+ resets = <&cpg 519>;
status = "disabled";
-
- channel0 {
- status = "disabled";
- };
-
- channel1 {
- status = "disabled";
- };
};
- drif00: rif@e6f40000 {
- compatible = "renesas,r8a7796-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f40000 0 0x64>;
- interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 515>;
- clock-names = "fck";
- dmas = <&dmac1 0x20>, <&dmac2 0x20>;
- dma-names = "rx", "rx";
+ 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 515>;
- renesas,bonding = <&drif01>;
+ resets = <&cpg 518>;
status = "disabled";
};
- drif01: rif@e6f50000 {
- compatible = "renesas,r8a7796-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f50000 0 0x64>;
- interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 514>;
- clock-names = "fck";
- dmas = <&dmac1 0x22>, <&dmac2 0x22>;
- dma-names = "rx", "rx";
+ 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 514>;
- renesas,bonding = <&drif00>;
+ resets = <&cpg 517>;
status = "disabled";
};
- drif10: rif@e6f60000 {
- compatible = "renesas,r8a7796-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f60000 0 0x64>;
- interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 513>;
- clock-names = "fck";
- dmas = <&dmac1 0x24>, <&dmac2 0x24>;
- dma-names = "rx", "rx";
+ 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 513>;
- renesas,bonding = <&drif11>;
+ resets = <&cpg 516>;
status = "disabled";
};
- drif11: rif@e6f70000 {
- compatible = "renesas,r8a7796-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f70000 0 0x64>;
- interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 512>;
- clock-names = "fck";
- dmas = <&dmac1 0x26>, <&dmac2 0x26>;
- dma-names = "rx", "rx";
+ hsusb: usb@e6590000 {
+ compatible = "renesas,usbhs-r8a7796",
+ "renesas,rcar-gen3-usbhs";
+ reg = <0 0xe6590000 0 0x100>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 704>;
+ dmas = <&usb_dmac0 0>, <&usb_dmac0 1>,
+ <&usb_dmac1 0>, <&usb_dmac1 1>;
+ dma-names = "ch0", "ch1", "ch2", "ch3";
+ renesas,buswait = <11>;
+ phys = <&usb2_phy0>;
+ phy-names = "usb";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 512>;
- renesas,bonding = <&drif10>;
+ resets = <&cpg 704>;
status = "disabled";
};
- drif20: rif@e6f80000 {
- compatible = "renesas,r8a7796-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f80000 0 0x64>;
- interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 511>;
- clock-names = "fck";
- dmas = <&dmac1 0x28>, <&dmac2 0x28>;
- dma-names = "rx", "rx";
+ usb_dmac0: dma-controller@e65a0000 {
+ compatible = "renesas,r8a7796-usb-dmac",
+ "renesas,usb-dmac";
+ reg = <0 0xe65a0000 0 0x100>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1";
+ clocks = <&cpg CPG_MOD 330>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 511>;
- renesas,bonding = <&drif21>;
+ resets = <&cpg 330>;
+ #dma-cells = <1>;
+ dma-channels = <2>;
+ };
+
+ usb_dmac1: dma-controller@e65b0000 {
+ compatible = "renesas,r8a7796-usb-dmac",
+ "renesas,usb-dmac";
+ reg = <0 0xe65b0000 0 0x100>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1";
+ clocks = <&cpg CPG_MOD 331>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 331>;
+ #dma-cells = <1>;
+ dma-channels = <2>;
+ };
+
+ usb3_phy0: usb-phy@e65ee000 {
+ compatible = "renesas,r8a7796-usb3-phy",
+ "renesas,rcar-gen3-usb3-phy";
+ reg = <0 0xe65ee000 0 0x90>;
+ clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>,
+ <&usb_extal_clk>;
+ clock-names = "usb3-if", "usb3s_clk", "usb_extal";
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 328>;
+ #phy-cells = <0>;
status = "disabled";
};
- drif21: rif@e6f90000 {
- compatible = "renesas,r8a7796-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6f90000 0 0x64>;
- interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 510>;
+ dmac0: dma-controller@e6700000 {
+ compatible = "renesas,dmac-r8a7796",
+ "renesas,rcar-dmac";
+ reg = <0 0xe6700000 0 0x10000>;
+ interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15";
+ clocks = <&cpg CPG_MOD 219>;
clock-names = "fck";
- dmas = <&dmac1 0x2a>, <&dmac2 0x2a>;
- dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 510>;
- renesas,bonding = <&drif20>;
- status = "disabled";
+ resets = <&cpg 219>;
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ iommus = <&ipmmu_ds0 0>, <&ipmmu_ds0 1>,
+ <&ipmmu_ds0 2>, <&ipmmu_ds0 3>,
+ <&ipmmu_ds0 4>, <&ipmmu_ds0 5>,
+ <&ipmmu_ds0 6>, <&ipmmu_ds0 7>,
+ <&ipmmu_ds0 8>, <&ipmmu_ds0 9>,
+ <&ipmmu_ds0 10>, <&ipmmu_ds0 11>,
+ <&ipmmu_ds0 12>, <&ipmmu_ds0 13>,
+ <&ipmmu_ds0 14>, <&ipmmu_ds0 15>;
};
- drif30: rif@e6fa0000 {
- compatible = "renesas,r8a7796-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6fa0000 0 0x64>;
- interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 509>;
+ dmac1: dma-controller@e7300000 {
+ compatible = "renesas,dmac-r8a7796",
+ "renesas,rcar-dmac";
+ reg = <0 0xe7300000 0 0x10000>;
+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15";
+ clocks = <&cpg CPG_MOD 218>;
clock-names = "fck";
- dmas = <&dmac1 0x2c>, <&dmac2 0x2c>;
- dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 509>;
- renesas,bonding = <&drif31>;
- status = "disabled";
+ resets = <&cpg 218>;
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ iommus = <&ipmmu_ds1 0>, <&ipmmu_ds1 1>,
+ <&ipmmu_ds1 2>, <&ipmmu_ds1 3>,
+ <&ipmmu_ds1 4>, <&ipmmu_ds1 5>,
+ <&ipmmu_ds1 6>, <&ipmmu_ds1 7>,
+ <&ipmmu_ds1 8>, <&ipmmu_ds1 9>,
+ <&ipmmu_ds1 10>, <&ipmmu_ds1 11>,
+ <&ipmmu_ds1 12>, <&ipmmu_ds1 13>,
+ <&ipmmu_ds1 14>, <&ipmmu_ds1 15>;
};
- drif31: rif@e6fb0000 {
- compatible = "renesas,r8a7796-drif",
- "renesas,rcar-gen3-drif";
- reg = <0 0xe6fb0000 0 0x64>;
- interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 508>;
+ dmac2: dma-controller@e7310000 {
+ compatible = "renesas,dmac-r8a7796",
+ "renesas,rcar-dmac";
+ reg = <0 0xe7310000 0 0x10000>;
+ interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15";
+ clocks = <&cpg CPG_MOD 217>;
clock-names = "fck";
- dmas = <&dmac1 0x2e>, <&dmac2 0x2e>;
- dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 508>;
- renesas,bonding = <&drif30>;
- status = "disabled";
+ resets = <&cpg 217>;
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ iommus = <&ipmmu_ds1 16>, <&ipmmu_ds1 17>,
+ <&ipmmu_ds1 18>, <&ipmmu_ds1 19>,
+ <&ipmmu_ds1 20>, <&ipmmu_ds1 21>,
+ <&ipmmu_ds1 22>, <&ipmmu_ds1 23>,
+ <&ipmmu_ds1 24>, <&ipmmu_ds1 25>,
+ <&ipmmu_ds1 26>, <&ipmmu_ds1 27>,
+ <&ipmmu_ds1 28>, <&ipmmu_ds1 29>,
+ <&ipmmu_ds1 30>, <&ipmmu_ds1 31>;
+ };
+
+ ipmmu_ds0: mmu@e6740000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xe6740000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 0>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_ds1: mmu@e7740000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xe7740000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 1>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_hc: mmu@e6570000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xe6570000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 2>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_ir: mmu@ff8b0000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xff8b0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 3>;
+ power-domains = <&sysc R8A7796_PD_A3IR>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_mm: mmu@e67b0000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xe67b0000 0 0x1000>;
+ interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_mp: mmu@ec670000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xec670000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 4>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_pv0: mmu@fd800000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xfd800000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 5>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_pv1: mmu@fd950000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xfd950000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 6>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_rt: mmu@ffc80000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xffc80000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 7>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vc0: mmu@fe6b0000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xfe6b0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 8>;
+ power-domains = <&sysc R8A7796_PD_A3VC>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vi0: mmu@febd0000 {
+ compatible = "renesas,ipmmu-r8a7796";
+ reg = <0 0xfebd0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 9>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
};
avb: ethernet@e6800000 {
@@ -981,91 +994,130 @@
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";
+ can0: can@e6c30000 {
+ compatible = "renesas,can-r8a7796",
+ "renesas,rcar-gen3-can";
+ reg = <0 0xe6c30000 0 0x1000>;
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 916>,
+ <&cpg CPG_CORE R8A7796_CLK_CANFD>,
+ <&can_clk>;
+ clock-names = "clkp1", "clkp2", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A7796_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 520>;
+ resets = <&cpg 916>;
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";
+ can1: can@e6c38000 {
+ compatible = "renesas,can-r8a7796",
+ "renesas,rcar-gen3-can";
+ reg = <0 0xe6c38000 0 0x1000>;
+ interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 915>,
+ <&cpg CPG_CORE R8A7796_CLK_CANFD>,
+ <&can_clk>;
+ clock-names = "clkp1", "clkp2", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A7796_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 519>;
+ resets = <&cpg 915>;
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";
+ canfd: can@e66c0000 {
+ compatible = "renesas,r8a7796-canfd",
+ "renesas,rcar-gen3-canfd";
+ reg = <0 0xe66c0000 0 0x8000>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 914>,
+ <&cpg CPG_CORE R8A7796_CLK_CANFD>,
+ <&can_clk>;
+ clock-names = "fck", "canfd", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A7796_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 518>;
+ resets = <&cpg 914>;
status = "disabled";
+
+ channel0 {
+ status = "disabled";
+ };
+
+ channel1 {
+ 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";
+ pwm0: pwm@e6e30000 {
+ compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
+ reg = <0 0xe6e30000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
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";
+ pwm1: pwm@e6e31000 {
+ compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
+ reg = <0 0xe6e31000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm2: pwm@e6e32000 {
+ compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
+ reg = <0 0xe6e32000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm3: pwm@e6e33000 {
+ compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
+ reg = <0 0xe6e33000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm4: pwm@e6e34000 {
+ compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
+ reg = <0 0xe6e34000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm5: pwm@e6e35000 {
+ compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
+ reg = <0 0xe6e35000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm6: pwm@e6e36000 {
+ compatible = "renesas,pwm-r8a7796", "renesas,pwm-rcar";
+ reg = <0 0xe6e36000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 516>;
status = "disabled";
};
@@ -1228,430 +1280,380 @@
status = "disabled";
};
- dmac0: dma-controller@e6700000 {
- compatible = "renesas,dmac-r8a7796",
- "renesas,rcar-dmac";
- reg = <0 0xe6700000 0 0x10000>;
- interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 210 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 211 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 213 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 214 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 215 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14", "ch15";
- clocks = <&cpg CPG_MOD 219>;
- clock-names = "fck";
+ vin0: video@e6ef0000 {
+ compatible = "renesas,vin-r8a7796";
+ reg = <0 0xe6ef0000 0 0x1000>;
+ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 811>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 219>;
- #dma-cells = <1>;
- dma-channels = <16>;
- iommus = <&ipmmu_ds0 0>, <&ipmmu_ds0 1>,
- <&ipmmu_ds0 2>, <&ipmmu_ds0 3>,
- <&ipmmu_ds0 4>, <&ipmmu_ds0 5>,
- <&ipmmu_ds0 6>, <&ipmmu_ds0 7>,
- <&ipmmu_ds0 8>, <&ipmmu_ds0 9>,
- <&ipmmu_ds0 10>, <&ipmmu_ds0 11>,
- <&ipmmu_ds0 12>, <&ipmmu_ds0 13>,
- <&ipmmu_ds0 14>, <&ipmmu_ds0 15>;
- };
+ resets = <&cpg 811>;
+ renesas,id = <0>;
+ status = "disabled";
- dmac1: dma-controller@e7300000 {
- compatible = "renesas,dmac-r8a7796",
- "renesas,rcar-dmac";
- reg = <0 0xe7300000 0 0x10000>;
- interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14", "ch15";
- clocks = <&cpg CPG_MOD 218>;
- clock-names = "fck";
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 218>;
- #dma-cells = <1>;
- dma-channels = <16>;
- iommus = <&ipmmu_ds1 0>, <&ipmmu_ds1 1>,
- <&ipmmu_ds1 2>, <&ipmmu_ds1 3>,
- <&ipmmu_ds1 4>, <&ipmmu_ds1 5>,
- <&ipmmu_ds1 6>, <&ipmmu_ds1 7>,
- <&ipmmu_ds1 8>, <&ipmmu_ds1 9>,
- <&ipmmu_ds1 10>, <&ipmmu_ds1 11>,
- <&ipmmu_ds1 12>, <&ipmmu_ds1 13>,
- <&ipmmu_ds1 14>, <&ipmmu_ds1 15>;
- };
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
- dmac2: dma-controller@e7310000 {
- compatible = "renesas,dmac-r8a7796",
- "renesas,rcar-dmac";
- reg = <0 0xe7310000 0 0x10000>;
- interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 430 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 431 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14", "ch15";
- clocks = <&cpg CPG_MOD 217>;
- clock-names = "fck";
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 217>;
- #dma-cells = <1>;
- dma-channels = <16>;
- iommus = <&ipmmu_ds1 16>, <&ipmmu_ds1 17>,
- <&ipmmu_ds1 18>, <&ipmmu_ds1 19>,
- <&ipmmu_ds1 20>, <&ipmmu_ds1 21>,
- <&ipmmu_ds1 22>, <&ipmmu_ds1 23>,
- <&ipmmu_ds1 24>, <&ipmmu_ds1 25>,
- <&ipmmu_ds1 26>, <&ipmmu_ds1 27>,
- <&ipmmu_ds1 28>, <&ipmmu_ds1 29>,
- <&ipmmu_ds1 30>, <&ipmmu_ds1 31>;
- };
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
- audma0: dma-controller@ec700000 {
- compatible = "renesas,dmac-r8a7796",
- "renesas,rcar-dmac";
- reg = <0 0xec700000 0 0x10000>;
- interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14", "ch15";
- clocks = <&cpg CPG_MOD 502>;
- clock-names = "fck";
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 502>;
- #dma-cells = <1>;
- dma-channels = <16>;
- iommus = <&ipmmu_mp 0>, <&ipmmu_mp 1>,
- <&ipmmu_mp 2>, <&ipmmu_mp 3>,
- <&ipmmu_mp 4>, <&ipmmu_mp 5>,
- <&ipmmu_mp 6>, <&ipmmu_mp 7>,
- <&ipmmu_mp 8>, <&ipmmu_mp 9>,
- <&ipmmu_mp 10>, <&ipmmu_mp 11>,
- <&ipmmu_mp 12>, <&ipmmu_mp 13>,
- <&ipmmu_mp 14>, <&ipmmu_mp 15>;
- };
+ reg = <1>;
- audma1: dma-controller@ec720000 {
- compatible = "renesas,dmac-r8a7796",
- "renesas,rcar-dmac";
- reg = <0 0xec720000 0 0x10000>;
- interrupts = <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14", "ch15";
- clocks = <&cpg CPG_MOD 501>;
- clock-names = "fck";
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 501>;
- #dma-cells = <1>;
- dma-channels = <16>;
- iommus = <&ipmmu_mp 16>, <&ipmmu_mp 17>,
- <&ipmmu_mp 18>, <&ipmmu_mp 19>,
- <&ipmmu_mp 20>, <&ipmmu_mp 21>,
- <&ipmmu_mp 22>, <&ipmmu_mp 23>,
- <&ipmmu_mp 24>, <&ipmmu_mp 25>,
- <&ipmmu_mp 26>, <&ipmmu_mp 27>,
- <&ipmmu_mp 28>, <&ipmmu_mp 29>,
- <&ipmmu_mp 30>, <&ipmmu_mp 31>;
+ vin0csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin0>;
+ };
+ vin0csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin0>;
+ };
+ };
+ };
};
- usb_dmac0: dma-controller@e65a0000 {
- compatible = "renesas,r8a7796-usb-dmac",
- "renesas,usb-dmac";
- reg = <0 0xe65a0000 0 0x100>;
- interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ch0", "ch1";
- clocks = <&cpg CPG_MOD 330>;
+ vin1: video@e6ef1000 {
+ compatible = "renesas,vin-r8a7796";
+ reg = <0 0xe6ef1000 0 0x1000>;
+ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 810>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 330>;
- #dma-cells = <1>;
- dma-channels = <2>;
- };
+ resets = <&cpg 810>;
+ renesas,id = <1>;
+ status = "disabled";
- usb_dmac1: dma-controller@e65b0000 {
- compatible = "renesas,r8a7796-usb-dmac",
- "renesas,usb-dmac";
- reg = <0 0xe65b0000 0 0x100>;
- interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ch0", "ch1";
- clocks = <&cpg CPG_MOD 331>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 331>;
- #dma-cells = <1>;
- dma-channels = <2>;
- };
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
- hsusb: usb@e6590000 {
- compatible = "renesas,usbhs-r8a7796",
- "renesas,rcar-gen3-usbhs";
- reg = <0 0xe6590000 0 0x100>;
- interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 704>;
- dmas = <&usb_dmac0 0>, <&usb_dmac0 1>,
- <&usb_dmac1 0>, <&usb_dmac1 1>;
- dma-names = "ch0", "ch1", "ch2", "ch3";
- renesas,buswait = <11>;
- phys = <&usb2_phy0>;
- phy-names = "usb";
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 704>;
- status = "disabled";
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin1csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin1>;
+ };
+ vin1csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin1>;
+ };
+ };
+ };
};
- usb3_phy0: usb-phy@e65ee000 {
- compatible = "renesas,r8a7796-usb3-phy",
- "renesas,rcar-gen3-usb3-phy";
- reg = <0 0xe65ee000 0 0x90>;
- clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>,
- <&usb_extal_clk>;
- clock-names = "usb3-if", "usb3s_clk", "usb_extal";
+ vin2: video@e6ef2000 {
+ compatible = "renesas,vin-r8a7796";
+ reg = <0 0xe6ef2000 0 0x1000>;
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 809>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 328>;
- #phy-cells = <0>;
+ resets = <&cpg 809>;
+ renesas,id = <2>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin2csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin2>;
+ };
+ vin2csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin2>;
+ };
+ };
+ };
};
- xhci0: usb@ee000000 {
- compatible = "renesas,xhci-r8a7796",
- "renesas,rcar-gen3-xhci";
- reg = <0 0xee000000 0 0xc00>;
- interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 328>;
+ vin3: video@e6ef3000 {
+ compatible = "renesas,vin-r8a7796";
+ reg = <0 0xe6ef3000 0 0x1000>;
+ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 808>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 328>;
+ resets = <&cpg 808>;
+ renesas,id = <3>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin3csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin3>;
+ };
+ vin3csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin3>;
+ };
+ };
+ };
};
- usb3_peri0: usb@ee020000 {
- compatible = "renesas,r8a7796-usb3-peri",
- "renesas,rcar-gen3-usb3-peri";
- reg = <0 0xee020000 0 0x400>;
- interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 328>;
+ vin4: video@e6ef4000 {
+ compatible = "renesas,vin-r8a7796";
+ reg = <0 0xe6ef4000 0 0x1000>;
+ interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 807>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 328>;
+ resets = <&cpg 807>;
+ renesas,id = <4>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin4csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin4>;
+ };
+ vin4csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin4>;
+ };
+ };
+ };
};
- ohci0: usb@ee080000 {
- compatible = "generic-ohci";
- reg = <0 0xee080000 0 0x100>;
- interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 703>;
- phys = <&usb2_phy0>;
- phy-names = "usb";
+ vin5: video@e6ef5000 {
+ compatible = "renesas,vin-r8a7796";
+ reg = <0 0xe6ef5000 0 0x1000>;
+ interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 806>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 703>;
+ resets = <&cpg 806>;
+ renesas,id = <5>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin5csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin5>;
+ };
+ vin5csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin5>;
+ };
+ };
+ };
};
- ehci0: usb@ee080100 {
- compatible = "generic-ehci";
- reg = <0 0xee080100 0 0x100>;
- interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 703>;
- phys = <&usb2_phy0>;
- phy-names = "usb";
- companion= <&ohci0>;
+ vin6: video@e6ef6000 {
+ compatible = "renesas,vin-r8a7796";
+ reg = <0 0xe6ef6000 0 0x1000>;
+ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 805>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 703>;
+ resets = <&cpg 805>;
+ renesas,id = <6>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin6csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin6>;
+ };
+ vin6csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin6>;
+ };
+ };
+ };
};
- usb2_phy0: usb-phy@ee080200 {
- compatible = "renesas,usb2-phy-r8a7796",
- "renesas,rcar-gen3-usb2-phy";
- reg = <0 0xee080200 0 0x700>;
- interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 703>;
+ vin7: video@e6ef7000 {
+ compatible = "renesas,vin-r8a7796";
+ reg = <0 0xe6ef7000 0 0x1000>;
+ interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 804>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 703>;
- #phy-cells = <0>;
+ resets = <&cpg 804>;
+ renesas,id = <7>;
status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin7csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin7>;
+ };
+ vin7csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin7>;
+ };
+ };
+ };
};
- ohci1: usb@ee0a0000 {
- compatible = "generic-ohci";
- reg = <0 0xee0a0000 0 0x100>;
- interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 702>;
- phys = <&usb2_phy1>;
- phy-names = "usb";
+ drif00: rif@e6f40000 {
+ compatible = "renesas,r8a7796-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f40000 0 0x64>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 515>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x20>, <&dmac2 0x20>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 702>;
+ resets = <&cpg 515>;
+ renesas,bonding = <&drif01>;
status = "disabled";
};
- ehci1: usb@ee0a0100 {
- compatible = "generic-ehci";
- reg = <0 0xee0a0100 0 0x100>;
- interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 702>;
- phys = <&usb2_phy1>;
- phy-names = "usb";
- companion= <&ohci1>;
+ drif01: rif@e6f50000 {
+ compatible = "renesas,r8a7796-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f50000 0 0x64>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 514>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x22>, <&dmac2 0x22>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 702>;
+ resets = <&cpg 514>;
+ renesas,bonding = <&drif00>;
status = "disabled";
};
- usb2_phy1: usb-phy@ee0a0200 {
- compatible = "renesas,usb2-phy-r8a7796",
- "renesas,rcar-gen3-usb2-phy";
- reg = <0 0xee0a0200 0 0x700>;
- clocks = <&cpg CPG_MOD 702>;
+ drif10: rif@e6f60000 {
+ compatible = "renesas,r8a7796-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f60000 0 0x64>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 513>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x24>, <&dmac2 0x24>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 702>;
- #phy-cells = <0>;
+ resets = <&cpg 513>;
+ renesas,bonding = <&drif11>;
status = "disabled";
};
- sdhi0: sd@ee100000 {
- compatible = "renesas,sdhi-r8a7796",
- "renesas,rcar-gen3-sdhi";
- reg = <0 0xee100000 0 0x2000>;
- interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 314>;
- max-frequency = <200000000>;
+ drif11: rif@e6f70000 {
+ compatible = "renesas,r8a7796-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f70000 0 0x64>;
+ interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 512>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x26>, <&dmac2 0x26>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 314>;
+ resets = <&cpg 512>;
+ renesas,bonding = <&drif10>;
status = "disabled";
};
- sdhi1: sd@ee120000 {
- compatible = "renesas,sdhi-r8a7796",
- "renesas,rcar-gen3-sdhi";
- reg = <0 0xee120000 0 0x2000>;
- interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 313>;
- max-frequency = <200000000>;
+ drif20: rif@e6f80000 {
+ compatible = "renesas,r8a7796-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f80000 0 0x64>;
+ interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 511>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x28>, <&dmac2 0x28>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 313>;
+ resets = <&cpg 511>;
+ renesas,bonding = <&drif21>;
status = "disabled";
};
- sdhi2: sd@ee140000 {
- compatible = "renesas,sdhi-r8a7796",
- "renesas,rcar-gen3-sdhi";
- reg = <0 0xee140000 0 0x2000>;
- interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 312>;
- max-frequency = <200000000>;
+ drif21: rif@e6f90000 {
+ compatible = "renesas,r8a7796-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6f90000 0 0x64>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 510>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x2a>, <&dmac2 0x2a>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 312>;
+ resets = <&cpg 510>;
+ renesas,bonding = <&drif20>;
status = "disabled";
};
- sdhi3: sd@ee160000 {
- compatible = "renesas,sdhi-r8a7796",
- "renesas,rcar-gen3-sdhi";
- reg = <0 0xee160000 0 0x2000>;
- interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 311>;
- max-frequency = <200000000>;
+ drif30: rif@e6fa0000 {
+ compatible = "renesas,r8a7796-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6fa0000 0 0x64>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 509>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x2c>, <&dmac2 0x2c>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 311>;
+ resets = <&cpg 509>;
+ renesas,bonding = <&drif31>;
status = "disabled";
};
- tsc: thermal@e6198000 {
- compatible = "renesas,r8a7796-thermal";
- reg = <0 0xe6198000 0 0x100>,
- <0 0xe61a0000 0 0x100>,
- <0 0xe61a8000 0 0x100>;
- interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 522>;
+ drif31: rif@e6fb0000 {
+ compatible = "renesas,r8a7796-drif",
+ "renesas,rcar-gen3-drif";
+ reg = <0 0xe6fb0000 0 0x64>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 508>;
+ clock-names = "fck";
+ dmas = <&dmac1 0x2e>, <&dmac2 0x2e>;
+ dma-names = "rx", "rx";
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 522>;
- #thermal-sensor-cells = <1>;
- status = "okay";
+ resets = <&cpg 508>;
+ renesas,bonding = <&drif30>;
+ status = "disabled";
};
rcar_sound: sound@ec500000 {
@@ -1848,6 +1850,261 @@
dma-names = "rx", "tx", "rxu", "txu";
};
};
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ };
+ port@1 {
+ reg = <1>;
+ };
+ };
+ };
+
+ audma0: dma-controller@ec700000 {
+ compatible = "renesas,dmac-r8a7796",
+ "renesas,rcar-dmac";
+ reg = <0 0xec700000 0 0x10000>;
+ interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15";
+ clocks = <&cpg CPG_MOD 502>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 502>;
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ iommus = <&ipmmu_mp 0>, <&ipmmu_mp 1>,
+ <&ipmmu_mp 2>, <&ipmmu_mp 3>,
+ <&ipmmu_mp 4>, <&ipmmu_mp 5>,
+ <&ipmmu_mp 6>, <&ipmmu_mp 7>,
+ <&ipmmu_mp 8>, <&ipmmu_mp 9>,
+ <&ipmmu_mp 10>, <&ipmmu_mp 11>,
+ <&ipmmu_mp 12>, <&ipmmu_mp 13>,
+ <&ipmmu_mp 14>, <&ipmmu_mp 15>;
+ };
+
+ audma1: dma-controller@ec720000 {
+ compatible = "renesas,dmac-r8a7796",
+ "renesas,rcar-dmac";
+ reg = <0 0xec720000 0 0x10000>;
+ interrupts = <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 349 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15";
+ clocks = <&cpg CPG_MOD 501>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 501>;
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ iommus = <&ipmmu_mp 16>, <&ipmmu_mp 17>,
+ <&ipmmu_mp 18>, <&ipmmu_mp 19>,
+ <&ipmmu_mp 20>, <&ipmmu_mp 21>,
+ <&ipmmu_mp 22>, <&ipmmu_mp 23>,
+ <&ipmmu_mp 24>, <&ipmmu_mp 25>,
+ <&ipmmu_mp 26>, <&ipmmu_mp 27>,
+ <&ipmmu_mp 28>, <&ipmmu_mp 29>,
+ <&ipmmu_mp 30>, <&ipmmu_mp 31>;
+ };
+
+ xhci0: usb@ee000000 {
+ compatible = "renesas,xhci-r8a7796",
+ "renesas,rcar-gen3-xhci";
+ reg = <0 0xee000000 0 0xc00>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 328>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 328>;
+ status = "disabled";
+ };
+
+ usb3_peri0: usb@ee020000 {
+ compatible = "renesas,r8a7796-usb3-peri",
+ "renesas,rcar-gen3-usb3-peri";
+ reg = <0 0xee020000 0 0x400>;
+ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 328>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 328>;
+ status = "disabled";
+ };
+
+ ohci0: usb@ee080000 {
+ compatible = "generic-ohci";
+ reg = <0 0xee080000 0 0x100>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 703>;
+ phys = <&usb2_phy0>;
+ phy-names = "usb";
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 703>;
+ status = "disabled";
+ };
+
+ ohci1: usb@ee0a0000 {
+ compatible = "generic-ohci";
+ reg = <0 0xee0a0000 0 0x100>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 702>;
+ phys = <&usb2_phy1>;
+ phy-names = "usb";
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 702>;
+ status = "disabled";
+ };
+
+ ehci0: usb@ee080100 {
+ compatible = "generic-ehci";
+ reg = <0 0xee080100 0 0x100>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 703>;
+ phys = <&usb2_phy0>;
+ phy-names = "usb";
+ companion= <&ohci0>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 703>;
+ status = "disabled";
+ };
+
+ ehci1: usb@ee0a0100 {
+ compatible = "generic-ehci";
+ reg = <0 0xee0a0100 0 0x100>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 702>;
+ phys = <&usb2_phy1>;
+ phy-names = "usb";
+ companion= <&ohci1>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 702>;
+ status = "disabled";
+ };
+
+ usb2_phy0: usb-phy@ee080200 {
+ compatible = "renesas,usb2-phy-r8a7796",
+ "renesas,rcar-gen3-usb2-phy";
+ reg = <0 0xee080200 0 0x700>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 703>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 703>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
+ usb2_phy1: usb-phy@ee0a0200 {
+ compatible = "renesas,usb2-phy-r8a7796",
+ "renesas,rcar-gen3-usb2-phy";
+ reg = <0 0xee0a0200 0 0x700>;
+ clocks = <&cpg CPG_MOD 702>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 702>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
+ sdhi0: sd@ee100000 {
+ compatible = "renesas,sdhi-r8a7796",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee100000 0 0x2000>;
+ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 314>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 314>;
+ status = "disabled";
+ };
+
+ sdhi1: sd@ee120000 {
+ compatible = "renesas,sdhi-r8a7796",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee120000 0 0x2000>;
+ interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 313>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 313>;
+ status = "disabled";
+ };
+
+ sdhi2: sd@ee140000 {
+ compatible = "renesas,sdhi-r8a7796",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee140000 0 0x2000>;
+ interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 312>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 312>;
+ status = "disabled";
+ };
+
+ sdhi3: sd@ee160000 {
+ compatible = "renesas,sdhi-r8a7796",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee160000 0 0x2000>;
+ interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 311>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 311>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@f1010000 {
+ compatible = "arm,gic-400";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x0 0xf1010000 0 0x1000>,
+ <0x0 0xf1020000 0 0x20000>,
+ <0x0 0xf1040000 0 0x20000>,
+ <0x0 0xf1060000 0 0x20000>;
+ interrupts = <GIC_PPI 9
+ (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>;
};
pciec0: pcie@fe000000 {
@@ -1860,6 +2117,26 @@
/* placeholder */
};
+ imr-lx4@fe860000 {
+ compatible = "renesas,r8a7796-imr-lx4",
+ "renesas,imr-lx4";
+ reg = <0 0xfe860000 0 0x2000>;
+ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 823>;
+ power-domains = <&sysc R8A7796_PD_A3VC>;
+ resets = <&cpg 823>;
+ };
+
+ imr-lx4@fe870000 {
+ compatible = "renesas,r8a7796-imr-lx4",
+ "renesas,imr-lx4";
+ reg = <0 0xfe870000 0 0x2000>;
+ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 822>;
+ power-domains = <&sysc R8A7796_PD_A3VC>;
+ resets = <&cpg 822>;
+ };
+
fdp1@fe940000 {
compatible = "renesas,fdp1";
reg = <0 0xfe940000 0 0x2400>;
@@ -1878,17 +2155,6 @@
resets = <&cpg 615>;
};
- vspb: vsp@fe960000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe960000 0 0x8000>;
- interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 626>;
- power-domains = <&sysc R8A7796_PD_A3VC>;
- resets = <&cpg 626>;
-
- renesas,fcp = <&fcpvb0>;
- };
-
fcpvb0: fcp@fe96f000 {
compatible = "renesas,fcpv";
reg = <0 0xfe96f000 0 0x200>;
@@ -1897,17 +2163,6 @@
resets = <&cpg 607>;
};
- vspi0: vsp@fe9a0000 {
- compatible = "renesas,vsp2";
- reg = <0 0xfe9a0000 0 0x8000>;
- interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 631>;
- power-domains = <&sysc R8A7796_PD_A3VC>;
- resets = <&cpg 631>;
-
- renesas,fcp = <&fcpvi0>;
- };
-
fcpvi0: fcp@fe9af000 {
compatible = "renesas,fcpv";
reg = <0 0xfe9af000 0 0x200>;
@@ -1917,6 +2172,44 @@
iommus = <&ipmmu_vc0 19>;
};
+ fcpvd0: fcp@fea27000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea27000 0 0x200>;
+ clocks = <&cpg CPG_MOD 603>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 603>;
+ iommus = <&ipmmu_vi0 8>;
+ };
+
+ fcpvd1: fcp@fea2f000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea2f000 0 0x200>;
+ clocks = <&cpg CPG_MOD 602>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 602>;
+ iommus = <&ipmmu_vi0 9>;
+ };
+
+ fcpvd2: fcp@fea37000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea37000 0 0x200>;
+ clocks = <&cpg CPG_MOD 601>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 601>;
+ iommus = <&ipmmu_vi0 10>;
+ };
+
+ vspb: vsp@fe960000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe960000 0 0x8000>;
+ interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 626>;
+ power-domains = <&sysc R8A7796_PD_A3VC>;
+ resets = <&cpg 626>;
+
+ renesas,fcp = <&fcpvb0>;
+ };
+
vspd0: vsp@fea20000 {
compatible = "renesas,vsp2";
reg = <0 0xfea20000 0 0x8000>;
@@ -1928,15 +2221,6 @@
renesas,fcp = <&fcpvd0>;
};
- fcpvd0: fcp@fea27000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfea27000 0 0x200>;
- clocks = <&cpg CPG_MOD 603>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 603>;
- iommus = <&ipmmu_vi0 8>;
- };
-
vspd1: vsp@fea28000 {
compatible = "renesas,vsp2";
reg = <0 0xfea28000 0 0x8000>;
@@ -1948,15 +2232,6 @@
renesas,fcp = <&fcpvd1>;
};
- fcpvd1: fcp@fea2f000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfea2f000 0 0x200>;
- clocks = <&cpg CPG_MOD 602>;
- power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 602>;
- iommus = <&ipmmu_vi0 9>;
- };
-
vspd2: vsp@fea30000 {
compatible = "renesas,vsp2";
reg = <0 0xfea30000 0 0x8000>;
@@ -1968,13 +2243,126 @@
renesas,fcp = <&fcpvd2>;
};
- fcpvd2: fcp@fea37000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfea37000 0 0x200>;
- clocks = <&cpg CPG_MOD 601>;
+ vspi0: vsp@fe9a0000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe9a0000 0 0x8000>;
+ interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 631>;
+ power-domains = <&sysc R8A7796_PD_A3VC>;
+ resets = <&cpg 631>;
+
+ renesas,fcp = <&fcpvi0>;
+ };
+
+ csi20: csi2@fea80000 {
+ compatible = "renesas,r8a7796-csi2";
+ reg = <0 0xfea80000 0 0x10000>;
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 714>;
power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
- resets = <&cpg 601>;
- iommus = <&ipmmu_vi0 10>;
+ resets = <&cpg 714>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ csi20vin0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vin0csi20>;
+ };
+ csi20vin1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&vin1csi20>;
+ };
+ csi20vin2: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&vin2csi20>;
+ };
+ csi20vin3: endpoint@3 {
+ reg = <3>;
+ remote-endpoint = <&vin3csi20>;
+ };
+ csi20vin4: endpoint@4 {
+ reg = <4>;
+ remote-endpoint = <&vin4csi20>;
+ };
+ csi20vin5: endpoint@5 {
+ reg = <5>;
+ remote-endpoint = <&vin5csi20>;
+ };
+ csi20vin6: endpoint@6 {
+ reg = <6>;
+ remote-endpoint = <&vin6csi20>;
+ };
+ csi20vin7: endpoint@7 {
+ reg = <7>;
+ remote-endpoint = <&vin7csi20>;
+ };
+ };
+ };
+ };
+
+ csi40: csi2@feaa0000 {
+ compatible = "renesas,r8a7796-csi2";
+ reg = <0 0xfeaa0000 0 0x10000>;
+ interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 716>;
+ power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+ resets = <&cpg 716>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ csi40vin0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vin0csi40>;
+ };
+ csi40vin1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&vin1csi40>;
+ };
+ csi40vin2: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&vin2csi40>;
+ };
+ csi40vin3: endpoint@3 {
+ reg = <3>;
+ remote-endpoint = <&vin3csi40>;
+ };
+ csi40vin4: endpoint@4 {
+ reg = <4>;
+ remote-endpoint = <&vin4csi40>;
+ };
+ csi40vin5: endpoint@5 {
+ reg = <5>;
+ remote-endpoint = <&vin5csi40>;
+ };
+ csi40vin6: endpoint@6 {
+ reg = <6>;
+ remote-endpoint = <&vin6csi40>;
+ };
+ csi40vin7: endpoint@7 {
+ reg = <7>;
+ remote-endpoint = <&vin7csi40>;
+ };
+ };
+
+ };
};
hdmi0: hdmi@fead0000 {
@@ -1999,6 +2387,10 @@
port@1 {
reg = <1>;
};
+ port@2 {
+ /* HDMI sound */
+ reg = <2>;
+ };
};
};
@@ -2042,35 +2434,12 @@
};
};
- imr-lx4@fe860000 {
- compatible = "renesas,r8a7796-imr-lx4",
- "renesas,imr-lx4";
- reg = <0 0xfe860000 0 0x2000>;
- interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 823>;
- power-domains = <&sysc R8A7796_PD_A3VC>;
- resets = <&cpg 823>;
- };
-
- imr-lx4@fe870000 {
- compatible = "renesas,r8a7796-imr-lx4",
- "renesas,imr-lx4";
- reg = <0 0xfe870000 0 0x2000>;
- interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 822>;
- power-domains = <&sysc R8A7796_PD_A3VC>;
- resets = <&cpg 822>;
+ prr: chipid@fff00044 {
+ compatible = "renesas,prr";
+ reg = <0 0xfff00044 0 4>;
};
};
- timer {
- compatible = "arm,armv8-timer";
- interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
- };
-
thermal-zones {
sensor_thermal1: sensor-thermal1 {
polling-delay-passive = <250>;
@@ -2080,12 +2449,12 @@
trips {
sensor1_passive: sensor1-passive {
temperature = <95000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "passive";
};
sensor1_crit: sensor1-crit {
temperature = <120000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -2106,12 +2475,12 @@
trips {
sensor2_passive: sensor2-passive {
temperature = <95000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "passive";
};
sensor2_crit: sensor2-crit {
temperature = <120000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -2132,12 +2501,12 @@
trips {
sensor3_passive: sensor3-passive {
temperature = <95000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "passive";
};
sensor3_crit: sensor3-crit {
temperature = <120000>;
- hysteresis = <2000>;
+ hysteresis = <1000>;
type = "critical";
};
};
@@ -2151,6 +2520,14 @@
};
};
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
/* External USB clocks - can be overridden by the board */
usb3s0_clk: usb3s0 {
compatible = "fixed-clock";
diff --git a/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts b/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts
index 75d890d..340a3c7 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77965-salvator-x.dts
@@ -19,3 +19,31 @@
reg = <0x0 0x48000000 0x0 0x78000000>;
};
};
+
+&du {
+ clocks = <&cpg CPG_MOD 724>,
+ <&cpg CPG_MOD 723>,
+ <&cpg CPG_MOD 721>,
+ <&versaclock5 1>,
+ <&x21_clk>,
+ <&versaclock5 2>;
+ clock-names = "du.0", "du.1", "du.3",
+ "dclkin.0", "dclkin.1", "dclkin.3";
+};
+
+&hdmi0 {
+ status = "okay";
+
+ ports {
+ port@1 {
+ reg = <1>;
+ rcar_dw_hdmi0_out: endpoint {
+ remote-endpoint = <&hdmi0_con>;
+ };
+ };
+ };
+};
+
+&hdmi0_con {
+ remote-endpoint = <&rcar_dw_hdmi0_out>;
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts b/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts
index a83a00d..9de4e3d 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77965-salvator-xs.dts
@@ -19,3 +19,31 @@
reg = <0x0 0x48000000 0x0 0x78000000>;
};
};
+
+&du {
+ clocks = <&cpg CPG_MOD 724>,
+ <&cpg CPG_MOD 723>,
+ <&cpg CPG_MOD 721>,
+ <&versaclock6 1>,
+ <&x21_clk>,
+ <&versaclock6 2>;
+ clock-names = "du.0", "du.1", "du.3",
+ "dclkin.0", "dclkin.1", "dclkin.3";
+};
+
+&hdmi0 {
+ status = "okay";
+
+ ports {
+ port@1 {
+ reg = <1>;
+ rcar_dw_hdmi0_out: endpoint {
+ remote-endpoint = <&hdmi0_con>;
+ };
+ };
+ };
+};
+
+&hdmi0_con {
+ remote-endpoint = <&rcar_dw_hdmi0_out>;
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
index f0871fc..486aeca 100644
--- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
@@ -8,8 +8,9 @@
* Copyright (C) 2016 Renesas Electronics Corp.
*/
-#include <dt-bindings/clock/renesas-cpg-mssr.h>
+#include <dt-bindings/clock/r8a77965-cpg-mssr.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/r8a77965-sysc.h>
#define CPG_AUDIO_CLK_I 10
@@ -19,12 +20,44 @@
#size-cells = <2>;
aliases {
+ i2c0 = &i2c0;
+ i2c1 = &i2c1;
+ i2c2 = &i2c2;
+ i2c3 = &i2c3;
+ i2c4 = &i2c4;
+ i2c5 = &i2c5;
+ i2c6 = &i2c6;
i2c7 = &i2c_dvfs;
};
- psci {
- compatible = "arm,psci-1.0", "arm,psci-0.2";
- method = "smc";
+ /*
+ * The external audio clocks are configured as 0 Hz fixed frequency
+ * clocks by default.
+ * Boards that provide audio clocks should override them.
+ */
+ audio_clk_a: audio_clk_a {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ audio_clk_b: audio_clk_b {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ audio_clk_c: audio_clk_c {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
+ /* External CAN clock - to be overridden by boards that provide it */
+ can_clk: can {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
};
cpus {
@@ -35,23 +68,23 @@
compatible = "arm,cortex-a57", "arm,armv8";
reg = <0x0>;
device_type = "cpu";
- power-domains = <&sysc 0>;
+ power-domains = <&sysc R8A77965_PD_CA57_CPU0>;
next-level-cache = <&L2_CA57>;
enable-method = "psci";
};
a57_1: cpu@1 {
- compatible = "arm,cortex-a57","arm,armv8";
+ compatible = "arm,cortex-a57", "arm,armv8";
reg = <0x1>;
device_type = "cpu";
- power-domains = <&sysc 1>;
+ power-domains = <&sysc R8A77965_PD_CA57_CPU1>;
next-level-cache = <&L2_CA57>;
enable-method = "psci";
};
L2_CA57: cache-controller-0 {
compatible = "cache";
- power-domains = <&sysc 12>;
+ power-domains = <&sysc R8A77965_PD_CA57_SCU>;
cache-unified;
cache-level = <2>;
};
@@ -71,34 +104,24 @@
clock-frequency = <0>;
};
- /*
- * The external audio clocks are configured as 0 Hz fixed frequency
- * clocks by default.
- * Boards that provide audio clocks should override them.
- */
- audio_clk_a: audio_clk_a {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- audio_clk_b: audio_clk_b {
+ /* External PCIe clock - can be overridden by the board */
+ pcie_bus_clk: pcie_bus {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <0>;
};
- audio_clk_c: audio_clk_c {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
+ pmu_a57 {
+ compatible = "arm,cortex-a57-pmu";
+ interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&a57_0>,
+ <&a57_1>;
};
- /* External CAN clock - to be overridden by boards that provide it */
- can_clk: can {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
+ psci {
+ compatible = "arm,psci-1.0", "arm,psci-0.2";
+ method = "smc";
};
/* External SCIF clock - to be overridden by boards that provide it */
@@ -108,42 +131,6 @@
clock-frequency = <0>;
};
- /* External PCIe clock - can be overridden by the board */
- pcie_bus_clk: pcie_bus {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- /* External USB clocks - can be overridden by the board */
- usb3s0_clk: usb3s0 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- usb_extal_clk: usb_extal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
- timer {
- compatible = "arm,armv8-timer";
- interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
- };
-
- pmu_a57 {
- compatible = "arm,cortex-a57-pmu";
- interrupts-extended = <&gic GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
- <&gic GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-affinity = <&a57_0>,
- <&a57_1>;
- };
-
soc {
compatible = "simple-bus";
interrupt-parent = <&gic>;
@@ -151,52 +138,9 @@
#size-cells = <2>;
ranges;
- gic: interrupt-controller@f1010000 {
- compatible = "arm,gic-400";
- #interrupt-cells = <3>;
- #address-cells = <0>;
- interrupt-controller;
- reg = <0x0 0xf1010000 0 0x1000>,
- <0x0 0xf1020000 0 0x20000>,
- <0x0 0xf1040000 0 0x20000>,
- <0x0 0xf1060000 0 0x20000>;
- interrupts = <GIC_PPI 9
- (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
- clocks = <&cpg CPG_MOD 408>;
- clock-names = "clk";
- power-domains = <&sysc 32>;
- resets = <&cpg 408>;
- };
-
- pfc: pin-controller@e6060000 {
- compatible = "renesas,pfc-r8a77965";
- reg = <0 0xe6060000 0 0x50c>;
- };
-
- cpg: clock-controller@e6150000 {
- compatible = "renesas,r8a77965-cpg-mssr";
- reg = <0 0xe6150000 0 0x1000>;
- clocks = <&extal_clk>, <&extalr_clk>;
- clock-names = "extal", "extalr";
- #clock-cells = <2>;
- #power-domain-cells = <0>;
- #reset-cells = <1>;
- };
-
- rst: reset-controller@e6160000 {
- compatible = "renesas,r8a77965-rst";
- reg = <0 0xe6160000 0 0x0200>;
- };
-
- prr: chipid@fff00044 {
- compatible = "renesas,prr";
- reg = <0 0xfff00044 0 4>;
- };
-
- sysc: system-controller@e6180000 {
- compatible = "renesas,r8a77965-sysc";
- reg = <0 0xe6180000 0 0x0400>;
- #power-domain-cells = <1>;
+ wdt0: watchdog@e6020000 {
+ reg = <0 0xe6020000 0 0x0c>;
+ /* placeholder */
};
gpio0: gpio@e6050000 {
@@ -210,7 +154,7 @@
#interrupt-cells = <2>;
interrupt-controller;
clocks = <&cpg CPG_MOD 912>;
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 912>;
};
@@ -225,7 +169,7 @@
#interrupt-cells = <2>;
interrupt-controller;
clocks = <&cpg CPG_MOD 911>;
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 911>;
};
@@ -240,7 +184,7 @@
#interrupt-cells = <2>;
interrupt-controller;
clocks = <&cpg CPG_MOD 910>;
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 910>;
};
@@ -255,7 +199,7 @@
#interrupt-cells = <2>;
interrupt-controller;
clocks = <&cpg CPG_MOD 909>;
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 909>;
};
@@ -270,7 +214,7 @@
#interrupt-cells = <2>;
interrupt-controller;
clocks = <&cpg CPG_MOD 908>;
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 908>;
};
@@ -285,7 +229,7 @@
#interrupt-cells = <2>;
interrupt-controller;
clocks = <&cpg CPG_MOD 907>;
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 907>;
};
@@ -300,7 +244,7 @@
#interrupt-cells = <2>;
interrupt-controller;
clocks = <&cpg CPG_MOD 906>;
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 906>;
};
@@ -315,10 +259,51 @@
#interrupt-cells = <2>;
interrupt-controller;
clocks = <&cpg CPG_MOD 905>;
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 905>;
};
+ pfc: pin-controller@e6060000 {
+ compatible = "renesas,pfc-r8a77965";
+ reg = <0 0xe6060000 0 0x50c>;
+ };
+
+ cpg: clock-controller@e6150000 {
+ compatible = "renesas,r8a77965-cpg-mssr";
+ reg = <0 0xe6150000 0 0x1000>;
+ clocks = <&extal_clk>, <&extalr_clk>;
+ clock-names = "extal", "extalr";
+ #clock-cells = <2>;
+ #power-domain-cells = <0>;
+ #reset-cells = <1>;
+ };
+
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a77965-rst";
+ reg = <0 0xe6160000 0 0x0200>;
+ };
+
+ sysc: system-controller@e6180000 {
+ compatible = "renesas,r8a77965-sysc";
+ reg = <0 0xe6180000 0 0x0400>;
+ #power-domain-cells = <1>;
+ };
+
+ tsc: thermal@e6198000 {
+ compatible = "renesas,r8a77965-thermal";
+ reg = <0 0xe6198000 0 0x100>,
+ <0 0xe61a0000 0 0x100>,
+ <0 0xe61a8000 0 0x100>;
+ interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 522>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 522>;
+ #thermal-sensor-cells = <1>;
+ status = "okay";
+ };
+
intc_ex: interrupt-controller@e61c0000 {
compatible = "renesas,intc-ex-r8a77965", "renesas,irqc";
#interrupt-cells = <2>;
@@ -331,10 +316,199 @@
GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH
GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 407>;
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 407>;
};
+ i2c0: i2c@e6500000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77965",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe6500000 0 0x40>;
+ interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 931>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 931>;
+ dmas = <&dmac1 0x91>, <&dmac1 0x90>,
+ <&dmac2 0x91>, <&dmac2 0x90>;
+ dma-names = "tx", "rx", "tx", "rx";
+ i2c-scl-internal-delay-ns = <110>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@e6508000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77965",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe6508000 0 0x40>;
+ interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 930>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 930>;
+ dmas = <&dmac1 0x93>, <&dmac1 0x92>,
+ <&dmac2 0x93>, <&dmac2 0x92>;
+ dma-names = "tx", "rx", "tx", "rx";
+ i2c-scl-internal-delay-ns = <6>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@e6510000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77965",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe6510000 0 0x40>;
+ interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 929>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 929>;
+ dmas = <&dmac1 0x95>, <&dmac1 0x94>,
+ <&dmac2 0x95>, <&dmac2 0x94>;
+ dma-names = "tx", "rx", "tx", "rx";
+ i2c-scl-internal-delay-ns = <6>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@e66d0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77965",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe66d0000 0 0x40>;
+ interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 928>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 928>;
+ dmas = <&dmac0 0x97>, <&dmac0 0x96>;
+ dma-names = "tx", "rx";
+ i2c-scl-internal-delay-ns = <110>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@e66d8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77965",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe66d8000 0 0x40>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 927>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 927>;
+ dmas = <&dmac0 0x99>, <&dmac0 0x98>;
+ dma-names = "tx", "rx";
+ i2c-scl-internal-delay-ns = <110>;
+ status = "disabled";
+ };
+
+ i2c5: i2c@e66e0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77965",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe66e0000 0 0x40>;
+ interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 919>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 919>;
+ dmas = <&dmac0 0x9b>, <&dmac0 0x9a>;
+ dma-names = "tx", "rx";
+ i2c-scl-internal-delay-ns = <110>;
+ status = "disabled";
+ };
+
+ i2c6: i2c@e66e8000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77965",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe66e8000 0 0x40>;
+ interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 918>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 918>;
+ dmas = <&dmac0 0x9d>, <&dmac0 0x9c>;
+ dma-names = "tx", "rx";
+ i2c-scl-internal-delay-ns = <6>;
+ status = "disabled";
+ };
+
+ i2c_dvfs: i2c@e60b0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,iic-r8a77965",
+ "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 R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 926>;
+ dmas = <&dmac0 0x11>, <&dmac0 0x10>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ hsusb: usb@e6590000 {
+ compatible = "renesas,usbhs-r8a7796",
+ "renesas,rcar-gen3-usbhs";
+ reg = <0 0xe6590000 0 0x100>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 704>;
+ dmas = <&usb_dmac0 0>, <&usb_dmac0 1>,
+ <&usb_dmac1 0>, <&usb_dmac1 1>;
+ dma-names = "ch0", "ch1", "ch2", "ch3";
+ renesas,buswait = <11>;
+ phys = <&usb2_phy0>;
+ phy-names = "usb";
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 704>;
+ status = "disabled";
+ };
+
+ usb_dmac0: dma-controller@e65a0000 {
+ compatible = "renesas,r8a77965-usb-dmac",
+ "renesas,usb-dmac";
+ reg = <0 0xe65a0000 0 0x100>;
+ interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1";
+ clocks = <&cpg CPG_MOD 330>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 330>;
+ #dma-cells = <1>;
+ dma-channels = <2>;
+ };
+
+ usb_dmac1: dma-controller@e65b0000 {
+ compatible = "renesas,r8a77965-usb-dmac",
+ "renesas,usb-dmac";
+ reg = <0 0xe65b0000 0 0x100>;
+ interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1";
+ clocks = <&cpg CPG_MOD 331>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 331>;
+ #dma-cells = <1>;
+ dma-channels = <2>;
+ };
+
+ usb3_phy0: usb-phy@e65ee000 {
+ compatible = "renesas,r8a77965-usb3-phy",
+ "renesas,rcar-gen3-usb3-phy";
+ reg = <0 0xe65ee000 0 0x90>;
+ clocks = <&cpg CPG_MOD 328>, <&usb3s0_clk>,
+ <&usb_extal_clk>;
+ clock-names = "usb3-if", "usb3s_clk", "usb_extal";
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 328>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
dmac0: dma-controller@e6700000 {
compatible = "renesas,dmac-r8a77965",
"renesas,rcar-dmac";
@@ -363,7 +537,7 @@
"ch12", "ch13", "ch14", "ch15";
clocks = <&cpg CPG_MOD 219>;
clock-names = "fck";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 219>;
#dma-cells = <1>;
dma-channels = <16>;
@@ -397,7 +571,7 @@
"ch12", "ch13", "ch14", "ch15";
clocks = <&cpg CPG_MOD 218>;
clock-names = "fck";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 218>;
#dma-cells = <1>;
dma-channels = <16>;
@@ -431,12 +605,127 @@
"ch12", "ch13", "ch14", "ch15";
clocks = <&cpg CPG_MOD 217>;
clock-names = "fck";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 217>;
#dma-cells = <1>;
dma-channels = <16>;
};
+ avb: ethernet@e6800000 {
+ compatible = "renesas,etheravb-r8a77965",
+ "renesas,etheravb-rcar-gen3";
+ reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
+ <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 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15",
+ "ch16", "ch17", "ch18", "ch19",
+ "ch20", "ch21", "ch22", "ch23",
+ "ch24";
+ clocks = <&cpg CPG_MOD 812>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 812>;
+ phy-mode = "rgmii";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ pwm0: pwm@e6e30000 {
+ compatible = "renesas,pwm-r8a77965", "renesas,pwm-rcar";
+ reg = <0 0xe6e30000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm1: pwm@e6e31000 {
+ compatible = "renesas,pwm-r8a77965", "renesas,pwm-rcar";
+ reg = <0 0xe6e31000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm2: pwm@e6e32000 {
+ compatible = "renesas,pwm-r8a77965", "renesas,pwm-rcar";
+ reg = <0 0xe6e32000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm3: pwm@e6e33000 {
+ compatible = "renesas,pwm-r8a77965", "renesas,pwm-rcar";
+ reg = <0 0xe6e33000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm4: pwm@e6e34000 {
+ compatible = "renesas,pwm-r8a77965", "renesas,pwm-rcar";
+ reg = <0 0xe6e34000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm5: pwm@e6e35000 {
+ compatible = "renesas,pwm-r8a77965", "renesas,pwm-rcar";
+ reg = <0 0xe6e35000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
+ pwm6: pwm@e6e36000 {
+ compatible = "renesas,pwm-r8a77965", "renesas,pwm-rcar";
+ reg = <0 0xe6e36000 0 8>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 523>;
+ resets = <&cpg 523>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ status = "disabled";
+ };
+
scif0: serial@e6e60000 {
compatible = "renesas,scif-r8a77965",
"renesas,rcar-gen3-scif", "renesas,scif";
@@ -449,7 +738,7 @@
dmas = <&dmac1 0x51>, <&dmac1 0x50>,
<&dmac2 0x51>, <&dmac2 0x50>;
dma-names = "tx", "rx", "tx", "rx";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 207>;
status = "disabled";
};
@@ -466,7 +755,7 @@
dmas = <&dmac1 0x53>, <&dmac1 0x52>,
<&dmac2 0x53>, <&dmac2 0x52>;
dma-names = "tx", "rx", "tx", "rx";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 206>;
status = "disabled";
};
@@ -480,7 +769,7 @@
<&cpg CPG_CORE 20>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 310>;
status = "disabled";
};
@@ -496,7 +785,7 @@
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac0 0x57>, <&dmac0 0x56>;
dma-names = "tx", "rx";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 204>;
status = "disabled";
};
@@ -512,7 +801,7 @@
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac0 0x59>, <&dmac0 0x58>;
dma-names = "tx", "rx";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 203>;
status = "disabled";
};
@@ -529,243 +818,772 @@
dmas = <&dmac1 0x5b>, <&dmac1 0x5a>,
<&dmac2 0x5b>, <&dmac2 0x5a>;
dma-names = "tx", "rx", "tx", "rx";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
resets = <&cpg 202>;
status = "disabled";
};
- avb: ethernet@e6800000 {
- compatible = "renesas,etheravb-r8a77965",
- "renesas,etheravb-rcar-gen3";
- reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>;
- interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
- <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 59 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14", "ch15",
- "ch16", "ch17", "ch18", "ch19",
- "ch20", "ch21", "ch22", "ch23",
- "ch24";
- clocks = <&cpg CPG_MOD 812>;
- power-domains = <&sysc 32>;
- resets = <&cpg 812>;
- phy-mode = "rgmii";
+ msiof0: spi@e6e90000 {
+ compatible = "renesas,msiof-r8a77965",
+ "renesas,rcar-gen3-msiof";
+ reg = <0 0xe6e90000 0 0x0064>;
+ interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 211>;
+ dmas = <&dmac1 0x41>, <&dmac1 0x40>,
+ <&dmac2 0x41>, <&dmac2 0x40>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 211>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
- csi20: csi2@fea80000 {
- reg = <0 0xfea80000 0 0x10000>;
- /* placeholder */
+ msiof1: spi@e6ea0000 {
+ compatible = "renesas,msiof-r8a77965",
+ "renesas,rcar-gen3-msiof";
+ reg = <0 0xe6ea0000 0 0x0064>;
+ interrupts = <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 210>;
+ dmas = <&dmac1 0x43>, <&dmac1 0x42>,
+ <&dmac2 0x43>, <&dmac2 0x42>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 210>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ msiof2: spi@e6c00000 {
+ compatible = "renesas,msiof-r8a77965",
+ "renesas,rcar-gen3-msiof";
+ reg = <0 0xe6c00000 0 0x0064>;
+ interrupts = <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 209>;
+ dmas = <&dmac0 0x45>, <&dmac0 0x44>;
+ dma-names = "tx", "rx";
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 209>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ msiof3: spi@e6c10000 {
+ compatible = "renesas,msiof-r8a77965",
+ "renesas,rcar-gen3-msiof";
+ reg = <0 0xe6c10000 0 0x0064>;
+ interrupts = <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 208>;
+ dmas = <&dmac0 0x47>, <&dmac0 0x46>;
+ dma-names = "tx", "rx";
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 208>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ vin0: video@e6ef0000 {
+ compatible = "renesas,vin-r8a77965";
+ reg = <0 0xe6ef0000 0 0x1000>;
+ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 811>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 811>;
+ renesas,id = <0>;
+ status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin0csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin0>;
+ };
+ vin0csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin0>;
+ };
+ };
};
};
- csi40: csi2@feaa0000 {
- reg = <0 0xfeaa0000 0 0x10000>;
- /* placeholder */
+ vin1: video@e6ef1000 {
+ compatible = "renesas,vin-r8a77965";
+ reg = <0 0xe6ef1000 0 0x1000>;
+ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 810>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 810>;
+ renesas,id = <1>;
+ status = "disabled";
ports {
#address-cells = <1>;
#size-cells = <0>;
- };
- };
- vin0: video@e6ef0000 {
- reg = <0 0xe6ef0000 0 0x1000>;
- /* placeholder */
- };
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
- vin1: video@e6ef1000 {
- reg = <0 0xe6ef1000 0 0x1000>;
- /* placeholder */
+ reg = <1>;
+
+ vin1csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin1>;
+ };
+ vin1csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin1>;
+ };
+ };
+ };
};
vin2: video@e6ef2000 {
+ compatible = "renesas,vin-r8a77965";
reg = <0 0xe6ef2000 0 0x1000>;
- /* placeholder */
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 809>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 809>;
+ renesas,id = <2>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin2csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin2>;
+ };
+ vin2csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin2>;
+ };
+ };
+ };
};
vin3: video@e6ef3000 {
+ compatible = "renesas,vin-r8a77965";
reg = <0 0xe6ef3000 0 0x1000>;
- /* placeholder */
+ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 808>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 808>;
+ renesas,id = <3>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin3csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin3>;
+ };
+ vin3csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin3>;
+ };
+ };
+ };
};
vin4: video@e6ef4000 {
+ compatible = "renesas,vin-r8a77965";
reg = <0 0xe6ef4000 0 0x1000>;
- /* placeholder */
+ interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 807>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 807>;
+ renesas,id = <4>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin4csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin4>;
+ };
+ vin4csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin4>;
+ };
+ };
+ };
};
vin5: video@e6ef5000 {
+ compatible = "renesas,vin-r8a77965";
reg = <0 0xe6ef5000 0 0x1000>;
- /* placeholder */
+ interrupts = <GIC_SPI 175 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 806>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 806>;
+ renesas,id = <5>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin5csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin5>;
+ };
+ vin5csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin5>;
+ };
+ };
+ };
};
vin6: video@e6ef6000 {
+ compatible = "renesas,vin-r8a77965";
reg = <0 0xe6ef6000 0 0x1000>;
- /* placeholder */
+ interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 805>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 805>;
+ renesas,id = <6>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin6csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin6>;
+ };
+ vin6csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin6>;
+ };
+ };
+ };
};
vin7: video@e6ef7000 {
+ compatible = "renesas,vin-r8a77965";
reg = <0 0xe6ef7000 0 0x1000>;
+ interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 804>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 804>;
+ renesas,id = <7>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin7csi20: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi20vin7>;
+ };
+ vin7csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin7>;
+ };
+ };
+ };
+ };
+
+ rcar_sound: sound@ec500000 {
+ reg = <0 0xec500000 0 0x1000>, /* SCU */
+ <0 0xec5a0000 0 0x100>, /* ADG */
+ <0 0xec540000 0 0x1000>, /* SSIU */
+ <0 0xec541000 0 0x280>, /* SSI */
+ <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/
/* placeholder */
+
+ rcar_sound,dvc {
+ dvc0: dvc-0 {
+ };
+ dvc1: dvc-1 {
+ };
+ };
+
+ rcar_sound,src {
+ src0: src-0 {
+ };
+ src1: src-1 {
+ };
+ };
+
+ rcar_sound,ssi {
+ ssi0: ssi-0 {
+ };
+ ssi1: ssi-1 {
+ };
+ };
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ };
+ };
+ };
+
+ xhci0: usb@ee000000 {
+ compatible = "renesas,xhci-r8a77965",
+ "renesas,rcar-gen3-xhci";
+ reg = <0 0xee000000 0 0xc00>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 328>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 328>;
+ status = "disabled";
+ };
+
+ usb3_peri0: usb@ee020000 {
+ compatible = "renesas,r8a77965-usb3-peri",
+ "renesas,rcar-gen3-usb3-peri";
+ reg = <0 0xee020000 0 0x400>;
+ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 328>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 328>;
+ status = "disabled";
};
ohci0: usb@ee080000 {
+ compatible = "generic-ohci";
reg = <0 0xee080000 0 0x100>;
- /* placeholder */
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 703>;
+ phys = <&usb2_phy0>;
+ phy-names = "usb";
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 703>;
+ status = "disabled";
+ };
+
+ ohci1: usb@ee0a0000 {
+ compatible = "generic-ohci";
+ reg = <0 0xee0a0000 0 0x100>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 702>;
+ phys = <&usb2_phy1>;
+ phy-names = "usb";
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 702>;
+ status = "disabled";
};
ehci0: usb@ee080100 {
+ compatible = "generic-ehci";
reg = <0 0xee080100 0 0x100>;
- /* placeholder */
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 703>;
+ phys = <&usb2_phy0>;
+ phy-names = "usb";
+ companion = <&ohci0>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 703>;
+ status = "disabled";
+ };
+
+ ehci1: usb@ee0a0100 {
+ compatible = "generic-ehci";
+ reg = <0 0xee0a0100 0 0x100>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 702>;
+ phys = <&usb2_phy1>;
+ phy-names = "usb";
+ companion = <&ohci1>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 702>;
+ status = "disabled";
};
usb2_phy0: usb-phy@ee080200 {
+ compatible = "renesas,usb2-phy-r8a77965",
+ "renesas,rcar-gen3-usb2-phy";
reg = <0 0xee080200 0 0x700>;
- /* placeholder */
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 703>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 703>;
+ #phy-cells = <0>;
+ status = "disabled";
};
usb2_phy1: usb-phy@ee0a0200 {
+ compatible = "renesas,usb2-phy-r8a77965",
+ "renesas,rcar-gen3-usb2-phy";
reg = <0 0xee0a0200 0 0x700>;
- /* placeholder */
+ clocks = <&cpg CPG_MOD 703>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 703>;
+ #phy-cells = <0>;
+ status = "disabled";
};
- ohci1: usb@ee0a0000 {
- reg = <0 0xee0a0000 0 0x100>;
- /* placeholder */
+ sdhi0: sd@ee100000 {
+ compatible = "renesas,sdhi-r8a77965",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee100000 0 0x2000>;
+ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 314>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 314>;
+ status = "disabled";
};
- ehci1: usb@ee0a0100 {
- reg = <0 0xee0a0100 0 0x100>;
- /* placeholder */
+ sdhi1: sd@ee120000 {
+ compatible = "renesas,sdhi-r8a77965",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee120000 0 0x2000>;
+ interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 313>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 313>;
+ status = "disabled";
};
- i2c0: i2c@e6500000 {
- reg = <0 0xe6500000 0 0x40>;
- /* placeholder */
+ sdhi2: sd@ee140000 {
+ compatible = "renesas,sdhi-r8a77965",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee140000 0 0x2000>;
+ interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 312>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 312>;
+ status = "disabled";
};
- i2c1: i2c@e6508000 {
- reg = <0 0xe6508000 0 0x40>;
- /* placeholder */
+ sdhi3: sd@ee160000 {
+ compatible = "renesas,sdhi-r8a77965",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee160000 0 0x2000>;
+ interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 311>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 311>;
+ status = "disabled";
};
- i2c2: i2c@e6510000 {
- #address-cells = <1>;
- #size-cells = <0>;
+ gic: interrupt-controller@f1010000 {
+ compatible = "arm,gic-400";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x0 0xf1010000 0 0x1000>,
+ <0x0 0xf1020000 0 0x20000>,
+ <0x0 0xf1040000 0 0x20000>,
+ <0x0 0xf1060000 0 0x20000>;
+ interrupts = <GIC_PPI 9
+ (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+ clocks = <&cpg CPG_MOD 408>;
+ clock-names = "clk";
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 408>;
+ };
- reg = <0 0xe6510000 0 0x40>;
+ pciec0: pcie@fe000000 {
+ reg = <0 0xfe000000 0 0x80000>;
/* placeholder */
};
- i2c3: i2c@e66d0000 {
- reg = <0 0xe66d0000 0 0x40>;
+ pciec1: pcie@ee800000 {
+ reg = <0 0xee800000 0 0x80000>;
/* placeholder */
};
- i2c4: i2c@e66d8000 {
- #address-cells = <1>;
- #size-cells = <0>;
+ fcpf0: fcp@fe950000 {
+ compatible = "renesas,fcpf";
+ reg = <0 0xfe950000 0 0x200>;
+ clocks = <&cpg CPG_MOD 615>;
+ power-domains = <&sysc R8A77965_PD_A3VP>;
+ resets = <&cpg 615>;
+ };
- reg = <0 0xe66d8000 0 0x40>;
- /* placeholder */
+ vspb: vsp@fe960000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe960000 0 0x8000>;
+ interrupts = <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 626>;
+ power-domains = <&sysc R8A77965_PD_A3VP>;
+ resets = <&cpg 626>;
+
+ renesas,fcp = <&fcpvb0>;
};
- i2c5: i2c@e66e0000 {
- reg = <0 0xe66e0000 0 0x40>;
- /* placeholder */
+ fcpvb0: fcp@fe96f000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfe96f000 0 0x200>;
+ clocks = <&cpg CPG_MOD 607>;
+ power-domains = <&sysc R8A77965_PD_A3VP>;
+ resets = <&cpg 607>;
};
- i2c6: i2c@e66e8000 {
- reg = <0 0xe66e8000 0 0x40>;
- /* placeholder */
+ vspi0: vsp@fe9a0000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfe9a0000 0 0x8000>;
+ interrupts = <GIC_SPI 444 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 631>;
+ power-domains = <&sysc R8A77965_PD_A3VP>;
+ resets = <&cpg 631>;
+
+ renesas,fcp = <&fcpvi0>;
};
- i2c_dvfs: i2c@e60b0000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,iic-r8a77965",
- "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 32>;
- resets = <&cpg 926>;
- dmas = <&dmac0 0x11>, <&dmac0 0x10>;
- dma-names = "tx", "rx";
- status = "disabled";
+ fcpvi0: fcp@fe9af000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfe9af000 0 0x200>;
+ clocks = <&cpg CPG_MOD 611>;
+ power-domains = <&sysc R8A77965_PD_A3VP>;
+ resets = <&cpg 611>;
};
- pwm0: pwm@e6e30000 {
- reg = <0 0xe6e30000 0 8>;
- /* placeholder */
+ vspd0: vsp@fea20000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfea20000 0 0x8000>;
+ interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 623>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 623>;
+
+ renesas,fcp = <&fcpvd0>;
};
- pwm1: pwm@e6e31000 {
- reg = <0 0xe6e31000 0 8>;
- #pwm-cells = <2>;
- /* placeholder */
+ fcpvd0: fcp@fea27000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea27000 0 0x200>;
+ clocks = <&cpg CPG_MOD 603>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 603>;
};
- pwm2: pwm@e6e32000 {
- reg = <0 0xe6e32000 0 8>;
- /* placeholder */
+ vspd1: vsp@fea28000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfea28000 0 0x8000>;
+ interrupts = <GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 622>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 622>;
+
+ renesas,fcp = <&fcpvd1>;
};
- pwm3: pwm@e6e33000 {
- reg = <0 0xe6e33000 0 8>;
- /* placeholder */
+ fcpvd1: fcp@fea2f000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea2f000 0 0x200>;
+ clocks = <&cpg CPG_MOD 602>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 602>;
};
- pwm4: pwm@e6e34000 {
- reg = <0 0xe6e34000 0 8>;
- /* placeholder */
+ csi20: csi2@fea80000 {
+ compatible = "renesas,r8a77965-csi2";
+ reg = <0 0xfea80000 0 0x10000>;
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 714>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 714>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ csi20vin0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vin0csi20>;
+ };
+ csi20vin1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&vin1csi20>;
+ };
+ csi20vin2: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&vin2csi20>;
+ };
+ csi20vin3: endpoint@3 {
+ reg = <3>;
+ remote-endpoint = <&vin3csi20>;
+ };
+ csi20vin4: endpoint@4 {
+ reg = <4>;
+ remote-endpoint = <&vin4csi20>;
+ };
+ csi20vin5: endpoint@5 {
+ reg = <5>;
+ remote-endpoint = <&vin5csi20>;
+ };
+ csi20vin6: endpoint@6 {
+ reg = <6>;
+ remote-endpoint = <&vin6csi20>;
+ };
+ csi20vin7: endpoint@7 {
+ reg = <7>;
+ remote-endpoint = <&vin7csi20>;
+ };
+ };
+ };
};
- pwm5: pwm@e6e35000 {
- reg = <0 0xe6e35000 0 8>;
- /* placeholder */
+ csi40: csi2@feaa0000 {
+ compatible = "renesas,r8a77965-csi2";
+ reg = <0 0xfeaa0000 0 0x10000>;
+ interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 716>;
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 716>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ csi40vin0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vin0csi40>;
+ };
+ csi40vin1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&vin1csi40>;
+ };
+ csi40vin2: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&vin2csi40>;
+ };
+ csi40vin3: endpoint@3 {
+ reg = <3>;
+ remote-endpoint = <&vin3csi40>;
+ };
+ csi40vin4: endpoint@4 {
+ reg = <4>;
+ remote-endpoint = <&vin4csi40>;
+ };
+ csi40vin5: endpoint@5 {
+ reg = <5>;
+ remote-endpoint = <&vin5csi40>;
+ };
+ csi40vin6: endpoint@6 {
+ reg = <6>;
+ remote-endpoint = <&vin6csi40>;
+ };
+ csi40vin7: endpoint@7 {
+ reg = <7>;
+ remote-endpoint = <&vin7csi40>;
+ };
+ };
+ };
};
- pwm6: pwm@e6e36000 {
- reg = <0 0xe6e36000 0 8>;
- /* placeholder */
+ hdmi0: hdmi@fead0000 {
+ compatible = "renesas,r8a77965-hdmi",
+ "renesas,rcar-gen3-hdmi";
+ reg = <0 0xfead0000 0 0x10000>;
+ interrupts = <GIC_SPI 389 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 729>,
+ <&cpg CPG_CORE R8A77965_CLK_HDMI>;
+ clock-names = "iahb", "isfr";
+ power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
+ resets = <&cpg 729>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ dw_hdmi0_in: endpoint {
+ remote-endpoint = <&du_out_hdmi0>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ };
+ };
};
du: display@feb00000 {
- reg = <0 0xfeb00000 0 0x80000>,
- <0 0xfeb90000 0 0x14>;
- /* placeholder */
+ compatible = "renesas,du-r8a77965";
+ reg = <0 0xfeb00000 0 0x80000>;
+ reg-names = "du";
+ interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 724>,
+ <&cpg CPG_MOD 723>,
+ <&cpg CPG_MOD 721>;
+ clock-names = "du.0", "du.1", "du.3";
+ status = "disabled";
+
+ vsps = <&vspd0 0 &vspd1 0 &vspd0 1>;
ports {
#address-cells = <1>;
@@ -779,6 +1597,7 @@
port@1 {
reg = <1>;
du_out_hdmi0: endpoint {
+ remote-endpoint = <&dw_hdmi0_in>;
};
};
port@2 {
@@ -789,90 +1608,74 @@
};
};
- hsusb: usb@e6590000 {
- reg = <0 0xe6590000 0 0x100>;
- /* placeholder */
- };
-
- pciec0: pcie@fe000000 {
- reg = <0 0xfe000000 0 0x80000>;
- /* placeholder */
- };
-
- pciec1: pcie@ee800000 {
- reg = <0 0xee800000 0 0x80000>;
- /* placeholder */
+ prr: chipid@fff00044 {
+ compatible = "renesas,prr";
+ reg = <0 0xfff00044 0 4>;
};
+ };
- rcar_sound: sound@ec500000 {
- reg = <0 0xec500000 0 0x1000>, /* SCU */
- <0 0xec5a0000 0 0x100>, /* ADG */
- <0 0xec540000 0 0x1000>, /* SSIU */
- <0 0xec541000 0 0x280>, /* SSI */
- <0 0xec740000 0 0x200>; /* Audio DMAC peri peri*/
- /* placeholder */
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
+ };
- rcar_sound,dvc {
- dvc0: dvc-0 {
- };
- dvc1: dvc-1 {
+ thermal-zones {
+ sensor_thermal1: sensor-thermal1 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&tsc 0>;
+
+ trips {
+ sensor1_crit: sensor1-crit {
+ temperature = <120000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
+ };
- rcar_sound,src {
- src0: src-0 {
- };
- src1: src-1 {
- };
- };
+ sensor_thermal2: sensor-thermal2 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&tsc 1>;
- rcar_sound,ssi {
- ssi0: ssi-0 {
- };
- ssi1: ssi-1 {
+ trips {
+ sensor2_crit: sensor2-crit {
+ temperature = <120000>;
+ hysteresis = <1000>;
+ type = "critical";
};
};
};
- sdhi0: sd@ee100000 {
- reg = <0 0xee100000 0 0x2000>;
- /* placeholder */
- };
-
- sdhi1: sd@ee120000 {
- reg = <0 0xee120000 0 0x2000>;
- /* placeholder */
- };
+ sensor_thermal3: sensor-thermal3 {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&tsc 2>;
- sdhi2: sd@ee140000 {
- reg = <0 0xee140000 0 0x2000>;
- /* placeholder */
- };
-
- sdhi3: sd@ee160000 {
- reg = <0 0xee160000 0 0x2000>;
- /* placeholder */
- };
-
- usb3_phy0: usb-phy@e65ee000 {
- reg = <0 0xe65ee000 0 0x90>;
- #phy-cells = <0>;
- /* placeholder */
- };
-
- usb3_peri0: usb@ee020000 {
- reg = <0 0xee020000 0 0x400>;
- /* placeholder */
+ trips {
+ sensor3_crit: sensor3-crit {
+ temperature = <120000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
};
+ };
- xhci0: usb@ee000000 {
- reg = <0 0xee000000 0 0xc00>;
- /* placeholder */
- };
+ /* External USB clocks - can be overridden by the board */
+ usb3s0_clk: usb3s0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
- wdt0: watchdog@e6020000 {
- reg = <0 0xe6020000 0 0x0c>;
- /* placeholder */
- };
+ usb_extal_clk: usb_extal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
index 3c5f598..21f9cf5 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77970-eagle.dts
@@ -31,9 +31,57 @@
/* first 128MB is reserved for secure area. */
reg = <0x0 0x48000000 0x0 0x38000000>;
};
+
+ hdmi-out {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_out: endpoint {
+ remote-endpoint = <&adv7511_out>;
+ };
+ };
+ };
+
+ d3p3: regulator-fixed {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ lvds-decoder {
+ compatible = "thine,thc63lvd1024";
+
+ vcc-supply = <&d3p3>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ thc63lvd1024_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ thc63lvd1024_out: endpoint {
+ remote-endpoint = <&adv7511_in>;
+ };
+ };
+ };
+ };
};
&avb {
+ pinctrl-0 = <&avb_pins>;
+ pinctrl-names = "default";
+
renesas,no-ether-link;
phy-handle = <&phy0>;
phy-mode = "rgmii-id";
@@ -47,6 +95,16 @@
};
};
+&canfd {
+ pinctrl-0 = <&canfd0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ channel0 {
+ status = "okay";
+ };
+};
+
&extal_clk {
clock-frequency = <16666666>;
};
@@ -68,9 +126,51 @@
gpio-controller;
#gpio-cells = <2>;
};
+
+ hdmi@39 {
+ compatible = "adi,adv7511w";
+ reg = <0x39>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+
+ adi,input-depth = <8>;
+ adi,input-colorspace = "rgb";
+ adi,input-clock = "1x";
+ adi,input-style = <1>;
+ adi,input-justification = "evenly";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ adv7511_in: endpoint {
+ remote-endpoint = <&thc63lvd1024_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ adv7511_out: endpoint {
+ remote-endpoint = <&hdmi_con_out>;
+ };
+ };
+ };
+ };
};
&pfc {
+ avb_pins: avb0 {
+ groups = "avb0_mdio", "avb0_rgmii", "avb0_txcrefclk";
+ function = "avb0";
+ };
+
+ canfd0_pins: canfd0 {
+ groups = "canfd0_data_a";
+ function = "canfd0";
+ };
+
i2c0_pins: i2c0 {
groups = "i2c0";
function = "i2c0";
@@ -93,3 +193,19 @@
status = "okay";
};
+
+&du {
+ status = "okay";
+};
+
+&lvds0 {
+ status = "okay";
+
+ ports {
+ port@1 {
+ lvds0_out: endpoint {
+ remote-endpoint = <&thc63lvd1024_in>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
index a8ceeac..9fce031 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts
@@ -29,9 +29,71 @@
/* first 128MB is reserved for secure area. */
reg = <0x0 0x48000000 0x0 0x38000000>;
};
+
+ osc5_clk: osc5-clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <148500000>;
+ };
+
+ vcc_d1_8v: regulator-0 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_D1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vcc_d3_3v: regulator-1 {
+ compatible = "regulator-fixed";
+ regulator-name = "VCC_D3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ lvds-decoder {
+ compatible = "thine,thc63lvd1024";
+ vcc-supply = <&vcc_d3_3v>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ thc63lvd1024_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ thc63lvd1024_out: endpoint {
+ remote-endpoint = <&adv7511_in>;
+ };
+ };
+ };
+ };
+
+ hdmi-out {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con: endpoint {
+ remote-endpoint = <&adv7511_out>;
+ };
+ };
+ };
};
&avb {
+ pinctrl-0 = <&avb_pins>;
+ pinctrl-names = "default";
+
renesas,no-ether-link;
phy-handle = <&phy0>;
phy-mode = "rgmii-id";
@@ -43,6 +105,13 @@
};
};
+&du {
+ clocks = <&cpg CPG_MOD 724>,
+ <&osc5_clk>;
+ clock-names = "du.0", "dclkin.0";
+ status = "okay";
+};
+
&extal_clk {
clock-frequency = <16666666>;
};
@@ -52,12 +121,80 @@
};
&pfc {
+ avb_pins: avb0 {
+ groups = "avb0_mdio", "avb0_rgmii", "avb0_txcrefclk";
+ function = "avb0";
+ };
+
+ i2c0_pins: i2c0 {
+ groups = "i2c0";
+ function = "i2c0";
+ };
+
scif0_pins: scif0 {
groups = "scif0_data";
function = "scif0";
};
};
+&i2c0 {
+ pinctrl-0 = <&i2c0_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+ clock-frequency = <400000>;
+
+ hdmi@39{
+ compatible = "adi,adv7511w";
+ #sound-dai-cells = <0>;
+ reg = <0x39>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+ avdd-supply = <&vcc_d1_8v>;
+ dvdd-supply = <&vcc_d1_8v>;
+ pvdd-supply = <&vcc_d1_8v>;
+ bgvdd-supply = <&vcc_d1_8v>;
+ dvdd-3v-supply = <&vcc_d3_3v>;
+
+ adi,input-depth = <8>;
+ adi,input-colorspace = "rgb";
+ adi,input-clock = "1x";
+ adi,input-style = <1>;
+ adi,input-justification = "evenly";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ adv7511_in: endpoint {
+ remote-endpoint = <&thc63lvd1024_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ adv7511_out: endpoint {
+ remote-endpoint = <&hdmi_con>;
+ };
+ };
+ };
+ };
+};
+
+&lvds0 {
+ status = "okay";
+
+ ports {
+ port@1 {
+ lvds0_out: endpoint {
+ remote-endpoint = <&thc63lvd1024_in>;
+ };
+ };
+ };
+};
+
&scif0 {
pinctrl-0 = <&scif0_pins>;
pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/renesas/r8a77970.dtsi b/arch/arm64/boot/dts/renesas/r8a77970.dtsi
index c6db8ea..98a2317 100644
--- a/arch/arm64/boot/dts/renesas/r8a77970.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77970.dtsi
@@ -41,6 +41,16 @@
enable-method = "psci";
};
+ a53_1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <1>;
+ clocks = <&cpg CPG_CORE R8A77970_CLK_Z2>;
+ power-domains = <&sysc R8A77970_PD_CA53_CPU1>;
+ next-level-cache = <&L2_CA53>;
+ enable-method = "psci";
+ };
+
L2_CA53: cache-controller {
compatible = "cache";
power-domains = <&sysc R8A77970_PD_CA53_SCU>;
@@ -63,11 +73,25 @@
clock-frequency = <0>;
};
+ pmu_a53 {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+ <&gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&a53_0>, <&a53_1>;
+ };
+
psci {
compatible = "arm,psci-1.0", "arm,psci-0.2";
method = "smc";
};
+ /* External CAN clock - to be overridden by boards that provide it */
+ can_clk: can {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
/* External SCIF clock - to be overridden by boards that provide it */
scif_clk: scif {
compatible = "fixed-clock";
@@ -83,23 +107,6 @@
#size-cells = <2>;
ranges;
- gic: interrupt-controller@f1010000 {
- compatible = "arm,gic-400";
- #interrupt-cells = <3>;
- #address-cells = <0>;
- interrupt-controller;
- reg = <0 0xf1010000 0 0x1000>,
- <0 0xf1020000 0 0x20000>,
- <0 0xf1040000 0 0x20000>,
- <0 0xf1060000 0 0x20000>;
- interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) |
- IRQ_TYPE_LEVEL_HIGH)>;
- clocks = <&cpg CPG_MOD 408>;
- clock-names = "clk";
- power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
- resets = <&cpg 408>;
- };
-
rwdt: watchdog@e6020000 {
compatible = "renesas,r8a77970-wdt",
"renesas,rcar-gen3-wdt";
@@ -110,75 +117,6 @@
status = "disabled";
};
- cpg: clock-controller@e6150000 {
- compatible = "renesas,r8a77970-cpg-mssr";
- reg = <0 0xe6150000 0 0x1000>;
- clocks = <&extal_clk>, <&extalr_clk>;
- clock-names = "extal", "extalr";
- #clock-cells = <2>;
- #power-domain-cells = <0>;
- #reset-cells = <1>;
- };
-
- rst: reset-controller@e6160000 {
- compatible = "renesas,r8a77970-rst";
- reg = <0 0xe6160000 0 0x200>;
- };
-
- sysc: system-controller@e6180000 {
- compatible = "renesas,r8a77970-sysc";
- reg = <0 0xe6180000 0 0x440>;
- #power-domain-cells = <1>;
- };
-
- ipmmu_vi0: mmu@febd0000 {
- compatible = "renesas,ipmmu-r8a77970";
- reg = <0 0xfebd0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 9>;
- power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_ir: mmu@ff8b0000 {
- compatible = "renesas,ipmmu-r8a77970";
- reg = <0 0xff8b0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 3>;
- power-domains = <&sysc R8A77970_PD_A3IR>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_rt: mmu@ffc80000 {
- compatible = "renesas,ipmmu-r8a77970";
- reg = <0 0xffc80000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 7>;
- power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- };
-
- ipmmu_ds1: mmu@e7740000 {
- compatible = "renesas,ipmmu-r8a77970";
- reg = <0 0xe7740000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 1>;
- power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- };
-
- ipmmu_mm: mmu@e67b0000 {
- compatible = "renesas,ipmmu-r8a77970";
- reg = <0 0xe67b0000 0 0x1000>;
- interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
- power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
- #iommu-cells = <1>;
- };
-
- pfc: pin-controller@e6060000 {
- compatible = "renesas,pfc-r8a77970";
- reg = <0 0xe6060000 0 0x504>;
- };
-
gpio0: gpio@e6050000 {
compatible = "renesas,gpio-r8a77970",
"renesas,rcar-gen3-gpio";
@@ -269,6 +207,32 @@
resets = <&cpg 907>;
};
+ pfc: pin-controller@e6060000 {
+ compatible = "renesas,pfc-r8a77970";
+ reg = <0 0xe6060000 0 0x504>;
+ };
+
+ cpg: clock-controller@e6150000 {
+ compatible = "renesas,r8a77970-cpg-mssr";
+ reg = <0 0xe6150000 0 0x1000>;
+ clocks = <&extal_clk>, <&extalr_clk>;
+ clock-names = "extal", "extalr";
+ #clock-cells = <2>;
+ #power-domain-cells = <0>;
+ #reset-cells = <1>;
+ };
+
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a77970-rst";
+ reg = <0 0xe6160000 0 0x200>;
+ };
+
+ sysc: system-controller@e6180000 {
+ compatible = "renesas,r8a77970-sysc";
+ reg = <0 0xe6180000 0 0x440>;
+ #power-domain-cells = <1>;
+ };
+
intc_ex: interrupt-controller@e61c0000 {
compatible = "renesas,intc-ex-r8a77970", "renesas,irqc";
#interrupt-cells = <2>;
@@ -285,67 +249,6 @@
resets = <&cpg 407>;
};
- prr: chipid@fff00044 {
- compatible = "renesas,prr";
- reg = <0 0xfff00044 0 4>;
- };
-
- dmac1: dma-controller@e7300000 {
- compatible = "renesas,dmac-r8a77970",
- "renesas,rcar-dmac";
- reg = <0 0xe7300000 0 0x10000>;
- interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7";
- clocks = <&cpg CPG_MOD 218>;
- clock-names = "fck";
- power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
- resets = <&cpg 218>;
- #dma-cells = <1>;
- dma-channels = <8>;
- iommus = <&ipmmu_ds1 0>, <&ipmmu_ds1 1>,
- <&ipmmu_ds1 2>, <&ipmmu_ds1 3>,
- <&ipmmu_ds1 4>, <&ipmmu_ds1 5>,
- <&ipmmu_ds1 6>, <&ipmmu_ds1 7>;
- };
-
- dmac2: dma-controller@e7310000 {
- compatible = "renesas,dmac-r8a77970",
- "renesas,rcar-dmac";
- reg = <0 0xe7310000 0 0x10000>;
- interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7";
- clocks = <&cpg CPG_MOD 217>;
- clock-names = "fck";
- power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
- resets = <&cpg 217>;
- #dma-cells = <1>;
- dma-channels = <8>;
- iommus = <&ipmmu_ds1 16>, <&ipmmu_ds1 17>,
- <&ipmmu_ds1 18>, <&ipmmu_ds1 19>,
- <&ipmmu_ds1 20>, <&ipmmu_ds1 21>,
- <&ipmmu_ds1 22>, <&ipmmu_ds1 23>;
- };
-
i2c0: i2c@e6500000 {
compatible = "renesas,i2c-r8a77970",
"renesas,rcar-gen3-i2c";
@@ -502,6 +405,77 @@
status = "disabled";
};
+ canfd: can@e66c0000 {
+ compatible = "renesas,r8a77970-canfd",
+ "renesas,rcar-gen3-canfd";
+ reg = <0 0xe66c0000 0 0x8000>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 914>,
+ <&cpg CPG_CORE R8A77970_CLK_CANFD>,
+ <&can_clk>;
+ clock-names = "fck", "canfd", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A77970_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 914>;
+ status = "disabled";
+
+ channel0 {
+ status = "disabled";
+ };
+
+ channel1 {
+ status = "disabled";
+ };
+ };
+
+ avb: ethernet@e6800000 {
+ compatible = "renesas,etheravb-r8a77970",
+ "renesas,etheravb-rcar-gen3";
+ reg = <0 0xe6800000 0 0x800>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
+ <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 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15",
+ "ch16", "ch17", "ch18", "ch19",
+ "ch20", "ch21", "ch22", "ch23",
+ "ch24";
+ clocks = <&cpg CPG_MOD 812>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 812>;
+ phy-mode = "rgmii";
+ iommus = <&ipmmu_rt 3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
scif0: serial@e6e60000 {
compatible = "renesas,scif-r8a77970",
"renesas,rcar-gen3-scif",
@@ -573,57 +547,358 @@
status = "disabled";
};
- avb: ethernet@e6800000 {
- compatible = "renesas,etheravb-r8a77970",
- "renesas,etheravb-rcar-gen3";
- reg = <0 0xe6800000 0 0x800>;
- interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
- <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 59 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7",
- "ch8", "ch9", "ch10", "ch11",
- "ch12", "ch13", "ch14", "ch15",
- "ch16", "ch17", "ch18", "ch19",
- "ch20", "ch21", "ch22", "ch23",
- "ch24";
- clocks = <&cpg CPG_MOD 812>;
+
+ vin0: video@e6ef0000 {
+ compatible = "renesas,vin-r8a77970";
+ reg = <0 0xe6ef0000 0 0x1000>;
+ interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 811>;
power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
- resets = <&cpg 812>;
- phy-mode = "rgmii";
- iommus = <&ipmmu_rt 3>;
- #address-cells = <1>;
- #size-cells = <0>;
+ resets = <&cpg 811>;
+ renesas,id = <0>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin0csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin0>;
+ };
+ };
+ };
+ };
+
+ vin1: video@e6ef1000 {
+ compatible = "renesas,vin-r8a77970";
+ reg = <0 0xe6ef1000 0 0x1000>;
+ interrupts = <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 810>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 810>;
+ renesas,id = <1>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin1csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin1>;
+ };
+ };
+ };
+ };
+
+ vin2: video@e6ef2000 {
+ compatible = "renesas,vin-r8a77970";
+ reg = <0 0xe6ef2000 0 0x1000>;
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 809>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 809>;
+ renesas,id = <2>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin2csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin2>;
+ };
+ };
+ };
+ };
+
+ vin3: video@e6ef3000 {
+ compatible = "renesas,vin-r8a77970";
+ reg = <0 0xe6ef3000 0 0x1000>;
+ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 808>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 808>;
+ renesas,id = <3>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ vin3csi40: endpoint@2 {
+ reg = <2>;
+ remote-endpoint= <&csi40vin3>;
+ };
+ };
+ };
+ };
+
+ dmac1: dma-controller@e7300000 {
+ compatible = "renesas,dmac-r8a77970",
+ "renesas,rcar-dmac";
+ reg = <0 0xe7300000 0 0x10000>;
+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7";
+ clocks = <&cpg CPG_MOD 218>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 218>;
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ iommus = <&ipmmu_ds1 0>, <&ipmmu_ds1 1>,
+ <&ipmmu_ds1 2>, <&ipmmu_ds1 3>,
+ <&ipmmu_ds1 4>, <&ipmmu_ds1 5>,
+ <&ipmmu_ds1 6>, <&ipmmu_ds1 7>;
+ };
+
+ dmac2: dma-controller@e7310000 {
+ compatible = "renesas,dmac-r8a77970",
+ "renesas,rcar-dmac";
+ reg = <0 0xe7310000 0 0x10000>;
+ interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7";
+ clocks = <&cpg CPG_MOD 217>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 217>;
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ iommus = <&ipmmu_ds1 16>, <&ipmmu_ds1 17>,
+ <&ipmmu_ds1 18>, <&ipmmu_ds1 19>,
+ <&ipmmu_ds1 20>, <&ipmmu_ds1 21>,
+ <&ipmmu_ds1 22>, <&ipmmu_ds1 23>;
+ };
+
+ ipmmu_ds1: mmu@e7740000 {
+ compatible = "renesas,ipmmu-r8a77970";
+ reg = <0 0xe7740000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 0>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_ir: mmu@ff8b0000 {
+ compatible = "renesas,ipmmu-r8a77970";
+ reg = <0 0xff8b0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 3>;
+ power-domains = <&sysc R8A77970_PD_A3IR>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_mm: mmu@e67b0000 {
+ compatible = "renesas,ipmmu-r8a77970";
+ reg = <0 0xe67b0000 0 0x1000>;
+ interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_rt: mmu@ffc80000 {
+ compatible = "renesas,ipmmu-r8a77970";
+ reg = <0 0xffc80000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 7>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vi0: mmu@febd0000 {
+ compatible = "renesas,ipmmu-r8a77970";
+ reg = <0 0xfebd0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 9>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ #iommu-cells = <1>;
+ };
+
+ gic: interrupt-controller@f1010000 {
+ compatible = "arm,gic-400";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0 0xf1010000 0 0x1000>,
+ <0 0xf1020000 0 0x20000>,
+ <0 0xf1040000 0 0x20000>,
+ <0 0xf1060000 0 0x20000>;
+ interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) |
+ IRQ_TYPE_LEVEL_HIGH)>;
+ clocks = <&cpg CPG_MOD 408>;
+ clock-names = "clk";
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 408>;
+ };
+
+ vspd0: vsp@fea20000 {
+ compatible = "renesas,vsp2";
+ reg = <0 0xfea20000 0 0x8000>;
+ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 623>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 623>;
+ renesas,fcp = <&fcpvd0>;
+ };
+
+ fcpvd0: fcp@fea27000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea27000 0 0x200>;
+ clocks = <&cpg CPG_MOD 603>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 603>;
+ };
+
+ csi40: csi2@feaa0000 {
+ compatible = "renesas,r8a77970-csi2";
+ reg = <0 0xfeaa0000 0 0x10000>;
+ interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 716>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 716>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ csi40vin0: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&vin0csi40>;
+ };
+ csi40vin1: endpoint@1 {
+ reg = <1>;
+ remote-endpoint = <&vin1csi40>;
+ };
+ csi40vin2: endpoint@2 {
+ reg = <2>;
+ remote-endpoint = <&vin2csi40>;
+ };
+ csi40vin3: endpoint@3 {
+ reg = <3>;
+ remote-endpoint = <&vin3csi40>;
+ };
+ };
+ };
+ };
+
+ du: display@feb00000 {
+ compatible = "renesas,du-r8a77970";
+ reg = <0 0xfeb00000 0 0x80000>;
+ interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 724>;
+ clock-names = "du.0";
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 724>;
+ vsps = <&vspd0>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ du_out_rgb: endpoint {
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ du_out_lvds0: endpoint {
+ remote-endpoint = <&lvds0_in>;
+ };
+ };
+ };
+ };
+
+ lvds0: lvds-encoder@feb90000 {
+ compatible = "renesas,r8a77970-lvds";
+ reg = <0 0xfeb90000 0 0x14>;
+ clocks = <&cpg CPG_MOD 727>;
+ power-domains = <&sysc R8A77970_PD_ALWAYS_ON>;
+ resets = <&cpg 727>;
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ lvds0_in: endpoint {
+ remote-endpoint =
+ <&du_out_lvds0>;
+ };
+ };
+ port@1 {
+ reg = <1>;
+ lvds0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ prr: chipid@fff00044 {
+ compatible = "renesas,prr";
+ reg = <0 0xfff00044 0 4>;
};
};
timer {
compatible = "arm,armv8-timer";
- interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_LOW)>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
index 06cf684..0b93a7d 100644
--- a/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77980-condor.dts
@@ -27,9 +27,30 @@
/* first 128MB is reserved for secure area. */
reg = <0 0x48000000 0 0x78000000>;
};
+
+ d3_3v: regulator-0 {
+ compatible = "regulator-fixed";
+ regulator-name = "D3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vddq_vin01: regulator-1 {
+ compatible = "regulator-fixed";
+ regulator-name = "VDDQ_VIN01";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
};
&avb {
+ pinctrl-0 = <&avb_pins>;
+ pinctrl-names = "default";
+
phy-mode = "rgmii-id";
phy-handle = <&phy0>;
renesas,no-ether-link;
@@ -41,6 +62,16 @@
};
};
+&canfd {
+ pinctrl-0 = <&canfd0_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ channel0 {
+ status = "okay";
+ };
+};
+
&extal_clk {
clock-frequency = <16666666>;
};
@@ -49,7 +80,57 @@
clock-frequency = <32768>;
};
+&mmc0 {
+ pinctrl-0 = <&mmc_pins>;
+ pinctrl-1 = <&mmc_pins_uhs>;
+ pinctrl-names = "default", "state_uhs";
+
+ vmmc-supply = <&d3_3v>;
+ vqmmc-supply = <&vddq_vin01>;
+ mmc-hs200-1_8v;
+ bus-width = <8>;
+ non-removable;
+ status = "okay";
+};
+
+&pfc {
+ avb_pins: avb {
+ groups = "avb_mdio", "avb_rgmii";
+ function = "avb";
+ };
+
+ canfd0_pins: canfd0 {
+ groups = "canfd0_data_a";
+ function = "canfd0";
+ };
+
+ mmc_pins: mmc {
+ groups = "mmc_data8", "mmc_ctrl", "mmc_ds";
+ function = "mmc";
+ power-source = <3300>;
+ };
+
+ mmc_pins_uhs: mmc_uhs {
+ groups = "mmc_data8", "mmc_ctrl", "mmc_ds";
+ function = "mmc";
+ power-source = <1800>;
+ };
+
+ scif0_pins: scif0 {
+ groups = "scif0_data";
+ function = "scif0";
+ };
+
+ scif_clk_pins: scif_clk {
+ groups = "scif_clk_b";
+ function = "scif_clk";
+ };
+};
+
&scif0 {
+ pinctrl-0 = <&scif0_pins>, <&scif_clk_pins>;
+ pinctrl-names = "default";
+
status = "okay";
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
new file mode 100644
index 0000000..c968099
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a77980-v3hsk.dts
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device Tree Source for the V3H Starter Kit board
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ * Copyright (C) 2018 Cogent Embedded, Inc.
+ */
+
+/dts-v1/;
+#include "r8a77980.dtsi"
+
+/ {
+ model = "Renesas V3H Starter Kit board";
+ compatible = "renesas,v3hsk", "renesas,r8a77980";
+
+ aliases {
+ serial0 = &scif0;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0 0x48000000 0 0x78000000>;
+ };
+};
+
+&extal_clk {
+ clock-frequency = <16666666>;
+};
+
+&extalr_clk {
+ clock-frequency = <32768>;
+};
+
+&pfc {
+ scif0_pins: scif0 {
+ groups = "scif0_data";
+ function = "scif0";
+ };
+
+ scif_clk_pins: scif_clk {
+ groups = "scif_clk_b";
+ function = "scif_clk";
+ };
+};
+
+&scif0 {
+ pinctrl-0 = <&scif0_pins>, <&scif_clk_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+};
+
+&scif_clk {
+ clock-frequency = <14745600>;
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a77980.dtsi b/arch/arm64/boot/dts/renesas/r8a77980.dtsi
index 03845fd..4c40f9f 100644
--- a/arch/arm64/boot/dts/renesas/r8a77980.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77980.dtsi
@@ -6,9 +6,10 @@
* Copyright (C) 2018 Cogent Embedded, Inc.
*/
+#include <dt-bindings/clock/r8a77980-cpg-mssr.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/clock/renesas-cpg-mssr.h>
+#include <dt-bindings/power/r8a77980-sysc.h>
/ {
compatible = "renesas,r8a77980";
@@ -23,20 +24,27 @@
device_type = "cpu";
compatible = "arm,cortex-a53", "arm,armv8";
reg = <0>;
- clocks = <&cpg CPG_CORE 0>;
- power-domains = <&sysc 5>;
+ clocks = <&cpg CPG_CORE R8A77980_CLK_Z2>;
+ power-domains = <&sysc R8A77980_PD_CA53_CPU0>;
next-level-cache = <&L2_CA53>;
enable-method = "psci";
};
L2_CA53: cache-controller {
compatible = "cache";
- power-domains = <&sysc 21>;
+ power-domains = <&sysc R8A77980_PD_CA53_SCU>;
cache-unified;
cache-level = <2>;
};
};
+ /* External CAN clock - to be overridden by boards that provide it */
+ can_clk: can {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
+ };
+
extal_clk: extal {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -71,6 +79,11 @@
#size-cells = <2>;
ranges;
+ pfc: pin-controller@e6060000 {
+ compatible = "renesas,pfc-r8a77980";
+ reg = <0 0xe6060000 0 0x50c>;
+ };
+
cpg: clock-controller@e6150000 {
compatible = "renesas,r8a77980-cpg-mssr";
reg = <0 0xe6150000 0 0x1000>;
@@ -99,13 +112,13 @@
reg = <0 0xe6540000 0 0x60>;
interrupts = <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 520>,
- <&cpg CPG_CORE 19>,
+ <&cpg CPG_CORE R8A77980_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 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 520>;
status = "disabled";
};
@@ -117,13 +130,13 @@
reg = <0 0xe6550000 0 0x60>;
interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 519>,
- <&cpg CPG_CORE 19>,
+ <&cpg CPG_CORE R8A77980_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 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 519>;
status = "disabled";
};
@@ -135,13 +148,13 @@
reg = <0 0xe6560000 0 0x60>;
interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 518>,
- <&cpg CPG_CORE 19>,
+ <&cpg CPG_CORE R8A77980_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 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 518>;
status = "disabled";
};
@@ -153,17 +166,42 @@
reg = <0 0xe66a0000 0 0x60>;
interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 517>,
- <&cpg CPG_CORE 19>,
+ <&cpg CPG_CORE R8A77980_CLK_S3D1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac1 0x37>, <&dmac1 0x36>,
<&dmac2 0x37>, <&dmac2 0x36>;
dma-names = "tx", "rx", "tx", "rx";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 517>;
status = "disabled";
};
+ canfd: can@e66c0000 {
+ compatible = "renesas,r8a77980-canfd",
+ "renesas,rcar-gen3-canfd";
+ reg = <0 0xe66c0000 0 0x8000>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 914>,
+ <&cpg CPG_CORE R8A77980_CLK_CANFD>,
+ <&can_clk>;
+ clock-names = "fck", "canfd", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A77980_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+ resets = <&cpg 914>;
+ status = "disabled";
+
+ channel0 {
+ status = "disabled";
+ };
+
+ channel1 {
+ status = "disabled";
+ };
+ };
+
avb: ethernet@e6800000 {
compatible = "renesas,etheravb-r8a77980",
"renesas,etheravb-rcar-gen3";
@@ -201,11 +239,12 @@
"ch20", "ch21", "ch22", "ch23",
"ch24";
clocks = <&cpg CPG_MOD 812>;
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 812>;
phy-mode = "rgmii";
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
};
scif0: serial@e6e60000 {
@@ -215,13 +254,13 @@
reg = <0 0xe6e60000 0 0x40>;
interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 207>,
- <&cpg CPG_CORE 19>,
+ <&cpg CPG_CORE R8A77980_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 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 207>;
status = "disabled";
};
@@ -233,13 +272,13 @@
reg = <0 0xe6e68000 0 0x40>;
interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 206>,
- <&cpg CPG_CORE 19>,
+ <&cpg CPG_CORE R8A77980_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 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 206>;
status = "disabled";
};
@@ -251,13 +290,13 @@
reg = <0 0xe6c50000 0 0x40>;
interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 204>,
- <&cpg CPG_CORE 19>,
+ <&cpg CPG_CORE R8A77980_CLK_S3D1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac1 0x57>, <&dmac1 0x56>,
<&dmac2 0x57>, <&dmac2 0x56>;
dma-names = "tx", "rx", "tx", "rx";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 204>;
status = "disabled";
};
@@ -269,13 +308,13 @@
reg = <0 0xe6c40000 0 0x40>;
interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 203>,
- <&cpg CPG_CORE 19>,
+ <&cpg CPG_CORE R8A77980_CLK_S3D1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac1 0x59>, <&dmac1 0x58>,
<&dmac2 0x59>, <&dmac2 0x58>;
dma-names = "tx", "rx", "tx", "rx";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 203>;
status = "disabled";
};
@@ -308,7 +347,7 @@
"ch12", "ch13", "ch14", "ch15";
clocks = <&cpg CPG_MOD 218>;
clock-names = "fck";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 218>;
#dma-cells = <1>;
dma-channels = <16>;
@@ -342,12 +381,24 @@
"ch12", "ch13", "ch14", "ch15";
clocks = <&cpg CPG_MOD 217>;
clock-names = "fck";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 217>;
#dma-cells = <1>;
dma-channels = <16>;
};
+ mmc0: mmc@ee140000 {
+ compatible = "renesas,sdhi-r8a77980",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee140000 0 0x2000>;
+ interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 314>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
+ resets = <&cpg 314>;
+ max-frequency = <200000000>;
+ status = "disabled";
+ };
+
gic: interrupt-controller@f1010000 {
compatible = "arm,gic-400";
#interrupt-cells = <3>;
@@ -361,7 +412,7 @@
IRQ_TYPE_LEVEL_HIGH)>;
clocks = <&cpg CPG_MOD 408>;
clock-names = "clk";
- power-domains = <&sysc 32>;
+ power-domains = <&sysc R8A77980_PD_ALWAYS_ON>;
resets = <&cpg 408>;
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
new file mode 100644
index 0000000..7a09d05
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Device Tree Source for the ebisu board
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+#include "r8a77990.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "Renesas Ebisu board based on r8a77990";
+ compatible = "renesas,ebisu", "renesas,r8a77990";
+
+ aliases {
+ serial0 = &scif2;
+ ethernet0 = &avb;
+ };
+
+ chosen {
+ bootargs = "ignore_loglevel";
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@48000000 {
+ device_type = "memory";
+ /* first 128MB is reserved for secure area. */
+ reg = <0x0 0x48000000 0x0 0x38000000>;
+ };
+};
+
+&avb {
+ pinctrl-0 = <&avb_pins>;
+ pinctrl-names = "default";
+ renesas,no-ether-link;
+ phy-handle = <&phy0>;
+ phy-mode = "rgmii-txid";
+ status = "okay";
+
+ phy0: ethernet-phy@0 {
+ rxc-skew-ps = <1500>;
+ reg = <0>;
+ interrupt-parent = <&gpio2>;
+ interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&extal_clk {
+ clock-frequency = <48000000>;
+};
+
+&pfc {
+ avb_pins: avb {
+ mux {
+ groups = "avb_link", "avb_mii";
+ function = "avb";
+ };
+ };
+};
+
+&scif2 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a77990.dtsi b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
new file mode 100644
index 0000000..be4f519
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r8a77990.dtsi
@@ -0,0 +1,281 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Device Tree Source for the r8a77990 SoC
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+#include <dt-bindings/clock/renesas-cpg-mssr.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+ compatible = "renesas,r8a77990";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* 1 core only at this point */
+ a53_0: cpu@0 {
+ compatible = "arm,cortex-a53", "arm,armv8";
+ reg = <0x0>;
+ device_type = "cpu";
+ power-domains = <&sysc 5>;
+ next-level-cache = <&L2_CA53>;
+ enable-method = "psci";
+ };
+
+ L2_CA53: cache-controller-0 {
+ compatible = "cache";
+ power-domains = <&sysc 21>;
+ cache-unified;
+ cache-level = <2>;
+ };
+ };
+
+ extal_clk: extal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ /* This value must be overridden by the board */
+ clock-frequency = <0>;
+ };
+
+ pmu_a53 {
+ compatible = "arm,cortex-a53-pmu";
+ interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-affinity = <&a53_0>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0", "arm,psci-0.2";
+ method = "smc";
+ };
+
+ soc: soc {
+ compatible = "simple-bus";
+ interrupt-parent = <&gic>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ gpio0: gpio@e6050000 {
+ compatible = "renesas,gpio-r8a77990",
+ "renesas,rcar-gen3-gpio";
+ reg = <0 0xe6050000 0 0x50>;
+ interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&pfc 0 0 18>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ clocks = <&cpg CPG_MOD 912>;
+ power-domains = <&sysc 32>;
+ resets = <&cpg 912>;
+ };
+
+ gpio1: gpio@e6051000 {
+ compatible = "renesas,gpio-r8a77990",
+ "renesas,rcar-gen3-gpio";
+ reg = <0 0xe6051000 0 0x50>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&pfc 0 32 23>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ clocks = <&cpg CPG_MOD 911>;
+ power-domains = <&sysc 32>;
+ resets = <&cpg 911>;
+ };
+
+ gpio2: gpio@e6052000 {
+ compatible = "renesas,gpio-r8a77990",
+ "renesas,rcar-gen3-gpio";
+ reg = <0 0xe6052000 0 0x50>;
+ interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&pfc 0 64 26>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ clocks = <&cpg CPG_MOD 910>;
+ power-domains = <&sysc 32>;
+ resets = <&cpg 910>;
+ };
+
+ gpio3: gpio@e6053000 {
+ compatible = "renesas,gpio-r8a77990",
+ "renesas,rcar-gen3-gpio";
+ reg = <0 0xe6053000 0 0x50>;
+ interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&pfc 0 96 16>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ clocks = <&cpg CPG_MOD 909>;
+ power-domains = <&sysc 32>;
+ resets = <&cpg 909>;
+ };
+
+ gpio4: gpio@e6054000 {
+ compatible = "renesas,gpio-r8a77990",
+ "renesas,rcar-gen3-gpio";
+ reg = <0 0xe6054000 0 0x50>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&pfc 0 128 11>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ clocks = <&cpg CPG_MOD 908>;
+ power-domains = <&sysc 32>;
+ resets = <&cpg 908>;
+ };
+
+ gpio5: gpio@e6055000 {
+ compatible = "renesas,gpio-r8a77990",
+ "renesas,rcar-gen3-gpio";
+ reg = <0 0xe6055000 0 0x50>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&pfc 0 160 20>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ clocks = <&cpg CPG_MOD 907>;
+ power-domains = <&sysc 32>;
+ resets = <&cpg 907>;
+ };
+
+ gpio6: gpio@e6055400 {
+ compatible = "renesas,gpio-r8a77990",
+ "renesas,rcar-gen3-gpio";
+ reg = <0 0xe6055400 0 0x50>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&pfc 0 192 18>;
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ clocks = <&cpg CPG_MOD 906>;
+ power-domains = <&sysc 32>;
+ resets = <&cpg 906>;
+ };
+
+ pfc: pin-controller@e6060000 {
+ compatible = "renesas,pfc-r8a77990";
+ reg = <0 0xe6060000 0 0x508>;
+ };
+
+ cpg: clock-controller@e6150000 {
+ compatible = "renesas,r8a77990-cpg-mssr";
+ reg = <0 0xe6150000 0 0x1000>;
+ clocks = <&extal_clk>;
+ clock-names = "extal";
+ #clock-cells = <2>;
+ #power-domain-cells = <0>;
+ #reset-cells = <1>;
+ };
+
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a77990-rst";
+ reg = <0 0xe6160000 0 0x0200>;
+ };
+
+ sysc: system-controller@e6180000 {
+ compatible = "renesas,r8a77990-sysc";
+ reg = <0 0xe6180000 0 0x0400>;
+ #power-domain-cells = <1>;
+ };
+
+ avb: ethernet@e6800000 {
+ compatible = "renesas,etheravb-r8a77990",
+ "renesas,etheravb-rcar-gen3";
+ reg = <0 0xe6800000 0 0x800>, <0 0xe6a00000 0 0x10000>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>,
+ <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 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7",
+ "ch8", "ch9", "ch10", "ch11",
+ "ch12", "ch13", "ch14", "ch15",
+ "ch16", "ch17", "ch18", "ch19",
+ "ch20", "ch21", "ch22", "ch23",
+ "ch24";
+ clocks = <&cpg CPG_MOD 812>;
+ power-domains = <&sysc 32>;
+ resets = <&cpg 812>;
+ phy-mode = "rgmii";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ scif2: serial@e6e88000 {
+ compatible = "renesas,scif-r8a77990",
+ "renesas,rcar-gen3-scif", "renesas,scif";
+ reg = <0 0xe6e88000 0 64>;
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 310>;
+ clock-names = "fck";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 310>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@f1010000 {
+ compatible = "arm,gic-400";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x0 0xf1010000 0 0x1000>,
+ <0x0 0xf1020000 0 0x20000>,
+ <0x0 0xf1040000 0 0x20000>,
+ <0x0 0xf1060000 0 0x20000>;
+ interrupts = <GIC_PPI 9
+ (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+ clocks = <&cpg CPG_MOD 408>;
+ clock-names = "clk";
+ power-domains = <&sysc 32>;
+ resets = <&cpg 408>;
+ };
+
+ prr: chipid@fff00044 {
+ compatible = "renesas,prr";
+ reg = <0 0xfff00044 0 4>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
index d03f194..9d73de8 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
+++ b/arch/arm64/boot/dts/renesas/r8a77995-draak.dts
@@ -91,7 +91,7 @@
&pfc {
avb0_pins: avb {
mux {
- groups = "avb0_link", "avb0_mdc", "avb0_mii";
+ groups = "avb0_link", "avb0_mdio", "avb0_mii";
function = "avb0";
};
};
diff --git a/arch/arm64/boot/dts/renesas/r8a77995.dtsi b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
index 82aed7e..2506f46 100644
--- a/arch/arm64/boot/dts/renesas/r8a77995.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a77995.dtsi
@@ -18,9 +18,11 @@
#address-cells = <2>;
#size-cells = <2>;
- psci {
- compatible = "arm,psci-1.0", "arm,psci-0.2";
- method = "smc";
+ /* External CAN clock - to be overridden by boards that provide it */
+ can_clk: can {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <0>;
};
cpus {
@@ -51,18 +53,16 @@
clock-frequency = <0>;
};
- /* External CAN clock - to be overridden by boards that provide it */
- can_clk: can {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <0>;
- };
-
pmu_a53 {
compatible = "arm,cortex-a53-pmu";
interrupts-extended = <&gic GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
};
+ psci {
+ compatible = "arm,psci-1.0", "arm,psci-0.2";
+ method = "smc";
+ };
+
scif_clk: scif {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -76,23 +76,6 @@
#size-cells = <2>;
ranges;
- gic: interrupt-controller@f1010000 {
- compatible = "arm,gic-400";
- #interrupt-cells = <3>;
- #address-cells = <0>;
- interrupt-controller;
- reg = <0x0 0xf1010000 0 0x1000>,
- <0x0 0xf1020000 0 0x20000>,
- <0x0 0xf1040000 0 0x20000>,
- <0x0 0xf1060000 0 0x20000>;
- interrupts = <GIC_PPI 9
- (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
- clocks = <&cpg CPG_MOD 408>;
- clock-names = "clk";
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 408>;
- };
-
rwdt: watchdog@e6020000 {
compatible = "renesas,r8a77995-wdt",
"renesas,rcar-gen3-wdt";
@@ -103,207 +86,6 @@
status = "disabled";
};
- ipmmu_vi0: mmu@febd0000 {
- compatible = "renesas,ipmmu-r8a77995";
- reg = <0 0xfebd0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 14>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_vp0: mmu@fe990000 {
- compatible = "renesas,ipmmu-r8a77995";
- reg = <0 0xfe990000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 16>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_vc0: mmu@fe6b0000 {
- compatible = "renesas,ipmmu-r8a77995";
- reg = <0 0xfe6b0000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 12>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_pv0: mmu@fd800000 {
- compatible = "renesas,ipmmu-r8a77995";
- reg = <0 0xfd800000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 6>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_hc: mmu@e6570000 {
- compatible = "renesas,ipmmu-r8a77995";
- reg = <0 0xe6570000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 2>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_rt: mmu@ffc80000 {
- compatible = "renesas,ipmmu-r8a77995";
- reg = <0 0xffc80000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 10>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_mp: mmu@ec670000 {
- compatible = "renesas,ipmmu-r8a77995";
- reg = <0 0xec670000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 4>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_ds0: mmu@e6740000 {
- compatible = "renesas,ipmmu-r8a77995";
- reg = <0 0xe6740000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 0>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_ds1: mmu@e7740000 {
- compatible = "renesas,ipmmu-r8a77995";
- reg = <0 0xe7740000 0 0x1000>;
- renesas,ipmmu-main = <&ipmmu_mm 1>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
- ipmmu_mm: mmu@e67b0000 {
- compatible = "renesas,ipmmu-r8a77995";
- reg = <0 0xe67b0000 0 0x1000>;
- interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
- #iommu-cells = <1>;
- status = "disabled";
- };
-
-
- cpg: clock-controller@e6150000 {
- compatible = "renesas,r8a77995-cpg-mssr";
- reg = <0 0xe6150000 0 0x1000>;
- clocks = <&extal_clk>;
- clock-names = "extal";
- #clock-cells = <2>;
- #power-domain-cells = <0>;
- #reset-cells = <1>;
- };
-
- rst: reset-controller@e6160000 {
- compatible = "renesas,r8a77995-rst";
- reg = <0 0xe6160000 0 0x0200>;
- };
-
- pfc: pin-controller@e6060000 {
- compatible = "renesas,pfc-r8a77995";
- reg = <0 0xe6060000 0 0x508>;
- };
-
- prr: chipid@fff00044 {
- compatible = "renesas,prr";
- reg = <0 0xfff00044 0 4>;
- };
-
- sysc: system-controller@e6180000 {
- compatible = "renesas,r8a77995-sysc";
- reg = <0 0xe6180000 0 0x0400>;
- #power-domain-cells = <1>;
- };
-
- intc_ex: interrupt-controller@e61c0000 {
- compatible = "renesas,intc-ex-r8a77995", "renesas,irqc";
- #interrupt-cells = <2>;
- interrupt-controller;
- reg = <0 0xe61c0000 0 0x200>;
- interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 407>;
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 407>;
- };
-
- dmac0: dma-controller@e6700000 {
- compatible = "renesas,dmac-r8a77995",
- "renesas,rcar-dmac";
- reg = <0 0xe6700000 0 0x10000>;
- interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7";
- clocks = <&cpg CPG_MOD 219>;
- clock-names = "fck";
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 219>;
- #dma-cells = <1>;
- dma-channels = <8>;
- };
-
- dmac1: dma-controller@e7300000 {
- compatible = "renesas,dmac-r8a77995",
- "renesas,rcar-dmac";
- reg = <0 0xe7300000 0 0x10000>;
- interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7";
- clocks = <&cpg CPG_MOD 218>;
- clock-names = "fck";
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 218>;
- #dma-cells = <1>;
- dma-channels = <8>;
- };
-
- dmac2: dma-controller@e7310000 {
- compatible = "renesas,dmac-r8a77995",
- "renesas,rcar-dmac";
- reg = <0 0xe7310000 0 0x10000>;
- interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH
- GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "error",
- "ch0", "ch1", "ch2", "ch3",
- "ch4", "ch5", "ch6", "ch7";
- clocks = <&cpg CPG_MOD 217>;
- clock-names = "fck";
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 217>;
- #dma-cells = <1>;
- dma-channels = <8>;
- };
-
gpio0: gpio@e6050000 {
compatible = "renesas,gpio-r8a77995",
"renesas,rcar-gen3-gpio",
@@ -416,35 +198,112 @@
resets = <&cpg 906>;
};
- can0: can@e6c30000 {
- compatible = "renesas,can-r8a77995",
- "renesas,rcar-gen3-can";
- reg = <0 0xe6c30000 0 0x1000>;
- interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 916>,
- <&cpg CPG_CORE R8A77995_CLK_CANFD>,
- <&can_clk>;
- clock-names = "clkp1", "clkp2", "can_clk";
- assigned-clocks = <&cpg CPG_CORE R8A77995_CLK_CANFD>;
- assigned-clock-rates = <40000000>;
+ pfc: pin-controller@e6060000 {
+ compatible = "renesas,pfc-r8a77995";
+ reg = <0 0xe6060000 0 0x508>;
+ };
+
+ cpg: clock-controller@e6150000 {
+ compatible = "renesas,r8a77995-cpg-mssr";
+ reg = <0 0xe6150000 0 0x1000>;
+ clocks = <&extal_clk>;
+ clock-names = "extal";
+ #clock-cells = <2>;
+ #power-domain-cells = <0>;
+ #reset-cells = <1>;
+ };
+
+ rst: reset-controller@e6160000 {
+ compatible = "renesas,r8a77995-rst";
+ reg = <0 0xe6160000 0 0x0200>;
+ };
+
+ sysc: system-controller@e6180000 {
+ compatible = "renesas,r8a77995-sysc";
+ reg = <0 0xe6180000 0 0x0400>;
+ #power-domain-cells = <1>;
+ };
+
+ intc_ex: interrupt-controller@e61c0000 {
+ compatible = "renesas,intc-ex-r8a77995", "renesas,irqc";
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ reg = <0 0xe61c0000 0 0x200>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 407>;
power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 916>;
+ resets = <&cpg 407>;
+ };
+
+ i2c0: i2c@e6500000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77995",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe6500000 0 0x40>;
+ interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 931>;
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 931>;
+ dmas = <&dmac1 0x91>, <&dmac1 0x90>,
+ <&dmac2 0x91>, <&dmac2 0x90>;
+ dma-names = "tx", "rx", "tx", "rx";
+ i2c-scl-internal-delay-ns = <6>;
status = "disabled";
};
- can1: can@e6c38000 {
- compatible = "renesas,can-r8a77995",
- "renesas,rcar-gen3-can";
- reg = <0 0xe6c38000 0 0x1000>;
- interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 915>,
- <&cpg CPG_CORE R8A77995_CLK_CANFD>,
- <&can_clk>;
- clock-names = "clkp1", "clkp2", "can_clk";
- assigned-clocks = <&cpg CPG_CORE R8A77995_CLK_CANFD>;
- assigned-clock-rates = <40000000>;
+ i2c1: i2c@e6508000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77995",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe6508000 0 0x40>;
+ interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 930>;
power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 915>;
+ resets = <&cpg 930>;
+ dmas = <&dmac1 0x93>, <&dmac1 0x92>,
+ <&dmac2 0x93>, <&dmac2 0x92>;
+ dma-names = "tx", "rx", "tx", "rx";
+ i2c-scl-internal-delay-ns = <6>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@e6510000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77995",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe6510000 0 0x40>;
+ interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 929>;
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 929>;
+ dmas = <&dmac1 0x95>, <&dmac1 0x94>,
+ <&dmac2 0x95>, <&dmac2 0x94>;
+ dma-names = "tx", "rx", "tx", "rx";
+ i2c-scl-internal-delay-ns = <6>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@e66d0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "renesas,i2c-r8a77995",
+ "renesas,rcar-gen3-i2c";
+ reg = <0 0xe66d0000 0 0x40>;
+ interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 928>;
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 928>;
+ dmas = <&dmac0 0x97>, <&dmac0 0x96>;
+ dma-names = "tx", "rx";
+ i2c-scl-internal-delay-ns = <6>;
status = "disabled";
};
@@ -473,6 +332,149 @@
};
};
+ dmac0: dma-controller@e6700000 {
+ compatible = "renesas,dmac-r8a77995",
+ "renesas,rcar-dmac";
+ reg = <0 0xe6700000 0 0x10000>;
+ interrupts = <GIC_SPI 199 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 200 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 201 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 202 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 203 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 205 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 206 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7";
+ clocks = <&cpg CPG_MOD 219>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 219>;
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ };
+
+ dmac1: dma-controller@e7300000 {
+ compatible = "renesas,dmac-r8a77995",
+ "renesas,rcar-dmac";
+ reg = <0 0xe7300000 0 0x10000>;
+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 216 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7";
+ clocks = <&cpg CPG_MOD 218>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 218>;
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ };
+
+ dmac2: dma-controller@e7310000 {
+ compatible = "renesas,dmac-r8a77995",
+ "renesas,rcar-dmac";
+ reg = <0 0xe7310000 0 0x10000>;
+ interrupts = <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH
+ GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3",
+ "ch4", "ch5", "ch6", "ch7";
+ clocks = <&cpg CPG_MOD 217>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 217>;
+ #dma-cells = <1>;
+ dma-channels = <8>;
+ };
+
+ ipmmu_ds0: mmu@e6740000 {
+ compatible = "renesas,ipmmu-r8a77995";
+ reg = <0 0xe6740000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 0>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_ds1: mmu@e7740000 {
+ compatible = "renesas,ipmmu-r8a77995";
+ reg = <0 0xe7740000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 1>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_hc: mmu@e6570000 {
+ compatible = "renesas,ipmmu-r8a77995";
+ reg = <0 0xe6570000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 2>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_mm: mmu@e67b0000 {
+ compatible = "renesas,ipmmu-r8a77995";
+ reg = <0 0xe67b0000 0 0x1000>;
+ interrupts = <GIC_SPI 196 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 197 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_mp: mmu@ec670000 {
+ compatible = "renesas,ipmmu-r8a77995";
+ reg = <0 0xec670000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 4>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_pv0: mmu@fd800000 {
+ compatible = "renesas,ipmmu-r8a77995";
+ reg = <0 0xfd800000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 6>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_rt: mmu@ffc80000 {
+ compatible = "renesas,ipmmu-r8a77995";
+ reg = <0 0xffc80000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 10>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vc0: mmu@fe6b0000 {
+ compatible = "renesas,ipmmu-r8a77995";
+ reg = <0 0xfe6b0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 12>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vi0: mmu@febd0000 {
+ compatible = "renesas,ipmmu-r8a77995";
+ reg = <0 0xfebd0000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 14>;
+ #iommu-cells = <1>;
+ };
+
+ ipmmu_vp0: mmu@fe990000 {
+ compatible = "renesas,ipmmu-r8a77995";
+ reg = <0 0xfe990000 0 0x1000>;
+ renesas,ipmmu-main = <&ipmmu_mm 16>;
+ #iommu-cells = <1>;
+ };
+
avb: ethernet@e6800000 {
compatible = "renesas,etheravb-r8a77995",
"renesas,etheravb-rcar-gen3";
@@ -519,87 +521,35 @@
status = "disabled";
};
- scif2: serial@e6e88000 {
- compatible = "renesas,scif-r8a77995",
- "renesas,rcar-gen3-scif", "renesas,scif";
- reg = <0 0xe6e88000 0 64>;
- interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 310>,
- <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
- <&scif_clk>;
- clock-names = "fck", "brg_int", "scif_clk";
- dmas = <&dmac1 0x13>, <&dmac1 0x12>,
- <&dmac2 0x13>, <&dmac2 0x12>;
- dma-names = "tx", "rx", "tx", "rx";
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 310>;
- status = "disabled";
- };
-
- i2c0: i2c@e6500000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a77995",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe6500000 0 0x40>;
- interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 931>;
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 931>;
- dmas = <&dmac1 0x91>, <&dmac1 0x90>,
- <&dmac2 0x91>, <&dmac2 0x90>;
- dma-names = "tx", "rx", "tx", "rx";
- i2c-scl-internal-delay-ns = <6>;
- status = "disabled";
- };
-
- i2c1: i2c@e6508000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a77995",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe6508000 0 0x40>;
- interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 930>;
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 930>;
- dmas = <&dmac1 0x93>, <&dmac1 0x92>,
- <&dmac2 0x93>, <&dmac2 0x92>;
- dma-names = "tx", "rx", "tx", "rx";
- i2c-scl-internal-delay-ns = <6>;
- status = "disabled";
- };
-
- i2c2: i2c@e6510000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a77995",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe6510000 0 0x40>;
- interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 929>;
+ can0: can@e6c30000 {
+ compatible = "renesas,can-r8a77995",
+ "renesas,rcar-gen3-can";
+ reg = <0 0xe6c30000 0 0x1000>;
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 916>,
+ <&cpg CPG_CORE R8A77995_CLK_CANFD>,
+ <&can_clk>;
+ clock-names = "clkp1", "clkp2", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A77995_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 929>;
- dmas = <&dmac1 0x95>, <&dmac1 0x94>,
- <&dmac2 0x95>, <&dmac2 0x94>;
- dma-names = "tx", "rx", "tx", "rx";
- i2c-scl-internal-delay-ns = <6>;
+ resets = <&cpg 916>;
status = "disabled";
};
- i2c3: i2c@e66d0000 {
- #address-cells = <1>;
- #size-cells = <0>;
- compatible = "renesas,i2c-r8a77995",
- "renesas,rcar-gen3-i2c";
- reg = <0 0xe66d0000 0 0x40>;
- interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 928>;
+ can1: can@e6c38000 {
+ compatible = "renesas,can-r8a77995",
+ "renesas,rcar-gen3-can";
+ reg = <0 0xe6c38000 0 0x1000>;
+ interrupts = <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 915>,
+ <&cpg CPG_CORE R8A77995_CLK_CANFD>,
+ <&can_clk>;
+ clock-names = "clkp1", "clkp2", "can_clk";
+ assigned-clocks = <&cpg CPG_CORE R8A77995_CLK_CANFD>;
+ assigned-clock-rates = <40000000>;
power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 928>;
- dmas = <&dmac0 0x97>, <&dmac0 0x96>;
- dma-names = "tx", "rx";
- i2c-scl-internal-delay-ns = <6>;
+ resets = <&cpg 915>;
status = "disabled";
};
@@ -643,38 +593,54 @@
status = "disabled";
};
- sdhi2: sd@ee140000 {
- compatible = "renesas,sdhi-r8a77995",
- "renesas,rcar-gen3-sdhi";
- reg = <0 0xee140000 0 0x2000>;
- interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&cpg CPG_MOD 312>;
- max-frequency = <200000000>;
+ scif2: serial@e6e88000 {
+ compatible = "renesas,scif-r8a77995",
+ "renesas,rcar-gen3-scif", "renesas,scif";
+ reg = <0 0xe6e88000 0 64>;
+ interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 310>,
+ <&cpg CPG_CORE R8A77995_CLK_S3D1C>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+ <&dmac2 0x13>, <&dmac2 0x12>;
+ dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 312>;
+ resets = <&cpg 310>;
status = "disabled";
};
- ehci0: usb@ee080100 {
- compatible = "generic-ehci";
- reg = <0 0xee080100 0 0x100>;
+ vin4: video@e6ef4000 {
+ compatible = "renesas,vin-r8a77995";
+ reg = <0 0xe6ef4000 0 0x1000>;
+ interrupts = <GIC_SPI 174 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 807>;
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 807>;
+ renesas,id = <4>;
+ status = "disabled";
+ };
+
+ ohci0: usb@ee080000 {
+ compatible = "generic-ohci";
+ reg = <0 0xee080000 0 0x100>;
interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 703>;
phys = <&usb2_phy0>;
phy-names = "usb";
- companion = <&ohci0>;
power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
resets = <&cpg 703>;
status = "disabled";
};
- ohci0: usb@ee080000 {
- compatible = "generic-ohci";
- reg = <0 0xee080000 0 0x100>;
+ ehci0: usb@ee080100 {
+ compatible = "generic-ehci";
+ reg = <0 0xee080100 0 0x100>;
interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 703>;
phys = <&usb2_phy0>;
phy-names = "usb";
+ companion = <&ohci0>;
power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
resets = <&cpg 703>;
status = "disabled";
@@ -692,6 +658,35 @@
status = "disabled";
};
+ sdhi2: sd@ee140000 {
+ compatible = "renesas,sdhi-r8a77995",
+ "renesas,rcar-gen3-sdhi";
+ reg = <0 0xee140000 0 0x2000>;
+ interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 312>;
+ max-frequency = <200000000>;
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 312>;
+ status = "disabled";
+ };
+
+ gic: interrupt-controller@f1010000 {
+ compatible = "arm,gic-400";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x0 0xf1010000 0 0x1000>,
+ <0x0 0xf1020000 0 0x20000>,
+ <0x0 0xf1040000 0 0x20000>,
+ <0x0 0xf1060000 0 0x20000>;
+ interrupts = <GIC_PPI 9
+ (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+ clocks = <&cpg CPG_MOD 408>;
+ clock-names = "clk";
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 408>;
+ };
+
vspbs: vsp@fe960000 {
compatible = "renesas,vsp2";
reg = <0 0xfe960000 0 0x8000>;
@@ -702,15 +697,6 @@
renesas,fcp = <&fcpvb0>;
};
- fcpvb0: fcp@fe96f000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfe96f000 0 0x200>;
- clocks = <&cpg CPG_MOD 607>;
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 607>;
- iommus = <&ipmmu_vp0 5>;
- };
-
vspd0: vsp@fea20000 {
compatible = "renesas,vsp2";
reg = <0 0xfea20000 0 0x8000>;
@@ -721,15 +707,6 @@
renesas,fcp = <&fcpvd0>;
};
- fcpvd0: fcp@fea27000 {
- compatible = "renesas,fcpv";
- reg = <0 0xfea27000 0 0x200>;
- clocks = <&cpg CPG_MOD 603>;
- power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
- resets = <&cpg 603>;
- iommus = <&ipmmu_vi0 8>;
- };
-
vspd1: vsp@fea28000 {
compatible = "renesas,vsp2";
reg = <0 0xfea28000 0 0x8000>;
@@ -740,6 +717,24 @@
renesas,fcp = <&fcpvd1>;
};
+ fcpvb0: fcp@fe96f000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfe96f000 0 0x200>;
+ clocks = <&cpg CPG_MOD 607>;
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 607>;
+ iommus = <&ipmmu_vp0 5>;
+ };
+
+ fcpvd0: fcp@fea27000 {
+ compatible = "renesas,fcpv";
+ reg = <0 0xfea27000 0 0x200>;
+ clocks = <&cpg CPG_MOD 603>;
+ power-domains = <&sysc R8A77995_PD_ALWAYS_ON>;
+ resets = <&cpg 603>;
+ iommus = <&ipmmu_vi0 8>;
+ };
+
fcpvd1: fcp@fea2f000 {
compatible = "renesas,fcpv";
reg = <0 0xfea2f000 0 0x200>;
@@ -783,6 +778,11 @@
};
};
};
+
+ prr: chipid@fff00044 {
+ compatible = "renesas,prr";
+ reg = <0 0xfff00044 0 4>;
+ };
};
timer {
diff --git a/arch/arm64/boot/dts/renesas/salvator-common.dtsi b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
index 2a7f36a..9256fba 100644
--- a/arch/arm64/boot/dts/renesas/salvator-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/salvator-common.dtsi
@@ -66,6 +66,29 @@
enable-gpios = <&gpio6 7 GPIO_ACTIVE_HIGH>;
};
+ cvbs-in {
+ compatible = "composite-video-connector";
+ label = "CVBS IN";
+
+ port {
+ cvbs_con: endpoint {
+ remote-endpoint = <&adv7482_ain7>;
+ };
+ };
+ };
+
+ hdmi-in {
+ compatible = "hdmi-connector";
+ label = "HDMI IN";
+ type = "a";
+
+ port {
+ hdmi_in_con: endpoint {
+ remote-endpoint = <&adv7482_hdmi>;
+ };
+ };
+ };
+
reg_1p8v: regulator0 {
compatible = "regulator-fixed";
regulator-name = "fixed-1.8V";
@@ -93,20 +116,12 @@
regulator-always-on;
};
- rsnd_ak4613: sound {
- compatible = "simple-audio-card";
-
- simple-audio-card,format = "left_j";
- simple-audio-card,bitclock-master = <&sndcpu>;
- simple-audio-card,frame-master = <&sndcpu>;
+ sound_card: sound {
+ compatible = "audio-graph-card";
- sndcpu: simple-audio-card,cpu {
- sound-dai = <&rcar_sound>;
- };
+ label = "rcar-sound";
- sndcodec: simple-audio-card,codec {
- sound-dai = <&ak4613>;
- };
+ dais = <&rsnd_port0>;
};
vbus0_usb2: regulator-vbus0-usb2 {
@@ -268,6 +283,37 @@
};
};
+&csi20 {
+ status = "okay";
+
+ ports {
+ port@0 {
+ reg = <0>;
+ csi20_in: endpoint {
+ clock-lanes = <0>;
+ data-lanes = <1>;
+ remote-endpoint = <&adv7482_txb>;
+ };
+ };
+ };
+};
+
+&csi40 {
+ status = "okay";
+
+ ports {
+ port@0 {
+ reg = <0>;
+
+ csi40_in: endpoint {
+ clock-lanes = <0>;
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&adv7482_txa>;
+ };
+ };
+ };
+};
+
&du {
pinctrl-0 = <&du_pins>;
pinctrl-names = "default";
@@ -322,6 +368,12 @@
asahi-kasei,out4-single-end;
asahi-kasei,out5-single-end;
asahi-kasei,out6-single-end;
+
+ port {
+ ak4613_endpoint: endpoint {
+ remote-endpoint = <&rsnd_endpoint0>;
+ };
+ };
};
cs2000: clk_multiplier@4f {
@@ -359,6 +411,55 @@
shunt-resistor-micro-ohms = <5000>;
};
+
+ video-receiver@70 {
+ compatible = "adi,adv7482";
+ reg = <0x70>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ interrupt-parent = <&gpio6>;
+ interrupt-names = "intrq1", "intrq2";
+ interrupts = <30 IRQ_TYPE_LEVEL_LOW>,
+ <31 IRQ_TYPE_LEVEL_LOW>;
+
+ port@7 {
+ reg = <7>;
+
+ adv7482_ain7: endpoint {
+ remote-endpoint = <&cvbs_con>;
+ };
+ };
+
+ port@8 {
+ reg = <8>;
+
+ adv7482_hdmi: endpoint {
+ remote-endpoint = <&hdmi_in_con>;
+ };
+ };
+
+ port@10 {
+ reg = <10>;
+
+ adv7482_txa: endpoint {
+ clock-lanes = <0>;
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&csi40_in>;
+ };
+ };
+
+ port@11 {
+ reg = <11>;
+
+ adv7482_txb: endpoint {
+ clock-lanes = <0>;
+ data-lanes = <1>;
+ remote-endpoint = <&csi20_in>;
+ };
+ };
+ };
};
&i2c_dvfs {
@@ -376,6 +477,8 @@
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
+ rohm,ddr-backup-power = <0xf>;
+ rohm,rstbmode-level;
regulators {
dvfs: dvfs {
@@ -387,6 +490,12 @@
};
};
};
+
+ eeprom@50 {
+ compatible = "rohm,br24t01", "atmel,24c01";
+ reg = <0x50>;
+ pagesize = <8>;
+ };
};
&ohci0 {
@@ -416,12 +525,12 @@
avb_pins: avb {
mux {
- groups = "avb_link", "avb_mdc", "avb_mii";
+ groups = "avb_link", "avb_mdio", "avb_mii";
function = "avb";
};
- pins_mdc {
- groups = "avb_mdc";
+ pins_mdio {
+ groups = "avb_mdio";
drive-strength = <24>;
};
@@ -581,10 +690,18 @@
<&audio_clk_c>,
<&cpg CPG_CORE CPG_AUDIO_CLK_I>;
- rcar_sound,dai {
- dai0 {
- playback = <&ssi0 &src0 &dvc0>;
- capture = <&ssi1 &src1 &dvc1>;
+ ports {
+ rsnd_port0: port@0 {
+ rsnd_endpoint0: endpoint {
+ remote-endpoint = <&ak4613_endpoint>;
+
+ dai-format = "left_j";
+ bitclock-master = <&rsnd_endpoint0>;
+ frame-master = <&rsnd_endpoint0>;
+
+ playback = <&ssi0 &src0 &dvc0>;
+ capture = <&ssi1 &src1 &dvc1>;
+ };
};
};
};
@@ -689,6 +806,38 @@
clock-frequency = <100000000>;
};
+&vin0 {
+ status = "okay";
+};
+
+&vin1 {
+ status = "okay";
+};
+
+&vin2 {
+ status = "okay";
+};
+
+&vin3 {
+ status = "okay";
+};
+
+&vin4 {
+ status = "okay";
+};
+
+&vin5 {
+ status = "okay";
+};
+
+&vin6 {
+ status = "okay";
+};
+
+&vin7 {
+ status = "okay";
+};
+
&wdt0 {
timeout-sec = <60>;
status = "okay";
diff --git a/arch/arm64/boot/dts/renesas/ulcb.dtsi b/arch/arm64/boot/dts/renesas/ulcb.dtsi
index 6f81484..0edb16e 100644
--- a/arch/arm64/boot/dts/renesas/ulcb.dtsi
+++ b/arch/arm64/boot/dts/renesas/ulcb.dtsi
@@ -243,6 +243,32 @@
&i2c_dvfs {
status = "okay";
+
+ pmic: pmic@30 {
+ pinctrl-0 = <&irq0_pins>;
+ pinctrl-names = "default";
+
+ compatible = "rohm,bd9571mwv";
+ reg = <0x30>;
+ interrupt-parent = <&intc_ex>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ rohm,ddr-backup-power = <0xf>;
+ rohm,rstbmode-pulse;
+
+ regulators {
+ dvfs: dvfs {
+ regulator-name = "dvfs";
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1030000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
};
&ohci1 {
@@ -255,12 +281,12 @@
avb_pins: avb {
mux {
- groups = "avb_link", "avb_mdc", "avb_mii";
+ groups = "avb_link", "avb_mdio", "avb_mii";
function = "avb";
};
- pins_mdc {
- groups = "avb_mdc";
+ pins_mdio {
+ groups = "avb_mdio";
drive-strength = <24>;
};
@@ -276,6 +302,11 @@
function = "i2c2";
};
+ irq0_pins: irq0 {
+ groups = "intc_ex_irq0";
+ function = "intc_ex";
+ };
+
scif2_pins: scif2 {
groups = "scif2_data_a";
function = "scif2";
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index be2bfbc..b8e9da1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -595,6 +595,8 @@
reg = <0x0 0xff330200 0 0x100>;
interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "h265e_mmu";
+ clocks = <&cru ACLK_H265>, <&cru PCLK_H265>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -604,6 +606,8 @@
reg = <0x0 0xff340800 0x0 0x40>;
interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vepu_mmu";
+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -613,6 +617,8 @@
reg = <0x0 0xff350800 0x0 0x40>;
interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vpu_mmu";
+ clocks = <&cru ACLK_VPU>, <&cru HCLK_VPU>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -622,6 +628,8 @@
reg = <0x0 0xff360480 0x0 0x40>, <0x0 0xff3604c0 0x0 0x40>;
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "rkvdec_mmu";
+ clocks = <&cru ACLK_RKVDEC>, <&cru HCLK_RKVDEC>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -631,6 +639,8 @@
reg = <0x0 0xff373f00 0x0 0x100>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vop_mmu";
+ clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3368.dtsi b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
index 03458ac..ad91ced 100644
--- a/arch/arm64/boot/dts/rockchip/rk3368.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3368.dtsi
@@ -742,6 +742,8 @@
reg = <0x0 0xff900800 0x0 0x100>;
interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "iep_mmu";
+ clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -752,6 +754,8 @@
<0x0 0xff915000 0x0 0x100>;
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "isp_mmu";
+ clocks = <&cru ACLK_ISP>, <&cru HCLK_ISP>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
rockchip,disable-mmu-reset;
status = "disabled";
@@ -762,6 +766,8 @@
reg = <0x0 0xff930300 0x0 0x100>;
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vop_mmu";
+ clocks = <&cru ACLK_VOP>, <&cru HCLK_VOP>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -772,6 +778,8 @@
<0x0 0xff9a0480 0x0 0x40>;
interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hevc_mmu";
+ clocks = <&cru ACLK_VIDEO>, <&cru HCLK_VIDEO>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -782,6 +790,8 @@
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vepu_mmu", "vdpu_mmu";
+ clocks = <&cru ACLK_VIDEO>, <&cru HCLK_VIDEO>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
index 4f28628..2a35276 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-firefly.dts
@@ -662,6 +662,14 @@
status = "okay";
};
+&tcphy0 {
+ status = "okay";
+};
+
+&tcphy1 {
+ status = "okay";
+};
+
&tsadc {
/* tshut mode 0:CRU 1:GPIO */
rockchip,hw-tshut-mode = <1>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
index 191a6bc..8217912 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
@@ -255,7 +255,7 @@ ap_i2c_dig: &i2c2 {
&ap_i2c_tp {
trackpad@4a {
- compatible = "atmel,atmel_mxt_tp";
+ compatible = "atmel,maxtouch";
reg = <0x4a>;
pinctrl-names = "default";
pinctrl-0 = <&trackpad_int_l>;
@@ -271,7 +271,7 @@ ap_i2c_dig: &i2c2 {
&ap_i2c_ts {
touchscreen@4b {
- compatible = "atmel,atmel_mxt_ts";
+ compatible = "atmel,maxtouch";
reg = <0x4b>;
pinctrl-names = "default";
pinctrl-0 = <&touch_int_l>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
index 18f546f..f49bfab 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
@@ -588,7 +588,9 @@
<&cru ACLK_PERILP0>, <&cru HCLK_PERILP0>,
<&cru PCLK_PERILP0>, <&cru ACLK_CCI>,
<&cru HCLK_PERILP1>, <&cru PCLK_PERILP1>,
- <&cru ACLK_VIO>;
+ <&cru ACLK_VIO>, <&cru ACLK_HDCP>,
+ <&cru ACLK_GIC_PRE>,
+ <&cru PCLK_DDR>;
assigned-clock-rates =
<600000000>, <800000000>,
<1000000000>,
@@ -597,7 +599,9 @@
<100000000>, <100000000>,
<50000000>, <800000000>,
<100000000>, <50000000>,
- <400000000>;
+ <400000000>, <400000000>,
+ <200000000>,
+ <200000000>;
};
&emmc_phy {
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
index 7d3e8bf..e0afdd8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
@@ -143,6 +143,11 @@
};
};
+&hdmi {
+ ddc-i2c-bus = <&i2c3>;
+ status = "okay";
+};
+
&i2c1 {
status = "okay";
clock-frequency = <400000>;
@@ -246,6 +251,10 @@
status = "okay";
};
+&tcphy0 {
+ status = "okay";
+};
+
&u2phy0 {
status = "okay";
};
@@ -281,3 +290,19 @@
&usb_host0_ohci {
status = "okay";
};
+
+&vopb {
+ status = "okay";
+};
+
+&vopb_mmu {
+ status = "okay";
+};
+
+&vopl {
+ status = "okay";
+};
+
+&vopl_mmu {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
index 4a2d06a..14a0f199 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi
@@ -527,6 +527,10 @@
};
};
+&tcphy1 {
+ status = "okay";
+};
+
&tsadc {
rockchip,hw-tshut-mode = <1>;
rockchip,hw-tshut-polarity = <1>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts b/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
index 56952d1..ad7548d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire-excavator.dts
@@ -190,6 +190,18 @@
status = "okay";
};
+&pcie_phy {
+ status = "okay";
+};
+
+&pcie0 {
+ ep-gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_HIGH>;
+ num-lanes = <4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_clkreqn_cpm>;
+ status = "okay";
+};
+
&pinctrl {
sdio-pwrseq {
wifi_enable_h: wifi-enable-h {
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
index e5daed7..941b627 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-sapphire.dtsi
@@ -471,21 +471,6 @@
gpio1830-supply = <&vcc_3v0>;
};
-&pcie_phy {
- status = "okay";
-};
-
-&pcie0 {
- assigned-clocks = <&cru SCLK_PCIEPHY_REF>;
- assigned-clock-parents = <&cru SCLK_PCIEPHY_REF100M>;
- assigned-clock-rates = <100000000>;
- ep-gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_HIGH>;
- num-lanes = <4>;
- pinctrl-names = "default";
- pinctrl-0 = <&pcie_clkreqn_cpm>;
- status = "okay";
-};
-
&pmu_io_domains {
pmu1830-supply = <&vcc_3v0>;
status = "okay";
@@ -560,6 +545,14 @@
status = "okay";
};
+&tcphy0 {
+ status = "okay";
+};
+
+&tcphy1 {
+ status = "okay";
+};
+
&tsadc {
/* tshut mode 0:CRU 1:GPIO */
rockchip,hw-tshut-mode = <1>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 4550c0f..e0040b6 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -312,6 +312,8 @@
reg = <0x0 0xfe320000 0x0 0x4000>;
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH 0>;
max-frequency = <150000000>;
+ assigned-clocks = <&cru HCLK_SD>;
+ assigned-clock-rates = <200000000>;
clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>,
<&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>;
clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
@@ -411,8 +413,8 @@
reg = <0x0 0xfe800000 0x0 0x100000>;
interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH 0>;
dr_mode = "otg";
- phys = <&u2phy0_otg>;
- phy-names = "usb2-phy";
+ phys = <&u2phy0_otg>, <&tcphy0_usb3>;
+ phy-names = "usb2-phy", "usb3-phy";
phy_type = "utmi_wide";
snps,dis_enblslpm_quirk;
snps,dis-u2-freeclk-exists-quirk;
@@ -444,8 +446,8 @@
reg = <0x0 0xfe900000 0x0 0x100000>;
interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH 0>;
dr_mode = "otg";
- phys = <&u2phy1_otg>;
- phy-names = "usb2-phy";
+ phys = <&u2phy1_otg>, <&tcphy1_usb3>;
+ phy-names = "usb2-phy", "usb3-phy";
phy_type = "utmi_wide";
snps,dis_enblslpm_quirk;
snps,dis-u2-freeclk-exists-quirk;
@@ -461,8 +463,8 @@
compatible = "rockchip,rk3399-cdn-dp";
reg = <0x0 0xfec00000 0x0 0x100000>;
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH 0>;
- assigned-clocks = <&cru SCLK_DP_CORE>;
- assigned-clock-rates = <100000000>;
+ assigned-clocks = <&cru SCLK_DP_CORE>, <&cru SCLK_SPDIF_REC_DPTX>;
+ assigned-clock-rates = <100000000>, <200000000>;
clocks = <&cru SCLK_DP_CORE>, <&cru PCLK_DP_CTRL>,
<&cru SCLK_SPDIF_REC_DPTX>, <&cru PCLK_VIO_GRF>;
clock-names = "core-clk", "pclk", "spdif", "grf";
@@ -1234,6 +1236,8 @@
reg = <0x0 0xff650800 0x0 0x40>;
interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "vpu_mmu";
+ clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -1243,6 +1247,8 @@
reg = <0x0 0xff660480 0x0 0x40>, <0x0 0xff6604c0 0x0 0x40>;
interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "vdec_mmu";
+ clocks = <&cru ACLK_VDU>, <&cru HCLK_VDU>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -1252,6 +1258,8 @@
reg = <0x0 0xff670800 0x0 0x40>;
interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "iep_mmu";
+ clocks = <&cru ACLK_IEP>, <&cru HCLK_IEP>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
status = "disabled";
};
@@ -1323,7 +1331,9 @@
<&cru ACLK_PERILP0>, <&cru HCLK_PERILP0>,
<&cru PCLK_PERILP0>, <&cru ACLK_CCI>,
<&cru HCLK_PERILP1>, <&cru PCLK_PERILP1>,
- <&cru ACLK_VIO>;
+ <&cru ACLK_VIO>, <&cru ACLK_HDCP>,
+ <&cru ACLK_GIC_PRE>,
+ <&cru PCLK_DDR>;
assigned-clock-rates =
<594000000>, <800000000>,
<1000000000>,
@@ -1332,7 +1342,9 @@
<100000000>, <100000000>,
<50000000>, <600000000>,
<100000000>, <50000000>,
- <400000000>;
+ <400000000>, <400000000>,
+ <200000000>,
+ <200000000>;
};
grf: syscon@ff770000 {
@@ -1599,7 +1611,7 @@
interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "vopl_mmu";
clocks = <&cru ACLK_VOP1>, <&cru HCLK_VOP1>;
- clock-names = "aclk", "hclk";
+ clock-names = "aclk", "iface";
power-domains = <&power RK3399_PD_VOPL>;
#iommu-cells = <0>;
status = "disabled";
@@ -1656,7 +1668,7 @@
interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "vopb_mmu";
clocks = <&cru ACLK_VOP0>, <&cru HCLK_VOP0>;
- clock-names = "aclk", "hclk";
+ clock-names = "aclk", "iface";
power-domains = <&power RK3399_PD_VOPB>;
#iommu-cells = <0>;
status = "disabled";
@@ -1667,6 +1679,8 @@
reg = <0x0 0xff914000 0x0 0x100>, <0x0 0xff915000 0x0 0x100>;
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "isp0_mmu";
+ clocks = <&cru ACLK_ISP0_NOC>, <&cru HCLK_ISP0_NOC>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
rockchip,disable-mmu-reset;
status = "disabled";
@@ -1677,6 +1691,8 @@
reg = <0x0 0xff924000 0x0 0x100>, <0x0 0xff925000 0x0 0x100>;
interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH 0>;
interrupt-names = "isp1_mmu";
+ clocks = <&cru ACLK_ISP1_NOC>, <&cru HCLK_ISP1_NOC>;
+ clock-names = "aclk", "iface";
#iommu-cells = <0>;
rockchip,disable-mmu-reset;
status = "disabled";
diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
index c32dd34..d63b56e 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
@@ -549,10 +549,13 @@
status = "disabled";
reg = <0x65000000 0x8500>;
interrupts = <0 66 4>;
+ clock-names = "ether";
clocks = <&sys_clk 6>;
+ reset-names = "ether";
resets = <&sys_rst 6>;
- phy-mode = "rmii";
+ phy-mode = "internal";
local-mac-address = [00 00 00 00 00 00];
+ socionext,syscon-phy-mode = <&soc_glue 0>;
mdio: mdio {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
index 3a5ed78..0298bd0 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
@@ -604,10 +604,13 @@
interrupts = <0 66 4>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ether_rgmii>;
+ clock-names = "ether";
clocks = <&sys_clk 6>;
+ reset-names = "ether";
resets = <&sys_rst 6>;
phy-mode = "rgmii";
local-mac-address = [00 00 00 00 00 00];
+ socionext,syscon-phy-mode = <&soc_glue 0>;
mdio: mdio {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi
index e85d6dd..2a4cf42 100644
--- a/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi
+++ b/arch/arm64/boot/dts/socionext/uniphier-pxs3.dtsi
@@ -341,7 +341,7 @@
cdns,phy-dll-delay-sdclk-hsmmc = <21>;
};
- soc-glue@5f800000 {
+ soc_glue: soc-glue@5f800000 {
compatible = "socionext,uniphier-pxs3-soc-glue",
"simple-mfd", "syscon";
reg = <0x5f800000 0x2000>;
@@ -412,10 +412,13 @@
interrupts = <0 66 4>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ether_rgmii>;
+ clock-names = "ether";
clocks = <&sys_clk 6>;
+ reset-names = "ether";
resets = <&sys_rst 6>;
phy-mode = "rgmii";
local-mac-address = [00 00 00 00 00 00];
+ socionext,syscon-phy-mode = <&soc_glue 0>;
mdio0: mdio {
#address-cells = <1>;
@@ -430,10 +433,13 @@
interrupts = <0 67 4>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_ether1_rgmii>;
+ clock-names = "ether";
clocks = <&sys_clk 7>;
+ reset-names = "ether";
resets = <&sys_rst 7>;
phy-mode = "rgmii";
local-mac-address = [00 00 00 00 00 00];
+ socionext,syscon-phy-mode = <&soc_glue 1>;
mdio1: mdio {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/sprd/sc2731.dtsi b/arch/arm64/boot/dts/sprd/sc2731.dtsi
index 4331006..98d3b4f 100644
--- a/arch/arm64/boot/dts/sprd/sc2731.dtsi
+++ b/arch/arm64/boot/dts/sprd/sc2731.dtsi
@@ -24,6 +24,17 @@
interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
};
+ pmic_eic: gpio@300 {
+ compatible = "sprd,sc27xx-eic";
+ reg = <0x300>;
+ interrupt-parent = <&sc2731_pmic>;
+ interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
regulators {
compatible = "sprd,sc27xx-regulator";
diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi
index 5dbfb79..3f5160d2 100644
--- a/arch/arm64/boot/dts/sprd/sc9860.dtsi
+++ b/arch/arm64/boot/dts/sprd/sc9860.dtsi
@@ -7,6 +7,8 @@
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
#include "whale2.dtsi"
/ {
@@ -326,7 +328,7 @@
reg = <4>;
soc_funnel_in_port1: endpoint {
slave-mode;
- remote-endpioint =
+ remote-endpoint =
<&stm_out_port>;
};
};
@@ -679,5 +681,33 @@
};
};
};
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ key-volumedown {
+ label = "Volume Down Key";
+ linux,code = <KEY_VOLUMEDOWN>;
+ gpios = <&eic_debounce 2 GPIO_ACTIVE_LOW>;
+ debounce-interval = <2>;
+ wakeup-source;
+ };
+
+ key-volumeup {
+ label = "Volume Up Key";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&pmic_eic 10 GPIO_ACTIVE_HIGH>;
+ debounce-interval = <2>;
+ wakeup-source;
+ };
+
+ key-power {
+ label = "Power Key";
+ linux,code = <KEY_POWER>;
+ gpios = <&pmic_eic 1 GPIO_ACTIVE_HIGH>;
+ debounce-interval = <2>;
+ wakeup-source;
+ };
+ };
};
};
diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi
index 66a881e..e9db910 100644
--- a/arch/arm64/boot/dts/sprd/whale2.dtsi
+++ b/arch/arm64/boot/dts/sprd/whale2.dtsi
@@ -154,6 +154,56 @@
clocks = <&aon_gate CLK_SPLK_EB>;
};
+ eic_debounce: gpio@40210000 {
+ compatible = "sprd,sc9860-eic-debounce";
+ reg = <0 0x40210000 0 0x80>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ eic_latch: gpio@40210080 {
+ compatible = "sprd,sc9860-eic-latch";
+ reg = <0 0x40210080 0 0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ eic_async: gpio@402100a0 {
+ compatible = "sprd,sc9860-eic-async";
+ reg = <0 0x402100a0 0 0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ eic_sync: gpio@402100c0 {
+ compatible = "sprd,sc9860-eic-sync";
+ reg = <0 0x402100c0 0 0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ ap_gpio: gpio@40280000 {
+ compatible = "sprd,sc9860-gpio";
+ reg = <0 0x40280000 0 0x1000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
pin_controller: pinctrl@402a0000 {
compatible = "sprd,sc9860-pinctrl";
reg = <0 0x402a0000 0 0x10000>;
@@ -164,8 +214,9 @@
reg = <0 0x40310000 0 0x1000>;
interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
timeout-sec = <12>;
- clock-names = "enable";
- clocks = <&aon_gate CLK_APCPU_WDG_EB>;
+ clock-names = "enable", "rtc_enable";
+ clocks = <&aon_gate CLK_APCPU_WDG_EB>,
+ <&aon_gate CLK_AP_WDG_RTC_EB>;
};
};
diff --git a/arch/arm64/boot/dts/synaptics/Makefile b/arch/arm64/boot/dts/synaptics/Makefile
new file mode 100644
index 0000000..de71ddd
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+# Berlin SoC Family
+dtb-$(CONFIG_ARCH_BERLIN) += berlin4ct-dmp.dtb
+dtb-$(CONFIG_ARCH_BERLIN) += berlin4ct-stb.dtb
diff --git a/arch/arm64/boot/dts/synaptics/berlin4ct-dmp.dts b/arch/arm64/boot/dts/synaptics/berlin4ct-dmp.dts
new file mode 100644
index 0000000..c64a179
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/berlin4ct-dmp.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2015 Marvell Technology Group Ltd.
+ *
+ * Author: Jisheng Zhang <jszhang@marvell.com>
+ */
+
+/dts-v1/;
+
+#include "berlin4ct.dtsi"
+
+/ {
+ model = "Marvell BG4CT DMP board";
+ compatible = "marvell,berlin4ct-dmp", "marvell,berlin4ct", "marvell,berlin";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@1000000 {
+ device_type = "memory";
+ /* the first 16MB is for firmwares' usage */
+ reg = <0 0x01000000 0 0x7f000000>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/synaptics/berlin4ct-stb.dts b/arch/arm64/boot/dts/synaptics/berlin4ct-stb.dts
new file mode 100644
index 0000000..277dccf
--- /dev/null
+++ b/arch/arm64/boot/dts/synaptics/berlin4ct-stb.dts
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/*
+ * Copyright (C) 2015 Marvell Technology Group Ltd.
+ *
+ * Author: Jisheng Zhang <jszhang@marvell.com>
+ */
+
+/dts-v1/;
+
+#include "berlin4ct.dtsi"
+
+/ {
+ model = "Marvell BG4CT STB board";
+ compatible = "marvell,berlin4ct-stb", "marvell,berlin4ct", "marvell,berlin";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@1000000 {
+ device_type = "memory";
+ /* the first 16MB is for firmwares' usage */
+ reg = <0 0x01000000 0 0x7f000000>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/marvell/berlin4ct.dtsi b/arch/arm64/boot/dts/synaptics/berlin4ct.dtsi
index d2f88b9..216767e 100644
--- a/arch/arm64/boot/dts/marvell/berlin4ct.dtsi
+++ b/arch/arm64/boot/dts/synaptics/berlin4ct.dtsi
@@ -1,45 +1,8 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (C) 2015 Marvell Technology Group Ltd.
*
* Author: Jisheng Zhang <jszhang@marvell.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>
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 17ea72b..3cfa8ca 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -53,6 +53,7 @@ CONFIG_ARCH_R8A7796=y
CONFIG_ARCH_R8A77965=y
CONFIG_ARCH_R8A77970=y
CONFIG_ARCH_R8A77980=y
+CONFIG_ARCH_R8A77990=y
CONFIG_ARCH_R8A77995=y
CONFIG_ARCH_STRATIX10=y
CONFIG_ARCH_TEGRA=y
@@ -75,6 +76,7 @@ CONFIG_PCI_HISI=y
CONFIG_PCIE_QCOM=y
CONFIG_PCIE_KIRIN=y
CONFIG_PCIE_ARMADA_8K=y
+CONFIG_PCIE_HISI_STB=y
CONFIG_PCI_AARDVARK=y
CONFIG_PCI_TEGRA=y
CONFIG_PCIE_RCAR=y
@@ -158,8 +160,10 @@ CONFIG_BT_HIDP=m
# CONFIG_BT_LE is not set
CONFIG_BT_LEDS=y
# CONFIG_BT_DEBUGFS is not set
+CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_LL=y
+CONFIG_BT_HCIUART_BCM=y
CONFIG_CFG80211=m
CONFIG_MAC80211=m
CONFIG_MAC80211_LEDS=y
@@ -170,6 +174,9 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_HISILICON_LPC=y
+CONFIG_SIMPLE_PM_BUS=y
CONFIG_MTD=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_M25P80=y
@@ -188,6 +195,9 @@ CONFIG_BLK_DEV_SD=y
CONFIG_SCSI_SAS_ATA=y
CONFIG_SCSI_HISI_SAS=y
CONFIG_SCSI_HISI_SAS_PCI=y
+CONFIG_SCSI_UFSHCD=m
+CONFIG_SCSI_UFSHCD_PLATFORM=m
+CONFIG_SCSI_UFS_QCOM=m
CONFIG_ATA=y
CONFIG_SATA_AHCI=y
CONFIG_SATA_AHCI_PLATFORM=y
@@ -207,8 +217,10 @@ CONFIG_VETH=m
CONFIG_VIRTIO_NET=y
CONFIG_AMD_XGBE=y
CONFIG_NET_XGENE=y
+CONFIG_ATL1C=m
CONFIG_MACB=y
CONFIG_THUNDER_NIC_PF=y
+CONFIG_HIX5HD2_GMAC=y
CONFIG_HNS_DSAF=y
CONFIG_HNS_ENET=y
CONFIG_E1000E=y
@@ -240,6 +252,7 @@ CONFIG_ROCKCHIP_PHY=y
CONFIG_USB_PEGASUS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
+CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=m
CONFIG_USB_NET_DM9601=m
CONFIG_USB_NET_SR9800=m
@@ -247,13 +260,19 @@ CONFIG_USB_NET_SMSC75XX=m
CONFIG_USB_NET_SMSC95XX=m
CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
+CONFIG_ATH10K=m
+CONFIG_ATH10K_PCI=m
CONFIG_BRCMFMAC=m
+CONFIG_MWIFIEX=m
+CONFIG_MWIFIEX_PCIE=m
CONFIG_WL18XX=m
CONFIG_WLCORE_SDIO=m
CONFIG_INPUT_EVDEV=y
CONFIG_KEYBOARD_ADC=m
CONFIG_KEYBOARD_CROS_EC=y
CONFIG_KEYBOARD_GPIO=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PM8941_PWRKEY=y
CONFIG_INPUT_HISI_POWERKEY=y
@@ -287,6 +306,7 @@ CONFIG_SERIAL_MVEBU_UART=y
CONFIG_SERIAL_DEV_BUS=y
CONFIG_SERIAL_DEV_CTRL_TTYPORT=y
CONFIG_VIRTIO_CONSOLE=y
+CONFIG_I2C_HID=m
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y
CONFIG_I2C_MUX_PCA954x=y
@@ -304,6 +324,7 @@ CONFIG_I2C_UNIPHIER_F=y
CONFIG_I2C_RCAR=y
CONFIG_I2C_CROS_EC_TUNNEL=y
CONFIG_SPI=y
+CONFIG_SPI_ARMADA_3700=y
CONFIG_SPI_MESON_SPICC=m
CONFIG_SPI_MESON_SPIFC=m
CONFIG_SPI_BCM2835=m
@@ -321,6 +342,7 @@ CONFIG_PINCTRL_MAX77620=y
CONFIG_PINCTRL_MSM8916=y
CONFIG_PINCTRL_MSM8994=y
CONFIG_PINCTRL_MSM8996=y
+CONFIG_PINCTRL_MT7622=y
CONFIG_PINCTRL_QDF2XXX=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_GPIO_DWAPB=y
@@ -333,6 +355,8 @@ CONFIG_GPIO_XGENE_SB=y
CONFIG_GPIO_PCA953X=y
CONFIG_GPIO_PCA953X_IRQ=y
CONFIG_GPIO_MAX77620=y
+CONFIG_POWER_AVS=y
+CONFIG_ROCKCHIP_IODOMAIN=y
CONFIG_POWER_RESET_MSM=y
CONFIG_POWER_RESET_XGENE=y
CONFIG_POWER_RESET_SYSCON=y
@@ -344,6 +368,7 @@ CONFIG_SENSORS_INA2XX=m
CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
CONFIG_CPU_THERMAL=y
CONFIG_THERMAL_EMULATION=y
+CONFIG_ARMADA_THERMAL=y
CONFIG_BRCMSTB_THERMAL=m
CONFIG_EXYNOS_THERMAL=y
CONFIG_RCAR_GEN3_THERMAL=y
@@ -362,6 +387,7 @@ CONFIG_MFD_AXP20X_RSB=y
CONFIG_MFD_CROS_EC=y
CONFIG_MFD_CROS_EC_I2C=y
CONFIG_MFD_CROS_EC_SPI=y
+CONFIG_MFD_CROS_EC_CHARDEV=m
CONFIG_MFD_EXYNOS_LPASS=m
CONFIG_MFD_HI6421_PMIC=y
CONFIG_MFD_HI655X_PMIC=y
@@ -440,7 +466,8 @@ CONFIG_SND_BCM2835_SOC_I2S=m
CONFIG_SND_SOC_SAMSUNG=y
CONFIG_SND_SOC_RCAR=m
CONFIG_SND_SOC_AK4613=m
-CONFIG_SND_SIMPLE_CARD=y
+CONFIG_SND_SIMPLE_CARD=m
+CONFIG_SND_AUDIO_GRAPH_CARD=m
CONFIG_USB=y
CONFIG_USB_OTG=y
CONFIG_USB_XHCI_HCD=y
@@ -486,6 +513,7 @@ CONFIG_MMC_SPI=y
CONFIG_MMC_SDHI=y
CONFIG_MMC_DW=y
CONFIG_MMC_DW_EXYNOS=y
+CONFIG_MMC_DW_HI3798CV200=y
CONFIG_MMC_DW_K3=y
CONFIG_MMC_DW_ROCKCHIP=y
CONFIG_MMC_SUNXI=y
@@ -515,6 +543,7 @@ CONFIG_RTC_DRV_SUN6I=y
CONFIG_RTC_DRV_ARMADA38X=y
CONFIG_RTC_DRV_TEGRA=y
CONFIG_RTC_DRV_XGENE=y
+CONFIG_RTC_DRV_CROS_EC=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2835=m
CONFIG_K3_DMA=y
@@ -557,6 +586,7 @@ CONFIG_TEGRA_IOMMU_SMMU=y
CONFIG_ARM_SMMU=y
CONFIG_ARM_SMMU_V3=y
CONFIG_QCOM_IOMMU=y
+CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_RPMSG_QCOM_SMD=y
CONFIG_RASPBERRYPI_POWER=y
CONFIG_QCOM_SMEM=y
@@ -568,12 +598,18 @@ CONFIG_ARCH_TEGRA_132_SOC=y
CONFIG_ARCH_TEGRA_210_SOC=y
CONFIG_ARCH_TEGRA_186_SOC=y
CONFIG_ARCH_TEGRA_194_SOC=y
+CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y
CONFIG_EXTCON_USB_GPIO=y
+CONFIG_EXTCON_USBC_CROS_EC=y
CONFIG_MEMORY=y
CONFIG_TEGRA_MC=y
CONFIG_IIO=y
CONFIG_EXYNOS_ADC=y
CONFIG_ROCKCHIP_SARADC=m
+CONFIG_IIO_CROS_EC_SENSORS_CORE=m
+CONFIG_IIO_CROS_EC_SENSORS=m
+CONFIG_IIO_CROS_EC_LIGHT_PROX=m
+CONFIG_IIO_CROS_EC_BARO=m
CONFIG_PWM=y
CONFIG_PWM_BCM2835=m
CONFIG_PWM_CROS_EC=m
@@ -582,21 +618,26 @@ CONFIG_PWM_RCAR=m
CONFIG_PWM_ROCKCHIP=y
CONFIG_PWM_SAMSUNG=y
CONFIG_PWM_TEGRA=m
+CONFIG_PHY_HISTB_COMBPHY=y
+CONFIG_PHY_HISI_INNO_USB2=y
CONFIG_PHY_RCAR_GEN3_USB2=y
CONFIG_PHY_RCAR_GEN3_USB3=m
CONFIG_PHY_HI6220_USB=y
CONFIG_PHY_QCOM_USB_HS=y
CONFIG_PHY_SUN4I_USB=y
CONFIG_PHY_MVEBU_CP110_COMPHY=y
+CONFIG_PHY_QCOM_QMP=m
CONFIG_PHY_ROCKCHIP_INNO_USB2=y
CONFIG_PHY_ROCKCHIP_EMMC=y
CONFIG_PHY_ROCKCHIP_PCIE=m
+CONFIG_PHY_ROCKCHIP_TYPEC=y
CONFIG_PHY_XGENE=y
CONFIG_PHY_TEGRA_XUSB=y
CONFIG_QCOM_L2_PMU=y
CONFIG_QCOM_L3_PMU=y
CONFIG_MESON_EFUSE=m
CONFIG_QCOM_QFPROM=y
+CONFIG_ROCKCHIP_EFUSE=y
CONFIG_UNIPHIER_EFUSE=y
CONFIG_TEE=y
CONFIG_OPTEE=y
diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c
index 253188f..e3e5095 100644
--- a/arch/arm64/crypto/aes-glue.c
+++ b/arch/arm64/crypto/aes-glue.c
@@ -223,8 +223,8 @@ static int ctr_encrypt(struct skcipher_request *req)
kernel_neon_begin();
aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
(u8 *)ctx->key_enc, rounds, blocks, walk.iv);
- err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
kernel_neon_end();
+ err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE);
}
if (walk.nbytes) {
u8 __aligned(8) tail[AES_BLOCK_SIZE];
diff --git a/arch/arm64/include/asm/cacheflush.h b/arch/arm64/include/asm/cacheflush.h
index 0094c66..d264a72 100644
--- a/arch/arm64/include/asm/cacheflush.h
+++ b/arch/arm64/include/asm/cacheflush.h
@@ -36,7 +36,7 @@
* Start addresses are inclusive and end addresses are exclusive; start
* addresses should be rounded down, end addresses up.
*
- * See Documentation/cachetlb.txt for more information. Please note that
+ * See Documentation/core-api/cachetlb.rst for more information. Please note that
* the implementation assumes non-aliasing VIPT D-cache and (aliasing)
* VIPT I-cache.
*
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index 55bc1f0..1717ba1 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -11,9 +11,7 @@
#include <asm/cpucaps.h>
#include <asm/cputype.h>
-#include <asm/fpsimd.h>
#include <asm/hwcap.h>
-#include <asm/sigcontext.h>
#include <asm/sysreg.h>
/*
@@ -510,33 +508,6 @@ static inline bool system_supports_sve(void)
cpus_have_const_cap(ARM64_SVE);
}
-/*
- * Read the pseudo-ZCR used by cpufeatures to identify the supported SVE
- * vector length.
- *
- * Use only if SVE is present.
- * This function clobbers the SVE vector length.
- */
-static inline u64 read_zcr_features(void)
-{
- u64 zcr;
- unsigned int vq_max;
-
- /*
- * Set the maximum possible VL, and write zeroes to all other
- * bits to see if they stick.
- */
- sve_kernel_enable(NULL);
- write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL1);
-
- zcr = read_sysreg_s(SYS_ZCR_EL1);
- zcr &= ~(u64)ZCR_ELx_LEN_MASK; /* find sticky 1s outside LEN field */
- vq_max = sve_vq_from_vl(sve_get_vl());
- zcr |= vq_max - 1; /* set LEN field to maximum effective value */
-
- return zcr;
-}
-
#define ARM64_SSBD_UNKNOWN -1
#define ARM64_SSBD_FORCE_DISABLE 0
#define ARM64_SSBD_KERNEL 1
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index aa7162a..fa92747 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -18,6 +18,8 @@
#include <asm/ptrace.h>
#include <asm/errno.h>
+#include <asm/processor.h>
+#include <asm/sigcontext.h>
#ifndef __ASSEMBLY__
@@ -41,6 +43,8 @@ struct task_struct;
extern void fpsimd_save_state(struct user_fpsimd_state *state);
extern void fpsimd_load_state(struct user_fpsimd_state *state);
+extern void fpsimd_save(void);
+
extern void fpsimd_thread_switch(struct task_struct *next);
extern void fpsimd_flush_thread(void);
@@ -49,12 +53,27 @@ extern void fpsimd_preserve_current_state(void);
extern void fpsimd_restore_current_state(void);
extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
+extern void fpsimd_bind_task_to_cpu(void);
+extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state);
+
extern void fpsimd_flush_task_state(struct task_struct *target);
+extern void fpsimd_flush_cpu_state(void);
extern void sve_flush_cpu_state(void);
/* Maximum VL that SVE VL-agnostic software can transparently support */
#define SVE_VL_ARCH_MAX 0x100
+/* Offset of FFR in the SVE register dump */
+static inline size_t sve_ffr_offset(int vl)
+{
+ return SVE_SIG_FFR_OFFSET(sve_vq_from_vl(vl)) - SVE_SIG_REGS_OFFSET;
+}
+
+static inline void *sve_pffr(struct thread_struct *thread)
+{
+ return (char *)thread->sve_state + sve_ffr_offset(thread->sve_vl);
+}
+
extern void sve_save_state(void *state, u32 *pfpsr);
extern void sve_load_state(void const *state, u32 const *pfpsr,
unsigned long vq_minus_1);
@@ -63,6 +82,8 @@ extern unsigned int sve_get_vl(void);
struct arm64_cpu_capabilities;
extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
+extern u64 read_zcr_features(void);
+
extern int __ro_after_init sve_max_vl;
#ifdef CONFIG_ARM64_SVE
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 951b207..102b5a5 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -33,19 +33,19 @@
/* The hyp-stub will return this for any kvm_call_hyp() call */
#define ARM_EXCEPTION_HYP_GONE HVC_STUB_ERR
-#define KVM_ARM64_DEBUG_DIRTY_SHIFT 0
-#define KVM_ARM64_DEBUG_DIRTY (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
+#ifndef __ASSEMBLY__
+
+#include <linux/mm.h>
/* Translate a kernel address of @sym into its equivalent linear mapping */
#define kvm_ksym_ref(sym) \
({ \
void *val = &sym; \
if (!is_kernel_in_hyp_mode()) \
- val = phys_to_virt((u64)&sym - kimage_voffset); \
+ val = lm_alias(&sym); \
val; \
})
-#ifndef __ASSEMBLY__
struct kvm;
struct kvm_vcpu;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 95d8a0e..fe8777b 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -30,6 +30,7 @@
#include <asm/kvm.h>
#include <asm/kvm_asm.h>
#include <asm/kvm_mmio.h>
+#include <asm/thread_info.h>
#define __KVM_HAVE_ARCH_INTC_INITIALIZED
@@ -219,8 +220,8 @@ struct kvm_vcpu_arch {
/* State of various workarounds, see kvm_asm.h for bit assignment */
u64 workaround_flags;
- /* Guest debug state */
- u64 debug_flags;
+ /* Miscellaneous vcpu state flags */
+ u64 flags;
/*
* We maintain more than a single set of debug registers to support
@@ -241,6 +242,10 @@ struct kvm_vcpu_arch {
/* Pointer to host CPU context */
kvm_cpu_context_t *host_cpu_context;
+
+ struct thread_info *host_thread_info; /* hyp VA */
+ struct user_fpsimd_state *host_fpsimd_state; /* hyp VA */
+
struct {
/* {Break,watch}point registers */
struct kvm_guest_debug_arch regs;
@@ -296,6 +301,13 @@ struct kvm_vcpu_arch {
bool sysregs_loaded_on_cpu;
};
+/* vcpu_arch flags field values: */
+#define KVM_ARM64_DEBUG_DIRTY (1 << 0)
+#define KVM_ARM64_FP_ENABLED (1 << 1) /* guest FP regs loaded */
+#define KVM_ARM64_FP_HOST (1 << 2) /* host FP regs loaded */
+#define KVM_ARM64_HOST_SVE_IN_USE (1 << 3) /* backup for host TIF_SVE */
+#define KVM_ARM64_HOST_SVE_ENABLED (1 << 4) /* SVE enabled for EL0 */
+
#define vcpu_gp_regs(v) (&(v)->arch.ctxt.gp_regs)
/*
@@ -397,6 +409,19 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
kvm_call_hyp(__kvm_set_tpidr_el2, tpidr_el2);
}
+static inline bool kvm_arch_check_sve_has_vhe(void)
+{
+ /*
+ * The Arm architecture specifies that implementation of SVE
+ * requires VHE also to be implemented. The KVM code for arm64
+ * relies on this when SVE is present:
+ */
+ if (system_supports_sve())
+ return has_vhe();
+ else
+ return true;
+}
+
static inline void kvm_arch_hardware_unsetup(void) {}
static inline void kvm_arch_sync_events(struct kvm *kvm) {}
static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
@@ -423,15 +448,18 @@ static inline void __cpu_init_stage2(void)
"PARange is %d bits, unsupported configuration!", parange);
}
-/*
- * All host FP/SIMD state is restored on guest exit, so nothing needs
- * doing here except in the SVE case:
-*/
-static inline void kvm_fpsimd_flush_cpu_state(void)
+/* Guest/host FPSIMD coordination helpers */
+int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
+void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu);
+void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu);
+void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu);
+
+#ifdef CONFIG_KVM /* Avoid conflicts with core headers if CONFIG_KVM=n */
+static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
{
- if (system_supports_sve())
- sve_flush_cpu_state();
+ return kvm_arch_vcpu_run_map_fp(vcpu);
}
+#endif
static inline void kvm_arm_vhe_guest_enter(void)
{
@@ -481,4 +509,8 @@ static inline int kvm_arm_have_ssbd(void)
void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu);
void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu);
+#define __KVM_HAVE_ARCH_VM_ALLOC
+struct kvm *kvm_arch_alloc_vm(void);
+void kvm_arch_free_vm(struct kvm *kvm);
+
#endif /* __ARM64_KVM_HOST_H__ */
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 65ab83e..a73ae1e 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -158,7 +158,9 @@ static inline void arch_thread_struct_whitelist(unsigned long *offset,
/* Sync TPIDR_EL0 back to thread_struct for current */
void tls_preserve_current_state(void);
-#define INIT_THREAD { }
+#define INIT_THREAD { \
+ .fpsimd_cpu = NR_CPUS, \
+}
static inline void start_thread_common(struct pt_regs *regs, unsigned long pc)
{
@@ -249,6 +251,17 @@ void cpu_clear_disr(const struct arm64_cpu_capabilities *__unused);
extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */
extern void __init minsigstksz_setup(void);
+/*
+ * Not at the top of the file due to a direct #include cycle between
+ * <asm/fpsimd.h> and <asm/processor.h>. Deferring this #include
+ * ensures that contents of processor.h are visible to fpsimd.h even if
+ * processor.h is included first.
+ *
+ * These prctl helpers are the only things in this file that require
+ * fpsimd.h. The core code expects them to be in this header.
+ */
+#include <asm/fpsimd.h>
+
/* Userspace interface for PR_SVE_{SET,GET}_VL prctl()s: */
#define SVE_SET_VL(arg) sve_set_current_vl(arg)
#define SVE_GET_VL() sve_get_current_vl()
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 6171178..a8f8481 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -728,6 +728,17 @@ asm(
asm volatile("msr_s " __stringify(r) ", %x0" : : "rZ" (__val)); \
} while (0)
+/*
+ * Modify bits in a sysreg. Bits in the clear mask are zeroed, then bits in the
+ * set mask are set. Other bits are left as-is.
+ */
+#define sysreg_clear_set(sysreg, clear, set) do { \
+ u64 __scs_val = read_sysreg(sysreg); \
+ u64 __scs_new = (__scs_val & ~(u64)(clear)) | (set); \
+ if (__scs_new != __scs_val) \
+ write_sysreg(__scs_new, sysreg); \
+} while (0)
+
static inline void config_sctlr_el1(u32 clear, u32 set)
{
u32 val;
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index cbcf11b..cb2c10a 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -45,12 +45,6 @@ struct thread_info {
int preempt_count; /* 0 => preemptable, <0 => bug */
};
-#define INIT_THREAD_INFO(tsk) \
-{ \
- .preempt_count = INIT_PREEMPT_COUNT, \
- .addr_limit = KERNEL_DS, \
-}
-
#define thread_saved_pc(tsk) \
((unsigned long)(tsk->thread.cpu_context.pc))
#define thread_saved_sp(tsk) \
@@ -118,5 +112,12 @@ void arch_release_task_struct(struct task_struct *tsk);
_TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
_TIF_NOHZ)
+#define INIT_THREAD_INFO(tsk) \
+{ \
+ .flags = _TIF_FOREIGN_FPSTATE, \
+ .preempt_count = INIT_PREEMPT_COUNT, \
+ .addr_limit = KERNEL_DS, \
+}
+
#endif /* __KERNEL__ */
#endif /* __ASM_THREAD_INFO_H */
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 04b3256..4e76630 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -91,6 +91,7 @@ struct kvm_regs {
#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
#define KVM_VGIC_ITS_ADDR_TYPE 4
+#define KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION 5
#define KVM_VGIC_V3_DIST_SIZE SZ_64K
#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index 97d45d5..d4707ab 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -234,8 +234,8 @@ static void __init register_insn_emulation_sysctl(void)
struct insn_emulation *insn;
struct ctl_table *insns_sysctl, *sysctl;
- insns_sysctl = kzalloc(sizeof(*sysctl) * (nr_insn_emulated + 1),
- GFP_KERNEL);
+ insns_sysctl = kcalloc(nr_insn_emulated + 1, sizeof(*sysctl),
+ GFP_KERNEL);
raw_spin_lock_irqsave(&insn_emulation_lock, flags);
list_for_each_entry(insn, &insn_emulation, node) {
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index d2856b1..f24892a 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -937,7 +937,7 @@ static int __init parse_kpti(char *str)
__kpti_forced = enabled ? 1 : -1;
return 0;
}
-__setup("kpti=", parse_kpti);
+early_param("kpti", parse_kpti);
#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */
#ifdef CONFIG_ARM64_HW_AFDBM
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 3b527ae..84c68b1 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -36,12 +36,14 @@
#include <linux/sched/task_stack.h>
#include <linux/signal.h>
#include <linux/slab.h>
+#include <linux/stddef.h>
#include <linux/sysctl.h>
#include <asm/esr.h>
#include <asm/fpsimd.h>
#include <asm/cpufeature.h>
#include <asm/cputype.h>
+#include <asm/processor.h>
#include <asm/simd.h>
#include <asm/sigcontext.h>
#include <asm/sysreg.h>
@@ -117,7 +119,6 @@
*/
struct fpsimd_last_state_struct {
struct user_fpsimd_state *st;
- bool sve_in_use;
};
static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state);
@@ -158,19 +159,6 @@ static void sve_free(struct task_struct *task)
__sve_free(task);
}
-
-/* Offset of FFR in the SVE register dump */
-static size_t sve_ffr_offset(int vl)
-{
- return SVE_SIG_FFR_OFFSET(sve_vq_from_vl(vl)) - SVE_SIG_REGS_OFFSET;
-}
-
-static void *sve_pffr(struct task_struct *task)
-{
- return (char *)task->thread.sve_state +
- sve_ffr_offset(task->thread.sve_vl);
-}
-
static void change_cpacr(u64 val, u64 mask)
{
u64 cpacr = read_sysreg(CPACR_EL1);
@@ -251,31 +239,24 @@ static void task_fpsimd_load(void)
WARN_ON(!in_softirq() && !irqs_disabled());
if (system_supports_sve() && test_thread_flag(TIF_SVE))
- sve_load_state(sve_pffr(current),
+ sve_load_state(sve_pffr(&current->thread),
&current->thread.uw.fpsimd_state.fpsr,
sve_vq_from_vl(current->thread.sve_vl) - 1);
else
fpsimd_load_state(&current->thread.uw.fpsimd_state);
-
- if (system_supports_sve()) {
- /* Toggle SVE trapping for userspace if needed */
- if (test_thread_flag(TIF_SVE))
- sve_user_enable();
- else
- sve_user_disable();
-
- /* Serialised by exception return to user */
- }
}
/*
- * Ensure current's FPSIMD/SVE storage in thread_struct is up to date
- * with respect to the CPU registers.
+ * Ensure FPSIMD/SVE storage in memory for the loaded context is up to
+ * date with respect to the CPU registers.
*
* Softirqs (and preemption) must be disabled.
*/
-static void task_fpsimd_save(void)
+void fpsimd_save(void)
{
+ struct user_fpsimd_state *st = __this_cpu_read(fpsimd_last_state.st);
+ /* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */
+
WARN_ON(!in_softirq() && !irqs_disabled());
if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {
@@ -290,10 +271,9 @@ static void task_fpsimd_save(void)
return;
}
- sve_save_state(sve_pffr(current),
- &current->thread.uw.fpsimd_state.fpsr);
+ sve_save_state(sve_pffr(&current->thread), &st->fpsr);
} else
- fpsimd_save_state(&current->thread.uw.fpsimd_state);
+ fpsimd_save_state(st);
}
}
@@ -588,7 +568,7 @@ int sve_set_vector_length(struct task_struct *task,
if (task == current) {
local_bh_disable();
- task_fpsimd_save();
+ fpsimd_save();
set_thread_flag(TIF_FOREIGN_FPSTATE);
}
@@ -608,10 +588,8 @@ int sve_set_vector_length(struct task_struct *task,
task->thread.sve_vl = vl;
out:
- if (flags & PR_SVE_VL_INHERIT)
- set_tsk_thread_flag(task, TIF_SVE_VL_INHERIT);
- else
- clear_tsk_thread_flag(task, TIF_SVE_VL_INHERIT);
+ update_tsk_thread_flag(task, TIF_SVE_VL_INHERIT,
+ flags & PR_SVE_VL_INHERIT);
return 0;
}
@@ -755,6 +733,33 @@ void sve_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
isb();
}
+/*
+ * Read the pseudo-ZCR used by cpufeatures to identify the supported SVE
+ * vector length.
+ *
+ * Use only if SVE is present.
+ * This function clobbers the SVE vector length.
+ */
+u64 read_zcr_features(void)
+{
+ u64 zcr;
+ unsigned int vq_max;
+
+ /*
+ * Set the maximum possible VL, and write zeroes to all other
+ * bits to see if they stick.
+ */
+ sve_kernel_enable(NULL);
+ write_sysreg_s(ZCR_ELx_LEN_MASK, SYS_ZCR_EL1);
+
+ zcr = read_sysreg_s(SYS_ZCR_EL1);
+ zcr &= ~(u64)ZCR_ELx_LEN_MASK; /* find sticky 1s outside LEN field */
+ vq_max = sve_vq_from_vl(sve_get_vl());
+ zcr |= vq_max - 1; /* set LEN field to maximum effective value */
+
+ return zcr;
+}
+
void __init sve_setup(void)
{
u64 zcr;
@@ -829,7 +834,7 @@ asmlinkage void do_sve_acc(unsigned int esr, struct pt_regs *regs)
local_bh_disable();
- task_fpsimd_save();
+ fpsimd_save();
fpsimd_to_sve(current);
/* Force ret_to_user to reload the registers: */
@@ -882,31 +887,25 @@ asmlinkage void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs)
void fpsimd_thread_switch(struct task_struct *next)
{
+ bool wrong_task, wrong_cpu;
+
if (!system_supports_fpsimd())
return;
+
+ /* Save unsaved fpsimd state, if any: */
+ fpsimd_save();
+
/*
- * Save the current FPSIMD state to memory, but only if whatever is in
- * the registers is in fact the most recent userland FPSIMD state of
- * 'current'.
+ * Fix up TIF_FOREIGN_FPSTATE to correctly describe next's
+ * state. For kernel threads, FPSIMD registers are never loaded
+ * and wrong_task and wrong_cpu will always be true.
*/
- if (current->mm)
- task_fpsimd_save();
+ wrong_task = __this_cpu_read(fpsimd_last_state.st) !=
+ &next->thread.uw.fpsimd_state;
+ wrong_cpu = next->thread.fpsimd_cpu != smp_processor_id();
- if (next->mm) {
- /*
- * If we are switching to a task whose most recent userland
- * FPSIMD state is already in the registers of *this* cpu,
- * we can skip loading the state from memory. Otherwise, set
- * the TIF_FOREIGN_FPSTATE flag so the state will be loaded
- * upon the next return to userland.
- */
- if (__this_cpu_read(fpsimd_last_state.st) ==
- &next->thread.uw.fpsimd_state
- && next->thread.fpsimd_cpu == smp_processor_id())
- clear_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE);
- else
- set_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE);
- }
+ update_tsk_thread_flag(next, TIF_FOREIGN_FPSTATE,
+ wrong_task || wrong_cpu);
}
void fpsimd_flush_thread(void)
@@ -972,7 +971,7 @@ void fpsimd_preserve_current_state(void)
return;
local_bh_disable();
- task_fpsimd_save();
+ fpsimd_save();
local_bh_enable();
}
@@ -992,14 +991,33 @@ void fpsimd_signal_preserve_current_state(void)
* Associate current's FPSIMD context with this cpu
* Preemption must be disabled when calling this function.
*/
-static void fpsimd_bind_to_cpu(void)
+void fpsimd_bind_task_to_cpu(void)
{
struct fpsimd_last_state_struct *last =
this_cpu_ptr(&fpsimd_last_state);
last->st = &current->thread.uw.fpsimd_state;
- last->sve_in_use = test_thread_flag(TIF_SVE);
current->thread.fpsimd_cpu = smp_processor_id();
+
+ if (system_supports_sve()) {
+ /* Toggle SVE trapping for userspace if needed */
+ if (test_thread_flag(TIF_SVE))
+ sve_user_enable();
+ else
+ sve_user_disable();
+
+ /* Serialised by exception return to user */
+ }
+}
+
+void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st)
+{
+ struct fpsimd_last_state_struct *last =
+ this_cpu_ptr(&fpsimd_last_state);
+
+ WARN_ON(!in_softirq() && !irqs_disabled());
+
+ last->st = st;
}
/*
@@ -1016,7 +1034,7 @@ void fpsimd_restore_current_state(void)
if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE)) {
task_fpsimd_load();
- fpsimd_bind_to_cpu();
+ fpsimd_bind_task_to_cpu();
}
local_bh_enable();
@@ -1039,9 +1057,9 @@ void fpsimd_update_current_state(struct user_fpsimd_state const *state)
fpsimd_to_sve(current);
task_fpsimd_load();
+ fpsimd_bind_task_to_cpu();
- if (test_and_clear_thread_flag(TIF_FOREIGN_FPSTATE))
- fpsimd_bind_to_cpu();
+ clear_thread_flag(TIF_FOREIGN_FPSTATE);
local_bh_enable();
}
@@ -1054,29 +1072,12 @@ void fpsimd_flush_task_state(struct task_struct *t)
t->thread.fpsimd_cpu = NR_CPUS;
}
-static inline void fpsimd_flush_cpu_state(void)
+void fpsimd_flush_cpu_state(void)
{
__this_cpu_write(fpsimd_last_state.st, NULL);
+ set_thread_flag(TIF_FOREIGN_FPSTATE);
}
-/*
- * Invalidate any task SVE state currently held in this CPU's regs.
- *
- * This is used to prevent the kernel from trying to reuse SVE register data
- * that is detroyed by KVM guest enter/exit. This function should go away when
- * KVM SVE support is implemented. Don't use it for anything else.
- */
-#ifdef CONFIG_ARM64_SVE
-void sve_flush_cpu_state(void)
-{
- struct fpsimd_last_state_struct const *last =
- this_cpu_ptr(&fpsimd_last_state);
-
- if (last->st && last->sve_in_use)
- fpsimd_flush_cpu_state();
-}
-#endif /* CONFIG_ARM64_SVE */
-
#ifdef CONFIG_KERNEL_MODE_NEON
DEFINE_PER_CPU(bool, kernel_neon_busy);
@@ -1110,11 +1111,8 @@ void kernel_neon_begin(void)
__this_cpu_write(kernel_neon_busy, true);
- /* Save unsaved task fpsimd state, if any: */
- if (current->mm) {
- task_fpsimd_save();
- set_thread_flag(TIF_FOREIGN_FPSTATE);
- }
+ /* Save unsaved fpsimd state, if any: */
+ fpsimd_save();
/* Invalidate any task state remaining in the fpsimd regs: */
fpsimd_flush_cpu_state();
@@ -1236,13 +1234,10 @@ static int fpsimd_cpu_pm_notifier(struct notifier_block *self,
{
switch (cmd) {
case CPU_PM_ENTER:
- if (current->mm)
- task_fpsimd_save();
+ fpsimd_save();
fpsimd_flush_cpu_state();
break;
case CPU_PM_EXIT:
- if (current->mm)
- set_thread_flag(TIF_FOREIGN_FPSTATE);
break;
case CPU_PM_ENTER_FAILED:
default:
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index f08a2ed..e10bc363 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -59,7 +59,7 @@
#include <asm/processor.h>
#include <asm/stacktrace.h>
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index bd73264..5c338ce 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -44,6 +44,7 @@
#include <asm/compat.h>
#include <asm/cpufeature.h>
#include <asm/debug-monitors.h>
+#include <asm/fpsimd.h>
#include <asm/pgtable.h>
#include <asm/stacktrace.h>
#include <asm/syscall.h>
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index f3e2e3ae..2faa986 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -179,7 +179,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
* This is the secondary CPU boot entry. We're using this CPUs
* idle thread stack, but a set of temporary page tables.
*/
-asmlinkage void secondary_start_kernel(void)
+asmlinkage notrace void secondary_start_kernel(void)
{
u64 mpidr = read_cpuid_mpidr() & MPIDR_HWID_BITMASK;
struct mm_struct *mm = &init_mm;
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index a2e3a5a..47b23bf 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -39,6 +39,7 @@ config KVM
select HAVE_KVM_IRQ_ROUTING
select IRQ_BYPASS_MANAGER
select HAVE_KVM_IRQ_BYPASS
+ select HAVE_KVM_VCPU_RUN_PID_CHANGE
---help---
Support hosting virtualized guest machines.
We don't support KVM with 16K page tables yet, due to the multiple
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 93afff9..0f2a135 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -19,7 +19,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o va_layout.o
kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
kvm-$(CONFIG_KVM_ARM_HOST) += guest.o debug.o reset.o sys_regs.o sys_regs_generic_v8.o
-kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += vgic-sys-reg-v3.o fpsimd.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/aarch32.o
kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic.o
diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
index a1f4ebd..00d4223 100644
--- a/arch/arm64/kvm/debug.c
+++ b/arch/arm64/kvm/debug.c
@@ -103,7 +103,7 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu)
*
* Additionally, KVM only traps guest accesses to the debug registers if
* the guest is not actively using them (see the KVM_ARM64_DEBUG_DIRTY
- * flag on vcpu->arch.debug_flags). Since the guest must not interfere
+ * flag on vcpu->arch.flags). Since the guest must not interfere
* with the hardware state when debugging the guest, we must ensure that
* trapping is enabled whenever we are debugging the guest using the
* debug registers.
@@ -111,7 +111,7 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu)
void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
{
- bool trap_debug = !(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY);
+ bool trap_debug = !(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY);
unsigned long mdscr;
trace_kvm_arm_setup_debug(vcpu, vcpu->guest_debug);
@@ -184,7 +184,7 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
vcpu_write_sys_reg(vcpu, mdscr, MDSCR_EL1);
vcpu->arch.debug_ptr = &vcpu->arch.external_debug_state;
- vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+ vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
trap_debug = true;
trace_kvm_arm_set_regset("BKPTS", get_num_brps(),
@@ -206,7 +206,7 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu)
/* If KDE or MDE are set, perform a full save/restore cycle. */
if (vcpu_read_sys_reg(vcpu, MDSCR_EL1) & (DBG_MDSCR_KDE | DBG_MDSCR_MDE))
- vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+ vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
trace_kvm_arm_set_dreg32("MDCR_EL2", vcpu->arch.mdcr_el2);
trace_kvm_arm_set_dreg32("MDSCR_EL1", vcpu_read_sys_reg(vcpu, MDSCR_EL1));
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
new file mode 100644
index 0000000..aac7808
--- /dev/null
+++ b/arch/arm64/kvm/fpsimd.c
@@ -0,0 +1,128 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * arch/arm64/kvm/fpsimd.c: Guest/host FPSIMD context coordination helpers
+ *
+ * Copyright 2018 Arm Limited
+ * Author: Dave Martin <Dave.Martin@arm.com>
+ */
+#include <linux/irqflags.h>
+#include <linux/sched.h>
+#include <linux/thread_info.h>
+#include <linux/kvm_host.h>
+#include <asm/kvm_asm.h>
+#include <asm/kvm_host.h>
+#include <asm/kvm_mmu.h>
+#include <asm/sysreg.h>
+
+/*
+ * Called on entry to KVM_RUN unless this vcpu previously ran at least
+ * once and the most recent prior KVM_RUN for this vcpu was called from
+ * the same task as current (highly likely).
+ *
+ * This is guaranteed to execute before kvm_arch_vcpu_load_fp(vcpu),
+ * such that on entering hyp the relevant parts of current are already
+ * mapped.
+ */
+int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu)
+{
+ int ret;
+
+ struct thread_info *ti = &current->thread_info;
+ struct user_fpsimd_state *fpsimd = &current->thread.uw.fpsimd_state;
+
+ /*
+ * Make sure the host task thread flags and fpsimd state are
+ * visible to hyp:
+ */
+ ret = create_hyp_mappings(ti, ti + 1, PAGE_HYP);
+ if (ret)
+ goto error;
+
+ ret = create_hyp_mappings(fpsimd, fpsimd + 1, PAGE_HYP);
+ if (ret)
+ goto error;
+
+ vcpu->arch.host_thread_info = kern_hyp_va(ti);
+ vcpu->arch.host_fpsimd_state = kern_hyp_va(fpsimd);
+error:
+ return ret;
+}
+
+/*
+ * Prepare vcpu for saving the host's FPSIMD state and loading the guest's.
+ * The actual loading is done by the FPSIMD access trap taken to hyp.
+ *
+ * Here, we just set the correct metadata to indicate that the FPSIMD
+ * state in the cpu regs (if any) belongs to current on the host.
+ *
+ * TIF_SVE is backed up here, since it may get clobbered with guest state.
+ * This flag is restored by kvm_arch_vcpu_put_fp(vcpu).
+ */
+void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
+{
+ BUG_ON(!current->mm);
+
+ vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED |
+ KVM_ARM64_HOST_SVE_IN_USE |
+ KVM_ARM64_HOST_SVE_ENABLED);
+ vcpu->arch.flags |= KVM_ARM64_FP_HOST;
+
+ if (test_thread_flag(TIF_SVE))
+ vcpu->arch.flags |= KVM_ARM64_HOST_SVE_IN_USE;
+
+ if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN)
+ vcpu->arch.flags |= KVM_ARM64_HOST_SVE_ENABLED;
+}
+
+/*
+ * If the guest FPSIMD state was loaded, update the host's context
+ * tracking data mark the CPU FPSIMD regs as dirty and belonging to vcpu
+ * so that they will be written back if the kernel clobbers them due to
+ * kernel-mode NEON before re-entry into the guest.
+ */
+void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
+{
+ WARN_ON_ONCE(!irqs_disabled());
+
+ if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
+ fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.gp_regs.fp_regs);
+ clear_thread_flag(TIF_FOREIGN_FPSTATE);
+ clear_thread_flag(TIF_SVE);
+ }
+}
+
+/*
+ * Write back the vcpu FPSIMD regs if they are dirty, and invalidate the
+ * cpu FPSIMD regs so that they can't be spuriously reused if this vcpu
+ * disappears and another task or vcpu appears that recycles the same
+ * struct fpsimd_state.
+ */
+void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
+ /* Clean guest FP state to memory and invalidate cpu view */
+ fpsimd_save();
+ fpsimd_flush_cpu_state();
+ } else if (system_supports_sve()) {
+ /*
+ * The FPSIMD/SVE state in the CPU has not been touched, and we
+ * have SVE (and VHE): CPACR_EL1 (alias CPTR_EL2) has been
+ * reset to CPACR_EL1_DEFAULT by the Hyp code, disabling SVE
+ * for EL0. To avoid spurious traps, restore the trap state
+ * seen by kvm_arch_vcpu_load_fp():
+ */
+ if (vcpu->arch.flags & KVM_ARM64_HOST_SVE_ENABLED)
+ sysreg_clear_set(CPACR_EL1, 0, CPACR_EL1_ZEN_EL0EN);
+ else
+ sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
+ }
+
+ update_thread_flag(TIF_SVE,
+ vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE);
+
+ local_irq_restore(flags);
+}
diff --git a/arch/arm64/kvm/hyp/debug-sr.c b/arch/arm64/kvm/hyp/debug-sr.c
index 3e717f6..5000976 100644
--- a/arch/arm64/kvm/hyp/debug-sr.c
+++ b/arch/arm64/kvm/hyp/debug-sr.c
@@ -163,7 +163,7 @@ void __hyp_text __debug_switch_to_guest(struct kvm_vcpu *vcpu)
if (!has_vhe())
__debug_save_spe_nvhe(&vcpu->arch.host_debug_state.pmscr_el1);
- if (!(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY))
+ if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
return;
host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
@@ -185,7 +185,7 @@ void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu)
if (!has_vhe())
__debug_restore_spe_nvhe(vcpu->arch.host_debug_state.pmscr_el1);
- if (!(vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY))
+ if (!(vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY))
return;
host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
@@ -196,7 +196,7 @@ void __hyp_text __debug_switch_to_host(struct kvm_vcpu *vcpu)
__debug_save_state(vcpu, guest_dbg, guest_ctxt);
__debug_restore_state(vcpu, host_dbg, host_ctxt);
- vcpu->arch.debug_flags &= ~KVM_ARM64_DEBUG_DIRTY;
+ vcpu->arch.flags &= ~KVM_ARM64_DEBUG_DIRTY;
}
u32 __hyp_text __kvm_get_mdcr_el2(void)
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index e41a161..fad1e16 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -166,46 +166,3 @@ abort_guest_exit_end:
orr x0, x0, x5
1: ret
ENDPROC(__guest_exit)
-
-ENTRY(__fpsimd_guest_restore)
- // x0: esr
- // x1: vcpu
- // x2-x29,lr: vcpu regs
- // vcpu x0-x1 on the stack
- stp x2, x3, [sp, #-16]!
- stp x4, lr, [sp, #-16]!
-
-alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
- mrs x2, cptr_el2
- bic x2, x2, #CPTR_EL2_TFP
- msr cptr_el2, x2
-alternative_else
- mrs x2, cpacr_el1
- orr x2, x2, #CPACR_EL1_FPEN
- msr cpacr_el1, x2
-alternative_endif
- isb
-
- mov x3, x1
-
- ldr x0, [x3, #VCPU_HOST_CONTEXT]
- kern_hyp_va x0
- add x0, x0, #CPU_GP_REG_OFFSET(CPU_FP_REGS)
- bl __fpsimd_save_state
-
- add x2, x3, #VCPU_CONTEXT
- add x0, x2, #CPU_GP_REG_OFFSET(CPU_FP_REGS)
- bl __fpsimd_restore_state
-
- // Skip restoring fpexc32 for AArch64 guests
- mrs x1, hcr_el2
- tbnz x1, #HCR_RW_SHIFT, 1f
- ldr x4, [x3, #VCPU_FPEXC32_EL2]
- msr fpexc32_el2, x4
-1:
- ldp x4, lr, [sp], #16
- ldp x2, x3, [sp], #16
- ldp x0, x1, [sp], #16
-
- eret
-ENDPROC(__fpsimd_guest_restore)
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index 05d8369..24b4fba 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -149,25 +149,6 @@ wa_epilogue:
el1_trap:
get_vcpu_ptr x1, x0
-
- mrs x0, esr_el2
- lsr x0, x0, #ESR_ELx_EC_SHIFT
- /*
- * x0: ESR_EC
- * x1: vcpu pointer
- */
-
- /*
- * We trap the first access to the FP/SIMD to save the host context
- * and restore the guest context lazily.
- * If FP/SIMD is not implemented, handle the trap and inject an
- * undefined instruction exception to the guest.
- */
-alternative_if_not ARM64_HAS_NO_FPSIMD
- cmp x0, #ESR_ELx_EC_FP_ASIMD
- b.eq __fpsimd_guest_restore
-alternative_else_nop_endif
-
mov x0, #ARM_EXCEPTION_TRAP
b __guest_exit
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index c50cedc..d496ef5 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -22,21 +22,25 @@
#include <kvm/arm_psci.h>
+#include <asm/cpufeature.h>
#include <asm/kvm_asm.h>
#include <asm/kvm_emulate.h>
+#include <asm/kvm_host.h>
#include <asm/kvm_hyp.h>
#include <asm/kvm_mmu.h>
#include <asm/fpsimd.h>
#include <asm/debug-monitors.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
-static bool __hyp_text __fpsimd_enabled_nvhe(void)
+/* Check whether the FP regs were dirtied while in the host-side run loop: */
+static bool __hyp_text update_fp_enabled(struct kvm_vcpu *vcpu)
{
- return !(read_sysreg(cptr_el2) & CPTR_EL2_TFP);
-}
+ if (vcpu->arch.host_thread_info->flags & _TIF_FOREIGN_FPSTATE)
+ vcpu->arch.flags &= ~(KVM_ARM64_FP_ENABLED |
+ KVM_ARM64_FP_HOST);
-static bool fpsimd_enabled_vhe(void)
-{
- return !!(read_sysreg(cpacr_el1) & CPACR_EL1_FPEN);
+ return !!(vcpu->arch.flags & KVM_ARM64_FP_ENABLED);
}
/* Save the 32-bit only FPSIMD system register state */
@@ -93,7 +97,10 @@ static void activate_traps_vhe(struct kvm_vcpu *vcpu)
val = read_sysreg(cpacr_el1);
val |= CPACR_EL1_TTA;
- val &= ~(CPACR_EL1_FPEN | CPACR_EL1_ZEN);
+ val &= ~CPACR_EL1_ZEN;
+ if (!update_fp_enabled(vcpu))
+ val &= ~CPACR_EL1_FPEN;
+
write_sysreg(val, cpacr_el1);
write_sysreg(kvm_get_hyp_vector(), vbar_el1);
@@ -106,7 +113,10 @@ static void __hyp_text __activate_traps_nvhe(struct kvm_vcpu *vcpu)
__activate_traps_common(vcpu);
val = CPTR_EL2_DEFAULT;
- val |= CPTR_EL2_TTA | CPTR_EL2_TFP | CPTR_EL2_TZ;
+ val |= CPTR_EL2_TTA | CPTR_EL2_TZ;
+ if (!update_fp_enabled(vcpu))
+ val |= CPTR_EL2_TFP;
+
write_sysreg(val, cptr_el2);
}
@@ -319,6 +329,50 @@ static bool __hyp_text __skip_instr(struct kvm_vcpu *vcpu)
}
}
+static bool __hyp_text __hyp_switch_fpsimd(struct kvm_vcpu *vcpu)
+{
+ struct user_fpsimd_state *host_fpsimd = vcpu->arch.host_fpsimd_state;
+
+ if (has_vhe())
+ write_sysreg(read_sysreg(cpacr_el1) | CPACR_EL1_FPEN,
+ cpacr_el1);
+ else
+ write_sysreg(read_sysreg(cptr_el2) & ~(u64)CPTR_EL2_TFP,
+ cptr_el2);
+
+ isb();
+
+ if (vcpu->arch.flags & KVM_ARM64_FP_HOST) {
+ /*
+ * In the SVE case, VHE is assumed: it is enforced by
+ * Kconfig and kvm_arch_init().
+ */
+ if (system_supports_sve() &&
+ (vcpu->arch.flags & KVM_ARM64_HOST_SVE_IN_USE)) {
+ struct thread_struct *thread = container_of(
+ host_fpsimd,
+ struct thread_struct, uw.fpsimd_state);
+
+ sve_save_state(sve_pffr(thread), &host_fpsimd->fpsr);
+ } else {
+ __fpsimd_save_state(host_fpsimd);
+ }
+
+ vcpu->arch.flags &= ~KVM_ARM64_FP_HOST;
+ }
+
+ __fpsimd_restore_state(&vcpu->arch.ctxt.gp_regs.fp_regs);
+
+ /* Skip restoring fpexc32 for AArch64 guests */
+ if (!(read_sysreg(hcr_el2) & HCR_RW))
+ write_sysreg(vcpu->arch.ctxt.sys_regs[FPEXC32_EL2],
+ fpexc32_el2);
+
+ vcpu->arch.flags |= KVM_ARM64_FP_ENABLED;
+
+ return true;
+}
+
/*
* Return true when we were able to fixup the guest exit and should return to
* the guest, false when we should restore the host state and return to the
@@ -335,11 +389,23 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
* same PC once the SError has been injected, and replay the
* trapping instruction.
*/
- if (*exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu))
+ if (*exit_code != ARM_EXCEPTION_TRAP)
+ goto exit;
+
+ /*
+ * We trap the first access to the FP/SIMD to save the host context
+ * and restore the guest context lazily.
+ * If FP/SIMD is not implemented, handle the trap and inject an
+ * undefined instruction exception to the guest.
+ */
+ if (system_supports_fpsimd() &&
+ kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_FP_ASIMD)
+ return __hyp_switch_fpsimd(vcpu);
+
+ if (!__populate_fault_info(vcpu))
return true;
- if (static_branch_unlikely(&vgic_v2_cpuif_trap) &&
- *exit_code == ARM_EXCEPTION_TRAP) {
+ if (static_branch_unlikely(&vgic_v2_cpuif_trap)) {
bool valid;
valid = kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_DABT_LOW &&
@@ -351,12 +417,8 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
if (valid) {
int ret = __vgic_v2_perform_cpuif_access(vcpu);
- if (ret == 1) {
- if (__skip_instr(vcpu))
- return true;
- else
- *exit_code = ARM_EXCEPTION_TRAP;
- }
+ if (ret == 1 && __skip_instr(vcpu))
+ return true;
if (ret == -1) {
/* Promote an illegal access to an
@@ -369,23 +431,21 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
*vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
*exit_code = ARM_EXCEPTION_EL1_SERROR;
}
+
+ goto exit;
}
}
if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
- *exit_code == ARM_EXCEPTION_TRAP &&
(kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 ||
kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_CP15_32)) {
int ret = __vgic_v3_perform_cpuif_access(vcpu);
- if (ret == 1) {
- if (__skip_instr(vcpu))
- return true;
- else
- *exit_code = ARM_EXCEPTION_TRAP;
- }
+ if (ret == 1 && __skip_instr(vcpu))
+ return true;
}
+exit:
/* Return to the host kernel and handle the exit */
return false;
}
@@ -428,7 +488,6 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
{
struct kvm_cpu_context *host_ctxt;
struct kvm_cpu_context *guest_ctxt;
- bool fp_enabled;
u64 exit_code;
host_ctxt = vcpu->arch.host_cpu_context;
@@ -454,19 +513,14 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
__set_host_arch_workaround_state(vcpu);
- fp_enabled = fpsimd_enabled_vhe();
-
sysreg_save_guest_state_vhe(guest_ctxt);
__deactivate_traps(vcpu);
sysreg_restore_host_state_vhe(host_ctxt);
- if (fp_enabled) {
- __fpsimd_save_state(&guest_ctxt->gp_regs.fp_regs);
- __fpsimd_restore_state(&host_ctxt->gp_regs.fp_regs);
+ if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED)
__fpsimd_save_fpexc32(vcpu);
- }
__debug_switch_to_host(vcpu);
@@ -478,7 +532,6 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
{
struct kvm_cpu_context *host_ctxt;
struct kvm_cpu_context *guest_ctxt;
- bool fp_enabled;
u64 exit_code;
vcpu = kern_hyp_va(vcpu);
@@ -514,8 +567,6 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
__set_host_arch_workaround_state(vcpu);
- fp_enabled = __fpsimd_enabled_nvhe();
-
__sysreg_save_state_nvhe(guest_ctxt);
__sysreg32_save_state(vcpu);
__timer_disable_traps(vcpu);
@@ -526,11 +577,8 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
__sysreg_restore_state_nvhe(host_ctxt);
- if (fp_enabled) {
- __fpsimd_save_state(&guest_ctxt->gp_regs.fp_regs);
- __fpsimd_restore_state(&host_ctxt->gp_regs.fp_regs);
+ if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED)
__fpsimd_save_fpexc32(vcpu);
- }
/*
* This must come after restoring the host sysregs, since a non-VHE
diff --git a/arch/arm64/kvm/hyp/sysreg-sr.c b/arch/arm64/kvm/hyp/sysreg-sr.c
index b3894df..35bc168 100644
--- a/arch/arm64/kvm/hyp/sysreg-sr.c
+++ b/arch/arm64/kvm/hyp/sysreg-sr.c
@@ -196,7 +196,7 @@ void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu)
sysreg[DACR32_EL2] = read_sysreg(dacr32_el2);
sysreg[IFSR32_EL2] = read_sysreg(ifsr32_el2);
- if (has_vhe() || vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
+ if (has_vhe() || vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY)
sysreg[DBGVCR32_EL2] = read_sysreg(dbgvcr32_el2);
}
@@ -218,7 +218,7 @@ void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu)
write_sysreg(sysreg[DACR32_EL2], dacr32_el2);
write_sysreg(sysreg[IFSR32_EL2], ifsr32_el2);
- if (has_vhe() || vcpu->arch.debug_flags & KVM_ARM64_DEBUG_DIRTY)
+ if (has_vhe() || vcpu->arch.flags & KVM_ARM64_DEBUG_DIRTY)
write_sysreg(sysreg[DBGVCR32_EL2], dbgvcr32_el2);
}
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 6e3b969..a436373 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -31,7 +31,6 @@
#include <asm/debug-monitors.h>
#include <asm/esr.h>
#include <asm/kvm_arm.h>
-#include <asm/kvm_asm.h>
#include <asm/kvm_coproc.h>
#include <asm/kvm_emulate.h>
#include <asm/kvm_host.h>
@@ -338,7 +337,7 @@ static bool trap_debug_regs(struct kvm_vcpu *vcpu,
{
if (p->is_write) {
vcpu_write_sys_reg(vcpu, p->regval, r->reg);
- vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+ vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
} else {
p->regval = vcpu_read_sys_reg(vcpu, r->reg);
}
@@ -369,7 +368,7 @@ static void reg_to_dbg(struct kvm_vcpu *vcpu,
}
*dbg_reg = val;
- vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+ vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
}
static void dbg_to_reg(struct kvm_vcpu *vcpu,
@@ -1441,7 +1440,7 @@ static bool trap_debug32(struct kvm_vcpu *vcpu,
{
if (p->is_write) {
vcpu_cp14(vcpu, r->reg) = p->regval;
- vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+ vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
} else {
p->regval = vcpu_cp14(vcpu, r->reg);
}
@@ -1473,7 +1472,7 @@ static bool trap_xvr(struct kvm_vcpu *vcpu,
val |= p->regval << 32;
*dbg_reg = val;
- vcpu->arch.debug_flags |= KVM_ARM64_DEBUG_DIRTY;
+ vcpu->arch.flags |= KVM_ARM64_DEBUG_DIRTY;
} else {
p->regval = *dbg_reg >> 32;
}
diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 301417a..c127f94 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -263,7 +263,7 @@ static int asids_init(void)
*/
WARN_ON(NUM_USER_ASIDS - 1 <= num_possible_cpus());
atomic64_set(&asid_generation, ASID_FIRST_VERSION);
- asid_map = kzalloc(BITS_TO_LONGS(NUM_USER_ASIDS) * sizeof(*asid_map),
+ asid_map = kcalloc(BITS_TO_LONGS(NUM_USER_ASIDS), sizeof(*asid_map),
GFP_KERNEL);
if (!asid_map)
panic("Failed to allocate bitmap for %lu ASIDs\n",
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 49e217a..61e93f0 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -583,13 +583,14 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
size >> PAGE_SHIFT);
return NULL;
}
- if (!coherent)
- __dma_flush_area(page_to_virt(page), iosize);
-
addr = dma_common_contiguous_remap(page, size, VM_USERMAP,
prot,
__builtin_return_address(0));
- if (!addr) {
+ if (addr) {
+ memset(addr, 0, size);
+ if (!coherent)
+ __dma_flush_area(page_to_virt(page), iosize);
+ } else {
iommu_dma_unmap_page(dev, *handle, iosize, 0, attrs);
dma_release_from_contiguous(dev, page,
size >> PAGE_SHIFT);
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 1b18b47..325cfb3 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -310,7 +310,7 @@ static void __init arm64_memory_present(void)
}
#endif
-static phys_addr_t memory_limit = (phys_addr_t)ULLONG_MAX;
+static phys_addr_t memory_limit = PHYS_ADDR_MAX;
/*
* Limit the memory size that was specified via FDT.
@@ -401,7 +401,7 @@ void __init arm64_memblock_init(void)
* high up in memory, add back the kernel region that must be accessible
* via the linear mapping.
*/
- if (memory_limit != (phys_addr_t)ULLONG_MAX) {
+ if (memory_limit != PHYS_ADDR_MAX) {
memblock_mem_limit_remove_map(memory_limit);
memblock_add(__pa_symbol(_text), (u64)(_end - _text));
}
@@ -666,7 +666,7 @@ __setup("keepinitrd", keepinitrd_setup);
*/
static int dump_mem_limit(struct notifier_block *self, unsigned long v, void *p)
{
- if (memory_limit != (phys_addr_t)ULLONG_MAX) {
+ if (memory_limit != PHYS_ADDR_MAX) {
pr_emerg("Memory Limit: %llu MB\n", memory_limit >> 20);
} else {
pr_emerg("Memory Limit: none\n");
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 5f9a73a..03646e6 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -217,8 +217,9 @@ ENDPROC(idmap_cpu_replace_ttbr1)
.macro __idmap_kpti_put_pgtable_ent_ng, type
orr \type, \type, #PTE_NG // Same bit for blocks and pages
- str \type, [cur_\()\type\()p] // Update the entry and ensure it
- dc civac, cur_\()\type\()p // is visible to all CPUs.
+ str \type, [cur_\()\type\()p] // Update the entry and ensure
+ dmb sy // that it is visible to all
+ dc civac, cur_\()\type\()p // CPUs.
.endm
/*
diff --git a/arch/hexagon/include/asm/pgtable.h b/arch/hexagon/include/asm/pgtable.h
index aef02f7..65125d0 100644
--- a/arch/hexagon/include/asm/pgtable.h
+++ b/arch/hexagon/include/asm/pgtable.h
@@ -30,7 +30,6 @@
/* A handy thing to have if one has the RAM. Declared in head.S */
extern unsigned long empty_zero_page;
-extern unsigned long zero_page_mask;
/*
* The PTE model described here is that of the Hexagon Virtual Machine,
diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c
index 6981949..dc8c7e7 100644
--- a/arch/hexagon/kernel/setup.c
+++ b/arch/hexagon/kernel/setup.c
@@ -66,7 +66,7 @@ void __init setup_arch(char **cmdline_p)
*/
__vmsetvec(_K_VM_event_vector);
- printk(KERN_INFO "PHYS_OFFSET=0x%08x\n", PHYS_OFFSET);
+ printk(KERN_INFO "PHYS_OFFSET=0x%08lx\n", PHYS_OFFSET);
/*
* Simulator has a few differences from the hardware.
diff --git a/arch/hexagon/mm/init.c b/arch/hexagon/mm/init.c
index 192584d..1495d45 100644
--- a/arch/hexagon/mm/init.c
+++ b/arch/hexagon/mm/init.c
@@ -39,9 +39,6 @@ unsigned long __phys_offset; /* physical kernel offset >> 12 */
/* Set as variable to limit PMD copies */
int max_kernel_seg = 0x303;
-/* think this should be (page_size-1) the way it's used...*/
-unsigned long zero_page_mask;
-
/* indicate pfn's of high memory */
unsigned long highstart_pfn, highend_pfn;
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 792437d..ff86142 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -455,6 +455,7 @@ config IA64_MCA_RECOVERY
config PERFMON
bool "Performance monitor support"
+ depends on BROKEN
help
Selects whether support for the IA-64 performance monitor hardware
is included in the kernel. This makes some kernel data-structures a
diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c
index 94f8bf7..dfe40cb 100644
--- a/arch/ia64/kernel/mca_drv.c
+++ b/arch/ia64/kernel/mca_drv.c
@@ -350,7 +350,8 @@ init_record_index_pools(void)
/* - 3 - */
slidx_pool.max_idx = (rec_max_size/sect_min_size) * 2 + 1;
slidx_pool.buffer =
- kmalloc(slidx_pool.max_idx * sizeof(slidx_list_t), GFP_KERNEL);
+ kmalloc_array(slidx_pool.max_idx, sizeof(slidx_list_t),
+ GFP_KERNEL);
return slidx_pool.buffer ? 0 : -ENOMEM;
}
diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c
index d76529c..9b820f7 100644
--- a/arch/ia64/kernel/topology.c
+++ b/arch/ia64/kernel/topology.c
@@ -85,7 +85,7 @@ static int __init topology_init(void)
}
#endif
- sysfs_cpus = kzalloc(sizeof(struct ia64_cpu) * NR_CPUS, GFP_KERNEL);
+ sysfs_cpus = kcalloc(NR_CPUS, sizeof(struct ia64_cpu), GFP_KERNEL);
if (!sysfs_cpus)
panic("kzalloc in topology_init failed - NR_CPUS too big?");
@@ -319,8 +319,8 @@ static int cpu_cache_sysfs_init(unsigned int cpu)
return -1;
}
- this_cache=kzalloc(sizeof(struct cache_info)*unique_caches,
- GFP_KERNEL);
+ this_cache=kcalloc(unique_caches, sizeof(struct cache_info),
+ GFP_KERNEL);
if (this_cache == NULL)
return -ENOMEM;
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index 46ecc5d..acf10eb 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -430,8 +430,9 @@ int ia64_itr_entry(u64 target_mask, u64 va, u64 pte, u64 log_size)
int cpu = smp_processor_id();
if (!ia64_idtrs[cpu]) {
- ia64_idtrs[cpu] = kmalloc(2 * IA64_TR_ALLOC_MAX *
- sizeof (struct ia64_tr_entry), GFP_KERNEL);
+ ia64_idtrs[cpu] = kmalloc_array(2 * IA64_TR_ALLOC_MAX,
+ sizeof(struct ia64_tr_entry),
+ GFP_KERNEL);
if (!ia64_idtrs[cpu])
return -ENOMEM;
}
diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c
index 8479e9a..102aaba 100644
--- a/arch/ia64/sn/kernel/io_common.c
+++ b/arch/ia64/sn/kernel/io_common.c
@@ -132,7 +132,7 @@ static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
printk_once(KERN_WARNING
"PROM version < 4.50 -- implementing old PROM flush WAR\n");
- war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
+ war_list = kcalloc(DEV_PER_WIDGET, sizeof(*war_list), GFP_KERNEL);
BUG_ON(!war_list);
SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 85d0951..d9b576d 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -474,7 +474,8 @@ void __init sn_irq_lh_init(void)
{
int i;
- sn_irq_lh = kmalloc(sizeof(struct list_head *) * NR_IRQS, GFP_KERNEL);
+ sn_irq_lh = kmalloc_array(NR_IRQS, sizeof(struct list_head *),
+ GFP_KERNEL);
if (!sn_irq_lh)
panic("SN PCI INIT: Failed to allocate memory for PCI init\n");
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 8dbbef4..7195df1 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -184,7 +184,7 @@ pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *cont
/* Setup the PMU ATE map */
soft->pbi_int_ate_resource.lowest_free_index = 0;
soft->pbi_int_ate_resource.ate =
- kzalloc(soft->pbi_int_ate_size * sizeof(u64), GFP_KERNEL);
+ kcalloc(soft->pbi_int_ate_size, sizeof(u64), GFP_KERNEL);
if (!soft->pbi_int_ate_resource.ate) {
kfree(soft);
diff --git a/arch/microblaze/include/asm/cacheflush.h b/arch/microblaze/include/asm/cacheflush.h
index ffea82a..b091de7 100644
--- a/arch/microblaze/include/asm/cacheflush.h
+++ b/arch/microblaze/include/asm/cacheflush.h
@@ -19,7 +19,7 @@
#include <linux/mm.h>
#include <linux/io.h>
-/* Look at Documentation/cachetlb.txt */
+/* Look at Documentation/core-api/cachetlb.rst */
/*
* Cache handling functions.
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 7074b22..08c10c5 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -22,6 +22,11 @@ config MIPS
select GENERIC_CPU_AUTOPROBE
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
+ select GENERIC_LIB_ASHLDI3
+ select GENERIC_LIB_ASHRDI3
+ select GENERIC_LIB_CMPDI2
+ select GENERIC_LIB_LSHRDI3
+ select GENERIC_LIB_UCMPDI2
select GENERIC_PCI_IOMAP
select GENERIC_SCHED_CLOCK if !CAVIUM_OCTEON_SOC
select GENERIC_SMP_IDLE_THREAD
@@ -36,7 +41,6 @@ config MIPS
select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
select HAVE_CBPF_JIT if (!64BIT && !CPU_MICROMIPS)
select HAVE_EBPF_JIT if (64BIT && !CPU_MICROMIPS)
- select HAVE_CC_STACKPROTECTOR
select HAVE_CONTEXT_TRACKING
select HAVE_COPY_THREAD_TLS
select HAVE_C_RECORDMCOUNT
@@ -61,6 +65,8 @@ config MIPS
select HAVE_OPROFILE
select HAVE_PERF_EVENTS
select HAVE_REGS_AND_STACK_ACCESS_API
+ select HAVE_RSEQ
+ select HAVE_STACKPROTECTOR
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_VIRT_CPU_ACCOUNTING_GEN if 64BIT || !SMP
select IRQ_FORCED_THREADING
diff --git a/arch/mips/alchemy/board-gpr.c b/arch/mips/alchemy/board-gpr.c
index 4e79dbd..fa75d75 100644
--- a/arch/mips/alchemy/board-gpr.c
+++ b/arch/mips/alchemy/board-gpr.c
@@ -29,7 +29,7 @@
#include <linux/leds.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <asm/bootinfo.h>
#include <asm/idle.h>
diff --git a/arch/mips/alchemy/common/clock.c b/arch/mips/alchemy/common/clock.c
index 6b6f685..d129475 100644
--- a/arch/mips/alchemy/common/clock.c
+++ b/arch/mips/alchemy/common/clock.c
@@ -985,7 +985,7 @@ static int __init alchemy_clk_setup_imux(int ctype)
return -ENODEV;
}
- a = kzalloc((sizeof(*a)) * 6, GFP_KERNEL);
+ a = kcalloc(6, sizeof(*a), GFP_KERNEL);
if (!a)
return -ENOMEM;
diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c
index fc482d9..4ca2c28 100644
--- a/arch/mips/alchemy/common/dbdma.c
+++ b/arch/mips/alchemy/common/dbdma.c
@@ -411,8 +411,8 @@ u32 au1xxx_dbdma_ring_alloc(u32 chanid, int entries)
* and if we try that first we are likely to not waste larger
* slabs of memory.
*/
- desc_base = (u32)kmalloc(entries * sizeof(au1x_ddma_desc_t),
- GFP_KERNEL|GFP_DMA);
+ desc_base = (u32)kmalloc_array(entries, sizeof(au1x_ddma_desc_t),
+ GFP_KERNEL|GFP_DMA);
if (desc_base == 0)
return 0;
@@ -1050,7 +1050,7 @@ static int __init dbdma_setup(unsigned int irq, dbdev_tab_t *idtable)
{
int ret;
- dbdev_tab = kzalloc(sizeof(dbdev_tab_t) * DBDEV_TAB_SIZE, GFP_KERNEL);
+ dbdev_tab = kcalloc(DBDEV_TAB_SIZE, sizeof(dbdev_tab_t), GFP_KERNEL);
if (!dbdev_tab)
return -ENOMEM;
diff --git a/arch/mips/alchemy/common/platform.c b/arch/mips/alchemy/common/platform.c
index d77a64f..1454d9f 100644
--- a/arch/mips/alchemy/common/platform.c
+++ b/arch/mips/alchemy/common/platform.c
@@ -115,7 +115,7 @@ static void __init alchemy_setup_uarts(int ctype)
uartclk = clk_get_rate(clk);
clk_put(clk);
- ports = kzalloc(s * (c + 1), GFP_KERNEL);
+ ports = kcalloc(s, (c + 1), GFP_KERNEL);
if (!ports) {
printk(KERN_INFO "Alchemy: no memory for UART data\n");
return;
@@ -198,7 +198,7 @@ static unsigned long alchemy_ehci_data[][2] __initdata = {
static int __init _new_usbres(struct resource **r, struct platform_device **d)
{
- *r = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
+ *r = kcalloc(2, sizeof(struct resource), GFP_KERNEL);
if (!*r)
return -ENOMEM;
*d = kzalloc(sizeof(struct platform_device), GFP_KERNEL);
diff --git a/arch/mips/alchemy/devboards/platform.c b/arch/mips/alchemy/devboards/platform.c
index 4640eda..203854d 100644
--- a/arch/mips/alchemy/devboards/platform.c
+++ b/arch/mips/alchemy/devboards/platform.c
@@ -103,7 +103,7 @@ int __init db1x_register_pcmcia_socket(phys_addr_t pcmcia_attr_start,
if (stschg_irq)
cnt++;
- sr = kzalloc(sizeof(struct resource) * cnt, GFP_KERNEL);
+ sr = kcalloc(cnt, sizeof(struct resource), GFP_KERNEL);
if (!sr)
return -ENOMEM;
@@ -178,7 +178,7 @@ int __init db1x_register_norflash(unsigned long size, int width,
return -EINVAL;
ret = -ENOMEM;
- parts = kzalloc(sizeof(struct mtd_partition) * 5, GFP_KERNEL);
+ parts = kcalloc(5, sizeof(struct mtd_partition), GFP_KERNEL);
if (!parts)
goto out;
diff --git a/arch/mips/ath79/mach-pb44.c b/arch/mips/ath79/mach-pb44.c
index 6b2c6f3..75fb96c 100644
--- a/arch/mips/ath79/mach-pb44.c
+++ b/arch/mips/ath79/mach-pb44.c
@@ -34,7 +34,7 @@
#define PB44_KEYS_DEBOUNCE_INTERVAL (3 * PB44_KEYS_POLL_INTERVAL)
static struct gpiod_lookup_table pb44_i2c_gpiod_table = {
- .dev_id = "i2c-gpio",
+ .dev_id = "i2c-gpio.0",
.table = {
GPIO_LOOKUP_IDX("ath79-gpio", PB44_GPIO_I2C_SDA,
NULL, 0, GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
diff --git a/arch/mips/bcm47xx/board.c b/arch/mips/bcm47xx/board.c
index edfaef0..a80910d 100644
--- a/arch/mips/bcm47xx/board.c
+++ b/arch/mips/bcm47xx/board.c
@@ -172,6 +172,8 @@ struct bcm47xx_board_type_list1 bcm47xx_board_list_board_id[] __initconst = {
{{BCM47XX_BOARD_NETGEAR_WNDR4000, "Netgear WNDR4000"}, "U12H181T00_NETGEAR"},
{{BCM47XX_BOARD_NETGEAR_WNDR4500V1, "Netgear WNDR4500 V1"}, "U12H189T00_NETGEAR"},
{{BCM47XX_BOARD_NETGEAR_WNDR4500V2, "Netgear WNDR4500 V2"}, "U12H224T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR1000_V3, "Netgear WNR1000 V3"}, "U12H139T00_NETGEAR"},
+ {{BCM47XX_BOARD_NETGEAR_WNR1000_V3, "Netgear WNR1000 V3"}, "U12H139T50_NETGEAR"},
{{BCM47XX_BOARD_NETGEAR_WNR2000, "Netgear WNR2000"}, "U12H114T00_NETGEAR"},
{{BCM47XX_BOARD_NETGEAR_WNR3500L, "Netgear WNR3500L"}, "U12H136T99_NETGEAR"},
{{BCM47XX_BOARD_NETGEAR_WNR3500U, "Netgear WNR3500U"}, "U12H136T00_NETGEAR"},
diff --git a/arch/mips/bcm47xx/buttons.c b/arch/mips/bcm47xx/buttons.c
index 88d400d..977990a 100644
--- a/arch/mips/bcm47xx/buttons.c
+++ b/arch/mips/bcm47xx/buttons.c
@@ -412,6 +412,12 @@ bcm47xx_buttons_netgear_wndr4500v1[] __initconst = {
};
static const struct gpio_keys_button
+bcm47xx_buttons_netgear_wnr1000_v3[] __initconst = {
+ BCM47XX_GPIO_KEY(2, KEY_WPS_BUTTON),
+ BCM47XX_GPIO_KEY(3, KEY_RESTART),
+};
+
+static const struct gpio_keys_button
bcm47xx_buttons_netgear_wnr3500lv1[] __initconst = {
BCM47XX_GPIO_KEY(4, KEY_RESTART),
BCM47XX_GPIO_KEY(6, KEY_WPS_BUTTON),
@@ -670,6 +676,9 @@ int __init bcm47xx_buttons_register(void)
case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wndr4500v1);
break;
+ case BCM47XX_BOARD_NETGEAR_WNR1000_V3:
+ err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr1000_v3);
+ break;
case BCM47XX_BOARD_NETGEAR_WNR3500L:
err = bcm47xx_copy_bdata(bcm47xx_buttons_netgear_wnr3500lv1);
break;
diff --git a/arch/mips/bcm47xx/leds.c b/arch/mips/bcm47xx/leds.c
index 34a7b3f..d85fcda 100644
--- a/arch/mips/bcm47xx/leds.c
+++ b/arch/mips/bcm47xx/leds.c
@@ -498,6 +498,12 @@ bcm47xx_leds_netgear_wndr4500v1[] __initconst = {
};
static const struct gpio_led
+bcm47xx_leds_netgear_wnr1000_v3[] __initconst = {
+ BCM47XX_GPIO_LED(0, "blue", "wlan", 0, LEDS_GPIO_DEFSTATE_OFF),
+ BCM47XX_GPIO_LED(1, "green", "wps", 0, LEDS_GPIO_DEFSTATE_OFF),
+};
+
+static const struct gpio_led
bcm47xx_leds_netgear_wnr3500lv1[] __initconst = {
BCM47XX_GPIO_LED(0, "blue", "wlan", 1, LEDS_GPIO_DEFSTATE_OFF),
BCM47XX_GPIO_LED(1, "green", "wps", 1, LEDS_GPIO_DEFSTATE_OFF),
@@ -532,7 +538,7 @@ bcm47xx_leds_simpletech_simpleshare[] __initconst = {
* Init
**************************************************/
-static struct gpio_led_platform_data bcm47xx_leds_pdata;
+static struct gpio_led_platform_data bcm47xx_leds_pdata __initdata;
#define bcm47xx_set_pdata(dev_leds) do { \
bcm47xx_leds_pdata.leds = dev_leds; \
@@ -758,6 +764,9 @@ void __init bcm47xx_leds_register(void)
case BCM47XX_BOARD_NETGEAR_WNDR4500V1:
bcm47xx_set_pdata(bcm47xx_leds_netgear_wndr4500v1);
break;
+ case BCM47XX_BOARD_NETGEAR_WNR1000_V3:
+ bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr1000_v3);
+ break;
case BCM47XX_BOARD_NETGEAR_WNR3500L:
bcm47xx_set_pdata(bcm47xx_leds_netgear_wnr3500lv1);
break;
diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c
index 6054d49..8c9cbf1 100644
--- a/arch/mips/bcm47xx/setup.c
+++ b/arch/mips/bcm47xx/setup.c
@@ -212,6 +212,12 @@ static int __init bcm47xx_cpu_fixes(void)
*/
if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706)
cpu_wait = NULL;
+
+ /*
+ * BCM47XX Erratum "R10: PCIe Transactions Periodically Fail"
+ * Enable ExternalSync for sync instruction to take effect
+ */
+ set_c0_config7(MIPS_CONF7_ES);
break;
#endif
}
diff --git a/arch/mips/bmips/dma.c b/arch/mips/bmips/dma.c
index 04790f4..6dec308 100644
--- a/arch/mips/bmips/dma.c
+++ b/arch/mips/bmips/dma.c
@@ -94,7 +94,7 @@ static int __init bmips_init_dma_ranges(void)
goto out_bad;
/* add a dummy (zero) entry at the end as a sentinel */
- bmips_dma_ranges = kzalloc(sizeof(struct bmips_dma_range) * (len + 1),
+ bmips_dma_ranges = kcalloc(len + 1, sizeof(struct bmips_dma_range),
GFP_KERNEL);
if (!bmips_dma_ranges)
goto out_bad;
diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index adce180..abe77ad 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -46,10 +46,13 @@ $(obj)/uart-ath79.c: $(srctree)/arch/mips/ath79/early_printk.c
vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o $(obj)/bswapsi.o
-extra-y += ashldi3.c bswapsi.c
-$(obj)/ashldi3.o $(obj)/bswapsi.o: KBUILD_CFLAGS += -I$(srctree)/arch/mips/lib
-$(obj)/ashldi3.c $(obj)/bswapsi.c: $(obj)/%.c: $(srctree)/arch/mips/lib/%.c
- $(call cmd,shipped)
+extra-y += ashldi3.c
+$(obj)/ashldi3.c: $(obj)/%.c: $(srctree)/lib/%.c FORCE
+ $(call if_changed,shipped)
+
+extra-y += bswapsi.c
+$(obj)/bswapsi.c: $(obj)/%.c: $(srctree)/arch/mips/lib/%.c FORCE
+ $(call if_changed,shipped)
targets := $(notdir $(vmlinuzobjs-y))
diff --git a/arch/mips/boot/dts/brcm/Makefile b/arch/mips/boot/dts/brcm/Makefile
index d8787c9..d85f446 100644
--- a/arch/mips/boot/dts/brcm/Makefile
+++ b/arch/mips/boot/dts/brcm/Makefile
@@ -34,4 +34,4 @@ dtb-$(CONFIG_DT_NONE) += \
bcm97425svmb.dtb \
bcm97435svmb.dtb
-obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/boot/dts/cavium-octeon/Makefile b/arch/mips/boot/dts/cavium-octeon/Makefile
index 24a8efc..17aef35 100644
--- a/arch/mips/boot/dts/cavium-octeon/Makefile
+++ b/arch/mips/boot/dts/cavium-octeon/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_CAVIUM_OCTEON_SOC) += octeon_3xxx.dtb octeon_68xx.dtb
-obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/boot/dts/ingenic/Makefile b/arch/mips/boot/dts/ingenic/Makefile
index 5b1361a..9cc4844 100644
--- a/arch/mips/boot/dts/ingenic/Makefile
+++ b/arch/mips/boot/dts/ingenic/Makefile
@@ -3,4 +3,4 @@ dtb-$(CONFIG_JZ4740_QI_LB60) += qi_lb60.dtb
dtb-$(CONFIG_JZ4770_GCW0) += gcw0.dtb
dtb-$(CONFIG_JZ4780_CI20) += ci20.dtb
-obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/boot/dts/ingenic/jz4740.dtsi b/arch/mips/boot/dts/ingenic/jz4740.dtsi
index cd5185b..26c6b56 100644
--- a/arch/mips/boot/dts/ingenic/jz4740.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4740.dtsi
@@ -45,6 +45,14 @@
#clock-cells = <1>;
};
+ watchdog: watchdog@10002000 {
+ compatible = "ingenic,jz4740-watchdog";
+ reg = <0x10002000 0x10>;
+
+ clocks = <&cgu JZ4740_CLK_RTC>;
+ clock-names = "rtc";
+ };
+
rtc_dev: rtc@10003000 {
compatible = "ingenic,jz4740-rtc";
reg = <0x10003000 0x40>;
diff --git a/arch/mips/boot/dts/ingenic/jz4780.dtsi b/arch/mips/boot/dts/ingenic/jz4780.dtsi
index b72e53b..aa4e8f7 100644
--- a/arch/mips/boot/dts/ingenic/jz4780.dtsi
+++ b/arch/mips/boot/dts/ingenic/jz4780.dtsi
@@ -222,7 +222,10 @@
watchdog: watchdog@10002000 {
compatible = "ingenic,jz4780-watchdog";
- reg = <0x10002000 0x100>;
+ reg = <0x10002000 0x10>;
+
+ clocks = <&cgu JZ4780_CLK_RTCLK>;
+ clock-names = "rtc";
};
nemc: nemc@13410000 {
diff --git a/arch/mips/boot/dts/lantiq/Makefile b/arch/mips/boot/dts/lantiq/Makefile
index 51ab9c1..f5dfc06 100644
--- a/arch/mips/boot/dts/lantiq/Makefile
+++ b/arch/mips/boot/dts/lantiq/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_DT_EASY50712) += easy50712.dtb
-obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/boot/dts/mscc/Makefile b/arch/mips/boot/dts/mscc/Makefile
index c511645..3c6aed9 100644
--- a/arch/mips/boot/dts/mscc/Makefile
+++ b/arch/mips/boot/dts/mscc/Makefile
@@ -1,3 +1,3 @@
dtb-$(CONFIG_LEGACY_BOARD_OCELOT) += ocelot_pcb123.dtb
-obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/boot/dts/mscc/ocelot.dtsi b/arch/mips/boot/dts/mscc/ocelot.dtsi
index dd239ca..4f33dbc 100644
--- a/arch/mips/boot/dts/mscc/ocelot.dtsi
+++ b/arch/mips/boot/dts/mscc/ocelot.dtsi
@@ -91,6 +91,72 @@
status = "disabled";
};
+ switch@1010000 {
+ compatible = "mscc,vsc7514-switch";
+ reg = <0x1010000 0x10000>,
+ <0x1030000 0x10000>,
+ <0x1080000 0x100>,
+ <0x10d0000 0x10000>,
+ <0x11e0000 0x100>,
+ <0x11f0000 0x100>,
+ <0x1200000 0x100>,
+ <0x1210000 0x100>,
+ <0x1220000 0x100>,
+ <0x1230000 0x100>,
+ <0x1240000 0x100>,
+ <0x1250000 0x100>,
+ <0x1260000 0x100>,
+ <0x1270000 0x100>,
+ <0x1280000 0x100>,
+ <0x1800000 0x80000>,
+ <0x1880000 0x10000>;
+ reg-names = "sys", "rew", "qs", "hsio", "port0",
+ "port1", "port2", "port3", "port4", "port5",
+ "port6", "port7", "port8", "port9", "port10",
+ "qsys", "ana";
+ interrupts = <21 22>;
+ interrupt-names = "xtr", "inj";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port0: port@0 {
+ reg = <0>;
+ };
+ port1: port@1 {
+ reg = <1>;
+ };
+ port2: port@2 {
+ reg = <2>;
+ };
+ port3: port@3 {
+ reg = <3>;
+ };
+ port4: port@4 {
+ reg = <4>;
+ };
+ port5: port@5 {
+ reg = <5>;
+ };
+ port6: port@6 {
+ reg = <6>;
+ };
+ port7: port@7 {
+ reg = <7>;
+ };
+ port8: port@8 {
+ reg = <8>;
+ };
+ port9: port@9 {
+ reg = <9>;
+ };
+ port10: port@10 {
+ reg = <10>;
+ };
+ };
+ };
+
reset@1070008 {
compatible = "mscc,ocelot-chip-reset";
reg = <0x1070008 0x4>;
@@ -113,5 +179,27 @@
function = "uart2";
};
};
+
+ mdio0: mdio@107009c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "mscc,ocelot-miim";
+ reg = <0x107009c 0x36>, <0x10700f0 0x8>;
+ interrupts = <14>;
+ status = "disabled";
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+ phy1: ethernet-phy@1 {
+ reg = <1>;
+ };
+ phy2: ethernet-phy@2 {
+ reg = <2>;
+ };
+ phy3: ethernet-phy@3 {
+ reg = <3>;
+ };
+ };
};
};
diff --git a/arch/mips/boot/dts/mscc/ocelot_pcb123.dts b/arch/mips/boot/dts/mscc/ocelot_pcb123.dts
index 29d6414..4ccd653 100644
--- a/arch/mips/boot/dts/mscc/ocelot_pcb123.dts
+++ b/arch/mips/boot/dts/mscc/ocelot_pcb123.dts
@@ -25,3 +25,23 @@
&uart2 {
status = "okay";
};
+
+&mdio0 {
+ status = "okay";
+};
+
+&port0 {
+ phy-handle = <&phy0>;
+};
+
+&port1 {
+ phy-handle = <&phy1>;
+};
+
+&port2 {
+ phy-handle = <&phy2>;
+};
+
+&port3 {
+ phy-handle = <&phy3>;
+};
diff --git a/arch/mips/boot/dts/mti/Makefile b/arch/mips/boot/dts/mti/Makefile
index 3508720..b5f7426 100644
--- a/arch/mips/boot/dts/mti/Makefile
+++ b/arch/mips/boot/dts/mti/Makefile
@@ -2,4 +2,4 @@
dtb-$(CONFIG_MIPS_MALTA) += malta.dtb
dtb-$(CONFIG_LEGACY_BOARD_SEAD3) += sead3.dtb
-obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/boot/dts/netlogic/Makefile b/arch/mips/boot/dts/netlogic/Makefile
index d630b27..45af422 100644
--- a/arch/mips/boot/dts/netlogic/Makefile
+++ b/arch/mips/boot/dts/netlogic/Makefile
@@ -5,4 +5,4 @@ dtb-$(CONFIG_DT_XLP_FVP) += xlp_fvp.dtb
dtb-$(CONFIG_DT_XLP_GVP) += xlp_gvp.dtb
dtb-$(CONFIG_DT_XLP_RVP) += xlp_rvp.dtb
-obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/boot/dts/pic32/Makefile b/arch/mips/boot/dts/pic32/Makefile
index ba9bcef..fb57f36 100644
--- a/arch/mips/boot/dts/pic32/Makefile
+++ b/arch/mips/boot/dts/pic32/Makefile
@@ -4,4 +4,4 @@ dtb-$(CONFIG_DTB_PIC32_MZDA_SK) += pic32mzda_sk.dtb
dtb-$(CONFIG_DTB_PIC32_NONE) += \
pic32mzda_sk.dtb
-obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/boot/dts/ralink/Makefile b/arch/mips/boot/dts/ralink/Makefile
index 94bee5b..6c26dfa 100644
--- a/arch/mips/boot/dts/ralink/Makefile
+++ b/arch/mips/boot/dts/ralink/Makefile
@@ -6,4 +6,4 @@ dtb-$(CONFIG_DTB_MT7620A_EVAL) += mt7620a_eval.dtb
dtb-$(CONFIG_DTB_OMEGA2P) += omega2p.dtb
dtb-$(CONFIG_DTB_VOCORE2) += vocore2.dtb
-obj-y += $(patsubst %.dtb, %.dtb.o, $(dtb-y))
+obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/configs/qi_lb60_defconfig b/arch/mips/configs/qi_lb60_defconfig
index 3b02ff9..d8b7211 100644
--- a/arch/mips/configs/qi_lb60_defconfig
+++ b/arch/mips/configs/qi_lb60_defconfig
@@ -72,6 +72,8 @@ CONFIG_POWER_SUPPLY=y
CONFIG_BATTERY_JZ4740=y
CONFIG_CHARGER_GPIO=y
# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_JZ4740_WDT=y
CONFIG_MFD_JZ4740_ADC=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
index a2a150e..c38686f 100644
--- a/arch/mips/dec/time.c
+++ b/arch/mips/dec/time.c
@@ -19,7 +19,7 @@
#include <asm/dec/ioasic.h>
#include <asm/dec/machtype.h>
-void read_persistent_clock(struct timespec *ts)
+void read_persistent_clock64(struct timespec64 *ts)
{
unsigned int year, mon, day, hour, min, sec, real_year;
unsigned long flags;
@@ -54,19 +54,20 @@ void read_persistent_clock(struct timespec *ts)
year += real_year - 72 + 2000;
- ts->tv_sec = mktime(year, mon, day, hour, min, sec);
+ ts->tv_sec = mktime64(year, mon, day, hour, min, sec);
ts->tv_nsec = 0;
}
/*
- * In order to set the CMOS clock precisely, rtc_mips_set_mmss has to
+ * In order to set the CMOS clock precisely, update_persistent_clock64 has to
* be called 500 ms after the second nowtime has started, because when
* nowtime is written into the registers of the CMOS clock, it will
* jump to the next second precisely 500 ms later. Check the Dallas
* DS1287 data sheet for details.
*/
-int rtc_mips_set_mmss(unsigned long nowtime)
+int update_persistent_clock64(struct timespec64 now)
{
+ time64_t nowtime = now.tv_sec;
int retval = 0;
int real_seconds, real_minutes, cmos_minutes;
unsigned char save_control, save_freq_select;
@@ -91,8 +92,7 @@ int rtc_mips_set_mmss(unsigned long nowtime)
* messing with unknown time zones but requires your
* RTC not to be off by more than 15 minutes
*/
- real_seconds = nowtime % 60;
- real_minutes = nowtime / 60;
+ real_minutes = div_s64_rem(nowtime, 60, &real_seconds);
if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
real_minutes += 30; /* correct for half hour time zone */
real_minutes %= 60;
diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h
index 5f74590..9cdb4e4 100644
--- a/arch/mips/include/asm/cpu-features.h
+++ b/arch/mips/include/asm/cpu-features.h
@@ -535,6 +535,13 @@
# define cpu_has_shared_ftlb_entries 0
#endif
+#ifdef CONFIG_MIPS_MT_SMP
+# define cpu_has_mipsmt_pertccounters \
+ (cpu_data[0].options & MIPS_CPU_MT_PER_TC_PERF_COUNTERS)
+#else
+# define cpu_has_mipsmt_pertccounters 0
+#endif /* CONFIG_MIPS_MT_SMP */
+
/*
* Guest capabilities
*/
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index d39324c..5b9d02e 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -418,6 +418,8 @@ enum cpu_type_enum {
MBIT_ULL(54) /* CPU shares FTLB RAM with another */
#define MIPS_CPU_SHARED_FTLB_ENTRIES \
MBIT_ULL(55) /* CPU shares FTLB entries with another */
+#define MIPS_CPU_MT_PER_TC_PERF_COUNTERS \
+ MBIT_ULL(56) /* CPU has perf counters implemented per TC (MIPSMT ASE) */
/*
* CPU ASE encodings
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index a7d0b83..cea8ad8 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -414,6 +414,8 @@ static inline type pfx##in##bwlq##p(unsigned long port) \
__val = *__addr; \
slow; \
\
+ /* prevent prefetching of coherent DMA data prematurely */ \
+ rmb(); \
return pfx##ioswab##bwlq(__addr, __val); \
}
diff --git a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
index cbf9da7..0ef8893 100644
--- a/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
+++ b/arch/mips/include/asm/mach-bcm47xx/bcm47xx_board.h
@@ -110,6 +110,7 @@ enum bcm47xx_board {
BCM47XX_BOARD_NETGEAR_WNDR4000,
BCM47XX_BOARD_NETGEAR_WNDR4500V1,
BCM47XX_BOARD_NETGEAR_WNDR4500V2,
+ BCM47XX_BOARD_NETGEAR_WNR1000_V3,
BCM47XX_BOARD_NETGEAR_WNR2000,
BCM47XX_BOARD_NETGEAR_WNR3500L,
BCM47XX_BOARD_NETGEAR_WNR3500U,
diff --git a/arch/mips/include/asm/mach-jz4740/platform.h b/arch/mips/include/asm/mach-jz4740/platform.h
index 3645974..c0c932a 100644
--- a/arch/mips/include/asm/mach-jz4740/platform.h
+++ b/arch/mips/include/asm/mach-jz4740/platform.h
@@ -29,7 +29,6 @@ extern struct platform_device jz4740_i2s_device;
extern struct platform_device jz4740_pcm_device;
extern struct platform_device jz4740_codec_device;
extern struct platform_device jz4740_adc_device;
-extern struct platform_device jz4740_wdt_device;
extern struct platform_device jz4740_pwm_device;
extern struct platform_device jz4740_dma_device;
diff --git a/arch/mips/include/asm/mc146818-time.h b/arch/mips/include/asm/mc146818-time.h
index 9e1ad26..cbf5cec 100644
--- a/arch/mips/include/asm/mc146818-time.h
+++ b/arch/mips/include/asm/mc146818-time.h
@@ -86,7 +86,7 @@ static inline int mc146818_set_rtc_mmss(unsigned long nowtime)
return retval;
}
-static inline unsigned long mc146818_get_cmos_time(void)
+static inline time64_t mc146818_get_cmos_time(void)
{
unsigned int year, mon, day, hour, min, sec;
unsigned long flags;
@@ -113,7 +113,7 @@ static inline unsigned long mc146818_get_cmos_time(void)
spin_unlock_irqrestore(&rtc_lock, flags);
year = mc146818_decode_year(year);
- return mktime(year, mon, day, hour, min, sec);
+ return mktime64(year, mon, day, hour, min, sec);
}
#endif /* __ASM_MC146818_TIME_H */
diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index f658597..0bc2708 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -681,10 +681,17 @@
#define MIPS_CONF7_WII (_ULCAST_(1) << 31)
#define MIPS_CONF7_RPS (_ULCAST_(1) << 2)
+/* ExternalSync */
+#define MIPS_CONF7_ES (_ULCAST_(1) << 8)
#define MIPS_CONF7_IAR (_ULCAST_(1) << 10)
#define MIPS_CONF7_AR (_ULCAST_(1) << 16)
+/* Config7 Bits specific to MIPS Technologies. */
+
+/* Performance counters implemented Per TC */
+#define MTI_CONF7_PTC (_ULCAST_(1) << 19)
+
/* WatchLo* register definitions */
#define MIPS_WATCHLO_IRW (_ULCAST_(0x7) << 0)
@@ -2760,6 +2767,7 @@ __BUILD_SET_C0(status)
__BUILD_SET_C0(cause)
__BUILD_SET_C0(config)
__BUILD_SET_C0(config5)
+__BUILD_SET_C0(config7)
__BUILD_SET_C0(intcontrol)
__BUILD_SET_C0(intctl)
__BUILD_SET_C0(srsmap)
diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index 17d4cd2..b85ec64 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -22,15 +22,6 @@
extern spinlock_t rtc_lock;
/*
- * RTC ops. By default, they point to weak no-op RTC functions.
- * rtc_mips_set_time - reverse the above translation and set time to RTC.
- * rtc_mips_set_mmss - similar to rtc_set_time, but only min and sec need
- * to be set. Used by RTC sync-up.
- */
-extern int rtc_mips_set_time(unsigned long);
-extern int rtc_mips_set_mmss(unsigned long);
-
-/*
* board specific routines required by time_init().
*/
extern void plat_time_init(void);
diff --git a/arch/mips/include/uapi/asm/unistd.h b/arch/mips/include/uapi/asm/unistd.h
index bb05e99..f25dd1d 100644
--- a/arch/mips/include/uapi/asm/unistd.h
+++ b/arch/mips/include/uapi/asm/unistd.h
@@ -388,17 +388,19 @@
#define __NR_pkey_alloc (__NR_Linux + 364)
#define __NR_pkey_free (__NR_Linux + 365)
#define __NR_statx (__NR_Linux + 366)
+#define __NR_rseq (__NR_Linux + 367)
+#define __NR_io_pgetevents (__NR_Linux + 368)
/*
* Offset of the last Linux o32 flavoured syscall
*/
-#define __NR_Linux_syscalls 366
+#define __NR_Linux_syscalls 368
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000
-#define __NR_O32_Linux_syscalls 366
+#define __NR_O32_Linux_syscalls 368
#if _MIPS_SIM == _MIPS_SIM_ABI64
@@ -733,16 +735,18 @@
#define __NR_pkey_alloc (__NR_Linux + 324)
#define __NR_pkey_free (__NR_Linux + 325)
#define __NR_statx (__NR_Linux + 326)
+#define __NR_rseq (__NR_Linux + 327)
+#define __NR_io_pgetevents (__NR_Linux + 328)
/*
* Offset of the last Linux 64-bit flavoured syscall
*/
-#define __NR_Linux_syscalls 326
+#define __NR_Linux_syscalls 328
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000
-#define __NR_64_Linux_syscalls 326
+#define __NR_64_Linux_syscalls 328
#if _MIPS_SIM == _MIPS_SIM_NABI32
@@ -1081,15 +1085,17 @@
#define __NR_pkey_alloc (__NR_Linux + 328)
#define __NR_pkey_free (__NR_Linux + 329)
#define __NR_statx (__NR_Linux + 330)
+#define __NR_rseq (__NR_Linux + 331)
+#define __NR_io_pgetevents (__NR_Linux + 332)
/*
* Offset of the last N32 flavoured syscall
*/
-#define __NR_Linux_syscalls 330
+#define __NR_Linux_syscalls 332
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000
-#define __NR_N32_Linux_syscalls 330
+#define __NR_N32_Linux_syscalls 332
#endif /* _UAPI_ASM_UNISTD_H */
diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
index 5b7cdd6..cbc5f8e 100644
--- a/arch/mips/jz4740/platform.c
+++ b/arch/mips/jz4740/platform.c
@@ -233,22 +233,6 @@ struct platform_device jz4740_adc_device = {
.resource = jz4740_adc_resources,
};
-/* Watchdog */
-static struct resource jz4740_wdt_resources[] = {
- {
- .start = JZ4740_WDT_BASE_ADDR,
- .end = JZ4740_WDT_BASE_ADDR + 0x10 - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-struct platform_device jz4740_wdt_device = {
- .name = "jz4740-wdt",
- .id = -1,
- .num_resources = ARRAY_SIZE(jz4740_wdt_resources),
- .resource = jz4740_wdt_resources,
-};
-
/* PWM */
struct platform_device jz4740_pwm_device = {
.name = "jz4740-pwm",
diff --git a/arch/mips/jz4740/reset.c b/arch/mips/jz4740/reset.c
index 67780c4..5bf0cf4 100644
--- a/arch/mips/jz4740/reset.c
+++ b/arch/mips/jz4740/reset.c
@@ -12,18 +12,9 @@
*
*/
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/pm.h>
-
#include <asm/reboot.h>
-#include <asm/mach-jz4740/base.h>
-#include <asm/mach-jz4740/timer.h>
-
#include "reset.h"
-#include "clock.h"
static void jz4740_halt(void)
{
@@ -36,29 +27,7 @@ static void jz4740_halt(void)
}
}
-#define JZ_REG_WDT_DATA 0x00
-#define JZ_REG_WDT_COUNTER_ENABLE 0x04
-#define JZ_REG_WDT_COUNTER 0x08
-#define JZ_REG_WDT_CTRL 0x0c
-
-static void jz4740_restart(char *command)
-{
- void __iomem *wdt_base = ioremap(JZ4740_WDT_BASE_ADDR, 0x0f);
-
- jz4740_timer_enable_watchdog();
-
- writeb(0, wdt_base + JZ_REG_WDT_COUNTER_ENABLE);
-
- writew(0, wdt_base + JZ_REG_WDT_COUNTER);
- writew(0, wdt_base + JZ_REG_WDT_DATA);
- writew(BIT(2), wdt_base + JZ_REG_WDT_CTRL);
-
- writeb(1, wdt_base + JZ_REG_WDT_COUNTER_ENABLE);
- jz4740_halt();
-}
-
void jz4740_reset_init(void)
{
- _machine_restart = jz4740_restart;
_machine_halt = jz4740_halt;
}
diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c
index c1cd414..cbe4742 100644
--- a/arch/mips/kernel/asm-offsets.c
+++ b/arch/mips/kernel/asm-offsets.c
@@ -83,7 +83,7 @@ void output_task_defines(void)
OFFSET(TASK_FLAGS, task_struct, flags);
OFFSET(TASK_MM, task_struct, mm);
OFFSET(TASK_PID, task_struct, pid);
-#if defined(CONFIG_CC_STACKPROTECTOR)
+#if defined(CONFIG_STACKPROTECTOR)
OFFSET(TASK_STACK_CANARY, task_struct, stack_canary);
#endif
DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct));
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 6b07b73..b2509c1 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -414,6 +414,14 @@ static int __init ftlb_disable(char *s)
__setup("noftlb", ftlb_disable);
+/*
+ * Check if the CPU has per tc perf counters
+ */
+static inline void cpu_set_mt_per_tc_perf(struct cpuinfo_mips *c)
+{
+ if (read_c0_config7() & MTI_CONF7_PTC)
+ c->options |= MIPS_CPU_MT_PER_TC_PERF_COUNTERS;
+}
static inline void check_errata(void)
{
@@ -1572,6 +1580,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
c->cputype = CPU_34K;
c->writecombine = _CACHE_UNCACHED;
__cpu_name[cpu] = "MIPS 34Kc";
+ cpu_set_mt_per_tc_perf(c);
break;
case PRID_IMP_74K:
c->cputype = CPU_74K;
@@ -1592,6 +1601,7 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
c->cputype = CPU_1004K;
c->writecombine = _CACHE_UNCACHED;
__cpu_name[cpu] = "MIPS 1004Kc";
+ cpu_set_mt_per_tc_perf(c);
break;
case PRID_IMP_1074K:
c->cputype = CPU_1074K;
@@ -1601,10 +1611,12 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
case PRID_IMP_INTERAPTIV_UP:
c->cputype = CPU_INTERAPTIV;
__cpu_name[cpu] = "MIPS interAptiv";
+ cpu_set_mt_per_tc_perf(c);
break;
case PRID_IMP_INTERAPTIV_MP:
c->cputype = CPU_INTERAPTIV;
__cpu_name[cpu] = "MIPS interAptiv (multi)";
+ cpu_set_mt_per_tc_perf(c);
break;
case PRID_IMP_PROAPTIV_UP:
c->cputype = CPU_PROAPTIV;
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 38a3029..d7de8ad 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -79,6 +79,10 @@ FEXPORT(ret_from_fork)
jal schedule_tail # a0 = struct task_struct *prev
FEXPORT(syscall_exit)
+#ifdef CONFIG_DEBUG_RSEQ
+ move a0, sp
+ jal rseq_syscall
+#endif
local_irq_disable # make sure need_resched and
# signals dont change between
# sampling and return
@@ -141,6 +145,10 @@ work_notifysig: # deal with pending signals and
j resume_userspace_check
FEXPORT(syscall_exit_partial)
+#ifdef CONFIG_DEBUG_RSEQ
+ move a0, sp
+ jal rseq_syscall
+#endif
local_irq_disable # make sure need_resched doesn't
# change between and return
LONG_L a2, TI_FLAGS($28) # current->work
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index f2ee7e1..cff52b2 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -119,10 +119,20 @@ NESTED(_mcount, PT_SIZE, ra)
EXPORT_SYMBOL(_mcount)
PTR_LA t1, ftrace_stub
PTR_L t2, ftrace_trace_function /* Prepare t2 for (1) */
- bne t1, t2, static_trace
+ beq t1, t2, fgraph_trace
nop
+ MCOUNT_SAVE_REGS
+
+ move a0, ra /* arg1: self return address */
+ jalr t2 /* (1) call *ftrace_trace_function */
+ move a1, AT /* arg2: parent's return address */
+
+ MCOUNT_RESTORE_REGS
+
+fgraph_trace:
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+ PTR_LA t1, ftrace_stub
PTR_L t3, ftrace_graph_return
bne t1, t3, ftrace_graph_caller
nop
@@ -131,24 +141,11 @@ EXPORT_SYMBOL(_mcount)
bne t1, t3, ftrace_graph_caller
nop
#endif
- b ftrace_stub
-#ifdef CONFIG_32BIT
- addiu sp, sp, 8
-#else
- nop
-#endif
-static_trace:
- MCOUNT_SAVE_REGS
-
- move a0, ra /* arg1: self return address */
- jalr t2 /* (1) call *ftrace_trace_function */
- move a1, AT /* arg2: parent's return address */
-
- MCOUNT_RESTORE_REGS
#ifdef CONFIG_32BIT
addiu sp, sp, 8
#endif
+
.globl ftrace_stub
ftrace_stub:
RETURN_BACK
diff --git a/arch/mips/kernel/octeon_switch.S b/arch/mips/kernel/octeon_switch.S
index e42113f..896080b 100644
--- a/arch/mips/kernel/octeon_switch.S
+++ b/arch/mips/kernel/octeon_switch.S
@@ -61,7 +61,7 @@
#endif
3:
-#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
+#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
PTR_LA t8, __stack_chk_guard
LONG_L t9, TASK_STACK_CANARY(a1)
LONG_S t9, 0(t8)
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index ee73550..4138635 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -129,20 +129,14 @@ static struct mips_pmu mipspmu;
#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
-static int cpu_has_mipsmt_pertccounters;
-
static DEFINE_RWLOCK(pmuint_rwlock);
#if defined(CONFIG_CPU_BMIPS5000)
#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
0 : (smp_processor_id() & MIPS_CPUID_TO_COUNTER_MASK))
#else
-/*
- * FIXME: For VSMP, vpe_id() is redefined for Perf-events, because
- * cpu_data[cpuid].vpe_id reports 0 for _both_ CPUs.
- */
#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
- 0 : smp_processor_id())
+ 0 : cpu_vpe_id(&current_cpu_data))
#endif
/* Copied from op_model_mipsxx.c */
@@ -329,7 +323,11 @@ static int mipsxx_pmu_alloc_counter(struct cpu_hw_events *cpuc,
static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
{
+ struct perf_event *event = container_of(evt, struct perf_event, hw);
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+#ifdef CONFIG_MIPS_MT_SMP
+ unsigned int range = evt->event_base >> 24;
+#endif /* CONFIG_MIPS_MT_SMP */
WARN_ON(idx < 0 || idx >= mipspmu.num_counters);
@@ -337,11 +335,37 @@ static void mipsxx_pmu_enable_event(struct hw_perf_event *evt, int idx)
(evt->config_base & M_PERFCTL_CONFIG_MASK) |
/* Make sure interrupt enabled. */
MIPS_PERFCTRL_IE;
- if (IS_ENABLED(CONFIG_CPU_BMIPS5000))
+
+#ifdef CONFIG_CPU_BMIPS5000
+ {
/* enable the counter for the calling thread */
cpuc->saved_ctrl[idx] |=
(1 << (12 + vpe_id())) | BRCM_PERFCTRL_TC;
+ }
+#else
+#ifdef CONFIG_MIPS_MT_SMP
+ if (range > V) {
+ /* The counter is processor wide. Set it up to count all TCs. */
+ pr_debug("Enabling perf counter for all TCs\n");
+ cpuc->saved_ctrl[idx] |= M_TC_EN_ALL;
+ } else
+#endif /* CONFIG_MIPS_MT_SMP */
+ {
+ unsigned int cpu, ctrl;
+
+ /*
+ * Set up the counter for a particular CPU when event->cpu is
+ * a valid CPU number. Otherwise set up the counter for the CPU
+ * scheduling this thread.
+ */
+ cpu = (event->cpu >= 0) ? event->cpu : smp_processor_id();
+ ctrl = M_PERFCTL_VPEID(cpu_vpe_id(&cpu_data[cpu]));
+ ctrl |= M_TC_EN_VPE;
+ cpuc->saved_ctrl[idx] |= ctrl;
+ pr_debug("Enabling perf counter for CPU%d\n", cpu);
+ }
+#endif /* CONFIG_CPU_BMIPS5000 */
/*
* We do not actually let the counter run. Leave it until start().
*/
@@ -655,13 +679,14 @@ static unsigned int mipspmu_perf_event_encode(const struct mips_perf_event *pev)
* event_id.
*/
#ifdef CONFIG_MIPS_MT_SMP
- return ((unsigned int)pev->range << 24) |
- (pev->cntr_mask & 0xffff00) |
- (pev->event_id & 0xff);
-#else
- return (pev->cntr_mask & 0xffff00) |
- (pev->event_id & 0xff);
-#endif
+ if (num_possible_cpus() > 1)
+ return ((unsigned int)pev->range << 24) |
+ (pev->cntr_mask & 0xffff00) |
+ (pev->event_id & 0xff);
+ else
+#endif /* CONFIG_MIPS_MT_SMP */
+ return ((pev->cntr_mask & 0xffff00) |
+ (pev->event_id & 0xff));
}
static const struct mips_perf_event *mipspmu_map_general_event(int idx)
@@ -1265,37 +1290,6 @@ static const struct mips_perf_event xlp_cache_map
},
};
-#ifdef CONFIG_MIPS_MT_SMP
-static void check_and_calc_range(struct perf_event *event,
- const struct mips_perf_event *pev)
-{
- struct hw_perf_event *hwc = &event->hw;
-
- if (event->cpu >= 0) {
- if (pev->range > V) {
- /*
- * The user selected an event that is processor
- * wide, while expecting it to be VPE wide.
- */
- hwc->config_base |= M_TC_EN_ALL;
- } else {
- /*
- * FIXME: cpu_data[event->cpu].vpe_id reports 0
- * for both CPUs.
- */
- hwc->config_base |= M_PERFCTL_VPEID(event->cpu);
- hwc->config_base |= M_TC_EN_VPE;
- }
- } else
- hwc->config_base |= M_TC_EN_ALL;
-}
-#else
-static void check_and_calc_range(struct perf_event *event,
- const struct mips_perf_event *pev)
-{
-}
-#endif
-
static int __hw_perf_event_init(struct perf_event *event)
{
struct perf_event_attr *attr = &event->attr;
@@ -1331,10 +1325,6 @@ static int __hw_perf_event_init(struct perf_event *event)
*/
hwc->config_base = MIPS_PERFCTRL_IE;
- /* Calculate range bits and validate it. */
- if (num_possible_cpus() > 1)
- check_and_calc_range(event, pev);
-
hwc->event_base = mipspmu_perf_event_encode(pev);
if (PERF_TYPE_RAW == event->attr.type)
mutex_unlock(&raw_event_mutex);
@@ -1723,7 +1713,6 @@ init_hw_perf_events(void)
}
#ifdef CONFIG_MIPS_PERF_SHARED_TC_COUNTERS
- cpu_has_mipsmt_pertccounters = read_c0_config7() & (1<<19);
if (!cpu_has_mipsmt_pertccounters)
counters = counters_total_to_per_cpu(counters);
#endif
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 3775a8d..8d85046 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -180,7 +180,7 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
return 0;
}
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 0c0c23c..9f6c3f2 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -811,7 +811,7 @@ long arch_ptrace(struct task_struct *child, long request,
/*
* The odd registers are actually the high
* order bits of the values stored in the even
- * registers - unless we're using r2k_switch.S.
+ * registers.
*/
tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE],
addr & 1);
@@ -906,7 +906,7 @@ long arch_ptrace(struct task_struct *child, long request,
/*
* The odd registers are actually the high
* order bits of the values stored in the even
- * registers - unless we're using r2k_switch.S.
+ * registers.
*/
set_fpr32(&fregs[(addr & ~1) - FPR_BASE],
addr & 1, data);
diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c
index f30c381..7edc629 100644
--- a/arch/mips/kernel/ptrace32.c
+++ b/arch/mips/kernel/ptrace32.c
@@ -103,7 +103,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
/*
* The odd registers are actually the high
* order bits of the values stored in the even
- * registers - unless we're using r2k_switch.S.
+ * registers.
*/
tmp = get_fpr32(&fregs[(addr & ~1) - FPR_BASE],
addr & 1);
@@ -216,7 +216,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
/*
* The odd registers are actually the high
* order bits of the values stored in the even
- * registers - unless we're using r2k_switch.S.
+ * registers.
*/
set_fpr32(&fregs[(addr & ~1) - FPR_BASE],
addr & 1, data);
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
index 6658971..71b1aaf 100644
--- a/arch/mips/kernel/r2300_switch.S
+++ b/arch/mips/kernel/r2300_switch.S
@@ -36,7 +36,7 @@ LEAF(resume)
cpu_save_nonscratch a0
sw ra, THREAD_REG31(a0)
-#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
+#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
PTR_LA t8, __stack_chk_guard
LONG_L t9, TASK_STACK_CANARY(a1)
LONG_S t9, 0(t8)
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 17cf934..58232ae 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -31,7 +31,7 @@
cpu_save_nonscratch a0
LONG_S ra, THREAD_REG31(a0)
-#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
+#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
PTR_LA t8, __stack_chk_guard
LONG_L t9, TASK_STACK_CANARY(a1)
LONG_S t9, 0(t8)
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index a9a7d78..91d3c8c 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -590,3 +590,5 @@ EXPORT(sys_call_table)
PTR sys_pkey_alloc
PTR sys_pkey_free /* 4365 */
PTR sys_statx
+ PTR sys_rseq
+ PTR sys_io_pgetevents
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 65d5aee..358d959 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -439,4 +439,6 @@ EXPORT(sys_call_table)
PTR sys_pkey_alloc
PTR sys_pkey_free /* 5325 */
PTR sys_statx
+ PTR sys_rseq
+ PTR sys_io_pgetevents
.size sys_call_table,.-sys_call_table
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index cbf190e..c65eaac 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -434,4 +434,6 @@ EXPORT(sysn32_call_table)
PTR sys_pkey_alloc
PTR sys_pkey_free
PTR sys_statx /* 6330 */
+ PTR sys_rseq
+ PTR compat_sys_io_pgetevents
.size sysn32_call_table,.-sysn32_call_table
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 9ebe3e2..73913f0 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -583,4 +583,6 @@ EXPORT(sys32_call_table)
PTR sys_pkey_alloc
PTR sys_pkey_free /* 4365 */
PTR sys_statx
+ PTR sys_rseq
+ PTR compat_sys_io_pgetevents
.size sys32_call_table,.-sys32_call_table
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 563188a..2c96c0c 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -93,7 +93,7 @@ void __init add_memory_region(phys_addr_t start, phys_addr_t size, long type)
* If the region reaches the top of the physical address space, adjust
* the size slightly so that (start + size) doesn't overflow
*/
- if (start + size - 1 == (phys_addr_t)ULLONG_MAX)
+ if (start + size - 1 == PHYS_ADDR_MAX)
--size;
/* Sanity check */
@@ -376,7 +376,7 @@ static void __init bootmem_init(void)
unsigned long reserved_end;
unsigned long mapstart = ~0UL;
unsigned long bootmap_size;
- phys_addr_t ramstart = (phys_addr_t)ULLONG_MAX;
+ phys_addr_t ramstart = PHYS_ADDR_MAX;
bool bootmap_valid = false;
int i;
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index 9e22446..00f2535 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -801,6 +801,8 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
regs->regs[0] = 0; /* Don't deal with this again. */
}
+ rseq_signal_deliver(regs);
+
if (sig_uses_siginfo(&ksig->ka, abi))
ret = abi->setup_rt_frame(vdso + abi->vdso->off_rt_sigreturn,
ksig, regs, oldset);
@@ -868,6 +870,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
+ rseq_handle_notify_resume(regs);
}
user_enter();
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index a6ebc81..bfe02de 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -34,21 +34,6 @@
DEFINE_SPINLOCK(rtc_lock);
EXPORT_SYMBOL(rtc_lock);
-int __weak rtc_mips_set_time(unsigned long sec)
-{
- return -ENODEV;
-}
-
-int __weak rtc_mips_set_mmss(unsigned long nowtime)
-{
- return rtc_mips_set_time(nowtime);
-}
-
-int update_persistent_clock(struct timespec now)
-{
- return rtc_mips_set_mmss(now.tv_sec);
-}
-
static int null_perf_irq(void)
{
return 0;
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index 544ea21..0bef238 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -872,7 +872,7 @@ static ssize_t vpe_write(struct file *file, const char __user *buffer,
return -ENODEV;
if ((count + v->len) > v->plen) {
- pr_warn("VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
+ pr_warn("VPE loader: elf size too big. Perhaps strip unneeded symbols\n");
return -ENOMEM;
}
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index 0f725e9..7cd76f9 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -1076,7 +1076,7 @@ int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
return -ENOIOCTLCMD;
}
-int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
{
return VM_FAULT_SIGBUS;
}
diff --git a/arch/mips/lasat/ds1603.c b/arch/mips/lasat/ds1603.c
index 8bd5cf8..e6ce39f 100644
--- a/arch/mips/lasat/ds1603.c
+++ b/arch/mips/lasat/ds1603.c
@@ -136,7 +136,7 @@ static void rtc_end_op(void)
lasat_ndelay(1000);
}
-void read_persistent_clock(struct timespec *ts)
+void read_persistent_clock64(struct timespec64 *ts)
{
unsigned long word;
unsigned long flags;
@@ -152,14 +152,19 @@ void read_persistent_clock(struct timespec *ts)
ts->tv_nsec = 0;
}
-int rtc_mips_set_mmss(unsigned long time)
+int update_persistent_clock64(struct timespec64 now)
{
+ time64_t time = now.tv_sec;
unsigned long flags;
spin_lock_irqsave(&rtc_lock, flags);
rtc_init_op();
rtc_write_byte(SET_TIME_CMD);
- rtc_write_word(time);
+ /*
+ * Due to the hardware limitation, we cast to 'unsigned long' type,
+ * so it will overflow in year 2106 on 32-bit machine.
+ */
+ rtc_write_word((unsigned long)time);
rtc_end_op();
spin_unlock_irqrestore(&rtc_lock, flags);
diff --git a/arch/mips/lasat/sysctl.c b/arch/mips/lasat/sysctl.c
index 6f74224..ead07c2 100644
--- a/arch/mips/lasat/sysctl.c
+++ b/arch/mips/lasat/sysctl.c
@@ -73,8 +73,16 @@ int proc_dolasatrtc(struct ctl_table *table, int write,
if (r)
return r;
- if (write)
- rtc_mips_set_mmss(rtctmp);
+ if (write) {
+ /*
+ * Due to the RTC hardware limitation, we can not actually
+ * use the full 64-bit range here.
+ */
+ ts.tv_sec = rtctmp;
+ ts.tv_nsec = 0;
+
+ update_persistent_clock64(ts);
+ }
return 0;
}
diff --git a/arch/mips/lib/Makefile b/arch/mips/lib/Makefile
index e84e126..6537e02 100644
--- a/arch/mips/lib/Makefile
+++ b/arch/mips/lib/Makefile
@@ -16,5 +16,4 @@ obj-$(CONFIG_CPU_R3000) += r3k_dump_tlb.o
obj-$(CONFIG_CPU_TX39XX) += r3k_dump_tlb.o
# libgcc-style stuff needed in the kernel
-obj-y += ashldi3.o ashrdi3.o bswapsi.o bswapdi.o cmpdi2.o lshrdi3.o multi3.o \
- ucmpdi2.o
+obj-y += bswapsi.o bswapdi.o multi3.o
diff --git a/arch/mips/lib/ashldi3.c b/arch/mips/lib/ashldi3.c
deleted file mode 100644
index 24cd690..0000000
--- a/arch/mips/lib/ashldi3.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/export.h>
-
-#include "libgcc.h"
-
-long long notrace __ashldi3(long long u, word_type b)
-{
- DWunion uu, w;
- word_type bm;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
- bm = 32 - b;
-
- if (bm <= 0) {
- w.s.low = 0;
- w.s.high = (unsigned int) uu.s.low << -bm;
- } else {
- const unsigned int carries = (unsigned int) uu.s.low >> bm;
-
- w.s.low = (unsigned int) uu.s.low << b;
- w.s.high = ((unsigned int) uu.s.high << b) | carries;
- }
-
- return w.ll;
-}
-
-EXPORT_SYMBOL(__ashldi3);
diff --git a/arch/mips/lib/ashrdi3.c b/arch/mips/lib/ashrdi3.c
deleted file mode 100644
index 23f5295..0000000
--- a/arch/mips/lib/ashrdi3.c
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/export.h>
-
-#include "libgcc.h"
-
-long long notrace __ashrdi3(long long u, word_type b)
-{
- DWunion uu, w;
- word_type bm;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
- bm = 32 - b;
-
- if (bm <= 0) {
- /* w.s.high = 1..1 or 0..0 */
- w.s.high =
- uu.s.high >> 31;
- w.s.low = uu.s.high >> -bm;
- } else {
- const unsigned int carries = (unsigned int) uu.s.high << bm;
-
- w.s.high = uu.s.high >> b;
- w.s.low = ((unsigned int) uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
-
-EXPORT_SYMBOL(__ashrdi3);
diff --git a/arch/mips/lib/cmpdi2.c b/arch/mips/lib/cmpdi2.c
deleted file mode 100644
index 93cfc785..0000000
--- a/arch/mips/lib/cmpdi2.c
+++ /dev/null
@@ -1,28 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/export.h>
-
-#include "libgcc.h"
-
-word_type notrace __cmpdi2(long long a, long long b)
-{
- const DWunion au = {
- .ll = a
- };
- const DWunion bu = {
- .ll = b
- };
-
- if (au.s.high < bu.s.high)
- return 0;
- else if (au.s.high > bu.s.high)
- return 2;
-
- if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
- return 0;
- else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
- return 2;
-
- return 1;
-}
-
-EXPORT_SYMBOL(__cmpdi2);
diff --git a/arch/mips/lib/lshrdi3.c b/arch/mips/lib/lshrdi3.c
deleted file mode 100644
index 914b971..0000000
--- a/arch/mips/lib/lshrdi3.c
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/export.h>
-
-#include "libgcc.h"
-
-long long notrace __lshrdi3(long long u, word_type b)
-{
- DWunion uu, w;
- word_type bm;
-
- if (b == 0)
- return u;
-
- uu.ll = u;
- bm = 32 - b;
-
- if (bm <= 0) {
- w.s.high = 0;
- w.s.low = (unsigned int) uu.s.high >> -bm;
- } else {
- const unsigned int carries = (unsigned int) uu.s.high << bm;
-
- w.s.high = (unsigned int) uu.s.high >> b;
- w.s.low = ((unsigned int) uu.s.low >> b) | carries;
- }
-
- return w.ll;
-}
-
-EXPORT_SYMBOL(__lshrdi3);
diff --git a/arch/mips/lib/memset.S b/arch/mips/lib/memset.S
index f732797..1cc3065 100644
--- a/arch/mips/lib/memset.S
+++ b/arch/mips/lib/memset.S
@@ -95,7 +95,7 @@
sltiu t0, a2, STORSIZE /* very small region? */
bnez t0, .Lsmall_memset\@
- andi t0, a0, STORMASK /* aligned? */
+ andi t0, a0, STORMASK /* aligned? */
#ifdef CONFIG_CPU_MICROMIPS
move t8, a1 /* used by 'swp' instruction */
@@ -103,12 +103,12 @@
#endif
#ifndef CONFIG_CPU_DADDI_WORKAROUNDS
beqz t0, 1f
- PTR_SUBU t0, STORSIZE /* alignment in bytes */
+ PTR_SUBU t0, STORSIZE /* alignment in bytes */
#else
.set noat
li AT, STORSIZE
beqz t0, 1f
- PTR_SUBU t0, AT /* alignment in bytes */
+ PTR_SUBU t0, AT /* alignment in bytes */
.set at
#endif
@@ -149,7 +149,7 @@
1: ori t1, a2, 0x3f /* # of full blocks */
xori t1, 0x3f
beqz t1, .Lmemset_partial\@ /* no block to fill */
- andi t0, a2, 0x40-STORSIZE
+ andi t0, a2, 0x40-STORSIZE
PTR_ADDU t1, a0 /* end address */
.set reorder
@@ -174,7 +174,7 @@
.set at
#endif
jr t1
- PTR_ADDU a0, t0 /* dest ptr */
+ PTR_ADDU a0, t0 /* dest ptr */
.set push
.set noreorder
@@ -186,7 +186,7 @@
beqz a2, 1f
#ifndef CONFIG_CPU_MIPSR6
- PTR_ADDU a0, a2 /* What's left */
+ PTR_ADDU a0, a2 /* What's left */
R10KCBARRIER(0(ra))
#ifdef __MIPSEB__
EX(LONG_S_R, a1, -1(a0), .Llast_fixup\@)
@@ -194,7 +194,7 @@
EX(LONG_S_L, a1, -1(a0), .Llast_fixup\@)
#endif
#else
- PTR_SUBU t0, $0, a2
+ PTR_SUBU t0, $0, a2
PTR_ADDIU t0, 1
STORE_BYTE(0)
STORE_BYTE(1)
@@ -210,11 +210,11 @@
0:
#endif
1: jr ra
- move a2, zero
+ move a2, zero
.Lsmall_memset\@:
beqz a2, 2f
- PTR_ADDU t1, a0, a2
+ PTR_ADDU t1, a0, a2
1: PTR_ADDIU a0, 1 /* fill bytewise */
R10KCBARRIER(0(ra))
@@ -222,7 +222,7 @@
EX(sb, a1, -1(a0), .Lsmall_fixup\@)
2: jr ra /* done */
- move a2, zero
+ move a2, zero
.if __memset == 1
END(memset)
.set __memset, 0
@@ -238,7 +238,7 @@
.Lfirst_fixup\@:
jr ra
- nop
+ nop
.Lfwd_fixup\@:
PTR_L t0, TI_TASK($28)
@@ -246,7 +246,7 @@
LONG_L t0, THREAD_BUADDR(t0)
LONG_ADDU a2, t1
jr ra
- LONG_SUBU a2, t0
+ LONG_SUBU a2, t0
.Lpartial_fixup\@:
PTR_L t0, TI_TASK($28)
@@ -254,7 +254,7 @@
LONG_L t0, THREAD_BUADDR(t0)
LONG_ADDU a2, a0
jr ra
- LONG_SUBU a2, t0
+ LONG_SUBU a2, t0
.Llast_fixup\@:
jr ra
@@ -278,7 +278,7 @@
LEAF(memset)
EXPORT_SYMBOL(memset)
beqz a1, 1f
- move v0, a0 /* result */
+ move v0, a0 /* result */
andi a1, 0xff /* spread fillword */
LONG_SLL t1, a1, 8
diff --git a/arch/mips/lib/ucmpdi2.c b/arch/mips/lib/ucmpdi2.c
deleted file mode 100644
index c31c78c..0000000
--- a/arch/mips/lib/ucmpdi2.c
+++ /dev/null
@@ -1,22 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <linux/export.h>
-
-#include "libgcc.h"
-
-word_type notrace __ucmpdi2(unsigned long long a, unsigned long long b)
-{
- const DWunion au = {.ll = a};
- const DWunion bu = {.ll = b};
-
- if ((unsigned int) au.s.high < (unsigned int) bu.s.high)
- return 0;
- else if ((unsigned int) au.s.high > (unsigned int) bu.s.high)
- return 2;
- if ((unsigned int) au.s.low < (unsigned int) bu.s.low)
- return 0;
- else if ((unsigned int) au.s.low > (unsigned int) bu.s.low)
- return 2;
- return 1;
-}
-
-EXPORT_SYMBOL(__ucmpdi2);
diff --git a/arch/mips/loongson64/common/time.c b/arch/mips/loongson64/common/time.c
index e1a5382a..0ba53c5 100644
--- a/arch/mips/loongson64/common/time.c
+++ b/arch/mips/loongson64/common/time.c
@@ -29,7 +29,7 @@ void __init plat_time_init(void)
#endif
}
-void read_persistent_clock(struct timespec *ts)
+void read_persistent_clock64(struct timespec64 *ts)
{
ts->tv_sec = mc146818_get_cmos_time();
ts->tv_nsec = 0;
diff --git a/arch/mips/mm/sc-debugfs.c b/arch/mips/mm/sc-debugfs.c
index 2e2132d..2a11608 100644
--- a/arch/mips/mm/sc-debugfs.c
+++ b/arch/mips/mm/sc-debugfs.c
@@ -31,17 +31,10 @@ static ssize_t sc_prefetch_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
- char buf[32];
- ssize_t buf_size;
bool enabled;
int err;
- buf_size = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
-
- buf[buf_size] = '\0';
- err = strtobool(buf, &enabled);
+ err = kstrtobool_from_user(user_buf, count, &enabled);
if (err)
return err;
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
index 66c8667..d22b7ed 100644
--- a/arch/mips/mti-malta/malta-time.c
+++ b/arch/mips/mti-malta/malta-time.c
@@ -134,7 +134,7 @@ static void __init estimate_frequencies(void)
}
}
-void read_persistent_clock(struct timespec *ts)
+void read_persistent_clock64(struct timespec64 *ts)
{
ts->tv_sec = mc146818_get_cmos_time();
ts->tv_nsec = 0;
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index c3e4c18..7c04b17 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -36,7 +36,6 @@ static int perfcount_irq;
#endif
#ifdef CONFIG_MIPS_MT_SMP
-static int cpu_has_mipsmt_pertccounters;
#define WHAT (MIPS_PERFCTRL_MT_EN_VPE | \
M_PERFCTL_VPEID(cpu_vpe_id(&current_cpu_data)))
#define vpe_id() (cpu_has_mipsmt_pertccounters ? \
@@ -326,7 +325,6 @@ static int __init mipsxx_init(void)
}
#ifdef CONFIG_MIPS_MT_SMP
- cpu_has_mipsmt_pertccounters = read_c0_config7() & (1<<19);
if (!cpu_has_mipsmt_pertccounters)
counters = counters_total_to_per_cpu(counters);
#endif
diff --git a/arch/mips/sibyte/swarm/rtc_m41t81.c b/arch/mips/sibyte/swarm/rtc_m41t81.c
index e624664..4ac8ccd 100644
--- a/arch/mips/sibyte/swarm/rtc_m41t81.c
+++ b/arch/mips/sibyte/swarm/rtc_m41t81.c
@@ -141,13 +141,13 @@ static int m41t81_write(uint8_t addr, int b)
return 0;
}
-int m41t81_set_time(unsigned long t)
+int m41t81_set_time(time64_t t)
{
struct rtc_time tm;
unsigned long flags;
/* Note we don't care about the century */
- rtc_time_to_tm(t, &tm);
+ rtc_time64_to_tm(t, &tm);
/*
* Note the write order matters as it ensures the correctness.
@@ -188,7 +188,7 @@ int m41t81_set_time(unsigned long t)
return 0;
}
-unsigned long m41t81_get_time(void)
+time64_t m41t81_get_time(void)
{
unsigned int year, mon, day, hour, min, sec;
unsigned long flags;
@@ -218,7 +218,7 @@ unsigned long m41t81_get_time(void)
year += 2000;
- return mktime(year, mon, day, hour, min, sec);
+ return mktime64(year, mon, day, hour, min, sec);
}
int m41t81_probe(void)
diff --git a/arch/mips/sibyte/swarm/rtc_xicor1241.c b/arch/mips/sibyte/swarm/rtc_xicor1241.c
index 50a82c4..2dcaaa7 100644
--- a/arch/mips/sibyte/swarm/rtc_xicor1241.c
+++ b/arch/mips/sibyte/swarm/rtc_xicor1241.c
@@ -109,13 +109,13 @@ static int xicor_write(uint8_t addr, int b)
}
}
-int xicor_set_time(unsigned long t)
+int xicor_set_time(time64_t t)
{
struct rtc_time tm;
int tmp;
unsigned long flags;
- rtc_time_to_tm(t, &tm);
+ rtc_time64_to_tm(t, &tm);
tm.tm_year += 1900;
spin_lock_irqsave(&rtc_lock, flags);
@@ -168,7 +168,7 @@ int xicor_set_time(unsigned long t)
return 0;
}
-unsigned long xicor_get_time(void)
+time64_t xicor_get_time(void)
{
unsigned int year, mon, day, hour, min, sec, y2k;
unsigned long flags;
@@ -201,7 +201,7 @@ unsigned long xicor_get_time(void)
year += (y2k * 100);
- return mktime(year, mon, day, hour, min, sec);
+ return mktime64(year, mon, day, hour, min, sec);
}
int xicor_probe(void)
diff --git a/arch/mips/sibyte/swarm/setup.c b/arch/mips/sibyte/swarm/setup.c
index 494fb0a..152ca71 100644
--- a/arch/mips/sibyte/swarm/setup.c
+++ b/arch/mips/sibyte/swarm/setup.c
@@ -57,12 +57,12 @@ extern void sb1250_setup(void);
#endif
extern int xicor_probe(void);
-extern int xicor_set_time(unsigned long);
-extern unsigned long xicor_get_time(void);
+extern int xicor_set_time(time64_t);
+extern time64_t xicor_get_time(void);
extern int m41t81_probe(void);
-extern int m41t81_set_time(unsigned long);
-extern unsigned long m41t81_get_time(void);
+extern int m41t81_set_time(time64_t);
+extern time64_t m41t81_get_time(void);
const char *get_system_type(void)
{
@@ -87,9 +87,9 @@ enum swarm_rtc_type {
enum swarm_rtc_type swarm_rtc_type;
-void read_persistent_clock(struct timespec *ts)
+void read_persistent_clock64(struct timespec64 *ts)
{
- unsigned long sec;
+ time64_t sec;
switch (swarm_rtc_type) {
case RTC_XICOR:
@@ -102,15 +102,17 @@ void read_persistent_clock(struct timespec *ts)
case RTC_NONE:
default:
- sec = mktime(2000, 1, 1, 0, 0, 0);
+ sec = mktime64(2000, 1, 1, 0, 0, 0);
break;
}
ts->tv_sec = sec;
ts->tv_nsec = 0;
}
-int rtc_mips_set_time(unsigned long sec)
+int update_persistent_clock64(struct timespec64 now)
{
+ time64_t sec = now.tv_sec;
+
switch (swarm_rtc_type) {
case RTC_XICOR:
return xicor_set_time(sec);
diff --git a/arch/mips/sni/time.c b/arch/mips/sni/time.c
index 0eb7d1e..dbace1f 100644
--- a/arch/mips/sni/time.c
+++ b/arch/mips/sni/time.c
@@ -171,9 +171,3 @@ void __init plat_time_init(void)
}
setup_pit_timer();
}
-
-void read_persistent_clock(struct timespec *ts)
-{
- ts->tv_sec = -1;
- ts->tv_nsec = 0;
-}
diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c
index fd26fad..ef29a9c 100644
--- a/arch/mips/txx9/rbtx4939/setup.c
+++ b/arch/mips/txx9/rbtx4939/setup.c
@@ -219,7 +219,7 @@ static int __init rbtx4939_led_probe(struct platform_device *pdev)
"nand-disk",
};
- leds_data = kzalloc(sizeof(*leds_data) * RBTX4939_MAX_7SEGLEDS,
+ leds_data = kcalloc(RBTX4939_MAX_7SEGLEDS, sizeof(*leds_data),
GFP_KERNEL);
if (!leds_data)
return -ENOMEM;
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig
index 4d8f64d..c480770 100644
--- a/arch/parisc/Kconfig
+++ b/arch/parisc/Kconfig
@@ -275,7 +275,7 @@ config SMP
machines, but will use only one CPU of a multiprocessor machine.
On a uniprocessor machine, the kernel will run faster if you say N.
- See also <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO
+ See also <file:Documentation/lockup-watchdogs.txt> and the SMP-HOWTO
available at <http://www.tldp.org/docs.html#howto>.
If you don't know what to do here, say N.
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index eaba592..9f2b75f 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -190,7 +190,7 @@ config PPC
select HAVE_FTRACE_MCOUNT_RECORD
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_TRACER
- select HAVE_GCC_PLUGINS
+ select HAVE_GCC_PLUGINS if GCC_VERSION >= 50200 # plugin support on gcc <= 5.1 is buggy on PPC
select HAVE_GENERIC_GUP
select HAVE_HW_BREAKPOINT if PERF_EVENTS && (PPC_BOOK3S || PPC_8xx)
select HAVE_IDE
@@ -461,23 +461,9 @@ config LD_HEAD_STUB_CATCH
If unsure, say "N".
-config DISABLE_MPROFILE_KERNEL
- bool "Disable use of mprofile-kernel for kernel tracing"
- depends on PPC64 && CPU_LITTLE_ENDIAN
- default y
- help
- Selecting this options disables use of the mprofile-kernel ABI for
- kernel tracing. That will cause options such as live patching
- (CONFIG_LIVEPATCH) which depend on CONFIG_DYNAMIC_FTRACE_WITH_REGS to
- be disabled also.
-
- If you have a toolchain which supports mprofile-kernel, then you can
- disable this. Otherwise leave it enabled. If you're not sure, say
- "Y".
-
config MPROFILE_KERNEL
depends on PPC64 && CPU_LITTLE_ENDIAN
- def_bool !DISABLE_MPROFILE_KERNEL
+ def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-mprofile-kernel.sh $(CC) -I$(srctree)/include -D__KERNEL__)
config HOTPLUG_CPU
bool "Support for enabling/disabling CPUs"
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 9b52e42..2ea575c 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -161,18 +161,7 @@ CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64
endif
ifdef CONFIG_MPROFILE_KERNEL
- ifeq ($(shell $(srctree)/arch/powerpc/tools/gcc-check-mprofile-kernel.sh $(CC) -I$(srctree)/include -D__KERNEL__),OK)
- CC_FLAGS_FTRACE := -pg -mprofile-kernel
- KBUILD_CPPFLAGS += -DCC_USING_MPROFILE_KERNEL
- else
- # If the user asked for mprofile-kernel but the toolchain doesn't
- # support it, emit a warning and deliberately break the build later
- # with mprofile-kernel-not-supported. We would prefer to make this an
- # error right here, but then the user would never be able to run
- # oldconfig to change their configuration.
- $(warning Compiler does not support mprofile-kernel, set CONFIG_DISABLE_MPROFILE_KERNEL)
- CC_FLAGS_FTRACE := -mprofile-kernel-not-supported
- endif
+ CC_FLAGS_FTRACE := -pg -mprofile-kernel
endif
CFLAGS-$(CONFIG_CELL_CPU) += $(call cc-option,-mcpu=cell)
@@ -255,6 +244,7 @@ cpu-as-$(CONFIG_4xx) += -Wa,-m405
cpu-as-$(CONFIG_ALTIVEC) += $(call as-option,-Wa$(comma)-maltivec)
cpu-as-$(CONFIG_E200) += -Wa,-me200
cpu-as-$(CONFIG_PPC_BOOK3S_64) += -Wa,-mpower4
+cpu-as-$(CONFIG_PPC_E500MC) += $(call as-option,-Wa$(comma)-me500mc)
KBUILD_AFLAGS += $(cpu-as-y)
KBUILD_CFLAGS += $(cpu-as-y)
diff --git a/arch/powerpc/include/asm/asm-prototypes.h b/arch/powerpc/include/asm/asm-prototypes.h
index aa9e785..7841b8a 100644
--- a/arch/powerpc/include/asm/asm-prototypes.h
+++ b/arch/powerpc/include/asm/asm-prototypes.h
@@ -134,7 +134,13 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip);
void pnv_power9_force_smt4_catch(void);
void pnv_power9_force_smt4_release(void);
+/* Transaction memory related */
void tm_enable(void);
void tm_disable(void);
void tm_abort(uint8_t cause);
+
+struct kvm_vcpu;
+void _kvmppc_restore_tm_pr(struct kvm_vcpu *vcpu, u64 guest_msr);
+void _kvmppc_save_tm_pr(struct kvm_vcpu *vcpu, u64 guest_msr);
+
#endif /* _ASM_POWERPC_ASM_PROTOTYPES_H */
diff --git a/arch/powerpc/include/asm/book3s/32/pgalloc.h b/arch/powerpc/include/asm/book3s/32/pgalloc.h
index 6a66739..e463380 100644
--- a/arch/powerpc/include/asm/book3s/32/pgalloc.h
+++ b/arch/powerpc/include/asm/book3s/32/pgalloc.h
@@ -108,6 +108,7 @@ static inline void pgtable_free(void *table, unsigned index_size)
}
#define check_pgt_cache() do { } while (0)
+#define get_hugepd_cache_index(x) (x)
#ifdef CONFIG_SMP
static inline void pgtable_free_tlb(struct mmu_gather *tlb,
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable-4k.h b/arch/powerpc/include/asm/book3s/64/pgtable-4k.h
index af5f2ba..a069dfc 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable-4k.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable-4k.h
@@ -49,6 +49,27 @@ static inline int hugepd_ok(hugepd_t hpd)
}
#define is_hugepd(hpd) (hugepd_ok(hpd))
+/*
+ * 16M and 16G huge page directory tables are allocated from slab cache
+ *
+ */
+#define H_16M_CACHE_INDEX (PAGE_SHIFT + H_PTE_INDEX_SIZE + H_PMD_INDEX_SIZE - 24)
+#define H_16G_CACHE_INDEX \
+ (PAGE_SHIFT + H_PTE_INDEX_SIZE + H_PMD_INDEX_SIZE + H_PUD_INDEX_SIZE - 34)
+
+static inline int get_hugepd_cache_index(int index)
+{
+ switch (index) {
+ case H_16M_CACHE_INDEX:
+ return HTLB_16M_INDEX;
+ case H_16G_CACHE_INDEX:
+ return HTLB_16G_INDEX;
+ default:
+ BUG();
+ }
+ /* should not reach */
+}
+
#else /* !CONFIG_HUGETLB_PAGE */
static inline int pmd_huge(pmd_t pmd) { return 0; }
static inline int pud_huge(pud_t pud) { return 0; }
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable-64k.h b/arch/powerpc/include/asm/book3s/64/pgtable-64k.h
index fb4b3ba..d7ee249 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable-64k.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable-64k.h
@@ -45,8 +45,17 @@ static inline int hugepd_ok(hugepd_t hpd)
{
return 0;
}
+
#define is_hugepd(pdep) 0
+/*
+ * This should never get called
+ */
+static inline int get_hugepd_cache_index(int index)
+{
+ BUG();
+}
+
#else /* !CONFIG_HUGETLB_PAGE */
static inline int pmd_huge(pmd_t pmd) { return 0; }
static inline int pud_huge(pud_t pud) { return 0; }
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h
index 63cee15..42aafba 100644
--- a/arch/powerpc/include/asm/book3s/64/pgtable.h
+++ b/arch/powerpc/include/asm/book3s/64/pgtable.h
@@ -287,6 +287,11 @@ enum pgtable_index {
PMD_INDEX,
PUD_INDEX,
PGD_INDEX,
+ /*
+ * Below are used with 4k page size and hugetlb
+ */
+ HTLB_16M_INDEX,
+ HTLB_16G_INDEX,
};
extern unsigned long __vmalloc_start;
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index e7377b7..1f345a0 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -104,6 +104,7 @@ struct kvmppc_vcore {
ulong vtb; /* virtual timebase */
ulong conferring_threads;
unsigned int halt_poll_ns;
+ atomic_t online_count;
};
struct kvmppc_vcpu_book3s {
@@ -209,6 +210,7 @@ extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
extern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
unsigned int vec);
extern void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags);
+extern void kvmppc_trigger_fac_interrupt(struct kvm_vcpu *vcpu, ulong fac);
extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat,
bool upper, u32 val);
extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr);
@@ -256,6 +258,21 @@ extern int kvmppc_hcall_impl_pr(unsigned long cmd);
extern int kvmppc_hcall_impl_hv_realmode(unsigned long cmd);
extern void kvmppc_copy_to_svcpu(struct kvm_vcpu *vcpu);
extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu);
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+void kvmppc_save_tm_pr(struct kvm_vcpu *vcpu);
+void kvmppc_restore_tm_pr(struct kvm_vcpu *vcpu);
+void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu);
+void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu);
+#else
+static inline void kvmppc_save_tm_pr(struct kvm_vcpu *vcpu) {}
+static inline void kvmppc_restore_tm_pr(struct kvm_vcpu *vcpu) {}
+static inline void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu) {}
+static inline void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu) {}
+#endif
+
+void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac);
+
extern int kvm_irq_bypass;
static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
@@ -274,12 +291,12 @@ static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu)
static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
{
- vcpu->arch.gpr[num] = val;
+ vcpu->arch.regs.gpr[num] = val;
}
static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num)
{
- return vcpu->arch.gpr[num];
+ return vcpu->arch.regs.gpr[num];
}
static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val)
@@ -294,42 +311,42 @@ static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu)
static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val)
{
- vcpu->arch.xer = val;
+ vcpu->arch.regs.xer = val;
}
static inline ulong kvmppc_get_xer(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.xer;
+ return vcpu->arch.regs.xer;
}
static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val)
{
- vcpu->arch.ctr = val;
+ vcpu->arch.regs.ctr = val;
}
static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.ctr;
+ return vcpu->arch.regs.ctr;
}
static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val)
{
- vcpu->arch.lr = val;
+ vcpu->arch.regs.link = val;
}
static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.lr;
+ return vcpu->arch.regs.link;
}
static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val)
{
- vcpu->arch.pc = val;
+ vcpu->arch.regs.nip = val;
}
static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.pc;
+ return vcpu->arch.regs.nip;
}
static inline u64 kvmppc_get_msr(struct kvm_vcpu *vcpu);
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h
index c424e44..dc435a5 100644
--- a/arch/powerpc/include/asm/kvm_book3s_64.h
+++ b/arch/powerpc/include/asm/kvm_book3s_64.h
@@ -483,15 +483,15 @@ static inline u64 sanitize_msr(u64 msr)
static inline void copy_from_checkpoint(struct kvm_vcpu *vcpu)
{
vcpu->arch.cr = vcpu->arch.cr_tm;
- vcpu->arch.xer = vcpu->arch.xer_tm;
- vcpu->arch.lr = vcpu->arch.lr_tm;
- vcpu->arch.ctr = vcpu->arch.ctr_tm;
+ vcpu->arch.regs.xer = vcpu->arch.xer_tm;
+ vcpu->arch.regs.link = vcpu->arch.lr_tm;
+ vcpu->arch.regs.ctr = vcpu->arch.ctr_tm;
vcpu->arch.amr = vcpu->arch.amr_tm;
vcpu->arch.ppr = vcpu->arch.ppr_tm;
vcpu->arch.dscr = vcpu->arch.dscr_tm;
vcpu->arch.tar = vcpu->arch.tar_tm;
- memcpy(vcpu->arch.gpr, vcpu->arch.gpr_tm,
- sizeof(vcpu->arch.gpr));
+ memcpy(vcpu->arch.regs.gpr, vcpu->arch.gpr_tm,
+ sizeof(vcpu->arch.regs.gpr));
vcpu->arch.fp = vcpu->arch.fp_tm;
vcpu->arch.vr = vcpu->arch.vr_tm;
vcpu->arch.vrsave = vcpu->arch.vrsave_tm;
@@ -500,15 +500,15 @@ static inline void copy_from_checkpoint(struct kvm_vcpu *vcpu)
static inline void copy_to_checkpoint(struct kvm_vcpu *vcpu)
{
vcpu->arch.cr_tm = vcpu->arch.cr;
- vcpu->arch.xer_tm = vcpu->arch.xer;
- vcpu->arch.lr_tm = vcpu->arch.lr;
- vcpu->arch.ctr_tm = vcpu->arch.ctr;
+ vcpu->arch.xer_tm = vcpu->arch.regs.xer;
+ vcpu->arch.lr_tm = vcpu->arch.regs.link;
+ vcpu->arch.ctr_tm = vcpu->arch.regs.ctr;
vcpu->arch.amr_tm = vcpu->arch.amr;
vcpu->arch.ppr_tm = vcpu->arch.ppr;
vcpu->arch.dscr_tm = vcpu->arch.dscr;
vcpu->arch.tar_tm = vcpu->arch.tar;
- memcpy(vcpu->arch.gpr_tm, vcpu->arch.gpr,
- sizeof(vcpu->arch.gpr));
+ memcpy(vcpu->arch.gpr_tm, vcpu->arch.regs.gpr,
+ sizeof(vcpu->arch.regs.gpr));
vcpu->arch.fp_tm = vcpu->arch.fp;
vcpu->arch.vr_tm = vcpu->arch.vr;
vcpu->arch.vrsave_tm = vcpu->arch.vrsave;
diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h
index bc6e29e..d513e3e 100644
--- a/arch/powerpc/include/asm/kvm_booke.h
+++ b/arch/powerpc/include/asm/kvm_booke.h
@@ -36,12 +36,12 @@
static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val)
{
- vcpu->arch.gpr[num] = val;
+ vcpu->arch.regs.gpr[num] = val;
}
static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num)
{
- return vcpu->arch.gpr[num];
+ return vcpu->arch.regs.gpr[num];
}
static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val)
@@ -56,12 +56,12 @@ static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu)
static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val)
{
- vcpu->arch.xer = val;
+ vcpu->arch.regs.xer = val;
}
static inline ulong kvmppc_get_xer(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.xer;
+ return vcpu->arch.regs.xer;
}
static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu)
@@ -72,32 +72,32 @@ static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu)
static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val)
{
- vcpu->arch.ctr = val;
+ vcpu->arch.regs.ctr = val;
}
static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.ctr;
+ return vcpu->arch.regs.ctr;
}
static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val)
{
- vcpu->arch.lr = val;
+ vcpu->arch.regs.link = val;
}
static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.lr;
+ return vcpu->arch.regs.link;
}
static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val)
{
- vcpu->arch.pc = val;
+ vcpu->arch.regs.nip = val;
}
static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.pc;
+ return vcpu->arch.regs.nip;
}
static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 17498e9..fa4efa7 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -269,7 +269,6 @@ struct kvm_arch {
unsigned long host_lpcr;
unsigned long sdr1;
unsigned long host_sdr1;
- int tlbie_lock;
unsigned long lpcr;
unsigned long vrma_slb_v;
int mmu_ready;
@@ -454,6 +453,12 @@ struct mmio_hpte_cache {
#define KVMPPC_VSX_COPY_WORD 1
#define KVMPPC_VSX_COPY_DWORD 2
#define KVMPPC_VSX_COPY_DWORD_LOAD_DUMP 3
+#define KVMPPC_VSX_COPY_WORD_LOAD_DUMP 4
+
+#define KVMPPC_VMX_COPY_BYTE 8
+#define KVMPPC_VMX_COPY_HWORD 9
+#define KVMPPC_VMX_COPY_WORD 10
+#define KVMPPC_VMX_COPY_DWORD 11
struct openpic;
@@ -486,7 +491,7 @@ struct kvm_vcpu_arch {
struct kvmppc_book3s_shadow_vcpu *shadow_vcpu;
#endif
- ulong gpr[32];
+ struct pt_regs regs;
struct thread_fp_state fp;
@@ -521,14 +526,10 @@ struct kvm_vcpu_arch {
u32 qpr[32];
#endif
- ulong pc;
- ulong ctr;
- ulong lr;
#ifdef CONFIG_PPC_BOOK3S
ulong tar;
#endif
- ulong xer;
u32 cr;
#ifdef CONFIG_PPC_BOOK3S
@@ -626,7 +627,6 @@ struct kvm_vcpu_arch {
struct thread_vr_state vr_tm;
u32 vrsave_tm; /* also USPRG0 */
-
#endif
#ifdef CONFIG_KVM_EXIT_TIMING
@@ -681,16 +681,17 @@ struct kvm_vcpu_arch {
* Number of simulations for vsx.
* If we use 2*8bytes to simulate 1*16bytes,
* then the number should be 2 and
- * mmio_vsx_copy_type=KVMPPC_VSX_COPY_DWORD.
+ * mmio_copy_type=KVMPPC_VSX_COPY_DWORD.
* If we use 4*4bytes to simulate 1*16bytes,
* the number should be 4 and
* mmio_vsx_copy_type=KVMPPC_VSX_COPY_WORD.
*/
u8 mmio_vsx_copy_nums;
u8 mmio_vsx_offset;
- u8 mmio_vsx_copy_type;
u8 mmio_vsx_tx_sx_enabled;
u8 mmio_vmx_copy_nums;
+ u8 mmio_vmx_offset;
+ u8 mmio_copy_type;
u8 osi_needed;
u8 osi_enabled;
u8 papr_enabled;
@@ -772,6 +773,8 @@ struct kvm_vcpu_arch {
u64 busy_preempt;
u32 emul_inst;
+
+ u32 online;
#endif
#ifdef CONFIG_KVM_BOOK3S_HV_EXIT_TIMING
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index abe7032..e991821 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -52,7 +52,7 @@ enum emulation_result {
EMULATE_EXIT_USER, /* emulation requires exit to user-space */
};
-enum instruction_type {
+enum instruction_fetch_type {
INST_GENERIC,
INST_SC, /* system call */
};
@@ -81,10 +81,10 @@ extern int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu,
extern int kvmppc_handle_vsx_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned int rt, unsigned int bytes,
int is_default_endian, int mmio_sign_extend);
-extern int kvmppc_handle_load128_by2x64(struct kvm_run *run,
- struct kvm_vcpu *vcpu, unsigned int rt, int is_default_endian);
-extern int kvmppc_handle_store128_by2x64(struct kvm_run *run,
- struct kvm_vcpu *vcpu, unsigned int rs, int is_default_endian);
+extern int kvmppc_handle_vmx_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ unsigned int rt, unsigned int bytes, int is_default_endian);
+extern int kvmppc_handle_vmx_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ unsigned int rs, unsigned int bytes, int is_default_endian);
extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
u64 val, unsigned int bytes,
int is_default_endian);
@@ -93,7 +93,7 @@ extern int kvmppc_handle_vsx_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
int is_default_endian);
extern int kvmppc_load_last_inst(struct kvm_vcpu *vcpu,
- enum instruction_type type, u32 *inst);
+ enum instruction_fetch_type type, u32 *inst);
extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
bool data);
@@ -265,6 +265,8 @@ union kvmppc_one_reg {
vector128 vval;
u64 vsxval[2];
u32 vsx32val[4];
+ u16 vsx16val[8];
+ u8 vsx8val[16];
struct {
u64 addr;
u64 length;
@@ -324,13 +326,14 @@ struct kvmppc_ops {
int (*get_rmmu_info)(struct kvm *kvm, struct kvm_ppc_rmmu_info *info);
int (*set_smt_mode)(struct kvm *kvm, unsigned long mode,
unsigned long flags);
+ void (*giveup_ext)(struct kvm_vcpu *vcpu, ulong msr);
};
extern struct kvmppc_ops *kvmppc_hv_ops;
extern struct kvmppc_ops *kvmppc_pr_ops;
static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu,
- enum instruction_type type, u32 *inst)
+ enum instruction_fetch_type type, u32 *inst)
{
int ret = EMULATE_DONE;
u32 fetched_inst;
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h
index d8374f9..d61b081 100644
--- a/arch/powerpc/include/asm/module.h
+++ b/arch/powerpc/include/asm/module.h
@@ -14,7 +14,7 @@
#include <asm-generic/module.h>
-#ifdef CC_USING_MPROFILE_KERNEL
+#ifdef CONFIG_MPROFILE_KERNEL
#define MODULE_ARCH_VERMAGIC_FTRACE "mprofile-kernel "
#else
#define MODULE_ARCH_VERMAGIC_FTRACE ""
diff --git a/arch/powerpc/include/asm/nmi.h b/arch/powerpc/include/asm/nmi.h
index 0f571e0..bd9ba8d 100644
--- a/arch/powerpc/include/asm/nmi.h
+++ b/arch/powerpc/include/asm/nmi.h
@@ -8,7 +8,7 @@ extern void arch_touch_nmi_watchdog(void);
static inline void arch_touch_nmi_watchdog(void) {}
#endif
-#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_STACKTRACE)
+#if defined(CONFIG_NMI_IPI) && defined(CONFIG_STACKTRACE)
extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask,
bool exclude_self);
#define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace
diff --git a/arch/powerpc/include/asm/nohash/32/pgalloc.h b/arch/powerpc/include/asm/nohash/32/pgalloc.h
index 1707781..9de40eb 100644
--- a/arch/powerpc/include/asm/nohash/32/pgalloc.h
+++ b/arch/powerpc/include/asm/nohash/32/pgalloc.h
@@ -109,6 +109,7 @@ static inline void pgtable_free(void *table, unsigned index_size)
}
#define check_pgt_cache() do { } while (0)
+#define get_hugepd_cache_index(x) (x)
#ifdef CONFIG_SMP
static inline void pgtable_free_tlb(struct mmu_gather *tlb,
diff --git a/arch/powerpc/include/asm/nohash/64/pgalloc.h b/arch/powerpc/include/asm/nohash/64/pgalloc.h
index 0e693f3..e2d62d0 100644
--- a/arch/powerpc/include/asm/nohash/64/pgalloc.h
+++ b/arch/powerpc/include/asm/nohash/64/pgalloc.h
@@ -141,6 +141,7 @@ static inline void pgtable_free(void *table, int shift)
}
}
+#define get_hugepd_cache_index(x) (x)
#ifdef CONFIG_SMP
static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift)
{
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 75c5b2c..5625684 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -385,6 +385,7 @@
#define SPRN_PSSCR 0x357 /* Processor Stop Status and Control Register (ISA 3.0) */
#define SPRN_PSSCR_PR 0x337 /* PSSCR ISA 3.0, privileged mode access */
#define SPRN_PMCR 0x374 /* Power Management Control Register */
+#define SPRN_RWMR 0x375 /* Region-Weighting Mode Register */
/* HFSCR and FSCR bit numbers are the same */
#define FSCR_SCV_LG 12 /* Enable System Call Vectored */
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h
index 833ed9a..1b32b56 100644
--- a/arch/powerpc/include/uapi/asm/kvm.h
+++ b/arch/powerpc/include/uapi/asm/kvm.h
@@ -633,6 +633,7 @@ struct kvm_ppc_cpu_char {
#define KVM_REG_PPC_PSSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbd)
#define KVM_REG_PPC_DEC_EXPIRY (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xbe)
+#define KVM_REG_PPC_ONLINE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbf)
/* Transactional Memory checkpointed state:
* This is all GPRs, all VSX regs and a subset of SPRs
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 9fc9e09..0a05443 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -426,20 +426,20 @@ int main(void)
OFFSET(VCPU_HOST_STACK, kvm_vcpu, arch.host_stack);
OFFSET(VCPU_HOST_PID, kvm_vcpu, arch.host_pid);
OFFSET(VCPU_GUEST_PID, kvm_vcpu, arch.pid);
- OFFSET(VCPU_GPRS, kvm_vcpu, arch.gpr);
+ OFFSET(VCPU_GPRS, kvm_vcpu, arch.regs.gpr);
OFFSET(VCPU_VRSAVE, kvm_vcpu, arch.vrsave);
OFFSET(VCPU_FPRS, kvm_vcpu, arch.fp.fpr);
#ifdef CONFIG_ALTIVEC
OFFSET(VCPU_VRS, kvm_vcpu, arch.vr.vr);
#endif
- OFFSET(VCPU_XER, kvm_vcpu, arch.xer);
- OFFSET(VCPU_CTR, kvm_vcpu, arch.ctr);
- OFFSET(VCPU_LR, kvm_vcpu, arch.lr);
+ OFFSET(VCPU_XER, kvm_vcpu, arch.regs.xer);
+ OFFSET(VCPU_CTR, kvm_vcpu, arch.regs.ctr);
+ OFFSET(VCPU_LR, kvm_vcpu, arch.regs.link);
#ifdef CONFIG_PPC_BOOK3S
OFFSET(VCPU_TAR, kvm_vcpu, arch.tar);
#endif
OFFSET(VCPU_CR, kvm_vcpu, arch.cr);
- OFFSET(VCPU_PC, kvm_vcpu, arch.pc);
+ OFFSET(VCPU_PC, kvm_vcpu, arch.regs.nip);
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
OFFSET(VCPU_MSR, kvm_vcpu, arch.shregs.msr);
OFFSET(VCPU_SRR0, kvm_vcpu, arch.shregs.srr0);
@@ -696,10 +696,10 @@ int main(void)
#else /* CONFIG_PPC_BOOK3S */
OFFSET(VCPU_CR, kvm_vcpu, arch.cr);
- OFFSET(VCPU_XER, kvm_vcpu, arch.xer);
- OFFSET(VCPU_LR, kvm_vcpu, arch.lr);
- OFFSET(VCPU_CTR, kvm_vcpu, arch.ctr);
- OFFSET(VCPU_PC, kvm_vcpu, arch.pc);
+ OFFSET(VCPU_XER, kvm_vcpu, arch.regs.xer);
+ OFFSET(VCPU_LR, kvm_vcpu, arch.regs.link);
+ OFFSET(VCPU_CTR, kvm_vcpu, arch.regs.ctr);
+ OFFSET(VCPU_PC, kvm_vcpu, arch.regs.nip);
OFFSET(VCPU_SPRG9, kvm_vcpu, arch.sprg9);
OFFSET(VCPU_LAST_INST, kvm_vcpu, arch.last_inst);
OFFSET(VCPU_FAULT_DEAR, kvm_vcpu, arch.fault_dear);
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
index 4be1c0d..96dd3d8 100644
--- a/arch/powerpc/kernel/dt_cpu_ftrs.c
+++ b/arch/powerpc/kernel/dt_cpu_ftrs.c
@@ -711,7 +711,8 @@ static __init void cpufeatures_cpu_quirks(void)
cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_HV_ASSIST;
cur_cpu_spec->cpu_features |= CPU_FTR_P9_TM_XER_SO_BUG;
cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1;
- } else /* DD2.1 and up have DD2_1 */
+ } else if ((version & 0xffff0000) == 0x004e0000)
+ /* DD2.1 and up have DD2_1 */
cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD2_1;
if ((version & 0xffff0000) == 0x004e0000) {
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c
index 1b74195..b8d61e0 100644
--- a/arch/powerpc/kernel/module_64.c
+++ b/arch/powerpc/kernel/module_64.c
@@ -466,7 +466,7 @@ static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs,
return (unsigned long)&stubs[i];
}
-#ifdef CC_USING_MPROFILE_KERNEL
+#ifdef CONFIG_MPROFILE_KERNEL
static bool is_mprofile_mcount_callsite(const char *name, u32 *instruction)
{
if (strcmp("_mcount", name))
@@ -753,7 +753,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
#ifdef CONFIG_DYNAMIC_FTRACE
-#ifdef CC_USING_MPROFILE_KERNEL
+#ifdef CONFIG_MPROFILE_KERNEL
#define PACATOC offsetof(struct paca_struct, kernel_toc)
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c
index f915db9..44d66c33d 100644
--- a/arch/powerpc/kernel/rtasd.c
+++ b/arch/powerpc/kernel/rtasd.c
@@ -559,7 +559,8 @@ static int __init rtas_event_scan_init(void)
rtas_error_log_max = rtas_get_error_log_max();
rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int);
- rtas_log_buf = vmalloc(rtas_error_log_buffer_max*LOG_NUMBER);
+ rtas_log_buf = vmalloc(array_size(LOG_NUMBER,
+ rtas_error_log_buffer_max));
if (!rtas_log_buf) {
printk(KERN_ERR "rtasd: no memory\n");
return -ENOMEM;
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 62b1a40..40b44bb 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -701,11 +701,18 @@ static int ppc_panic_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
/*
+ * panic does a local_irq_disable, but we really
+ * want interrupts to be hard disabled.
+ */
+ hard_irq_disable();
+
+ /*
* If firmware-assisted dump has been registered then trigger
* firmware-assisted dump and let firmware handle everything else.
*/
crash_fadump(NULL, ptr);
- ppc_md.panic(ptr); /* May not return */
+ if (ppc_md.panic)
+ ppc_md.panic(ptr); /* May not return */
return NOTIFY_DONE;
}
@@ -716,7 +723,8 @@ static struct notifier_block ppc_panic_block = {
void __init setup_panic(void)
{
- if (!ppc_md.panic)
+ /* PPC64 always does a hard irq disable in its panic handler */
+ if (!IS_ENABLED(CONFIG_PPC64) && !ppc_md.panic)
return;
atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block);
}
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 7a7ce8a..225bc5f 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -387,6 +387,14 @@ void early_setup_secondary(void)
#endif /* CONFIG_SMP */
+void panic_smp_self_stop(void)
+{
+ hard_irq_disable();
+ spin_begin();
+ while (1)
+ spin_cpu_relax();
+}
+
#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE)
static bool use_spinloop(void)
{
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index 17fe433..b3e8db3 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -134,7 +134,7 @@ static void do_signal(struct task_struct *tsk)
/* Re-enable the breakpoints for the signal stack */
thread_change_pc(tsk, tsk->thread.regs);
- rseq_signal_deliver(tsk->thread.regs);
+ rseq_signal_deliver(&ksig, tsk->thread.regs);
if (is32) {
if (ksig.ka.sa.sa_flags & SA_SIGINFO)
@@ -170,7 +170,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
- rseq_handle_notify_resume(regs);
+ rseq_handle_notify_resume(NULL, regs);
}
user_enter();
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 5eadfff..4794d6b 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -600,9 +600,6 @@ static void nmi_stop_this_cpu(struct pt_regs *regs)
nmi_ipi_busy_count--;
nmi_ipi_unlock();
- /* Remove this CPU */
- set_cpu_online(smp_processor_id(), false);
-
spin_begin();
while (1)
spin_cpu_relax();
@@ -617,9 +614,6 @@ void smp_send_stop(void)
static void stop_this_cpu(void *dummy)
{
- /* Remove this CPU */
- set_cpu_online(smp_processor_id(), false);
-
hard_irq_disable();
spin_begin();
while (1)
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c
index 07e97f2..e2c50b5 100644
--- a/arch/powerpc/kernel/stacktrace.c
+++ b/arch/powerpc/kernel/stacktrace.c
@@ -196,7 +196,7 @@ save_stack_trace_tsk_reliable(struct task_struct *tsk,
EXPORT_SYMBOL_GPL(save_stack_trace_tsk_reliable);
#endif /* CONFIG_HAVE_RELIABLE_STACKTRACE */
-#ifdef CONFIG_PPC_BOOK3S_64
+#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_NMI_IPI)
static void handle_backtrace_ipi(struct pt_regs *regs)
{
nmi_cpu_backtrace(regs);
@@ -242,4 +242,4 @@ void arch_trigger_cpumask_backtrace(const cpumask_t *mask, bool exclude_self)
{
nmi_trigger_cpumask_backtrace(mask, exclude_self, raise_backtrace_ipi);
}
-#endif /* CONFIG_PPC64 */
+#endif /* defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_NMI_IPI) */
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c
index c076a32..4bfbb54 100644
--- a/arch/powerpc/kernel/trace/ftrace.c
+++ b/arch/powerpc/kernel/trace/ftrace.c
@@ -144,7 +144,7 @@ __ftrace_make_nop(struct module *mod,
return -EINVAL;
}
-#ifdef CC_USING_MPROFILE_KERNEL
+#ifdef CONFIG_MPROFILE_KERNEL
/* When using -mkernel_profile there is no load to jump over */
pop = PPC_INST_NOP;
@@ -188,7 +188,7 @@ __ftrace_make_nop(struct module *mod,
pr_err("Expected %08x found %08x\n", PPC_INST_LD_TOC, op);
return -EINVAL;
}
-#endif /* CC_USING_MPROFILE_KERNEL */
+#endif /* CONFIG_MPROFILE_KERNEL */
if (patch_instruction((unsigned int *)ip, pop)) {
pr_err("Patching NOP failed.\n");
@@ -324,7 +324,7 @@ int ftrace_make_nop(struct module *mod,
* They should effectively be a NOP, and follow formal constraints,
* depending on the ABI. Return false if they don't.
*/
-#ifndef CC_USING_MPROFILE_KERNEL
+#ifndef CONFIG_MPROFILE_KERNEL
static int
expected_nop_sequence(void *ip, unsigned int op0, unsigned int op1)
{
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index b44ec10..d2205b9 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -791,7 +791,7 @@ static int __init vdso_init(void)
#ifdef CONFIG_VDSO32
/* Make sure pages are in the correct state */
- vdso32_pagelist = kzalloc(sizeof(struct page *) * (vdso32_pages + 2),
+ vdso32_pagelist = kcalloc(vdso32_pages + 2, sizeof(struct page *),
GFP_KERNEL);
BUG_ON(vdso32_pagelist == NULL);
for (i = 0; i < vdso32_pages; i++) {
@@ -805,7 +805,7 @@ static int __init vdso_init(void)
#endif
#ifdef CONFIG_PPC64
- vdso64_pagelist = kzalloc(sizeof(struct page *) * (vdso64_pages + 2),
+ vdso64_pagelist = kcalloc(vdso64_pages + 2, sizeof(struct page *),
GFP_KERNEL);
BUG_ON(vdso64_pagelist == NULL);
for (i = 0; i < vdso64_pages; i++) {
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 4b19da8..f872c04 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -63,6 +63,9 @@ kvm-pr-y := \
book3s_64_mmu.o \
book3s_32_mmu.o
+kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \
+ tm.o
+
ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \
book3s_rmhandlers.o
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 97d4a11..edaf4720 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -134,7 +134,7 @@ void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
{
kvmppc_unfixup_split_real(vcpu);
kvmppc_set_srr0(vcpu, kvmppc_get_pc(vcpu));
- kvmppc_set_srr1(vcpu, kvmppc_get_msr(vcpu) | flags);
+ kvmppc_set_srr1(vcpu, (kvmppc_get_msr(vcpu) & ~0x783f0000ul) | flags);
kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec);
vcpu->arch.mmu.reset_msr(vcpu);
}
@@ -256,18 +256,15 @@ void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, ulong dar,
{
kvmppc_set_dar(vcpu, dar);
kvmppc_set_dsisr(vcpu, flags);
- kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE);
+ kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE, 0);
}
-EXPORT_SYMBOL_GPL(kvmppc_core_queue_data_storage); /* used by kvm_hv */
+EXPORT_SYMBOL_GPL(kvmppc_core_queue_data_storage);
void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, ulong flags)
{
- u64 msr = kvmppc_get_msr(vcpu);
- msr &= ~(SRR1_ISI_NOPT | SRR1_ISI_N_OR_G | SRR1_ISI_PROT);
- msr |= flags & (SRR1_ISI_NOPT | SRR1_ISI_N_OR_G | SRR1_ISI_PROT);
- kvmppc_set_msr_fast(vcpu, msr);
- kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE);
+ kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_INST_STORAGE, flags);
}
+EXPORT_SYMBOL_GPL(kvmppc_core_queue_inst_storage);
static int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu,
unsigned int priority)
@@ -450,8 +447,8 @@ int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, enum xlate_instdata xlid,
return r;
}
-int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
- u32 *inst)
+int kvmppc_load_last_inst(struct kvm_vcpu *vcpu,
+ enum instruction_fetch_type type, u32 *inst)
{
ulong pc = kvmppc_get_pc(vcpu);
int r;
@@ -509,8 +506,6 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
{
int i;
- vcpu_load(vcpu);
-
regs->pc = kvmppc_get_pc(vcpu);
regs->cr = kvmppc_get_cr(vcpu);
regs->ctr = kvmppc_get_ctr(vcpu);
@@ -532,7 +527,6 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
- vcpu_put(vcpu);
return 0;
}
@@ -540,8 +534,6 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
{
int i;
- vcpu_load(vcpu);
-
kvmppc_set_pc(vcpu, regs->pc);
kvmppc_set_cr(vcpu, regs->cr);
kvmppc_set_ctr(vcpu, regs->ctr);
@@ -562,7 +554,6 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
- vcpu_put(vcpu);
return 0;
}
diff --git a/arch/powerpc/kvm/book3s.h b/arch/powerpc/kvm/book3s.h
index 4ad5e28..14ef035 100644
--- a/arch/powerpc/kvm/book3s.h
+++ b/arch/powerpc/kvm/book3s.h
@@ -31,4 +31,10 @@ extern int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu,
extern int kvmppc_book3s_init_pr(void);
extern void kvmppc_book3s_exit_pr(void);
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+extern void kvmppc_emulate_tabort(struct kvm_vcpu *vcpu, int ra_val);
+#else
+static inline void kvmppc_emulate_tabort(struct kvm_vcpu *vcpu, int ra_val) {}
+#endif
+
#endif
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c
index 1992676..45c8ea4 100644
--- a/arch/powerpc/kvm/book3s_32_mmu.c
+++ b/arch/powerpc/kvm/book3s_32_mmu.c
@@ -52,7 +52,7 @@
static inline bool check_debug_ip(struct kvm_vcpu *vcpu)
{
#ifdef DEBUG_MMU_PTE_IP
- return vcpu->arch.pc == DEBUG_MMU_PTE_IP;
+ return vcpu->arch.regs.nip == DEBUG_MMU_PTE_IP;
#else
return true;
#endif
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c
index a93d719..cf9d686 100644
--- a/arch/powerpc/kvm/book3s_64_mmu.c
+++ b/arch/powerpc/kvm/book3s_64_mmu.c
@@ -38,7 +38,16 @@
static void kvmppc_mmu_book3s_64_reset_msr(struct kvm_vcpu *vcpu)
{
- kvmppc_set_msr(vcpu, vcpu->arch.intr_msr);
+ unsigned long msr = vcpu->arch.intr_msr;
+ unsigned long cur_msr = kvmppc_get_msr(vcpu);
+
+ /* If transactional, change to suspend mode on IRQ delivery */
+ if (MSR_TM_TRANSACTIONAL(cur_msr))
+ msr |= MSR_TS_S;
+ else
+ msr |= cur_msr & MSR_TS_MASK;
+
+ kvmppc_set_msr(vcpu, msr);
}
static struct kvmppc_slb *kvmppc_mmu_book3s_64_find_slbe(
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
index a670fa5..7f3a8cf 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
@@ -108,7 +108,7 @@ int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order)
npte = 1ul << (order - 4);
/* Allocate reverse map array */
- rev = vmalloc(sizeof(struct revmap_entry) * npte);
+ rev = vmalloc(array_size(npte, sizeof(struct revmap_entry)));
if (!rev) {
if (cma)
kvm_free_hpt_cma(page, 1 << (order - PAGE_SHIFT));
@@ -272,6 +272,9 @@ int kvmppc_mmu_hv_init(void)
if (!cpu_has_feature(CPU_FTR_HVMODE))
return -EINVAL;
+ if (!mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE))
+ return -EINVAL;
+
/* POWER7 has 10-bit LPIDs (12-bit in POWER8) */
host_lpid = mfspr(SPRN_LPID);
rsvd_lpid = LPID_RSVD;
diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c
index 481da8f..176f911 100644
--- a/arch/powerpc/kvm/book3s_64_mmu_radix.c
+++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c
@@ -139,44 +139,24 @@ int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr,
return 0;
}
-#ifdef CONFIG_PPC_64K_PAGES
-#define MMU_BASE_PSIZE MMU_PAGE_64K
-#else
-#define MMU_BASE_PSIZE MMU_PAGE_4K
-#endif
-
static void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr,
unsigned int pshift)
{
- int psize = MMU_BASE_PSIZE;
-
- if (pshift >= PUD_SHIFT)
- psize = MMU_PAGE_1G;
- else if (pshift >= PMD_SHIFT)
- psize = MMU_PAGE_2M;
- addr &= ~0xfffUL;
- addr |= mmu_psize_defs[psize].ap << 5;
- asm volatile("ptesync": : :"memory");
- asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
- : : "r" (addr), "r" (kvm->arch.lpid) : "memory");
- if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG))
- asm volatile(PPC_TLBIE_5(%0, %1, 0, 0, 1)
- : : "r" (addr), "r" (kvm->arch.lpid) : "memory");
- asm volatile("eieio ; tlbsync ; ptesync": : :"memory");
+ unsigned long psize = PAGE_SIZE;
+
+ if (pshift)
+ psize = 1UL << pshift;
+
+ addr &= ~(psize - 1);
+ radix__flush_tlb_lpid_page(kvm->arch.lpid, addr, psize);
}
-static void kvmppc_radix_flush_pwc(struct kvm *kvm, unsigned long addr)
+static void kvmppc_radix_flush_pwc(struct kvm *kvm)
{
- unsigned long rb = 0x2 << PPC_BITLSHIFT(53); /* IS = 2 */
-
- asm volatile("ptesync": : :"memory");
- /* RIC=1 PRS=0 R=1 IS=2 */
- asm volatile(PPC_TLBIE_5(%0, %1, 1, 0, 1)
- : : "r" (rb), "r" (kvm->arch.lpid) : "memory");
- asm volatile("eieio ; tlbsync ; ptesync": : :"memory");
+ radix__flush_pwc_lpid(kvm->arch.lpid);
}
-unsigned long kvmppc_radix_update_pte(struct kvm *kvm, pte_t *ptep,
+static unsigned long kvmppc_radix_update_pte(struct kvm *kvm, pte_t *ptep,
unsigned long clr, unsigned long set,
unsigned long addr, unsigned int shift)
{
@@ -228,6 +208,167 @@ static void kvmppc_pmd_free(pmd_t *pmdp)
kmem_cache_free(kvm_pmd_cache, pmdp);
}
+static void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte,
+ unsigned long gpa, unsigned int shift)
+
+{
+ unsigned long page_size = 1ul << shift;
+ unsigned long old;
+
+ old = kvmppc_radix_update_pte(kvm, pte, ~0UL, 0, gpa, shift);
+ kvmppc_radix_tlbie_page(kvm, gpa, shift);
+ if (old & _PAGE_DIRTY) {
+ unsigned long gfn = gpa >> PAGE_SHIFT;
+ struct kvm_memory_slot *memslot;
+
+ memslot = gfn_to_memslot(kvm, gfn);
+ if (memslot && memslot->dirty_bitmap)
+ kvmppc_update_dirty_map(memslot, gfn, page_size);
+ }
+}
+
+/*
+ * kvmppc_free_p?d are used to free existing page tables, and recursively
+ * descend and clear and free children.
+ * Callers are responsible for flushing the PWC.
+ *
+ * When page tables are being unmapped/freed as part of page fault path
+ * (full == false), ptes are not expected. There is code to unmap them
+ * and emit a warning if encountered, but there may already be data
+ * corruption due to the unexpected mappings.
+ */
+static void kvmppc_unmap_free_pte(struct kvm *kvm, pte_t *pte, bool full)
+{
+ if (full) {
+ memset(pte, 0, sizeof(long) << PTE_INDEX_SIZE);
+ } else {
+ pte_t *p = pte;
+ unsigned long it;
+
+ for (it = 0; it < PTRS_PER_PTE; ++it, ++p) {
+ if (pte_val(*p) == 0)
+ continue;
+ WARN_ON_ONCE(1);
+ kvmppc_unmap_pte(kvm, p,
+ pte_pfn(*p) << PAGE_SHIFT,
+ PAGE_SHIFT);
+ }
+ }
+
+ kvmppc_pte_free(pte);
+}
+
+static void kvmppc_unmap_free_pmd(struct kvm *kvm, pmd_t *pmd, bool full)
+{
+ unsigned long im;
+ pmd_t *p = pmd;
+
+ for (im = 0; im < PTRS_PER_PMD; ++im, ++p) {
+ if (!pmd_present(*p))
+ continue;
+ if (pmd_is_leaf(*p)) {
+ if (full) {
+ pmd_clear(p);
+ } else {
+ WARN_ON_ONCE(1);
+ kvmppc_unmap_pte(kvm, (pte_t *)p,
+ pte_pfn(*(pte_t *)p) << PAGE_SHIFT,
+ PMD_SHIFT);
+ }
+ } else {
+ pte_t *pte;
+
+ pte = pte_offset_map(p, 0);
+ kvmppc_unmap_free_pte(kvm, pte, full);
+ pmd_clear(p);
+ }
+ }
+ kvmppc_pmd_free(pmd);
+}
+
+static void kvmppc_unmap_free_pud(struct kvm *kvm, pud_t *pud)
+{
+ unsigned long iu;
+ pud_t *p = pud;
+
+ for (iu = 0; iu < PTRS_PER_PUD; ++iu, ++p) {
+ if (!pud_present(*p))
+ continue;
+ if (pud_huge(*p)) {
+ pud_clear(p);
+ } else {
+ pmd_t *pmd;
+
+ pmd = pmd_offset(p, 0);
+ kvmppc_unmap_free_pmd(kvm, pmd, true);
+ pud_clear(p);
+ }
+ }
+ pud_free(kvm->mm, pud);
+}
+
+void kvmppc_free_radix(struct kvm *kvm)
+{
+ unsigned long ig;
+ pgd_t *pgd;
+
+ if (!kvm->arch.pgtable)
+ return;
+ pgd = kvm->arch.pgtable;
+ for (ig = 0; ig < PTRS_PER_PGD; ++ig, ++pgd) {
+ pud_t *pud;
+
+ if (!pgd_present(*pgd))
+ continue;
+ pud = pud_offset(pgd, 0);
+ kvmppc_unmap_free_pud(kvm, pud);
+ pgd_clear(pgd);
+ }
+ pgd_free(kvm->mm, kvm->arch.pgtable);
+ kvm->arch.pgtable = NULL;
+}
+
+static void kvmppc_unmap_free_pmd_entry_table(struct kvm *kvm, pmd_t *pmd,
+ unsigned long gpa)
+{
+ pte_t *pte = pte_offset_kernel(pmd, 0);
+
+ /*
+ * Clearing the pmd entry then flushing the PWC ensures that the pte
+ * page no longer be cached by the MMU, so can be freed without
+ * flushing the PWC again.
+ */
+ pmd_clear(pmd);
+ kvmppc_radix_flush_pwc(kvm);
+
+ kvmppc_unmap_free_pte(kvm, pte, false);
+}
+
+static void kvmppc_unmap_free_pud_entry_table(struct kvm *kvm, pud_t *pud,
+ unsigned long gpa)
+{
+ pmd_t *pmd = pmd_offset(pud, 0);
+
+ /*
+ * Clearing the pud entry then flushing the PWC ensures that the pmd
+ * page and any children pte pages will no longer be cached by the MMU,
+ * so can be freed without flushing the PWC again.
+ */
+ pud_clear(pud);
+ kvmppc_radix_flush_pwc(kvm);
+
+ kvmppc_unmap_free_pmd(kvm, pmd, false);
+}
+
+/*
+ * There are a number of bits which may differ between different faults to
+ * the same partition scope entry. RC bits, in the course of cleaning and
+ * aging. And the write bit can change, either the access could have been
+ * upgraded, or a read fault could happen concurrently with a write fault
+ * that sets those bits first.
+ */
+#define PTE_BITS_MUST_MATCH (~(_PAGE_WRITE | _PAGE_DIRTY | _PAGE_ACCESSED))
+
static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
unsigned int level, unsigned long mmu_seq)
{
@@ -235,7 +376,6 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
pud_t *pud, *new_pud = NULL;
pmd_t *pmd, *new_pmd = NULL;
pte_t *ptep, *new_ptep = NULL;
- unsigned long old;
int ret;
/* Traverse the guest's 2nd-level tree, allocate new levels needed */
@@ -273,42 +413,39 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
if (pud_huge(*pud)) {
unsigned long hgpa = gpa & PUD_MASK;
+ /* Check if we raced and someone else has set the same thing */
+ if (level == 2) {
+ if (pud_raw(*pud) == pte_raw(pte)) {
+ ret = 0;
+ goto out_unlock;
+ }
+ /* Valid 1GB page here already, add our extra bits */
+ WARN_ON_ONCE((pud_val(*pud) ^ pte_val(pte)) &
+ PTE_BITS_MUST_MATCH);
+ kvmppc_radix_update_pte(kvm, (pte_t *)pud,
+ 0, pte_val(pte), hgpa, PUD_SHIFT);
+ ret = 0;
+ goto out_unlock;
+ }
/*
* If we raced with another CPU which has just put
* a 1GB pte in after we saw a pmd page, try again.
*/
- if (level <= 1 && !new_pmd) {
+ if (!new_pmd) {
ret = -EAGAIN;
goto out_unlock;
}
- /* Check if we raced and someone else has set the same thing */
- if (level == 2 && pud_raw(*pud) == pte_raw(pte)) {
- ret = 0;
- goto out_unlock;
- }
/* Valid 1GB page here already, remove it */
- old = kvmppc_radix_update_pte(kvm, (pte_t *)pud,
- ~0UL, 0, hgpa, PUD_SHIFT);
- kvmppc_radix_tlbie_page(kvm, hgpa, PUD_SHIFT);
- if (old & _PAGE_DIRTY) {
- unsigned long gfn = hgpa >> PAGE_SHIFT;
- struct kvm_memory_slot *memslot;
- memslot = gfn_to_memslot(kvm, gfn);
- if (memslot && memslot->dirty_bitmap)
- kvmppc_update_dirty_map(memslot,
- gfn, PUD_SIZE);
- }
+ kvmppc_unmap_pte(kvm, (pte_t *)pud, hgpa, PUD_SHIFT);
}
if (level == 2) {
if (!pud_none(*pud)) {
/*
* There's a page table page here, but we wanted to
* install a large page, so remove and free the page
- * table page. new_pmd will be NULL since level == 2.
+ * table page.
*/
- new_pmd = pmd_offset(pud, 0);
- pud_clear(pud);
- kvmppc_radix_flush_pwc(kvm, gpa);
+ kvmppc_unmap_free_pud_entry_table(kvm, pud, gpa);
}
kvmppc_radix_set_pte_at(kvm, gpa, (pte_t *)pud, pte);
ret = 0;
@@ -324,42 +461,40 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
if (pmd_is_leaf(*pmd)) {
unsigned long lgpa = gpa & PMD_MASK;
+ /* Check if we raced and someone else has set the same thing */
+ if (level == 1) {
+ if (pmd_raw(*pmd) == pte_raw(pte)) {
+ ret = 0;
+ goto out_unlock;
+ }
+ /* Valid 2MB page here already, add our extra bits */
+ WARN_ON_ONCE((pmd_val(*pmd) ^ pte_val(pte)) &
+ PTE_BITS_MUST_MATCH);
+ kvmppc_radix_update_pte(kvm, pmdp_ptep(pmd),
+ 0, pte_val(pte), lgpa, PMD_SHIFT);
+ ret = 0;
+ goto out_unlock;
+ }
+
/*
* If we raced with another CPU which has just put
* a 2MB pte in after we saw a pte page, try again.
*/
- if (level == 0 && !new_ptep) {
+ if (!new_ptep) {
ret = -EAGAIN;
goto out_unlock;
}
- /* Check if we raced and someone else has set the same thing */
- if (level == 1 && pmd_raw(*pmd) == pte_raw(pte)) {
- ret = 0;
- goto out_unlock;
- }
/* Valid 2MB page here already, remove it */
- old = kvmppc_radix_update_pte(kvm, pmdp_ptep(pmd),
- ~0UL, 0, lgpa, PMD_SHIFT);
- kvmppc_radix_tlbie_page(kvm, lgpa, PMD_SHIFT);
- if (old & _PAGE_DIRTY) {
- unsigned long gfn = lgpa >> PAGE_SHIFT;
- struct kvm_memory_slot *memslot;
- memslot = gfn_to_memslot(kvm, gfn);
- if (memslot && memslot->dirty_bitmap)
- kvmppc_update_dirty_map(memslot,
- gfn, PMD_SIZE);
- }
+ kvmppc_unmap_pte(kvm, pmdp_ptep(pmd), lgpa, PMD_SHIFT);
}
if (level == 1) {
if (!pmd_none(*pmd)) {
/*
* There's a page table page here, but we wanted to
* install a large page, so remove and free the page
- * table page. new_ptep will be NULL since level == 1.
+ * table page.
*/
- new_ptep = pte_offset_kernel(pmd, 0);
- pmd_clear(pmd);
- kvmppc_radix_flush_pwc(kvm, gpa);
+ kvmppc_unmap_free_pmd_entry_table(kvm, pmd, gpa);
}
kvmppc_radix_set_pte_at(kvm, gpa, pmdp_ptep(pmd), pte);
ret = 0;
@@ -378,12 +513,12 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa,
ret = 0;
goto out_unlock;
}
- /* PTE was previously valid, so invalidate it */
- old = kvmppc_radix_update_pte(kvm, ptep, _PAGE_PRESENT,
- 0, gpa, 0);
- kvmppc_radix_tlbie_page(kvm, gpa, 0);
- if (old & _PAGE_DIRTY)
- mark_page_dirty(kvm, gpa >> PAGE_SHIFT);
+ /* Valid page here already, add our extra bits */
+ WARN_ON_ONCE((pte_val(*ptep) ^ pte_val(pte)) &
+ PTE_BITS_MUST_MATCH);
+ kvmppc_radix_update_pte(kvm, ptep, 0, pte_val(pte), gpa, 0);
+ ret = 0;
+ goto out_unlock;
}
kvmppc_radix_set_pte_at(kvm, gpa, ptep, pte);
ret = 0;
@@ -565,9 +700,13 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned long mask = (1ul << shift) - PAGE_SIZE;
pte = __pte(pte_val(pte) | (hva & mask));
}
- if (!(writing || upgrade_write))
- pte = __pte(pte_val(pte) & ~ _PAGE_WRITE);
- pte = __pte(pte_val(pte) | _PAGE_EXEC);
+ pte = __pte(pte_val(pte) | _PAGE_EXEC | _PAGE_ACCESSED);
+ if (writing || upgrade_write) {
+ if (pte_val(pte) & _PAGE_WRITE)
+ pte = __pte(pte_val(pte) | _PAGE_DIRTY);
+ } else {
+ pte = __pte(pte_val(pte) & ~(_PAGE_WRITE | _PAGE_DIRTY));
+ }
}
/* Allocate space in the tree and write the PTE */
@@ -734,51 +873,6 @@ int kvmppc_init_vm_radix(struct kvm *kvm)
return 0;
}
-void kvmppc_free_radix(struct kvm *kvm)
-{
- unsigned long ig, iu, im;
- pte_t *pte;
- pmd_t *pmd;
- pud_t *pud;
- pgd_t *pgd;
-
- if (!kvm->arch.pgtable)
- return;
- pgd = kvm->arch.pgtable;
- for (ig = 0; ig < PTRS_PER_PGD; ++ig, ++pgd) {
- if (!pgd_present(*pgd))
- continue;
- pud = pud_offset(pgd, 0);
- for (iu = 0; iu < PTRS_PER_PUD; ++iu, ++pud) {
- if (!pud_present(*pud))
- continue;
- if (pud_huge(*pud)) {
- pud_clear(pud);
- continue;
- }
- pmd = pmd_offset(pud, 0);
- for (im = 0; im < PTRS_PER_PMD; ++im, ++pmd) {
- if (pmd_is_leaf(*pmd)) {
- pmd_clear(pmd);
- continue;
- }
- if (!pmd_present(*pmd))
- continue;
- pte = pte_offset_map(pmd, 0);
- memset(pte, 0, sizeof(long) << PTE_INDEX_SIZE);
- kvmppc_pte_free(pte);
- pmd_clear(pmd);
- }
- kvmppc_pmd_free(pmd_offset(pud, 0));
- pud_clear(pud);
- }
- pud_free(kvm->mm, pud_offset(pgd, 0));
- pgd_clear(pgd);
- }
- pgd_free(kvm->mm, kvm->arch.pgtable);
- kvm->arch.pgtable = NULL;
-}
-
static void pte_ctor(void *addr)
{
memset(addr, 0, RADIX_PTE_TABLE_SIZE);
diff --git a/arch/powerpc/kvm/book3s_64_vio.c b/arch/powerpc/kvm/book3s_64_vio.c
index 4dffa61..d066e37 100644
--- a/arch/powerpc/kvm/book3s_64_vio.c
+++ b/arch/powerpc/kvm/book3s_64_vio.c
@@ -176,14 +176,12 @@ extern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
if (!tbltmp)
continue;
- /*
- * Make sure hardware table parameters are exactly the same;
- * this is used in the TCE handlers where boundary checks
- * use only the first attached table.
- */
- if ((tbltmp->it_page_shift == stt->page_shift) &&
- (tbltmp->it_offset == stt->offset) &&
- (tbltmp->it_size == stt->size)) {
+ /* Make sure hardware table parameters are compatible */
+ if ((tbltmp->it_page_shift <= stt->page_shift) &&
+ (tbltmp->it_offset << tbltmp->it_page_shift ==
+ stt->offset << stt->page_shift) &&
+ (tbltmp->it_size << tbltmp->it_page_shift ==
+ stt->size << stt->page_shift)) {
/*
* Reference the table to avoid races with
* add/remove DMA windows.
@@ -237,7 +235,7 @@ static void release_spapr_tce_table(struct rcu_head *head)
kfree(stt);
}
-static int kvm_spapr_tce_fault(struct vm_fault *vmf)
+static vm_fault_t kvm_spapr_tce_fault(struct vm_fault *vmf)
{
struct kvmppc_spapr_tce_table *stt = vmf->vma->vm_file->private_data;
struct page *page;
@@ -302,7 +300,8 @@ long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
int ret = -ENOMEM;
int i;
- if (!args->size)
+ if (!args->size || args->page_shift < 12 || args->page_shift > 34 ||
+ (args->offset + args->size > (ULLONG_MAX >> args->page_shift)))
return -EINVAL;
size = _ALIGN_UP(args->size, PAGE_SIZE >> 3);
@@ -396,7 +395,7 @@ static long kvmppc_tce_iommu_mapped_dec(struct kvm *kvm,
return H_SUCCESS;
}
-static long kvmppc_tce_iommu_unmap(struct kvm *kvm,
+static long kvmppc_tce_iommu_do_unmap(struct kvm *kvm,
struct iommu_table *tbl, unsigned long entry)
{
enum dma_data_direction dir = DMA_NONE;
@@ -416,7 +415,24 @@ static long kvmppc_tce_iommu_unmap(struct kvm *kvm,
return ret;
}
-long kvmppc_tce_iommu_map(struct kvm *kvm, struct iommu_table *tbl,
+static long kvmppc_tce_iommu_unmap(struct kvm *kvm,
+ struct kvmppc_spapr_tce_table *stt, struct iommu_table *tbl,
+ unsigned long entry)
+{
+ unsigned long i, ret = H_SUCCESS;
+ unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
+ unsigned long io_entry = entry * subpages;
+
+ for (i = 0; i < subpages; ++i) {
+ ret = kvmppc_tce_iommu_do_unmap(kvm, tbl, io_entry + i);
+ if (ret != H_SUCCESS)
+ break;
+ }
+
+ return ret;
+}
+
+long kvmppc_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl,
unsigned long entry, unsigned long ua,
enum dma_data_direction dir)
{
@@ -453,6 +469,27 @@ long kvmppc_tce_iommu_map(struct kvm *kvm, struct iommu_table *tbl,
return 0;
}
+static long kvmppc_tce_iommu_map(struct kvm *kvm,
+ struct kvmppc_spapr_tce_table *stt, struct iommu_table *tbl,
+ unsigned long entry, unsigned long ua,
+ enum dma_data_direction dir)
+{
+ unsigned long i, pgoff, ret = H_SUCCESS;
+ unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
+ unsigned long io_entry = entry * subpages;
+
+ for (i = 0, pgoff = 0; i < subpages;
+ ++i, pgoff += IOMMU_PAGE_SIZE(tbl)) {
+
+ ret = kvmppc_tce_iommu_do_map(kvm, tbl,
+ io_entry + i, ua + pgoff, dir);
+ if (ret != H_SUCCESS)
+ break;
+ }
+
+ return ret;
+}
+
long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
unsigned long ioba, unsigned long tce)
{
@@ -491,10 +528,10 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
if (dir == DMA_NONE)
- ret = kvmppc_tce_iommu_unmap(vcpu->kvm,
+ ret = kvmppc_tce_iommu_unmap(vcpu->kvm, stt,
stit->tbl, entry);
else
- ret = kvmppc_tce_iommu_map(vcpu->kvm, stit->tbl,
+ ret = kvmppc_tce_iommu_map(vcpu->kvm, stt, stit->tbl,
entry, ua, dir);
if (ret == H_SUCCESS)
@@ -570,7 +607,7 @@ long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
return H_PARAMETER;
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
- ret = kvmppc_tce_iommu_map(vcpu->kvm,
+ ret = kvmppc_tce_iommu_map(vcpu->kvm, stt,
stit->tbl, entry + i, ua,
iommu_tce_direction(tce));
@@ -615,10 +652,10 @@ long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu,
return H_PARAMETER;
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
- unsigned long entry = ioba >> stit->tbl->it_page_shift;
+ unsigned long entry = ioba >> stt->page_shift;
for (i = 0; i < npages; ++i) {
- ret = kvmppc_tce_iommu_unmap(vcpu->kvm,
+ ret = kvmppc_tce_iommu_unmap(vcpu->kvm, stt,
stit->tbl, entry + i);
if (ret == H_SUCCESS)
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
index 6651f73..925fc31 100644
--- a/arch/powerpc/kvm/book3s_64_vio_hv.c
+++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
@@ -221,7 +221,7 @@ static long kvmppc_rm_tce_iommu_mapped_dec(struct kvm *kvm,
return H_SUCCESS;
}
-static long kvmppc_rm_tce_iommu_unmap(struct kvm *kvm,
+static long kvmppc_rm_tce_iommu_do_unmap(struct kvm *kvm,
struct iommu_table *tbl, unsigned long entry)
{
enum dma_data_direction dir = DMA_NONE;
@@ -245,7 +245,24 @@ static long kvmppc_rm_tce_iommu_unmap(struct kvm *kvm,
return ret;
}
-static long kvmppc_rm_tce_iommu_map(struct kvm *kvm, struct iommu_table *tbl,
+static long kvmppc_rm_tce_iommu_unmap(struct kvm *kvm,
+ struct kvmppc_spapr_tce_table *stt, struct iommu_table *tbl,
+ unsigned long entry)
+{
+ unsigned long i, ret = H_SUCCESS;
+ unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
+ unsigned long io_entry = entry * subpages;
+
+ for (i = 0; i < subpages; ++i) {
+ ret = kvmppc_rm_tce_iommu_do_unmap(kvm, tbl, io_entry + i);
+ if (ret != H_SUCCESS)
+ break;
+ }
+
+ return ret;
+}
+
+static long kvmppc_rm_tce_iommu_do_map(struct kvm *kvm, struct iommu_table *tbl,
unsigned long entry, unsigned long ua,
enum dma_data_direction dir)
{
@@ -290,6 +307,27 @@ static long kvmppc_rm_tce_iommu_map(struct kvm *kvm, struct iommu_table *tbl,
return 0;
}
+static long kvmppc_rm_tce_iommu_map(struct kvm *kvm,
+ struct kvmppc_spapr_tce_table *stt, struct iommu_table *tbl,
+ unsigned long entry, unsigned long ua,
+ enum dma_data_direction dir)
+{
+ unsigned long i, pgoff, ret = H_SUCCESS;
+ unsigned long subpages = 1ULL << (stt->page_shift - tbl->it_page_shift);
+ unsigned long io_entry = entry * subpages;
+
+ for (i = 0, pgoff = 0; i < subpages;
+ ++i, pgoff += IOMMU_PAGE_SIZE(tbl)) {
+
+ ret = kvmppc_rm_tce_iommu_do_map(kvm, tbl,
+ io_entry + i, ua + pgoff, dir);
+ if (ret != H_SUCCESS)
+ break;
+ }
+
+ return ret;
+}
+
long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
unsigned long ioba, unsigned long tce)
{
@@ -327,10 +365,10 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
if (dir == DMA_NONE)
- ret = kvmppc_rm_tce_iommu_unmap(vcpu->kvm,
+ ret = kvmppc_rm_tce_iommu_unmap(vcpu->kvm, stt,
stit->tbl, entry);
else
- ret = kvmppc_rm_tce_iommu_map(vcpu->kvm,
+ ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt,
stit->tbl, entry, ua, dir);
if (ret == H_SUCCESS)
@@ -477,7 +515,7 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
return H_PARAMETER;
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
- ret = kvmppc_rm_tce_iommu_map(vcpu->kvm,
+ ret = kvmppc_rm_tce_iommu_map(vcpu->kvm, stt,
stit->tbl, entry + i, ua,
iommu_tce_direction(tce));
@@ -526,10 +564,10 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
return H_PARAMETER;
list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
- unsigned long entry = ioba >> stit->tbl->it_page_shift;
+ unsigned long entry = ioba >> stt->page_shift;
for (i = 0; i < npages; ++i) {
- ret = kvmppc_rm_tce_iommu_unmap(vcpu->kvm,
+ ret = kvmppc_rm_tce_iommu_unmap(vcpu->kvm, stt,
stit->tbl, entry + i);
if (ret == H_SUCCESS)
@@ -571,7 +609,7 @@ long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
page = stt->pages[idx / TCES_PER_PAGE];
tbl = (u64 *)page_address(page);
- vcpu->arch.gpr[4] = tbl[idx % TCES_PER_PAGE];
+ vcpu->arch.regs.gpr[4] = tbl[idx % TCES_PER_PAGE];
return H_SUCCESS;
}
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 68d6898..36b11c5 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -23,7 +23,9 @@
#include <asm/reg.h>
#include <asm/switch_to.h>
#include <asm/time.h>
+#include <asm/tm.h>
#include "book3s.h"
+#include <asm/asm-prototypes.h>
#define OP_19_XOP_RFID 18
#define OP_19_XOP_RFI 50
@@ -47,6 +49,12 @@
#define OP_31_XOP_EIOIO 854
#define OP_31_XOP_SLBMFEE 915
+#define OP_31_XOP_TBEGIN 654
+#define OP_31_XOP_TABORT 910
+
+#define OP_31_XOP_TRECLAIM 942
+#define OP_31_XOP_TRCHKPT 1006
+
/* DCBZ is actually 1014, but we patch it to 1010 so we get a trap */
#define OP_31_XOP_DCBZ 1010
@@ -87,6 +95,157 @@ static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level)
return true;
}
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+static inline void kvmppc_copyto_vcpu_tm(struct kvm_vcpu *vcpu)
+{
+ memcpy(&vcpu->arch.gpr_tm[0], &vcpu->arch.regs.gpr[0],
+ sizeof(vcpu->arch.gpr_tm));
+ memcpy(&vcpu->arch.fp_tm, &vcpu->arch.fp,
+ sizeof(struct thread_fp_state));
+ memcpy(&vcpu->arch.vr_tm, &vcpu->arch.vr,
+ sizeof(struct thread_vr_state));
+ vcpu->arch.ppr_tm = vcpu->arch.ppr;
+ vcpu->arch.dscr_tm = vcpu->arch.dscr;
+ vcpu->arch.amr_tm = vcpu->arch.amr;
+ vcpu->arch.ctr_tm = vcpu->arch.regs.ctr;
+ vcpu->arch.tar_tm = vcpu->arch.tar;
+ vcpu->arch.lr_tm = vcpu->arch.regs.link;
+ vcpu->arch.cr_tm = vcpu->arch.cr;
+ vcpu->arch.xer_tm = vcpu->arch.regs.xer;
+ vcpu->arch.vrsave_tm = vcpu->arch.vrsave;
+}
+
+static inline void kvmppc_copyfrom_vcpu_tm(struct kvm_vcpu *vcpu)
+{
+ memcpy(&vcpu->arch.regs.gpr[0], &vcpu->arch.gpr_tm[0],
+ sizeof(vcpu->arch.regs.gpr));
+ memcpy(&vcpu->arch.fp, &vcpu->arch.fp_tm,
+ sizeof(struct thread_fp_state));
+ memcpy(&vcpu->arch.vr, &vcpu->arch.vr_tm,
+ sizeof(struct thread_vr_state));
+ vcpu->arch.ppr = vcpu->arch.ppr_tm;
+ vcpu->arch.dscr = vcpu->arch.dscr_tm;
+ vcpu->arch.amr = vcpu->arch.amr_tm;
+ vcpu->arch.regs.ctr = vcpu->arch.ctr_tm;
+ vcpu->arch.tar = vcpu->arch.tar_tm;
+ vcpu->arch.regs.link = vcpu->arch.lr_tm;
+ vcpu->arch.cr = vcpu->arch.cr_tm;
+ vcpu->arch.regs.xer = vcpu->arch.xer_tm;
+ vcpu->arch.vrsave = vcpu->arch.vrsave_tm;
+}
+
+static void kvmppc_emulate_treclaim(struct kvm_vcpu *vcpu, int ra_val)
+{
+ unsigned long guest_msr = kvmppc_get_msr(vcpu);
+ int fc_val = ra_val ? ra_val : 1;
+ uint64_t texasr;
+
+ /* CR0 = 0 | MSR[TS] | 0 */
+ vcpu->arch.cr = (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT)) |
+ (((guest_msr & MSR_TS_MASK) >> (MSR_TS_S_LG - 1))
+ << CR0_SHIFT);
+
+ preempt_disable();
+ tm_enable();
+ texasr = mfspr(SPRN_TEXASR);
+ kvmppc_save_tm_pr(vcpu);
+ kvmppc_copyfrom_vcpu_tm(vcpu);
+
+ /* failure recording depends on Failure Summary bit */
+ if (!(texasr & TEXASR_FS)) {
+ texasr &= ~TEXASR_FC;
+ texasr |= ((u64)fc_val << TEXASR_FC_LG) | TEXASR_FS;
+
+ texasr &= ~(TEXASR_PR | TEXASR_HV);
+ if (kvmppc_get_msr(vcpu) & MSR_PR)
+ texasr |= TEXASR_PR;
+
+ if (kvmppc_get_msr(vcpu) & MSR_HV)
+ texasr |= TEXASR_HV;
+
+ vcpu->arch.texasr = texasr;
+ vcpu->arch.tfiar = kvmppc_get_pc(vcpu);
+ mtspr(SPRN_TEXASR, texasr);
+ mtspr(SPRN_TFIAR, vcpu->arch.tfiar);
+ }
+ tm_disable();
+ /*
+ * treclaim need quit to non-transactional state.
+ */
+ guest_msr &= ~(MSR_TS_MASK);
+ kvmppc_set_msr(vcpu, guest_msr);
+ preempt_enable();
+
+ if (vcpu->arch.shadow_fscr & FSCR_TAR)
+ mtspr(SPRN_TAR, vcpu->arch.tar);
+}
+
+static void kvmppc_emulate_trchkpt(struct kvm_vcpu *vcpu)
+{
+ unsigned long guest_msr = kvmppc_get_msr(vcpu);
+
+ preempt_disable();
+ /*
+ * need flush FP/VEC/VSX to vcpu save area before
+ * copy.
+ */
+ kvmppc_giveup_ext(vcpu, MSR_VSX);
+ kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
+ kvmppc_copyto_vcpu_tm(vcpu);
+ kvmppc_save_tm_sprs(vcpu);
+
+ /*
+ * as a result of trecheckpoint. set TS to suspended.
+ */
+ guest_msr &= ~(MSR_TS_MASK);
+ guest_msr |= MSR_TS_S;
+ kvmppc_set_msr(vcpu, guest_msr);
+ kvmppc_restore_tm_pr(vcpu);
+ preempt_enable();
+}
+
+/* emulate tabort. at guest privilege state */
+void kvmppc_emulate_tabort(struct kvm_vcpu *vcpu, int ra_val)
+{
+ /* currently we only emulate tabort. but no emulation of other
+ * tabort variants since there is no kernel usage of them at
+ * present.
+ */
+ unsigned long guest_msr = kvmppc_get_msr(vcpu);
+ uint64_t org_texasr;
+
+ preempt_disable();
+ tm_enable();
+ org_texasr = mfspr(SPRN_TEXASR);
+ tm_abort(ra_val);
+
+ /* CR0 = 0 | MSR[TS] | 0 */
+ vcpu->arch.cr = (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT)) |
+ (((guest_msr & MSR_TS_MASK) >> (MSR_TS_S_LG - 1))
+ << CR0_SHIFT);
+
+ vcpu->arch.texasr = mfspr(SPRN_TEXASR);
+ /* failure recording depends on Failure Summary bit,
+ * and tabort will be treated as nops in non-transactional
+ * state.
+ */
+ if (!(org_texasr & TEXASR_FS) &&
+ MSR_TM_ACTIVE(guest_msr)) {
+ vcpu->arch.texasr &= ~(TEXASR_PR | TEXASR_HV);
+ if (guest_msr & MSR_PR)
+ vcpu->arch.texasr |= TEXASR_PR;
+
+ if (guest_msr & MSR_HV)
+ vcpu->arch.texasr |= TEXASR_HV;
+
+ vcpu->arch.tfiar = kvmppc_get_pc(vcpu);
+ }
+ tm_disable();
+ preempt_enable();
+}
+
+#endif
+
int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
unsigned int inst, int *advance)
{
@@ -117,11 +276,28 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
case 19:
switch (get_xop(inst)) {
case OP_19_XOP_RFID:
- case OP_19_XOP_RFI:
+ case OP_19_XOP_RFI: {
+ unsigned long srr1 = kvmppc_get_srr1(vcpu);
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ unsigned long cur_msr = kvmppc_get_msr(vcpu);
+
+ /*
+ * add rules to fit in ISA specification regarding TM
+ * state transistion in TM disable/Suspended state,
+ * and target TM state is TM inactive(00) state. (the
+ * change should be suppressed).
+ */
+ if (((cur_msr & MSR_TM) == 0) &&
+ ((srr1 & MSR_TM) == 0) &&
+ MSR_TM_SUSPENDED(cur_msr) &&
+ !MSR_TM_ACTIVE(srr1))
+ srr1 |= MSR_TS_S;
+#endif
kvmppc_set_pc(vcpu, kvmppc_get_srr0(vcpu));
- kvmppc_set_msr(vcpu, kvmppc_get_srr1(vcpu));
+ kvmppc_set_msr(vcpu, srr1);
*advance = 0;
break;
+ }
default:
emulated = EMULATE_FAIL;
@@ -304,6 +480,140 @@ int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
break;
}
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ case OP_31_XOP_TBEGIN:
+ {
+ if (!cpu_has_feature(CPU_FTR_TM))
+ break;
+
+ if (!(kvmppc_get_msr(vcpu) & MSR_TM)) {
+ kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ if (!(kvmppc_get_msr(vcpu) & MSR_PR)) {
+ preempt_disable();
+ vcpu->arch.cr = (CR0_TBEGIN_FAILURE |
+ (vcpu->arch.cr & ~(CR0_MASK << CR0_SHIFT)));
+
+ vcpu->arch.texasr = (TEXASR_FS | TEXASR_EXACT |
+ (((u64)(TM_CAUSE_EMULATE | TM_CAUSE_PERSISTENT))
+ << TEXASR_FC_LG));
+
+ if ((inst >> 21) & 0x1)
+ vcpu->arch.texasr |= TEXASR_ROT;
+
+ if (kvmppc_get_msr(vcpu) & MSR_HV)
+ vcpu->arch.texasr |= TEXASR_HV;
+
+ vcpu->arch.tfhar = kvmppc_get_pc(vcpu) + 4;
+ vcpu->arch.tfiar = kvmppc_get_pc(vcpu);
+
+ kvmppc_restore_tm_sprs(vcpu);
+ preempt_enable();
+ } else
+ emulated = EMULATE_FAIL;
+ break;
+ }
+ case OP_31_XOP_TABORT:
+ {
+ ulong guest_msr = kvmppc_get_msr(vcpu);
+ unsigned long ra_val = 0;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ break;
+
+ if (!(kvmppc_get_msr(vcpu) & MSR_TM)) {
+ kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ /* only emulate for privilege guest, since problem state
+ * guest can run with TM enabled and we don't expect to
+ * trap at here for that case.
+ */
+ WARN_ON(guest_msr & MSR_PR);
+
+ if (ra)
+ ra_val = kvmppc_get_gpr(vcpu, ra);
+
+ kvmppc_emulate_tabort(vcpu, ra_val);
+ break;
+ }
+ case OP_31_XOP_TRECLAIM:
+ {
+ ulong guest_msr = kvmppc_get_msr(vcpu);
+ unsigned long ra_val = 0;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ break;
+
+ if (!(kvmppc_get_msr(vcpu) & MSR_TM)) {
+ kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ /* generate interrupts based on priorities */
+ if (guest_msr & MSR_PR) {
+ /* Privileged Instruction type Program Interrupt */
+ kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ if (!MSR_TM_ACTIVE(guest_msr)) {
+ /* TM bad thing interrupt */
+ kvmppc_core_queue_program(vcpu, SRR1_PROGTM);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ if (ra)
+ ra_val = kvmppc_get_gpr(vcpu, ra);
+ kvmppc_emulate_treclaim(vcpu, ra_val);
+ break;
+ }
+ case OP_31_XOP_TRCHKPT:
+ {
+ ulong guest_msr = kvmppc_get_msr(vcpu);
+ unsigned long texasr;
+
+ if (!cpu_has_feature(CPU_FTR_TM))
+ break;
+
+ if (!(kvmppc_get_msr(vcpu) & MSR_TM)) {
+ kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ /* generate interrupt based on priorities */
+ if (guest_msr & MSR_PR) {
+ /* Privileged Instruction type Program Intr */
+ kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ tm_enable();
+ texasr = mfspr(SPRN_TEXASR);
+ tm_disable();
+
+ if (MSR_TM_ACTIVE(guest_msr) ||
+ !(texasr & (TEXASR_FS))) {
+ /* TM bad thing interrupt */
+ kvmppc_core_queue_program(vcpu, SRR1_PROGTM);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ kvmppc_emulate_trchkpt(vcpu);
+ break;
+ }
+#endif
default:
emulated = EMULATE_FAIL;
}
@@ -465,13 +775,38 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
break;
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
case SPRN_TFHAR:
- vcpu->arch.tfhar = spr_val;
- break;
case SPRN_TEXASR:
- vcpu->arch.texasr = spr_val;
- break;
case SPRN_TFIAR:
- vcpu->arch.tfiar = spr_val;
+ if (!cpu_has_feature(CPU_FTR_TM))
+ break;
+
+ if (!(kvmppc_get_msr(vcpu) & MSR_TM)) {
+ kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ if (MSR_TM_ACTIVE(kvmppc_get_msr(vcpu)) &&
+ !((MSR_TM_SUSPENDED(kvmppc_get_msr(vcpu))) &&
+ (sprn == SPRN_TFHAR))) {
+ /* it is illegal to mtspr() TM regs in
+ * other than non-transactional state, with
+ * the exception of TFHAR in suspend state.
+ */
+ kvmppc_core_queue_program(vcpu, SRR1_PROGTM);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ tm_enable();
+ if (sprn == SPRN_TFHAR)
+ mtspr(SPRN_TFHAR, spr_val);
+ else if (sprn == SPRN_TEXASR)
+ mtspr(SPRN_TEXASR, spr_val);
+ else
+ mtspr(SPRN_TFIAR, spr_val);
+ tm_disable();
+
break;
#endif
#endif
@@ -618,13 +953,25 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
break;
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
case SPRN_TFHAR:
- *spr_val = vcpu->arch.tfhar;
- break;
case SPRN_TEXASR:
- *spr_val = vcpu->arch.texasr;
- break;
case SPRN_TFIAR:
- *spr_val = vcpu->arch.tfiar;
+ if (!cpu_has_feature(CPU_FTR_TM))
+ break;
+
+ if (!(kvmppc_get_msr(vcpu) & MSR_TM)) {
+ kvmppc_trigger_fac_interrupt(vcpu, FSCR_TM_LG);
+ emulated = EMULATE_AGAIN;
+ break;
+ }
+
+ tm_enable();
+ if (sprn == SPRN_TFHAR)
+ *spr_val = mfspr(SPRN_TFHAR);
+ else if (sprn == SPRN_TEXASR)
+ *spr_val = mfspr(SPRN_TEXASR);
+ else if (sprn == SPRN_TFIAR)
+ *spr_val = mfspr(SPRN_TFIAR);
+ tm_disable();
break;
#endif
#endif
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index cb6d231..de686b3 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -123,6 +123,32 @@ static bool no_mixing_hpt_and_radix;
static void kvmppc_end_cede(struct kvm_vcpu *vcpu);
static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu);
+/*
+ * RWMR values for POWER8. These control the rate at which PURR
+ * and SPURR count and should be set according to the number of
+ * online threads in the vcore being run.
+ */
+#define RWMR_RPA_P8_1THREAD 0x164520C62609AECA
+#define RWMR_RPA_P8_2THREAD 0x7FFF2908450D8DA9
+#define RWMR_RPA_P8_3THREAD 0x164520C62609AECA
+#define RWMR_RPA_P8_4THREAD 0x199A421245058DA9
+#define RWMR_RPA_P8_5THREAD 0x164520C62609AECA
+#define RWMR_RPA_P8_6THREAD 0x164520C62609AECA
+#define RWMR_RPA_P8_7THREAD 0x164520C62609AECA
+#define RWMR_RPA_P8_8THREAD 0x164520C62609AECA
+
+static unsigned long p8_rwmr_values[MAX_SMT_THREADS + 1] = {
+ RWMR_RPA_P8_1THREAD,
+ RWMR_RPA_P8_1THREAD,
+ RWMR_RPA_P8_2THREAD,
+ RWMR_RPA_P8_3THREAD,
+ RWMR_RPA_P8_4THREAD,
+ RWMR_RPA_P8_5THREAD,
+ RWMR_RPA_P8_6THREAD,
+ RWMR_RPA_P8_7THREAD,
+ RWMR_RPA_P8_8THREAD,
+};
+
static inline struct kvm_vcpu *next_runnable_thread(struct kvmppc_vcore *vc,
int *ip)
{
@@ -371,13 +397,13 @@ static void kvmppc_dump_regs(struct kvm_vcpu *vcpu)
pr_err("vcpu %p (%d):\n", vcpu, vcpu->vcpu_id);
pr_err("pc = %.16lx msr = %.16llx trap = %x\n",
- vcpu->arch.pc, vcpu->arch.shregs.msr, vcpu->arch.trap);
+ vcpu->arch.regs.nip, vcpu->arch.shregs.msr, vcpu->arch.trap);
for (r = 0; r < 16; ++r)
pr_err("r%2d = %.16lx r%d = %.16lx\n",
r, kvmppc_get_gpr(vcpu, r),
r+16, kvmppc_get_gpr(vcpu, r+16));
pr_err("ctr = %.16lx lr = %.16lx\n",
- vcpu->arch.ctr, vcpu->arch.lr);
+ vcpu->arch.regs.ctr, vcpu->arch.regs.link);
pr_err("srr0 = %.16llx srr1 = %.16llx\n",
vcpu->arch.shregs.srr0, vcpu->arch.shregs.srr1);
pr_err("sprg0 = %.16llx sprg1 = %.16llx\n",
@@ -385,7 +411,7 @@ static void kvmppc_dump_regs(struct kvm_vcpu *vcpu)
pr_err("sprg2 = %.16llx sprg3 = %.16llx\n",
vcpu->arch.shregs.sprg2, vcpu->arch.shregs.sprg3);
pr_err("cr = %.8x xer = %.16lx dsisr = %.8x\n",
- vcpu->arch.cr, vcpu->arch.xer, vcpu->arch.shregs.dsisr);
+ vcpu->arch.cr, vcpu->arch.regs.xer, vcpu->arch.shregs.dsisr);
pr_err("dar = %.16llx\n", vcpu->arch.shregs.dar);
pr_err("fault dar = %.16lx dsisr = %.8x\n",
vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
@@ -1526,6 +1552,9 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
*val = get_reg_val(id, vcpu->arch.dec_expires +
vcpu->arch.vcore->tb_offset);
break;
+ case KVM_REG_PPC_ONLINE:
+ *val = get_reg_val(id, vcpu->arch.online);
+ break;
default:
r = -EINVAL;
break;
@@ -1757,6 +1786,14 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id,
vcpu->arch.dec_expires = set_reg_val(id, *val) -
vcpu->arch.vcore->tb_offset;
break;
+ case KVM_REG_PPC_ONLINE:
+ i = set_reg_val(id, *val);
+ if (i && !vcpu->arch.online)
+ atomic_inc(&vcpu->arch.vcore->online_count);
+ else if (!i && vcpu->arch.online)
+ atomic_dec(&vcpu->arch.vcore->online_count);
+ vcpu->arch.online = i;
+ break;
default:
r = -EINVAL;
break;
@@ -2850,6 +2887,25 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
}
}
+ /*
+ * On POWER8, set RWMR register.
+ * Since it only affects PURR and SPURR, it doesn't affect
+ * the host, so we don't save/restore the host value.
+ */
+ if (is_power8) {
+ unsigned long rwmr_val = RWMR_RPA_P8_8THREAD;
+ int n_online = atomic_read(&vc->online_count);
+
+ /*
+ * Use the 8-thread value if we're doing split-core
+ * or if the vcore's online count looks bogus.
+ */
+ if (split == 1 && threads_per_subcore == MAX_SMT_THREADS &&
+ n_online >= 1 && n_online <= MAX_SMT_THREADS)
+ rwmr_val = p8_rwmr_values[n_online];
+ mtspr(SPRN_RWMR, rwmr_val);
+ }
+
/* Start all the threads */
active = 0;
for (sub = 0; sub < core_info.n_subcores; ++sub) {
@@ -2902,6 +2958,32 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
for (sub = 0; sub < core_info.n_subcores; ++sub)
spin_unlock(&core_info.vc[sub]->lock);
+ if (kvm_is_radix(vc->kvm)) {
+ int tmp = pcpu;
+
+ /*
+ * Do we need to flush the process scoped TLB for the LPAR?
+ *
+ * On POWER9, individual threads can come in here, but the
+ * TLB is shared between the 4 threads in a core, hence
+ * invalidating on one thread invalidates for all.
+ * Thus we make all 4 threads use the same bit here.
+ *
+ * Hash must be flushed in realmode in order to use tlbiel.
+ */
+ mtspr(SPRN_LPID, vc->kvm->arch.lpid);
+ isync();
+
+ if (cpu_has_feature(CPU_FTR_ARCH_300))
+ tmp &= ~0x3UL;
+
+ if (cpumask_test_cpu(tmp, &vc->kvm->arch.need_tlb_flush)) {
+ radix__local_flush_tlb_lpid_guest(vc->kvm->arch.lpid);
+ /* Clear the bit after the TLB flush */
+ cpumask_clear_cpu(tmp, &vc->kvm->arch.need_tlb_flush);
+ }
+ }
+
/*
* Interrupts will be enabled once we get into the guest,
* so tell lockdep that we're about to enable interrupts.
@@ -3356,6 +3438,15 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
}
#endif
+ /*
+ * Force online to 1 for the sake of old userspace which doesn't
+ * set it.
+ */
+ if (!vcpu->arch.online) {
+ atomic_inc(&vcpu->arch.vcore->online_count);
+ vcpu->arch.online = 1;
+ }
+
kvmppc_core_prepare_to_enter(vcpu);
/* No need to go into the guest when all we'll do is come back out */
@@ -3548,7 +3639,7 @@ static void kvmppc_core_free_memslot_hv(struct kvm_memory_slot *free,
static int kvmppc_core_create_memslot_hv(struct kvm_memory_slot *slot,
unsigned long npages)
{
- slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap));
+ slot->arch.rmap = vzalloc(array_size(npages, sizeof(*slot->arch.rmap)));
if (!slot->arch.rmap)
return -ENOMEM;
@@ -3955,8 +4046,7 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
*/
snprintf(buf, sizeof(buf), "vm%d", current->pid);
kvm->arch.debugfs_dir = debugfs_create_dir(buf, kvm_debugfs_dir);
- if (!IS_ERR_OR_NULL(kvm->arch.debugfs_dir))
- kvmppc_mmu_debugfs_init(kvm);
+ kvmppc_mmu_debugfs_init(kvm);
return 0;
}
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
index de18299..d4a3f4d 100644
--- a/arch/powerpc/kvm/book3s_hv_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_builtin.c
@@ -18,6 +18,7 @@
#include <linux/cma.h>
#include <linux/bitops.h>
+#include <asm/asm-prototypes.h>
#include <asm/cputable.h>
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s.h>
@@ -211,9 +212,9 @@ long kvmppc_h_random(struct kvm_vcpu *vcpu)
/* 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]);
+ r = powernv_get_random_long(&vcpu->arch.regs.gpr[4]);
else
- r = powernv_get_random_real_mode(&vcpu->arch.gpr[4]);
+ r = powernv_get_random_real_mode(&vcpu->arch.regs.gpr[4]);
if (r)
return H_SUCCESS;
@@ -562,7 +563,7 @@ unsigned long kvmppc_rm_h_xirr_x(struct kvm_vcpu *vcpu)
{
if (!kvmppc_xics_enabled(vcpu))
return H_TOO_HARD;
- vcpu->arch.gpr[5] = get_tb();
+ vcpu->arch.regs.gpr[5] = get_tb();
if (xive_enabled()) {
if (is_rm())
return xive_rm_h_xirr(vcpu);
@@ -633,7 +634,19 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
void kvmppc_bad_interrupt(struct pt_regs *regs)
{
- die("Bad interrupt in KVM entry/exit code", regs, SIGABRT);
+ /*
+ * 100 could happen at any time, 200 can happen due to invalid real
+ * address access for example (or any time due to a hardware problem).
+ */
+ if (TRAP(regs) == 0x100) {
+ get_paca()->in_nmi++;
+ system_reset_exception(regs);
+ get_paca()->in_nmi--;
+ } else if (TRAP(regs) == 0x200) {
+ machine_check_exception(regs);
+ } else {
+ die("Bad interrupt in KVM entry/exit code", regs, SIGABRT);
+ }
panic("Bad KVM trap");
}
diff --git a/arch/powerpc/kvm/book3s_hv_interrupts.S b/arch/powerpc/kvm/book3s_hv_interrupts.S
index 0e84930..82f2ff9 100644
--- a/arch/powerpc/kvm/book3s_hv_interrupts.S
+++ b/arch/powerpc/kvm/book3s_hv_interrupts.S
@@ -137,7 +137,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
/*
* We return here in virtual mode after the guest exits
* with something that we can't handle in real mode.
- * Interrupts are enabled again at this point.
+ * Interrupts are still hard-disabled.
*/
/*
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index 78e6a39..1f22d9e 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -418,7 +418,8 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
long pte_index, unsigned long pteh, unsigned long ptel)
{
return kvmppc_do_h_enter(vcpu->kvm, flags, pte_index, pteh, ptel,
- vcpu->arch.pgdir, true, &vcpu->arch.gpr[4]);
+ vcpu->arch.pgdir, true,
+ &vcpu->arch.regs.gpr[4]);
}
#ifdef __BIG_ENDIAN__
@@ -434,24 +435,6 @@ static inline int is_mmio_hpte(unsigned long v, unsigned long r)
(HPTE_R_KEY_HI | HPTE_R_KEY_LO));
}
-static inline int try_lock_tlbie(unsigned int *lock)
-{
- unsigned int tmp, old;
- unsigned int token = LOCK_TOKEN;
-
- asm volatile("1:lwarx %1,0,%2\n"
- " cmpwi cr0,%1,0\n"
- " bne 2f\n"
- " stwcx. %3,0,%2\n"
- " bne- 1b\n"
- " isync\n"
- "2:"
- : "=&r" (tmp), "=&r" (old)
- : "r" (lock), "r" (token)
- : "cc", "memory");
- return old == 0;
-}
-
static void do_tlbies(struct kvm *kvm, unsigned long *rbvalues,
long npages, int global, bool need_sync)
{
@@ -463,8 +446,6 @@ static void do_tlbies(struct kvm *kvm, unsigned long *rbvalues,
* the RS field, this is backwards-compatible with P7 and P8.
*/
if (global) {
- while (!try_lock_tlbie(&kvm->arch.tlbie_lock))
- cpu_relax();
if (need_sync)
asm volatile("ptesync" : : : "memory");
for (i = 0; i < npages; ++i) {
@@ -483,7 +464,6 @@ static void do_tlbies(struct kvm *kvm, unsigned long *rbvalues,
}
asm volatile("eieio; tlbsync; ptesync" : : : "memory");
- kvm->arch.tlbie_lock = 0;
} else {
if (need_sync)
asm volatile("ptesync" : : : "memory");
@@ -561,13 +541,13 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
unsigned long pte_index, unsigned long avpn)
{
return kvmppc_do_h_remove(vcpu->kvm, flags, pte_index, avpn,
- &vcpu->arch.gpr[4]);
+ &vcpu->arch.regs.gpr[4]);
}
long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = vcpu->kvm;
- unsigned long *args = &vcpu->arch.gpr[4];
+ unsigned long *args = &vcpu->arch.regs.gpr[4];
__be64 *hp, *hptes[4];
unsigned long tlbrb[4];
long int i, j, k, n, found, indexes[4];
@@ -787,8 +767,8 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
r = rev[i].guest_rpte | (r & (HPTE_R_R | HPTE_R_C));
r &= ~HPTE_GR_RESERVED;
}
- vcpu->arch.gpr[4 + i * 2] = v;
- vcpu->arch.gpr[5 + i * 2] = r;
+ vcpu->arch.regs.gpr[4 + i * 2] = v;
+ vcpu->arch.regs.gpr[5 + i * 2] = r;
}
return H_SUCCESS;
}
@@ -834,7 +814,7 @@ long kvmppc_h_clear_ref(struct kvm_vcpu *vcpu, unsigned long flags,
}
}
}
- vcpu->arch.gpr[4] = gr;
+ vcpu->arch.regs.gpr[4] = gr;
ret = H_SUCCESS;
out:
unlock_hpte(hpte, v & ~HPTE_V_HVLOCK);
@@ -881,7 +861,7 @@ long kvmppc_h_clear_mod(struct kvm_vcpu *vcpu, unsigned long flags,
kvmppc_set_dirty_from_hpte(kvm, v, gr);
}
}
- vcpu->arch.gpr[4] = gr;
+ vcpu->arch.regs.gpr[4] = gr;
ret = H_SUCCESS;
out:
unlock_hpte(hpte, v & ~HPTE_V_HVLOCK);
diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c
index 2a86261..758d1d2 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_xics.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c
@@ -517,7 +517,7 @@ unsigned long xics_rm_h_xirr(struct kvm_vcpu *vcpu)
} while (!icp_rm_try_update(icp, old_state, new_state));
/* Return the result in GPR4 */
- vcpu->arch.gpr[4] = xirr;
+ vcpu->arch.regs.gpr[4] = xirr;
return check_too_hard(xics, icp);
}
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index b97d261..153988d 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -39,8 +39,6 @@ BEGIN_FTR_SECTION; \
extsw reg, reg; \
END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
-#define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM)
-
/* Values in HSTATE_NAPPING(r13) */
#define NAPPING_CEDE 1
#define NAPPING_NOVCPU 2
@@ -639,6 +637,10 @@ kvmppc_hv_entry:
/* Primary thread switches to guest partition. */
cmpwi r6,0
bne 10f
+
+ /* Radix has already switched LPID and flushed core TLB */
+ bne cr7, 22f
+
lwz r7,KVM_LPID(r9)
BEGIN_FTR_SECTION
ld r6,KVM_SDR1(r9)
@@ -650,7 +652,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
mtspr SPRN_LPID,r7
isync
- /* See if we need to flush the TLB */
+ /* See if we need to flush the TLB. Hash has to be done in RM */
lhz r6,PACAPACAINDEX(r13) /* test_bit(cpu, need_tlb_flush) */
BEGIN_FTR_SECTION
/*
@@ -677,15 +679,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
li r7,0x800 /* IS field = 0b10 */
ptesync
li r0,0 /* RS for P9 version of tlbiel */
- bne cr7, 29f
28: tlbiel r7 /* On P9, rs=0, RIC=0, PRS=0, R=0 */
addi r7,r7,0x1000
bdnz 28b
- b 30f
-29: PPC_TLBIEL(7,0,2,1,1) /* for radix, RIC=2, PRS=1, R=1 */
- addi r7,r7,0x1000
- bdnz 29b
-30: ptesync
+ ptesync
23: ldarx r7,0,r6 /* clear the bit after TLB flushed */
andc r7,r7,r8
stdcx. r7,0,r6
@@ -799,7 +796,10 @@ END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
/*
* NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
*/
- bl kvmppc_restore_tm
+ mr r3, r4
+ ld r4, VCPU_MSR(r3)
+ bl kvmppc_restore_tm_hv
+ ld r4, HSTATE_KVM_VCPU(r13)
91:
#endif
@@ -1783,7 +1783,10 @@ END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
/*
* NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
*/
- bl kvmppc_save_tm
+ mr r3, r9
+ ld r4, VCPU_MSR(r3)
+ bl kvmppc_save_tm_hv
+ ld r9, HSTATE_KVM_VCPU(r13)
91:
#endif
@@ -2686,8 +2689,9 @@ END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
/*
* NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
*/
- ld r9, HSTATE_KVM_VCPU(r13)
- bl kvmppc_save_tm
+ ld r3, HSTATE_KVM_VCPU(r13)
+ ld r4, VCPU_MSR(r3)
+ bl kvmppc_save_tm_hv
91:
#endif
@@ -2805,7 +2809,10 @@ END_FTR_SECTION(CPU_FTR_TM | CPU_FTR_P9_TM_HV_ASSIST, 0)
/*
* NOTE THAT THIS TRASHES ALL NON-VOLATILE REGISTERS INCLUDING CR
*/
- bl kvmppc_restore_tm
+ mr r3, r4
+ ld r4, VCPU_MSR(r3)
+ bl kvmppc_restore_tm_hv
+ ld r4, HSTATE_KVM_VCPU(r13)
91:
#endif
@@ -3126,11 +3133,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
/*
* Save transactional state and TM-related registers.
- * Called with r9 pointing to the vcpu struct.
+ * Called with r3 pointing to the vcpu struct and r4 containing
+ * the guest MSR value.
* This can modify all checkpointed registers, but
- * restores r1, r2 and r9 (vcpu pointer) before exit.
+ * restores r1 and r2 before exit.
*/
-kvmppc_save_tm:
+kvmppc_save_tm_hv:
+ /* See if we need to handle fake suspend mode */
+BEGIN_FTR_SECTION
+ b __kvmppc_save_tm
+END_FTR_SECTION_IFCLR(CPU_FTR_P9_TM_HV_ASSIST)
+
+ lbz r0, HSTATE_FAKE_SUSPEND(r13) /* Were we fake suspended? */
+ cmpwi r0, 0
+ beq __kvmppc_save_tm
+
+ /* The following code handles the fake_suspend = 1 case */
mflr r0
std r0, PPC_LR_STKOFF(r1)
stdu r1, -PPC_MIN_STKFRM(r1)
@@ -3141,59 +3159,37 @@ kvmppc_save_tm:
rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG
mtmsrd r8
- ld r5, VCPU_MSR(r9)
- rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
- beq 1f /* TM not active in guest. */
-
- std r1, HSTATE_HOST_R1(r13)
- li r3, TM_CAUSE_KVM_RESCHED
-
-BEGIN_FTR_SECTION
- lbz r0, HSTATE_FAKE_SUSPEND(r13) /* Were we fake suspended? */
- cmpwi r0, 0
- beq 3f
rldicl. r8, r8, 64 - MSR_TS_S_LG, 62 /* Did we actually hrfid? */
beq 4f
-BEGIN_FTR_SECTION_NESTED(96)
+BEGIN_FTR_SECTION
bl pnv_power9_force_smt4_catch
-END_FTR_SECTION_NESTED(CPU_FTR_P9_TM_XER_SO_BUG, CPU_FTR_P9_TM_XER_SO_BUG, 96)
+END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_XER_SO_BUG)
nop
- b 6f
-3:
- /* Emulation of the treclaim instruction needs TEXASR before treclaim */
- mfspr r6, SPRN_TEXASR
- std r6, VCPU_ORIG_TEXASR(r9)
-6:
-END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
- /* Clear the MSR RI since r1, r13 are all going to be foobar. */
+ std r1, HSTATE_HOST_R1(r13)
+
+ /* Clear the MSR RI since r1, r13 may be foobar. */
li r5, 0
mtmsrd r5, 1
- /* All GPRs are volatile at this point. */
+ /* We have to treclaim here because that's the only way to do S->N */
+ li r3, TM_CAUSE_KVM_RESCHED
TRECLAIM(R3)
- /* Temporarily store r13 and r9 so we have some regs to play with */
- SET_SCRATCH0(r13)
- GET_PACA(r13)
- std r9, PACATMSCRATCH(r13)
-
- /* If doing TM emulation on POWER9 DD2.2, check for fake suspend mode */
-BEGIN_FTR_SECTION
- lbz r9, HSTATE_FAKE_SUSPEND(r13)
- cmpwi r9, 0
- beq 2f
/*
* We were in fake suspend, so we are not going to save the
* register state as the guest checkpointed state (since
* we already have it), therefore we can now use any volatile GPR.
*/
- /* Reload stack pointer and TOC. */
+ /* Reload PACA pointer, stack pointer and TOC. */
+ GET_PACA(r13)
ld r1, HSTATE_HOST_R1(r13)
ld r2, PACATOC(r13)
+
/* Set MSR RI now we have r1 and r13 back. */
li r5, MSR_RI
mtmsrd r5, 1
+
HMT_MEDIUM
ld r6, HSTATE_DSCR(r13)
mtspr SPRN_DSCR, r6
@@ -3208,85 +3204,9 @@ END_FTR_SECTION_NESTED(CPU_FTR_P9_TM_XER_SO_BUG, CPU_FTR_P9_TM_XER_SO_BUG, 96)
li r0, PSSCR_FAKE_SUSPEND
andc r3, r3, r0
mtspr SPRN_PSSCR, r3
- ld r9, HSTATE_KVM_VCPU(r13)
- /* Don't save TEXASR, use value from last exit in real suspend state */
- b 11f
-2:
-END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
+ /* Don't save TEXASR, use value from last exit in real suspend state */
ld r9, HSTATE_KVM_VCPU(r13)
-
- /* Get a few more GPRs free. */
- std r29, VCPU_GPRS_TM(29)(r9)
- std r30, VCPU_GPRS_TM(30)(r9)
- std r31, VCPU_GPRS_TM(31)(r9)
-
- /* Save away PPR and DSCR soon so don't run with user values. */
- mfspr r31, SPRN_PPR
- HMT_MEDIUM
- mfspr r30, SPRN_DSCR
- ld r29, HSTATE_DSCR(r13)
- mtspr SPRN_DSCR, r29
-
- /* Save all but r9, r13 & r29-r31 */
- reg = 0
- .rept 29
- .if (reg != 9) && (reg != 13)
- std reg, VCPU_GPRS_TM(reg)(r9)
- .endif
- reg = reg + 1
- .endr
- /* ... now save r13 */
- GET_SCRATCH0(r4)
- std r4, VCPU_GPRS_TM(13)(r9)
- /* ... and save r9 */
- ld r4, PACATMSCRATCH(r13)
- std r4, VCPU_GPRS_TM(9)(r9)
-
- /* Reload stack pointer and TOC. */
- ld r1, HSTATE_HOST_R1(r13)
- ld r2, PACATOC(r13)
-
- /* Set MSR RI now we have r1 and r13 back. */
- li r5, MSR_RI
- mtmsrd r5, 1
-
- /* Save away checkpinted SPRs. */
- std r31, VCPU_PPR_TM(r9)
- std r30, VCPU_DSCR_TM(r9)
- mflr r5
- mfcr r6
- mfctr r7
- mfspr r8, SPRN_AMR
- mfspr r10, SPRN_TAR
- mfxer r11
- std r5, VCPU_LR_TM(r9)
- stw r6, VCPU_CR_TM(r9)
- std r7, VCPU_CTR_TM(r9)
- std r8, VCPU_AMR_TM(r9)
- std r10, VCPU_TAR_TM(r9)
- std r11, VCPU_XER_TM(r9)
-
- /* Restore r12 as trap number. */
- lwz r12, VCPU_TRAP(r9)
-
- /* Save FP/VSX. */
- addi r3, r9, VCPU_FPRS_TM
- bl store_fp_state
- addi r3, r9, VCPU_VRS_TM
- bl store_vr_state
- mfspr r6, SPRN_VRSAVE
- stw r6, VCPU_VRSAVE_TM(r9)
-1:
- /*
- * We need to save these SPRs after the treclaim so that the software
- * error code is recorded correctly in the TEXASR. Also the user may
- * change these outside of a transaction, so they must always be
- * context switched.
- */
- mfspr r7, SPRN_TEXASR
- std r7, VCPU_TEXASR(r9)
-11:
mfspr r5, SPRN_TFHAR
mfspr r6, SPRN_TFIAR
std r5, VCPU_TFHAR(r9)
@@ -3299,149 +3219,63 @@ END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
/*
* Restore transactional state and TM-related registers.
- * Called with r4 pointing to the vcpu struct.
+ * Called with r3 pointing to the vcpu struct
+ * and r4 containing the guest MSR value.
* This potentially modifies all checkpointed registers.
- * It restores r1, r2, r4 from the PACA.
+ * It restores r1 and r2 from the PACA.
*/
-kvmppc_restore_tm:
+kvmppc_restore_tm_hv:
+ /*
+ * If we are doing TM emulation for the guest on a POWER9 DD2,
+ * then we don't actually do a trechkpt -- we either set up
+ * fake-suspend mode, or emulate a TM rollback.
+ */
+BEGIN_FTR_SECTION
+ b __kvmppc_restore_tm
+END_FTR_SECTION_IFCLR(CPU_FTR_P9_TM_HV_ASSIST)
mflr r0
std r0, PPC_LR_STKOFF(r1)
- /* Turn on TM/FP/VSX/VMX so we can restore them. */
+ li r0, 0
+ stb r0, HSTATE_FAKE_SUSPEND(r13)
+
+ /* Turn on TM so we can restore TM SPRs */
mfmsr r5
- li r6, MSR_TM >> 32
- sldi r6, r6, 32
- or r5, r5, r6
- ori r5, r5, MSR_FP
- oris r5, r5, (MSR_VEC | MSR_VSX)@h
+ li r0, 1
+ rldimi r5, r0, MSR_TM_LG, 63-MSR_TM_LG
mtmsrd r5
/*
* The user may change these outside of a transaction, so they must
* always be context switched.
*/
- ld r5, VCPU_TFHAR(r4)
- ld r6, VCPU_TFIAR(r4)
- ld r7, VCPU_TEXASR(r4)
+ ld r5, VCPU_TFHAR(r3)
+ ld r6, VCPU_TFIAR(r3)
+ ld r7, VCPU_TEXASR(r3)
mtspr SPRN_TFHAR, r5
mtspr SPRN_TFIAR, r6
mtspr SPRN_TEXASR, r7
- li r0, 0
- stb r0, HSTATE_FAKE_SUSPEND(r13)
- ld r5, VCPU_MSR(r4)
- rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
+ rldicl. r5, r4, 64 - MSR_TS_S_LG, 62
beqlr /* TM not active in guest */
- std r1, HSTATE_HOST_R1(r13)
- /* Make sure the failure summary is set, otherwise we'll program check
- * when we trechkpt. It's possible that this might have been not set
- * on a kvmppc_set_one_reg() call but we shouldn't let this crash the
- * host.
- */
+ /* Make sure the failure summary is set */
oris r7, r7, (TEXASR_FS)@h
mtspr SPRN_TEXASR, r7
- /*
- * If we are doing TM emulation for the guest on a POWER9 DD2,
- * then we don't actually do a trechkpt -- we either set up
- * fake-suspend mode, or emulate a TM rollback.
- */
-BEGIN_FTR_SECTION
- b .Ldo_tm_fake_load
-END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
-
- /*
- * We need to load up the checkpointed state for the guest.
- * We need to do this early as it will blow away any GPRs, VSRs and
- * some SPRs.
- */
-
- mr r31, r4
- addi r3, r31, VCPU_FPRS_TM
- bl load_fp_state
- addi r3, r31, VCPU_VRS_TM
- bl load_vr_state
- mr r4, r31
- lwz r7, VCPU_VRSAVE_TM(r4)
- mtspr SPRN_VRSAVE, r7
-
- ld r5, VCPU_LR_TM(r4)
- lwz r6, VCPU_CR_TM(r4)
- ld r7, VCPU_CTR_TM(r4)
- ld r8, VCPU_AMR_TM(r4)
- ld r9, VCPU_TAR_TM(r4)
- ld r10, VCPU_XER_TM(r4)
- mtlr r5
- mtcr r6
- mtctr r7
- mtspr SPRN_AMR, r8
- mtspr SPRN_TAR, r9
- mtxer r10
-
- /*
- * Load up PPR and DSCR values but don't put them in the actual SPRs
- * till the last moment to avoid running with userspace PPR and DSCR for
- * too long.
- */
- ld r29, VCPU_DSCR_TM(r4)
- ld r30, VCPU_PPR_TM(r4)
-
- std r2, PACATMSCRATCH(r13) /* Save TOC */
-
- /* Clear the MSR RI since r1, r13 are all going to be foobar. */
- li r5, 0
- mtmsrd r5, 1
-
- /* Load GPRs r0-r28 */
- reg = 0
- .rept 29
- ld reg, VCPU_GPRS_TM(reg)(r31)
- reg = reg + 1
- .endr
-
- mtspr SPRN_DSCR, r29
- mtspr SPRN_PPR, r30
-
- /* Load final GPRs */
- ld 29, VCPU_GPRS_TM(29)(r31)
- ld 30, VCPU_GPRS_TM(30)(r31)
- ld 31, VCPU_GPRS_TM(31)(r31)
-
- /* TM checkpointed state is now setup. All GPRs are now volatile. */
- TRECHKPT
-
- /* Now let's get back the state we need. */
- HMT_MEDIUM
- GET_PACA(r13)
- ld r29, HSTATE_DSCR(r13)
- mtspr SPRN_DSCR, r29
- ld r4, HSTATE_KVM_VCPU(r13)
- ld r1, HSTATE_HOST_R1(r13)
- ld r2, PACATMSCRATCH(r13)
-
- /* Set the MSR RI since we have our registers back. */
- li r5, MSR_RI
- mtmsrd r5, 1
-9:
- ld r0, PPC_LR_STKOFF(r1)
- mtlr r0
- blr
-
-.Ldo_tm_fake_load:
cmpwi r5, 1 /* check for suspended state */
bgt 10f
stb r5, HSTATE_FAKE_SUSPEND(r13)
- b 9b /* and return */
+ b 9f /* and return */
10: stdu r1, -PPC_MIN_STKFRM(r1)
/* guest is in transactional state, so simulate rollback */
- mr r3, r4
bl kvmhv_emulate_tm_rollback
nop
- ld r4, HSTATE_KVM_VCPU(r13) /* our vcpu pointer has been trashed */
addi r1, r1, PPC_MIN_STKFRM
- b 9b
-#endif
+9: ld r0, PPC_LR_STKOFF(r1)
+ mtlr r0
+ blr
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
/*
* We come here if we get any exception or interrupt while we are
@@ -3572,6 +3406,8 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_TYPE_RADIX)
bcl 20, 31, .+4
5: mflr r3
addi r3, r3, 9f - 5b
+ li r4, -1
+ rldimi r3, r4, 62, 0 /* ensure 0xc000000000000000 bits are set */
ld r4, PACAKMSR(r13)
mtspr SPRN_SRR0, r3
mtspr SPRN_SRR1, r4
diff --git a/arch/powerpc/kvm/book3s_hv_tm.c b/arch/powerpc/kvm/book3s_hv_tm.c
index bf710ad..0082850 100644
--- a/arch/powerpc/kvm/book3s_hv_tm.c
+++ b/arch/powerpc/kvm/book3s_hv_tm.c
@@ -19,7 +19,7 @@ static void emulate_tx_failure(struct kvm_vcpu *vcpu, u64 failure_cause)
u64 texasr, tfiar;
u64 msr = vcpu->arch.shregs.msr;
- tfiar = vcpu->arch.pc & ~0x3ull;
+ tfiar = vcpu->arch.regs.nip & ~0x3ull;
texasr = (failure_cause << 56) | TEXASR_ABORT | TEXASR_FS | TEXASR_EXACT;
if (MSR_TM_SUSPENDED(vcpu->arch.shregs.msr))
texasr |= TEXASR_SUSP;
@@ -57,8 +57,8 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
(newmsr & MSR_TM)));
newmsr = sanitize_msr(newmsr);
vcpu->arch.shregs.msr = newmsr;
- vcpu->arch.cfar = vcpu->arch.pc - 4;
- vcpu->arch.pc = vcpu->arch.shregs.srr0;
+ vcpu->arch.cfar = vcpu->arch.regs.nip - 4;
+ vcpu->arch.regs.nip = vcpu->arch.shregs.srr0;
return RESUME_GUEST;
case PPC_INST_RFEBB:
@@ -90,8 +90,8 @@ int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu)
vcpu->arch.bescr = bescr;
msr = (msr & ~MSR_TS_MASK) | MSR_TS_T;
vcpu->arch.shregs.msr = msr;
- vcpu->arch.cfar = vcpu->arch.pc - 4;
- vcpu->arch.pc = vcpu->arch.ebbrr;
+ vcpu->arch.cfar = vcpu->arch.regs.nip - 4;
+ vcpu->arch.regs.nip = vcpu->arch.ebbrr;
return RESUME_GUEST;
case PPC_INST_MTMSRD:
diff --git a/arch/powerpc/kvm/book3s_hv_tm_builtin.c b/arch/powerpc/kvm/book3s_hv_tm_builtin.c
index d98ccfd..b2c7c6f 100644
--- a/arch/powerpc/kvm/book3s_hv_tm_builtin.c
+++ b/arch/powerpc/kvm/book3s_hv_tm_builtin.c
@@ -35,8 +35,8 @@ int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu)
return 0;
newmsr = sanitize_msr(newmsr);
vcpu->arch.shregs.msr = newmsr;
- vcpu->arch.cfar = vcpu->arch.pc - 4;
- vcpu->arch.pc = vcpu->arch.shregs.srr0;
+ vcpu->arch.cfar = vcpu->arch.regs.nip - 4;
+ vcpu->arch.regs.nip = vcpu->arch.shregs.srr0;
return 1;
case PPC_INST_RFEBB:
@@ -58,8 +58,8 @@ int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu)
mtspr(SPRN_BESCR, bescr);
msr = (msr & ~MSR_TS_MASK) | MSR_TS_T;
vcpu->arch.shregs.msr = msr;
- vcpu->arch.cfar = vcpu->arch.pc - 4;
- vcpu->arch.pc = mfspr(SPRN_EBBRR);
+ vcpu->arch.cfar = vcpu->arch.regs.nip - 4;
+ vcpu->arch.regs.nip = mfspr(SPRN_EBBRR);
return 1;
case PPC_INST_MTMSRD:
@@ -103,7 +103,7 @@ int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu)
void kvmhv_emulate_tm_rollback(struct kvm_vcpu *vcpu)
{
vcpu->arch.shregs.msr &= ~MSR_TS_MASK; /* go to N state */
- vcpu->arch.pc = vcpu->arch.tfhar;
+ vcpu->arch.regs.nip = vcpu->arch.tfhar;
copy_from_checkpoint(vcpu);
vcpu->arch.cr = (vcpu->arch.cr & 0x0fffffff) | 0xa0000000;
}
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c
index d3f304d..c3b8006 100644
--- a/arch/powerpc/kvm/book3s_pr.c
+++ b/arch/powerpc/kvm/book3s_pr.c
@@ -42,6 +42,8 @@
#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
+#include <asm/asm-prototypes.h>
+#include <asm/tm.h>
#include "book3s.h"
@@ -53,7 +55,9 @@
static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr,
ulong msr);
-static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac);
+#ifdef CONFIG_PPC_BOOK3S_64
+static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac);
+#endif
/* Some compatibility defines */
#ifdef CONFIG_PPC_BOOK3S_32
@@ -114,6 +118,8 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu)
if (kvmppc_is_split_real(vcpu))
kvmppc_fixup_split_real(vcpu);
+
+ kvmppc_restore_tm_pr(vcpu);
}
static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
@@ -133,6 +139,7 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu)
kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX);
kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
+ kvmppc_save_tm_pr(vcpu);
/* Enable AIL if supported */
if (cpu_has_feature(CPU_FTR_HVMODE) &&
@@ -147,25 +154,25 @@ void kvmppc_copy_to_svcpu(struct kvm_vcpu *vcpu)
{
struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
- svcpu->gpr[0] = vcpu->arch.gpr[0];
- svcpu->gpr[1] = vcpu->arch.gpr[1];
- svcpu->gpr[2] = vcpu->arch.gpr[2];
- svcpu->gpr[3] = vcpu->arch.gpr[3];
- svcpu->gpr[4] = vcpu->arch.gpr[4];
- svcpu->gpr[5] = vcpu->arch.gpr[5];
- svcpu->gpr[6] = vcpu->arch.gpr[6];
- svcpu->gpr[7] = vcpu->arch.gpr[7];
- svcpu->gpr[8] = vcpu->arch.gpr[8];
- svcpu->gpr[9] = vcpu->arch.gpr[9];
- svcpu->gpr[10] = vcpu->arch.gpr[10];
- svcpu->gpr[11] = vcpu->arch.gpr[11];
- svcpu->gpr[12] = vcpu->arch.gpr[12];
- svcpu->gpr[13] = vcpu->arch.gpr[13];
+ svcpu->gpr[0] = vcpu->arch.regs.gpr[0];
+ svcpu->gpr[1] = vcpu->arch.regs.gpr[1];
+ svcpu->gpr[2] = vcpu->arch.regs.gpr[2];
+ svcpu->gpr[3] = vcpu->arch.regs.gpr[3];
+ svcpu->gpr[4] = vcpu->arch.regs.gpr[4];
+ svcpu->gpr[5] = vcpu->arch.regs.gpr[5];
+ svcpu->gpr[6] = vcpu->arch.regs.gpr[6];
+ svcpu->gpr[7] = vcpu->arch.regs.gpr[7];
+ svcpu->gpr[8] = vcpu->arch.regs.gpr[8];
+ svcpu->gpr[9] = vcpu->arch.regs.gpr[9];
+ svcpu->gpr[10] = vcpu->arch.regs.gpr[10];
+ svcpu->gpr[11] = vcpu->arch.regs.gpr[11];
+ svcpu->gpr[12] = vcpu->arch.regs.gpr[12];
+ svcpu->gpr[13] = vcpu->arch.regs.gpr[13];
svcpu->cr = vcpu->arch.cr;
- svcpu->xer = vcpu->arch.xer;
- svcpu->ctr = vcpu->arch.ctr;
- svcpu->lr = vcpu->arch.lr;
- svcpu->pc = vcpu->arch.pc;
+ svcpu->xer = vcpu->arch.regs.xer;
+ svcpu->ctr = vcpu->arch.regs.ctr;
+ svcpu->lr = vcpu->arch.regs.link;
+ svcpu->pc = vcpu->arch.regs.nip;
#ifdef CONFIG_PPC_BOOK3S_64
svcpu->shadow_fscr = vcpu->arch.shadow_fscr;
#endif
@@ -182,10 +189,45 @@ void kvmppc_copy_to_svcpu(struct kvm_vcpu *vcpu)
svcpu_put(svcpu);
}
+static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
+{
+ ulong guest_msr = kvmppc_get_msr(vcpu);
+ ulong smsr = guest_msr;
+
+ /* Guest MSR values */
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_LE |
+ MSR_TM | MSR_TS_MASK;
+#else
+ smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_LE;
+#endif
+ /* Process MSR values */
+ smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
+ /* External providers the guest reserved */
+ smsr |= (guest_msr & vcpu->arch.guest_owned_ext);
+ /* 64-bit Process MSR values */
+#ifdef CONFIG_PPC_BOOK3S_64
+ smsr |= MSR_ISF | MSR_HV;
+#endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ /*
+ * in guest privileged state, we want to fail all TM transactions.
+ * So disable MSR TM bit so that all tbegin. will be able to be
+ * trapped into host.
+ */
+ if (!(guest_msr & MSR_PR))
+ smsr &= ~MSR_TM;
+#endif
+ vcpu->arch.shadow_msr = smsr;
+}
+
/* Copy data touched by real-mode code from shadow vcpu back to vcpu */
void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu)
{
struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu);
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ ulong old_msr;
+#endif
/*
* Maybe we were already preempted and synced the svcpu from
@@ -194,25 +236,25 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu)
if (!svcpu->in_use)
goto out;
- vcpu->arch.gpr[0] = svcpu->gpr[0];
- vcpu->arch.gpr[1] = svcpu->gpr[1];
- vcpu->arch.gpr[2] = svcpu->gpr[2];
- vcpu->arch.gpr[3] = svcpu->gpr[3];
- vcpu->arch.gpr[4] = svcpu->gpr[4];
- vcpu->arch.gpr[5] = svcpu->gpr[5];
- vcpu->arch.gpr[6] = svcpu->gpr[6];
- vcpu->arch.gpr[7] = svcpu->gpr[7];
- vcpu->arch.gpr[8] = svcpu->gpr[8];
- vcpu->arch.gpr[9] = svcpu->gpr[9];
- vcpu->arch.gpr[10] = svcpu->gpr[10];
- vcpu->arch.gpr[11] = svcpu->gpr[11];
- vcpu->arch.gpr[12] = svcpu->gpr[12];
- vcpu->arch.gpr[13] = svcpu->gpr[13];
+ vcpu->arch.regs.gpr[0] = svcpu->gpr[0];
+ vcpu->arch.regs.gpr[1] = svcpu->gpr[1];
+ vcpu->arch.regs.gpr[2] = svcpu->gpr[2];
+ vcpu->arch.regs.gpr[3] = svcpu->gpr[3];
+ vcpu->arch.regs.gpr[4] = svcpu->gpr[4];
+ vcpu->arch.regs.gpr[5] = svcpu->gpr[5];
+ vcpu->arch.regs.gpr[6] = svcpu->gpr[6];
+ vcpu->arch.regs.gpr[7] = svcpu->gpr[7];
+ vcpu->arch.regs.gpr[8] = svcpu->gpr[8];
+ vcpu->arch.regs.gpr[9] = svcpu->gpr[9];
+ vcpu->arch.regs.gpr[10] = svcpu->gpr[10];
+ vcpu->arch.regs.gpr[11] = svcpu->gpr[11];
+ vcpu->arch.regs.gpr[12] = svcpu->gpr[12];
+ vcpu->arch.regs.gpr[13] = svcpu->gpr[13];
vcpu->arch.cr = svcpu->cr;
- vcpu->arch.xer = svcpu->xer;
- vcpu->arch.ctr = svcpu->ctr;
- vcpu->arch.lr = svcpu->lr;
- vcpu->arch.pc = svcpu->pc;
+ vcpu->arch.regs.xer = svcpu->xer;
+ vcpu->arch.regs.ctr = svcpu->ctr;
+ vcpu->arch.regs.link = svcpu->lr;
+ vcpu->arch.regs.nip = svcpu->pc;
vcpu->arch.shadow_srr1 = svcpu->shadow_srr1;
vcpu->arch.fault_dar = svcpu->fault_dar;
vcpu->arch.fault_dsisr = svcpu->fault_dsisr;
@@ -228,12 +270,116 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu)
to_book3s(vcpu)->vtb += get_vtb() - vcpu->arch.entry_vtb;
if (cpu_has_feature(CPU_FTR_ARCH_207S))
vcpu->arch.ic += mfspr(SPRN_IC) - vcpu->arch.entry_ic;
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ /*
+ * Unlike other MSR bits, MSR[TS]bits can be changed at guest without
+ * notifying host:
+ * modified by unprivileged instructions like "tbegin"/"tend"/
+ * "tresume"/"tsuspend" in PR KVM guest.
+ *
+ * It is necessary to sync here to calculate a correct shadow_msr.
+ *
+ * privileged guest's tbegin will be failed at present. So we
+ * only take care of problem state guest.
+ */
+ old_msr = kvmppc_get_msr(vcpu);
+ if (unlikely((old_msr & MSR_PR) &&
+ (vcpu->arch.shadow_srr1 & (MSR_TS_MASK)) !=
+ (old_msr & (MSR_TS_MASK)))) {
+ old_msr &= ~(MSR_TS_MASK);
+ old_msr |= (vcpu->arch.shadow_srr1 & (MSR_TS_MASK));
+ kvmppc_set_msr_fast(vcpu, old_msr);
+ kvmppc_recalc_shadow_msr(vcpu);
+ }
+#endif
+
svcpu->in_use = false;
out:
svcpu_put(svcpu);
}
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu)
+{
+ tm_enable();
+ vcpu->arch.tfhar = mfspr(SPRN_TFHAR);
+ vcpu->arch.texasr = mfspr(SPRN_TEXASR);
+ vcpu->arch.tfiar = mfspr(SPRN_TFIAR);
+ tm_disable();
+}
+
+void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu)
+{
+ tm_enable();
+ mtspr(SPRN_TFHAR, vcpu->arch.tfhar);
+ mtspr(SPRN_TEXASR, vcpu->arch.texasr);
+ mtspr(SPRN_TFIAR, vcpu->arch.tfiar);
+ tm_disable();
+}
+
+/* loadup math bits which is enabled at kvmppc_get_msr() but not enabled at
+ * hardware.
+ */
+static void kvmppc_handle_lost_math_exts(struct kvm_vcpu *vcpu)
+{
+ ulong exit_nr;
+ ulong ext_diff = (kvmppc_get_msr(vcpu) & ~vcpu->arch.guest_owned_ext) &
+ (MSR_FP | MSR_VEC | MSR_VSX);
+
+ if (!ext_diff)
+ return;
+
+ if (ext_diff == MSR_FP)
+ exit_nr = BOOK3S_INTERRUPT_FP_UNAVAIL;
+ else if (ext_diff == MSR_VEC)
+ exit_nr = BOOK3S_INTERRUPT_ALTIVEC;
+ else
+ exit_nr = BOOK3S_INTERRUPT_VSX;
+
+ kvmppc_handle_ext(vcpu, exit_nr, ext_diff);
+}
+
+void kvmppc_save_tm_pr(struct kvm_vcpu *vcpu)
+{
+ if (!(MSR_TM_ACTIVE(kvmppc_get_msr(vcpu)))) {
+ kvmppc_save_tm_sprs(vcpu);
+ return;
+ }
+
+ kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
+ kvmppc_giveup_ext(vcpu, MSR_VSX);
+
+ preempt_disable();
+ _kvmppc_save_tm_pr(vcpu, mfmsr());
+ preempt_enable();
+}
+
+void kvmppc_restore_tm_pr(struct kvm_vcpu *vcpu)
+{
+ if (!MSR_TM_ACTIVE(kvmppc_get_msr(vcpu))) {
+ kvmppc_restore_tm_sprs(vcpu);
+ if (kvmppc_get_msr(vcpu) & MSR_TM) {
+ kvmppc_handle_lost_math_exts(vcpu);
+ if (vcpu->arch.fscr & FSCR_TAR)
+ kvmppc_handle_fac(vcpu, FSCR_TAR_LG);
+ }
+ return;
+ }
+
+ preempt_disable();
+ _kvmppc_restore_tm_pr(vcpu, kvmppc_get_msr(vcpu));
+ preempt_enable();
+
+ if (kvmppc_get_msr(vcpu) & MSR_TM) {
+ kvmppc_handle_lost_math_exts(vcpu);
+ if (vcpu->arch.fscr & FSCR_TAR)
+ kvmppc_handle_fac(vcpu, FSCR_TAR_LG);
+ }
+}
+#endif
+
static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu)
{
int r = 1; /* Indicate we want to get back into the guest */
@@ -306,32 +452,29 @@ static void kvm_set_spte_hva_pr(struct kvm *kvm, unsigned long hva, pte_t pte)
/*****************************************/
-static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu)
-{
- ulong guest_msr = kvmppc_get_msr(vcpu);
- ulong smsr = guest_msr;
-
- /* Guest MSR values */
- smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_LE;
- /* Process MSR values */
- smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE;
- /* External providers the guest reserved */
- smsr |= (guest_msr & vcpu->arch.guest_owned_ext);
- /* 64-bit Process MSR values */
-#ifdef CONFIG_PPC_BOOK3S_64
- smsr |= MSR_ISF | MSR_HV;
-#endif
- vcpu->arch.shadow_msr = smsr;
-}
-
static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
{
- ulong old_msr = kvmppc_get_msr(vcpu);
+ ulong old_msr;
+
+ /* For PAPR guest, make sure MSR reflects guest mode */
+ if (vcpu->arch.papr_enabled)
+ msr = (msr & ~MSR_HV) | MSR_ME;
#ifdef EXIT_DEBUG
printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr);
#endif
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ /* We should never target guest MSR to TS=10 && PR=0,
+ * since we always fail transaction for guest privilege
+ * state.
+ */
+ if (!(msr & MSR_PR) && MSR_TM_TRANSACTIONAL(msr))
+ kvmppc_emulate_tabort(vcpu,
+ TM_CAUSE_KVM_FAC_UNAV | TM_CAUSE_PERSISTENT);
+#endif
+
+ old_msr = kvmppc_get_msr(vcpu);
msr &= to_book3s(vcpu)->msr_mask;
kvmppc_set_msr_fast(vcpu, msr);
kvmppc_recalc_shadow_msr(vcpu);
@@ -387,6 +530,11 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr)
/* Preload FPU if it's enabled */
if (kvmppc_get_msr(vcpu) & MSR_FP)
kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP);
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ if (kvmppc_get_msr(vcpu) & MSR_TM)
+ kvmppc_handle_lost_math_exts(vcpu);
+#endif
}
void kvmppc_set_pvr_pr(struct kvm_vcpu *vcpu, u32 pvr)
@@ -584,24 +732,20 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu,
pte.may_execute = !data;
}
- if (page_found == -ENOENT) {
- /* Page not found in guest PTE entries */
- u64 ssrr1 = vcpu->arch.shadow_srr1;
- u64 msr = kvmppc_get_msr(vcpu);
- kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
- kvmppc_set_dsisr(vcpu, vcpu->arch.fault_dsisr);
- kvmppc_set_msr_fast(vcpu, msr | (ssrr1 & 0xf8000000ULL));
- kvmppc_book3s_queue_irqprio(vcpu, vec);
- } else if (page_found == -EPERM) {
- /* Storage protection */
- u32 dsisr = vcpu->arch.fault_dsisr;
- u64 ssrr1 = vcpu->arch.shadow_srr1;
- u64 msr = kvmppc_get_msr(vcpu);
- kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
- dsisr = (dsisr & ~DSISR_NOHPTE) | DSISR_PROTFAULT;
- kvmppc_set_dsisr(vcpu, dsisr);
- kvmppc_set_msr_fast(vcpu, msr | (ssrr1 & 0xf8000000ULL));
- kvmppc_book3s_queue_irqprio(vcpu, vec);
+ if (page_found == -ENOENT || page_found == -EPERM) {
+ /* Page not found in guest PTE entries, or protection fault */
+ u64 flags;
+
+ if (page_found == -EPERM)
+ flags = DSISR_PROTFAULT;
+ else
+ flags = DSISR_NOHPTE;
+ if (data) {
+ flags |= vcpu->arch.fault_dsisr & DSISR_ISSTORE;
+ kvmppc_core_queue_data_storage(vcpu, eaddr, flags);
+ } else {
+ kvmppc_core_queue_inst_storage(vcpu, flags);
+ }
} else if (page_found == -EINVAL) {
/* Page not found in guest SLB */
kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu));
@@ -683,7 +827,7 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr)
}
/* Give up facility (TAR / EBB / DSCR) */
-static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac)
+void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac)
{
#ifdef CONFIG_PPC_BOOK3S_64
if (!(vcpu->arch.shadow_fscr & (1ULL << fac))) {
@@ -802,7 +946,7 @@ static void kvmppc_handle_lost_ext(struct kvm_vcpu *vcpu)
#ifdef CONFIG_PPC_BOOK3S_64
-static void kvmppc_trigger_fac_interrupt(struct kvm_vcpu *vcpu, ulong fac)
+void kvmppc_trigger_fac_interrupt(struct kvm_vcpu *vcpu, ulong fac)
{
/* Inject the Interrupt Cause field and trigger a guest interrupt */
vcpu->arch.fscr &= ~(0xffULL << 56);
@@ -864,6 +1008,18 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac)
break;
}
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ /* Since we disabled MSR_TM at privilege state, the mfspr instruction
+ * for TM spr can trigger TM fac unavailable. In this case, the
+ * emulation is handled by kvmppc_emulate_fac(), which invokes
+ * kvmppc_emulate_mfspr() finally. But note the mfspr can include
+ * RT for NV registers. So it need to restore those NV reg to reflect
+ * the update.
+ */
+ if ((fac == FSCR_TM_LG) && !(kvmppc_get_msr(vcpu) & MSR_PR))
+ return RESUME_GUEST_NV;
+#endif
+
return RESUME_GUEST;
}
@@ -872,7 +1028,12 @@ void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr)
if ((vcpu->arch.fscr & FSCR_TAR) && !(fscr & FSCR_TAR)) {
/* TAR got dropped, drop it in shadow too */
kvmppc_giveup_fac(vcpu, FSCR_TAR_LG);
+ } else if (!(vcpu->arch.fscr & FSCR_TAR) && (fscr & FSCR_TAR)) {
+ vcpu->arch.fscr = fscr;
+ kvmppc_handle_fac(vcpu, FSCR_TAR_LG);
+ return;
}
+
vcpu->arch.fscr = fscr;
}
#endif
@@ -1017,10 +1178,8 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL);
r = RESUME_GUEST;
} else {
- u64 msr = kvmppc_get_msr(vcpu);
- msr |= shadow_srr1 & 0x58000000;
- kvmppc_set_msr_fast(vcpu, msr);
- kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+ kvmppc_core_queue_inst_storage(vcpu,
+ shadow_srr1 & 0x58000000);
r = RESUME_GUEST;
}
break;
@@ -1059,9 +1218,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr);
srcu_read_unlock(&vcpu->kvm->srcu, idx);
} else {
- kvmppc_set_dar(vcpu, dar);
- kvmppc_set_dsisr(vcpu, fault_dsisr);
- kvmppc_book3s_queue_irqprio(vcpu, exit_nr);
+ kvmppc_core_queue_data_storage(vcpu, dar, fault_dsisr);
r = RESUME_GUEST;
}
break;
@@ -1092,10 +1249,13 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
case BOOK3S_INTERRUPT_EXTERNAL:
case BOOK3S_INTERRUPT_EXTERNAL_LEVEL:
case BOOK3S_INTERRUPT_EXTERNAL_HV:
+ case BOOK3S_INTERRUPT_H_VIRT:
vcpu->stat.ext_intr_exits++;
r = RESUME_GUEST;
break;
+ case BOOK3S_INTERRUPT_HMI:
case BOOK3S_INTERRUPT_PERFMON:
+ case BOOK3S_INTERRUPT_SYSTEM_RESET:
r = RESUME_GUEST;
break;
case BOOK3S_INTERRUPT_PROGRAM:
@@ -1225,8 +1385,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu,
}
#ifdef CONFIG_PPC_BOOK3S_64
case BOOK3S_INTERRUPT_FAC_UNAVAIL:
- kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56);
- r = RESUME_GUEST;
+ r = kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56);
break;
#endif
case BOOK3S_INTERRUPT_MACHINE_CHECK:
@@ -1379,6 +1538,73 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
else
*val = get_reg_val(id, 0);
break;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ case KVM_REG_PPC_TFHAR:
+ *val = get_reg_val(id, vcpu->arch.tfhar);
+ break;
+ case KVM_REG_PPC_TFIAR:
+ *val = get_reg_val(id, vcpu->arch.tfiar);
+ break;
+ case KVM_REG_PPC_TEXASR:
+ *val = get_reg_val(id, vcpu->arch.texasr);
+ break;
+ case KVM_REG_PPC_TM_GPR0 ... KVM_REG_PPC_TM_GPR31:
+ *val = get_reg_val(id,
+ vcpu->arch.gpr_tm[id-KVM_REG_PPC_TM_GPR0]);
+ break;
+ case KVM_REG_PPC_TM_VSR0 ... KVM_REG_PPC_TM_VSR63:
+ {
+ int i, j;
+
+ i = id - KVM_REG_PPC_TM_VSR0;
+ if (i < 32)
+ for (j = 0; j < TS_FPRWIDTH; j++)
+ val->vsxval[j] = vcpu->arch.fp_tm.fpr[i][j];
+ else {
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
+ val->vval = vcpu->arch.vr_tm.vr[i-32];
+ else
+ r = -ENXIO;
+ }
+ break;
+ }
+ case KVM_REG_PPC_TM_CR:
+ *val = get_reg_val(id, vcpu->arch.cr_tm);
+ break;
+ case KVM_REG_PPC_TM_XER:
+ *val = get_reg_val(id, vcpu->arch.xer_tm);
+ break;
+ case KVM_REG_PPC_TM_LR:
+ *val = get_reg_val(id, vcpu->arch.lr_tm);
+ break;
+ case KVM_REG_PPC_TM_CTR:
+ *val = get_reg_val(id, vcpu->arch.ctr_tm);
+ break;
+ case KVM_REG_PPC_TM_FPSCR:
+ *val = get_reg_val(id, vcpu->arch.fp_tm.fpscr);
+ break;
+ case KVM_REG_PPC_TM_AMR:
+ *val = get_reg_val(id, vcpu->arch.amr_tm);
+ break;
+ case KVM_REG_PPC_TM_PPR:
+ *val = get_reg_val(id, vcpu->arch.ppr_tm);
+ break;
+ case KVM_REG_PPC_TM_VRSAVE:
+ *val = get_reg_val(id, vcpu->arch.vrsave_tm);
+ break;
+ case KVM_REG_PPC_TM_VSCR:
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
+ *val = get_reg_val(id, vcpu->arch.vr_tm.vscr.u[3]);
+ else
+ r = -ENXIO;
+ break;
+ case KVM_REG_PPC_TM_DSCR:
+ *val = get_reg_val(id, vcpu->arch.dscr_tm);
+ break;
+ case KVM_REG_PPC_TM_TAR:
+ *val = get_reg_val(id, vcpu->arch.tar_tm);
+ break;
+#endif
default:
r = -EINVAL;
break;
@@ -1412,6 +1638,72 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id,
case KVM_REG_PPC_LPCR_64:
kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val));
break;
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ case KVM_REG_PPC_TFHAR:
+ vcpu->arch.tfhar = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TFIAR:
+ vcpu->arch.tfiar = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TEXASR:
+ vcpu->arch.texasr = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_GPR0 ... KVM_REG_PPC_TM_GPR31:
+ vcpu->arch.gpr_tm[id - KVM_REG_PPC_TM_GPR0] =
+ set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_VSR0 ... KVM_REG_PPC_TM_VSR63:
+ {
+ int i, j;
+
+ i = id - KVM_REG_PPC_TM_VSR0;
+ if (i < 32)
+ for (j = 0; j < TS_FPRWIDTH; j++)
+ vcpu->arch.fp_tm.fpr[i][j] = val->vsxval[j];
+ else
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
+ vcpu->arch.vr_tm.vr[i-32] = val->vval;
+ else
+ r = -ENXIO;
+ break;
+ }
+ case KVM_REG_PPC_TM_CR:
+ vcpu->arch.cr_tm = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_XER:
+ vcpu->arch.xer_tm = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_LR:
+ vcpu->arch.lr_tm = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_CTR:
+ vcpu->arch.ctr_tm = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_FPSCR:
+ vcpu->arch.fp_tm.fpscr = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_AMR:
+ vcpu->arch.amr_tm = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_PPR:
+ vcpu->arch.ppr_tm = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_VRSAVE:
+ vcpu->arch.vrsave_tm = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_VSCR:
+ if (cpu_has_feature(CPU_FTR_ALTIVEC))
+ vcpu->arch.vr.vscr.u[3] = set_reg_val(id, *val);
+ else
+ r = -ENXIO;
+ break;
+ case KVM_REG_PPC_TM_DSCR:
+ vcpu->arch.dscr_tm = set_reg_val(id, *val);
+ break;
+ case KVM_REG_PPC_TM_TAR:
+ vcpu->arch.tar_tm = set_reg_val(id, *val);
+ break;
+#endif
default:
r = -EINVAL;
break;
@@ -1687,6 +1979,17 @@ static int kvm_vm_ioctl_get_smmu_info_pr(struct kvm *kvm,
return 0;
}
+
+static int kvm_configure_mmu_pr(struct kvm *kvm, struct kvm_ppc_mmuv3_cfg *cfg)
+{
+ if (!cpu_has_feature(CPU_FTR_ARCH_300))
+ return -ENODEV;
+ /* Require flags and process table base and size to all be zero. */
+ if (cfg->flags || cfg->process_table)
+ return -EINVAL;
+ return 0;
+}
+
#else
static int kvm_vm_ioctl_get_smmu_info_pr(struct kvm *kvm,
struct kvm_ppc_smmu_info *info)
@@ -1735,9 +2038,12 @@ static void kvmppc_core_destroy_vm_pr(struct kvm *kvm)
static int kvmppc_core_check_processor_compat_pr(void)
{
/*
- * Disable KVM for Power9 untill the required bits merged.
+ * PR KVM can work on POWER9 inside a guest partition
+ * running in HPT mode. It can't work if we are using
+ * radix translation (because radix provides no way for
+ * a process to have unique translations in quadrant 3).
*/
- if (cpu_has_feature(CPU_FTR_ARCH_300))
+ if (cpu_has_feature(CPU_FTR_ARCH_300) && radix_enabled())
return -EIO;
return 0;
}
@@ -1781,7 +2087,9 @@ static struct kvmppc_ops kvm_ops_pr = {
.arch_vm_ioctl = kvm_arch_vm_ioctl_pr,
#ifdef CONFIG_PPC_BOOK3S_64
.hcall_implemented = kvmppc_hcall_impl_pr,
+ .configure_mmu = kvm_configure_mmu_pr,
#endif
+ .giveup_ext = kvmppc_giveup_ext,
};
diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S
index 93a180c..98ccc7e 100644
--- a/arch/powerpc/kvm/book3s_segment.S
+++ b/arch/powerpc/kvm/book3s_segment.S
@@ -383,6 +383,19 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
*/
PPC_LL r6, HSTATE_HOST_MSR(r13)
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ /*
+ * We don't want to change MSR[TS] bits via rfi here.
+ * The actual TM handling logic will be in host with
+ * recovered DR/IR bits after HSTATE_VMHANDLER.
+ * And MSR_TM can be enabled in HOST_MSR so rfid may
+ * not suppress this change and can lead to exception.
+ * Manually set MSR to prevent TS state change here.
+ */
+ mfmsr r7
+ rldicl r7, r7, 64 - MSR_TS_S_LG, 62
+ rldimi r6, r7, MSR_TS_S_LG, 63 - MSR_TS_T_LG
+#endif
PPC_LL r8, HSTATE_VMHANDLER(r13)
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kvm/book3s_xive_template.c b/arch/powerpc/kvm/book3s_xive_template.c
index 99c3620..6e41ba7 100644
--- a/arch/powerpc/kvm/book3s_xive_template.c
+++ b/arch/powerpc/kvm/book3s_xive_template.c
@@ -334,7 +334,7 @@ X_STATIC unsigned long GLUE(X_PFX,h_xirr)(struct kvm_vcpu *vcpu)
*/
/* Return interrupt and old CPPR in GPR4 */
- vcpu->arch.gpr[4] = hirq | (old_cppr << 24);
+ vcpu->arch.regs.gpr[4] = hirq | (old_cppr << 24);
return H_SUCCESS;
}
@@ -369,7 +369,7 @@ X_STATIC unsigned long GLUE(X_PFX,h_ipoll)(struct kvm_vcpu *vcpu, unsigned long
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);
+ vcpu->arch.regs.gpr[4] = hirq | (xc->cppr << 24);
return H_SUCCESS;
}
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 876d4f2..a9ca016 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -77,8 +77,10 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu)
{
int i;
- printk("pc: %08lx msr: %08llx\n", vcpu->arch.pc, vcpu->arch.shared->msr);
- printk("lr: %08lx ctr: %08lx\n", vcpu->arch.lr, vcpu->arch.ctr);
+ printk("pc: %08lx msr: %08llx\n", vcpu->arch.regs.nip,
+ vcpu->arch.shared->msr);
+ printk("lr: %08lx ctr: %08lx\n", vcpu->arch.regs.link,
+ vcpu->arch.regs.ctr);
printk("srr0: %08llx srr1: %08llx\n", vcpu->arch.shared->srr0,
vcpu->arch.shared->srr1);
@@ -491,24 +493,25 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
if (allowed) {
switch (int_class) {
case INT_CLASS_NONCRIT:
- set_guest_srr(vcpu, vcpu->arch.pc,
+ set_guest_srr(vcpu, vcpu->arch.regs.nip,
vcpu->arch.shared->msr);
break;
case INT_CLASS_CRIT:
- set_guest_csrr(vcpu, vcpu->arch.pc,
+ set_guest_csrr(vcpu, vcpu->arch.regs.nip,
vcpu->arch.shared->msr);
break;
case INT_CLASS_DBG:
- set_guest_dsrr(vcpu, vcpu->arch.pc,
+ set_guest_dsrr(vcpu, vcpu->arch.regs.nip,
vcpu->arch.shared->msr);
break;
case INT_CLASS_MC:
- set_guest_mcsrr(vcpu, vcpu->arch.pc,
+ set_guest_mcsrr(vcpu, vcpu->arch.regs.nip,
vcpu->arch.shared->msr);
break;
}
- vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority];
+ vcpu->arch.regs.nip = vcpu->arch.ivpr |
+ vcpu->arch.ivor[priority];
if (update_esr == true)
kvmppc_set_esr(vcpu, vcpu->arch.queued_esr);
if (update_dear == true)
@@ -826,7 +829,7 @@ static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu)
case EMULATE_FAIL:
printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n",
- __func__, vcpu->arch.pc, vcpu->arch.last_inst);
+ __func__, vcpu->arch.regs.nip, vcpu->arch.last_inst);
/* For debugging, encode the failing instruction and
* report it to userspace. */
run->hw.hardware_exit_reason = ~0ULL << 32;
@@ -875,7 +878,7 @@ static int kvmppc_handle_debug(struct kvm_run *run, struct kvm_vcpu *vcpu)
*/
vcpu->arch.dbsr = 0;
run->debug.arch.status = 0;
- run->debug.arch.address = vcpu->arch.pc;
+ run->debug.arch.address = vcpu->arch.regs.nip;
if (dbsr & (DBSR_IAC1 | DBSR_IAC2 | DBSR_IAC3 | DBSR_IAC4)) {
run->debug.arch.status |= KVMPPC_DEBUG_BREAKPOINT;
@@ -971,7 +974,7 @@ static int kvmppc_resume_inst_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
case EMULATE_FAIL:
pr_debug("%s: load instruction from guest address %lx failed\n",
- __func__, vcpu->arch.pc);
+ __func__, vcpu->arch.regs.nip);
/* For debugging, encode the failing instruction and
* report it to userspace. */
run->hw.hardware_exit_reason = ~0ULL << 32;
@@ -1169,7 +1172,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
case BOOKE_INTERRUPT_SPE_FP_DATA:
case BOOKE_INTERRUPT_SPE_FP_ROUND:
printk(KERN_CRIT "%s: unexpected SPE interrupt %u at %08lx\n",
- __func__, exit_nr, vcpu->arch.pc);
+ __func__, exit_nr, vcpu->arch.regs.nip);
run->hw.hardware_exit_reason = exit_nr;
r = RESUME_HOST;
break;
@@ -1299,7 +1302,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
}
case BOOKE_INTERRUPT_ITLB_MISS: {
- unsigned long eaddr = vcpu->arch.pc;
+ unsigned long eaddr = vcpu->arch.regs.nip;
gpa_t gpaddr;
gfn_t gfn;
int gtlb_index;
@@ -1391,7 +1394,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
int i;
int r;
- vcpu->arch.pc = 0;
+ vcpu->arch.regs.nip = 0;
vcpu->arch.shared->pir = vcpu->vcpu_id;
kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */
kvmppc_set_msr(vcpu, 0);
@@ -1440,10 +1443,10 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
vcpu_load(vcpu);
- regs->pc = vcpu->arch.pc;
+ regs->pc = vcpu->arch.regs.nip;
regs->cr = kvmppc_get_cr(vcpu);
- regs->ctr = vcpu->arch.ctr;
- regs->lr = vcpu->arch.lr;
+ regs->ctr = vcpu->arch.regs.ctr;
+ regs->lr = vcpu->arch.regs.link;
regs->xer = kvmppc_get_xer(vcpu);
regs->msr = vcpu->arch.shared->msr;
regs->srr0 = kvmppc_get_srr0(vcpu);
@@ -1471,10 +1474,10 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
vcpu_load(vcpu);
- vcpu->arch.pc = regs->pc;
+ vcpu->arch.regs.nip = regs->pc;
kvmppc_set_cr(vcpu, regs->cr);
- vcpu->arch.ctr = regs->ctr;
- vcpu->arch.lr = regs->lr;
+ vcpu->arch.regs.ctr = regs->ctr;
+ vcpu->arch.regs.link = regs->lr;
kvmppc_set_xer(vcpu, regs->xer);
kvmppc_set_msr(vcpu, regs->msr);
kvmppc_set_srr0(vcpu, regs->srr0);
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c
index a82f645..d23e582 100644
--- a/arch/powerpc/kvm/booke_emulate.c
+++ b/arch/powerpc/kvm/booke_emulate.c
@@ -34,19 +34,19 @@
static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu)
{
- vcpu->arch.pc = vcpu->arch.shared->srr0;
+ vcpu->arch.regs.nip = vcpu->arch.shared->srr0;
kvmppc_set_msr(vcpu, vcpu->arch.shared->srr1);
}
static void kvmppc_emul_rfdi(struct kvm_vcpu *vcpu)
{
- vcpu->arch.pc = vcpu->arch.dsrr0;
+ vcpu->arch.regs.nip = vcpu->arch.dsrr0;
kvmppc_set_msr(vcpu, vcpu->arch.dsrr1);
}
static void kvmppc_emul_rfci(struct kvm_vcpu *vcpu)
{
- vcpu->arch.pc = vcpu->arch.csrr0;
+ vcpu->arch.regs.nip = vcpu->arch.csrr0;
kvmppc_set_msr(vcpu, vcpu->arch.csrr1);
}
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c
index 990db69..3f8189e 100644
--- a/arch/powerpc/kvm/e500_emulate.c
+++ b/arch/powerpc/kvm/e500_emulate.c
@@ -53,7 +53,7 @@ static int dbell2prio(ulong param)
static int kvmppc_e500_emul_msgclr(struct kvm_vcpu *vcpu, int rb)
{
- ulong param = vcpu->arch.gpr[rb];
+ ulong param = vcpu->arch.regs.gpr[rb];
int prio = dbell2prio(param);
if (prio < 0)
@@ -65,7 +65,7 @@ static int kvmppc_e500_emul_msgclr(struct kvm_vcpu *vcpu, int rb)
static int kvmppc_e500_emul_msgsnd(struct kvm_vcpu *vcpu, int rb)
{
- ulong param = vcpu->arch.gpr[rb];
+ ulong param = vcpu->arch.regs.gpr[rb];
int prio = dbell2prio(rb);
int pir = param & PPC_DBELL_PIR_MASK;
int i;
@@ -94,7 +94,7 @@ static int kvmppc_e500_emul_ehpriv(struct kvm_run *run, struct kvm_vcpu *vcpu,
switch (get_oc(inst)) {
case EHPRIV_OC_DEBUG:
run->exit_reason = KVM_EXIT_DEBUG;
- run->debug.arch.address = vcpu->arch.pc;
+ run->debug.arch.address = vcpu->arch.regs.nip;
run->debug.arch.status = 0;
kvmppc_account_exit(vcpu, DEBUG_EXITS);
emulated = EMULATE_EXIT_USER;
diff --git a/arch/powerpc/kvm/e500_mmu.c b/arch/powerpc/kvm/e500_mmu.c
index ddbf8f0..24296f4 100644
--- a/arch/powerpc/kvm/e500_mmu.c
+++ b/arch/powerpc/kvm/e500_mmu.c
@@ -513,7 +513,7 @@ void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu)
{
unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS);
- kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.pc, as);
+ kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.regs.nip, as);
}
void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu)
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c
index c878b4f..8f2985e 100644
--- a/arch/powerpc/kvm/e500_mmu_host.c
+++ b/arch/powerpc/kvm/e500_mmu_host.c
@@ -625,8 +625,8 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
}
#ifdef CONFIG_KVM_BOOKE_HV
-int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
- u32 *instr)
+int kvmppc_load_last_inst(struct kvm_vcpu *vcpu,
+ enum instruction_fetch_type type, u32 *instr)
{
gva_t geaddr;
hpa_t addr;
@@ -715,8 +715,8 @@ int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
return EMULATE_DONE;
}
#else
-int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type,
- u32 *instr)
+int kvmppc_load_last_inst(struct kvm_vcpu *vcpu,
+ enum instruction_fetch_type type, u32 *instr)
{
return EMULATE_AGAIN;
}
diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c
index a382e15..afde788 100644
--- a/arch/powerpc/kvm/emulate_loadstore.c
+++ b/arch/powerpc/kvm/emulate_loadstore.c
@@ -31,6 +31,7 @@
#include <asm/kvm_ppc.h>
#include <asm/disassemble.h>
#include <asm/ppc-opcode.h>
+#include <asm/sstep.h>
#include "timing.h"
#include "trace.h"
@@ -84,8 +85,9 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
struct kvm_run *run = vcpu->run;
u32 inst;
int ra, rs, rt;
- enum emulation_result emulated;
+ enum emulation_result emulated = EMULATE_FAIL;
int advance = 1;
+ struct instruction_op op;
/* this default type might be overwritten by subcategories */
kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
@@ -107,580 +109,276 @@ int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu)
vcpu->arch.mmio_vsx_tx_sx_enabled = get_tx_or_sx(inst);
vcpu->arch.mmio_vsx_copy_nums = 0;
vcpu->arch.mmio_vsx_offset = 0;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_NONE;
+ vcpu->arch.mmio_copy_type = KVMPPC_VSX_COPY_NONE;
vcpu->arch.mmio_sp64_extend = 0;
vcpu->arch.mmio_sign_extend = 0;
vcpu->arch.mmio_vmx_copy_nums = 0;
+ vcpu->arch.mmio_vmx_offset = 0;
+ vcpu->arch.mmio_host_swabbed = 0;
- switch (get_op(inst)) {
- case 31:
- switch (get_xop(inst)) {
- case OP_31_XOP_LWZX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
- break;
-
- case OP_31_XOP_LWZUX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
+ emulated = EMULATE_FAIL;
+ vcpu->arch.regs.msr = vcpu->arch.shared->msr;
+ vcpu->arch.regs.ccr = vcpu->arch.cr;
+ if (analyse_instr(&op, &vcpu->arch.regs, inst) == 0) {
+ int type = op.type & INSTR_TYPE_MASK;
+ int size = GETSIZE(op.type);
- case OP_31_XOP_LBZX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
- break;
-
- case OP_31_XOP_LBZUX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
+ switch (type) {
+ case LOAD: {
+ int instr_byte_swap = op.type & BYTEREV;
- case OP_31_XOP_STDX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 8, 1);
- break;
+ if (op.type & SIGNEXT)
+ emulated = kvmppc_handle_loads(run, vcpu,
+ op.reg, size, !instr_byte_swap);
+ else
+ emulated = kvmppc_handle_load(run, vcpu,
+ op.reg, size, !instr_byte_swap);
- case OP_31_XOP_STDUX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 8, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
+ if ((op.type & UPDATE) && (emulated != EMULATE_FAIL))
+ kvmppc_set_gpr(vcpu, op.update_reg, op.ea);
- case OP_31_XOP_STWX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 4, 1);
- break;
-
- case OP_31_XOP_STWUX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_31_XOP_STBX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 1, 1);
- break;
-
- case OP_31_XOP_STBUX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 1, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_31_XOP_LHAX:
- emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
- break;
-
- case OP_31_XOP_LHAUX:
- emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_31_XOP_LHZX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
- break;
-
- case OP_31_XOP_LHZUX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_31_XOP_STHX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 2, 1);
- break;
-
- case OP_31_XOP_STHUX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_31_XOP_DCBST:
- case OP_31_XOP_DCBF:
- case OP_31_XOP_DCBI:
- /* Do nothing. The guest is performing dcbi because
- * hardware DMA is not snooped by the dcache, but
- * emulated DMA either goes through the dcache as
- * normal writes, or the host kernel has handled dcache
- * coherence. */
- break;
-
- case OP_31_XOP_LWBRX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0);
- break;
-
- case OP_31_XOP_STWBRX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 4, 0);
break;
-
- case OP_31_XOP_LHBRX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0);
- break;
-
- case OP_31_XOP_STHBRX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 2, 0);
- break;
-
- case OP_31_XOP_LDBRX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 8, 0);
- break;
-
- case OP_31_XOP_STDBRX:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 8, 0);
- break;
-
- case OP_31_XOP_LDX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);
- break;
-
- case OP_31_XOP_LDUX:
- emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_31_XOP_LWAX:
- emulated = kvmppc_handle_loads(run, vcpu, rt, 4, 1);
- break;
-
- case OP_31_XOP_LWAUX:
- emulated = kvmppc_handle_loads(run, vcpu, rt, 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
+ }
#ifdef CONFIG_PPC_FPU
- case OP_31_XOP_LFSX:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_sp64_extend = 1;
- emulated = kvmppc_handle_load(run, vcpu,
- KVM_MMIO_REG_FPR|rt, 4, 1);
- break;
-
- case OP_31_XOP_LFSUX:
+ case LOAD_FP:
if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
- vcpu->arch.mmio_sp64_extend = 1;
- emulated = kvmppc_handle_load(run, vcpu,
- KVM_MMIO_REG_FPR|rt, 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
- case OP_31_XOP_LFDX:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- emulated = kvmppc_handle_load(run, vcpu,
- KVM_MMIO_REG_FPR|rt, 8, 1);
- break;
+ if (op.type & FPCONV)
+ vcpu->arch.mmio_sp64_extend = 1;
- case OP_31_XOP_LFDUX:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- emulated = kvmppc_handle_load(run, vcpu,
- KVM_MMIO_REG_FPR|rt, 8, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_31_XOP_LFIWAX:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- emulated = kvmppc_handle_loads(run, vcpu,
- KVM_MMIO_REG_FPR|rt, 4, 1);
- break;
+ if (op.type & SIGNEXT)
+ emulated = kvmppc_handle_loads(run, vcpu,
+ KVM_MMIO_REG_FPR|op.reg, size, 1);
+ else
+ emulated = kvmppc_handle_load(run, vcpu,
+ KVM_MMIO_REG_FPR|op.reg, size, 1);
- case OP_31_XOP_LFIWZX:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- emulated = kvmppc_handle_load(run, vcpu,
- KVM_MMIO_REG_FPR|rt, 4, 1);
- break;
+ if ((op.type & UPDATE) && (emulated != EMULATE_FAIL))
+ kvmppc_set_gpr(vcpu, op.update_reg, op.ea);
- case OP_31_XOP_STFSX:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_sp64_extend = 1;
- emulated = kvmppc_handle_store(run, vcpu,
- VCPU_FPR(vcpu, rs), 4, 1);
break;
-
- case OP_31_XOP_STFSUX:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_sp64_extend = 1;
- emulated = kvmppc_handle_store(run, vcpu,
- VCPU_FPR(vcpu, rs), 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_31_XOP_STFDX:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- emulated = kvmppc_handle_store(run, vcpu,
- VCPU_FPR(vcpu, rs), 8, 1);
- break;
-
- case OP_31_XOP_STFDUX:
- if (kvmppc_check_fp_disabled(vcpu))
+#endif
+#ifdef CONFIG_ALTIVEC
+ case LOAD_VMX:
+ if (kvmppc_check_altivec_disabled(vcpu))
return EMULATE_DONE;
- emulated = kvmppc_handle_store(run, vcpu,
- VCPU_FPR(vcpu, rs), 8, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
- case OP_31_XOP_STFIWX:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- emulated = kvmppc_handle_store(run, vcpu,
- VCPU_FPR(vcpu, rs), 4, 1);
+ /* Hardware enforces alignment of VMX accesses */
+ vcpu->arch.vaddr_accessed &= ~((unsigned long)size - 1);
+ vcpu->arch.paddr_accessed &= ~((unsigned long)size - 1);
+
+ if (size == 16) { /* lvx */
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VMX_COPY_DWORD;
+ } else if (size == 4) { /* lvewx */
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VMX_COPY_WORD;
+ } else if (size == 2) { /* lvehx */
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VMX_COPY_HWORD;
+ } else if (size == 1) { /* lvebx */
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VMX_COPY_BYTE;
+ } else
+ break;
+
+ vcpu->arch.mmio_vmx_offset =
+ (vcpu->arch.vaddr_accessed & 0xf)/size;
+
+ if (size == 16) {
+ vcpu->arch.mmio_vmx_copy_nums = 2;
+ emulated = kvmppc_handle_vmx_load(run,
+ vcpu, KVM_MMIO_REG_VMX|op.reg,
+ 8, 1);
+ } else {
+ vcpu->arch.mmio_vmx_copy_nums = 1;
+ emulated = kvmppc_handle_vmx_load(run, vcpu,
+ KVM_MMIO_REG_VMX|op.reg,
+ size, 1);
+ }
break;
#endif
-
#ifdef CONFIG_VSX
- case OP_31_XOP_LXSDX:
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 1;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;
- emulated = kvmppc_handle_vsx_load(run, vcpu,
- KVM_MMIO_REG_VSX|rt, 8, 1, 0);
- break;
-
- case OP_31_XOP_LXSSPX:
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 1;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;
- vcpu->arch.mmio_sp64_extend = 1;
- emulated = kvmppc_handle_vsx_load(run, vcpu,
- KVM_MMIO_REG_VSX|rt, 4, 1, 0);
- break;
+ case LOAD_VSX: {
+ int io_size_each;
+
+ if (op.vsx_flags & VSX_CHECK_VEC) {
+ if (kvmppc_check_altivec_disabled(vcpu))
+ return EMULATE_DONE;
+ } else {
+ if (kvmppc_check_vsx_disabled(vcpu))
+ return EMULATE_DONE;
+ }
+
+ if (op.vsx_flags & VSX_FPCONV)
+ vcpu->arch.mmio_sp64_extend = 1;
+
+ if (op.element_size == 8) {
+ if (op.vsx_flags & VSX_SPLAT)
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VSX_COPY_DWORD_LOAD_DUMP;
+ else
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VSX_COPY_DWORD;
+ } else if (op.element_size == 4) {
+ if (op.vsx_flags & VSX_SPLAT)
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VSX_COPY_WORD_LOAD_DUMP;
+ else
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VSX_COPY_WORD;
+ } else
+ break;
+
+ if (size < op.element_size) {
+ /* precision convert case: lxsspx, etc */
+ vcpu->arch.mmio_vsx_copy_nums = 1;
+ io_size_each = size;
+ } else { /* lxvw4x, lxvd2x, etc */
+ vcpu->arch.mmio_vsx_copy_nums =
+ size/op.element_size;
+ io_size_each = op.element_size;
+ }
- case OP_31_XOP_LXSIWAX:
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 1;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;
emulated = kvmppc_handle_vsx_load(run, vcpu,
- KVM_MMIO_REG_VSX|rt, 4, 1, 1);
- break;
-
- case OP_31_XOP_LXSIWZX:
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 1;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;
- emulated = kvmppc_handle_vsx_load(run, vcpu,
- KVM_MMIO_REG_VSX|rt, 4, 1, 0);
+ KVM_MMIO_REG_VSX | (op.reg & 0x1f),
+ io_size_each, 1, op.type & SIGNEXT);
break;
+ }
+#endif
+ case STORE:
+ /* if need byte reverse, op.val has been reversed by
+ * analyse_instr().
+ */
+ emulated = kvmppc_handle_store(run, vcpu, op.val,
+ size, 1);
- case OP_31_XOP_LXVD2X:
- /*
- * In this case, the official load/store process is like this:
- * Step1, exit from vm by page fault isr, then kvm save vsr.
- * Please see guest_exit_cont->store_fp_state->SAVE_32VSRS
- * as reference.
- *
- * Step2, copy data between memory and VCPU
- * Notice: for LXVD2X/STXVD2X/LXVW4X/STXVW4X, we use
- * 2copies*8bytes or 4copies*4bytes
- * to simulate one copy of 16bytes.
- * Also there is an endian issue here, we should notice the
- * layout of memory.
- * Please see MARCO of LXVD2X_ROT/STXVD2X_ROT as more reference.
- * If host is little-endian, kvm will call XXSWAPD for
- * LXVD2X_ROT/STXVD2X_ROT.
- * So, if host is little-endian,
- * the postion of memeory should be swapped.
- *
- * Step3, return to guest, kvm reset register.
- * Please see kvmppc_hv_entry->load_fp_state->REST_32VSRS
- * as reference.
- */
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 2;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;
- emulated = kvmppc_handle_vsx_load(run, vcpu,
- KVM_MMIO_REG_VSX|rt, 8, 1, 0);
- break;
+ if ((op.type & UPDATE) && (emulated != EMULATE_FAIL))
+ kvmppc_set_gpr(vcpu, op.update_reg, op.ea);
- case OP_31_XOP_LXVW4X:
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 4;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_WORD;
- emulated = kvmppc_handle_vsx_load(run, vcpu,
- KVM_MMIO_REG_VSX|rt, 4, 1, 0);
break;
-
- case OP_31_XOP_LXVDSX:
- if (kvmppc_check_vsx_disabled(vcpu))
+#ifdef CONFIG_PPC_FPU
+ case STORE_FP:
+ if (kvmppc_check_fp_disabled(vcpu))
return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 1;
- vcpu->arch.mmio_vsx_copy_type =
- KVMPPC_VSX_COPY_DWORD_LOAD_DUMP;
- emulated = kvmppc_handle_vsx_load(run, vcpu,
- KVM_MMIO_REG_VSX|rt, 8, 1, 0);
- break;
- case OP_31_XOP_STXSDX:
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 1;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;
- emulated = kvmppc_handle_vsx_store(run, vcpu,
- rs, 8, 1);
- break;
+ /* The FP registers need to be flushed so that
+ * kvmppc_handle_store() can read actual FP vals
+ * from vcpu->arch.
+ */
+ if (vcpu->kvm->arch.kvm_ops->giveup_ext)
+ vcpu->kvm->arch.kvm_ops->giveup_ext(vcpu,
+ MSR_FP);
- case OP_31_XOP_STXSSPX:
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 1;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;
- vcpu->arch.mmio_sp64_extend = 1;
- emulated = kvmppc_handle_vsx_store(run, vcpu,
- rs, 4, 1);
- break;
+ if (op.type & FPCONV)
+ vcpu->arch.mmio_sp64_extend = 1;
- case OP_31_XOP_STXSIWX:
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_offset = 1;
- vcpu->arch.mmio_vsx_copy_nums = 1;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_WORD;
- emulated = kvmppc_handle_vsx_store(run, vcpu,
- rs, 4, 1);
- break;
+ emulated = kvmppc_handle_store(run, vcpu,
+ VCPU_FPR(vcpu, op.reg), size, 1);
- case OP_31_XOP_STXVD2X:
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 2;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_DWORD;
- emulated = kvmppc_handle_vsx_store(run, vcpu,
- rs, 8, 1);
- break;
+ if ((op.type & UPDATE) && (emulated != EMULATE_FAIL))
+ kvmppc_set_gpr(vcpu, op.update_reg, op.ea);
- case OP_31_XOP_STXVW4X:
- if (kvmppc_check_vsx_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_vsx_copy_nums = 4;
- vcpu->arch.mmio_vsx_copy_type = KVMPPC_VSX_COPY_WORD;
- emulated = kvmppc_handle_vsx_store(run, vcpu,
- rs, 4, 1);
break;
-#endif /* CONFIG_VSX */
-
+#endif
#ifdef CONFIG_ALTIVEC
- case OP_31_XOP_LVX:
+ case STORE_VMX:
if (kvmppc_check_altivec_disabled(vcpu))
return EMULATE_DONE;
- vcpu->arch.vaddr_accessed &= ~0xFULL;
- vcpu->arch.paddr_accessed &= ~0xFULL;
- vcpu->arch.mmio_vmx_copy_nums = 2;
- emulated = kvmppc_handle_load128_by2x64(run, vcpu,
- KVM_MMIO_REG_VMX|rt, 1);
- break;
- case OP_31_XOP_STVX:
- if (kvmppc_check_altivec_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.vaddr_accessed &= ~0xFULL;
- vcpu->arch.paddr_accessed &= ~0xFULL;
- vcpu->arch.mmio_vmx_copy_nums = 2;
- emulated = kvmppc_handle_store128_by2x64(run, vcpu,
- rs, 1);
- break;
-#endif /* CONFIG_ALTIVEC */
+ /* Hardware enforces alignment of VMX accesses. */
+ vcpu->arch.vaddr_accessed &= ~((unsigned long)size - 1);
+ vcpu->arch.paddr_accessed &= ~((unsigned long)size - 1);
+
+ if (vcpu->kvm->arch.kvm_ops->giveup_ext)
+ vcpu->kvm->arch.kvm_ops->giveup_ext(vcpu,
+ MSR_VEC);
+ if (size == 16) { /* stvx */
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VMX_COPY_DWORD;
+ } else if (size == 4) { /* stvewx */
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VMX_COPY_WORD;
+ } else if (size == 2) { /* stvehx */
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VMX_COPY_HWORD;
+ } else if (size == 1) { /* stvebx */
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VMX_COPY_BYTE;
+ } else
+ break;
+
+ vcpu->arch.mmio_vmx_offset =
+ (vcpu->arch.vaddr_accessed & 0xf)/size;
+
+ if (size == 16) {
+ vcpu->arch.mmio_vmx_copy_nums = 2;
+ emulated = kvmppc_handle_vmx_store(run,
+ vcpu, op.reg, 8, 1);
+ } else {
+ vcpu->arch.mmio_vmx_copy_nums = 1;
+ emulated = kvmppc_handle_vmx_store(run,
+ vcpu, op.reg, size, 1);
+ }
- default:
- emulated = EMULATE_FAIL;
break;
- }
- break;
-
- case OP_LWZ:
- emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
- break;
-
-#ifdef CONFIG_PPC_FPU
- case OP_STFS:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_sp64_extend = 1;
- emulated = kvmppc_handle_store(run, vcpu,
- VCPU_FPR(vcpu, rs),
- 4, 1);
- break;
-
- case OP_STFSU:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_sp64_extend = 1;
- emulated = kvmppc_handle_store(run, vcpu,
- VCPU_FPR(vcpu, rs),
- 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_STFD:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- emulated = kvmppc_handle_store(run, vcpu,
- VCPU_FPR(vcpu, rs),
- 8, 1);
- break;
-
- case OP_STFDU:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- emulated = kvmppc_handle_store(run, vcpu,
- VCPU_FPR(vcpu, rs),
- 8, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
#endif
+#ifdef CONFIG_VSX
+ case STORE_VSX: {
+ int io_size_each;
+
+ if (op.vsx_flags & VSX_CHECK_VEC) {
+ if (kvmppc_check_altivec_disabled(vcpu))
+ return EMULATE_DONE;
+ } else {
+ if (kvmppc_check_vsx_disabled(vcpu))
+ return EMULATE_DONE;
+ }
+
+ if (vcpu->kvm->arch.kvm_ops->giveup_ext)
+ vcpu->kvm->arch.kvm_ops->giveup_ext(vcpu,
+ MSR_VSX);
+
+ if (op.vsx_flags & VSX_FPCONV)
+ vcpu->arch.mmio_sp64_extend = 1;
+
+ if (op.element_size == 8)
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VSX_COPY_DWORD;
+ else if (op.element_size == 4)
+ vcpu->arch.mmio_copy_type =
+ KVMPPC_VSX_COPY_WORD;
+ else
+ break;
+
+ if (size < op.element_size) {
+ /* precise conversion case, like stxsspx */
+ vcpu->arch.mmio_vsx_copy_nums = 1;
+ io_size_each = size;
+ } else { /* stxvw4x, stxvd2x, etc */
+ vcpu->arch.mmio_vsx_copy_nums =
+ size/op.element_size;
+ io_size_each = op.element_size;
+ }
- case OP_LD:
- rt = get_rt(inst);
- switch (inst & 3) {
- case 0: /* ld */
- emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);
- break;
- case 1: /* ldu */
- emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
- case 2: /* lwa */
- emulated = kvmppc_handle_loads(run, vcpu, rt, 4, 1);
+ emulated = kvmppc_handle_vsx_store(run, vcpu,
+ op.reg & 0x1f, io_size_each, 1);
break;
- default:
- emulated = EMULATE_FAIL;
}
- break;
-
- case OP_LWZU:
- emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_LBZ:
- emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
- break;
-
- case OP_LBZU:
- emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_STW:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs),
- 4, 1);
- break;
-
- case OP_STD:
- rs = get_rs(inst);
- switch (inst & 3) {
- case 0: /* std */
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 8, 1);
- break;
- case 1: /* stdu */
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 8, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
+#endif
+ case CACHEOP:
+ /* Do nothing. The guest is performing dcbi because
+ * hardware DMA is not snooped by the dcache, but
+ * emulated DMA either goes through the dcache as
+ * normal writes, or the host kernel has handled dcache
+ * coherence.
+ */
+ emulated = EMULATE_DONE;
break;
default:
- emulated = EMULATE_FAIL;
+ break;
}
- break;
-
- case OP_STWU:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_STB:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 1, 1);
- break;
-
- case OP_STBU:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 1, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_LHZ:
- emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
- break;
-
- case OP_LHZU:
- emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_LHA:
- emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
- break;
-
- case OP_LHAU:
- emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_STH:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 2, 1);
- break;
-
- case OP_STHU:
- emulated = kvmppc_handle_store(run, vcpu,
- kvmppc_get_gpr(vcpu, rs), 2, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
-#ifdef CONFIG_PPC_FPU
- case OP_LFS:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_sp64_extend = 1;
- emulated = kvmppc_handle_load(run, vcpu,
- KVM_MMIO_REG_FPR|rt, 4, 1);
- break;
-
- case OP_LFSU:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- vcpu->arch.mmio_sp64_extend = 1;
- emulated = kvmppc_handle_load(run, vcpu,
- KVM_MMIO_REG_FPR|rt, 4, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-
- case OP_LFD:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- emulated = kvmppc_handle_load(run, vcpu,
- KVM_MMIO_REG_FPR|rt, 8, 1);
- break;
-
- case OP_LFDU:
- if (kvmppc_check_fp_disabled(vcpu))
- return EMULATE_DONE;
- emulated = kvmppc_handle_load(run, vcpu,
- KVM_MMIO_REG_FPR|rt, 8, 1);
- kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
- break;
-#endif
-
- default:
- emulated = EMULATE_FAIL;
- break;
}
if (emulated == EMULATE_FAIL) {
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 4e38764..0e8c20c5 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -648,9 +648,8 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
#endif
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
case KVM_CAP_PPC_HTM:
- r = hv_enabled &&
- (!!(cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_HTM) ||
- cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST));
+ r = !!(cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_HTM) ||
+ (hv_enabled && cpu_has_feature(CPU_FTR_P9_TM_HV_ASSIST));
break;
#endif
default:
@@ -907,6 +906,26 @@ static inline void kvmppc_set_vsr_dword_dump(struct kvm_vcpu *vcpu,
}
}
+static inline void kvmppc_set_vsr_word_dump(struct kvm_vcpu *vcpu,
+ u32 gpr)
+{
+ union kvmppc_one_reg val;
+ int index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;
+
+ if (vcpu->arch.mmio_vsx_tx_sx_enabled) {
+ val.vsx32val[0] = gpr;
+ val.vsx32val[1] = gpr;
+ val.vsx32val[2] = gpr;
+ val.vsx32val[3] = gpr;
+ VCPU_VSX_VR(vcpu, index) = val.vval;
+ } else {
+ val.vsx32val[0] = gpr;
+ val.vsx32val[1] = gpr;
+ VCPU_VSX_FPR(vcpu, index, 0) = val.vsxval[0];
+ VCPU_VSX_FPR(vcpu, index, 1) = val.vsxval[0];
+ }
+}
+
static inline void kvmppc_set_vsr_word(struct kvm_vcpu *vcpu,
u32 gpr32)
{
@@ -933,30 +952,110 @@ static inline void kvmppc_set_vsr_word(struct kvm_vcpu *vcpu,
#endif /* CONFIG_VSX */
#ifdef CONFIG_ALTIVEC
+static inline int kvmppc_get_vmx_offset_generic(struct kvm_vcpu *vcpu,
+ int index, int element_size)
+{
+ int offset;
+ int elts = sizeof(vector128)/element_size;
+
+ if ((index < 0) || (index >= elts))
+ return -1;
+
+ if (kvmppc_need_byteswap(vcpu))
+ offset = elts - index - 1;
+ else
+ offset = index;
+
+ return offset;
+}
+
+static inline int kvmppc_get_vmx_dword_offset(struct kvm_vcpu *vcpu,
+ int index)
+{
+ return kvmppc_get_vmx_offset_generic(vcpu, index, 8);
+}
+
+static inline int kvmppc_get_vmx_word_offset(struct kvm_vcpu *vcpu,
+ int index)
+{
+ return kvmppc_get_vmx_offset_generic(vcpu, index, 4);
+}
+
+static inline int kvmppc_get_vmx_hword_offset(struct kvm_vcpu *vcpu,
+ int index)
+{
+ return kvmppc_get_vmx_offset_generic(vcpu, index, 2);
+}
+
+static inline int kvmppc_get_vmx_byte_offset(struct kvm_vcpu *vcpu,
+ int index)
+{
+ return kvmppc_get_vmx_offset_generic(vcpu, index, 1);
+}
+
+
static inline void kvmppc_set_vmx_dword(struct kvm_vcpu *vcpu,
- u64 gpr)
+ u64 gpr)
{
+ union kvmppc_one_reg val;
+ int offset = kvmppc_get_vmx_dword_offset(vcpu,
+ vcpu->arch.mmio_vmx_offset);
int index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;
- u32 hi, lo;
- u32 di;
-#ifdef __BIG_ENDIAN
- hi = gpr >> 32;
- lo = gpr & 0xffffffff;
-#else
- lo = gpr >> 32;
- hi = gpr & 0xffffffff;
-#endif
+ if (offset == -1)
+ return;
+
+ val.vval = VCPU_VSX_VR(vcpu, index);
+ val.vsxval[offset] = gpr;
+ VCPU_VSX_VR(vcpu, index) = val.vval;
+}
+
+static inline void kvmppc_set_vmx_word(struct kvm_vcpu *vcpu,
+ u32 gpr32)
+{
+ union kvmppc_one_reg val;
+ int offset = kvmppc_get_vmx_word_offset(vcpu,
+ vcpu->arch.mmio_vmx_offset);
+ int index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;
- di = 2 - vcpu->arch.mmio_vmx_copy_nums; /* doubleword index */
- if (di > 1)
+ if (offset == -1)
return;
- if (vcpu->arch.mmio_host_swabbed)
- di = 1 - di;
+ val.vval = VCPU_VSX_VR(vcpu, index);
+ val.vsx32val[offset] = gpr32;
+ VCPU_VSX_VR(vcpu, index) = val.vval;
+}
+
+static inline void kvmppc_set_vmx_hword(struct kvm_vcpu *vcpu,
+ u16 gpr16)
+{
+ union kvmppc_one_reg val;
+ int offset = kvmppc_get_vmx_hword_offset(vcpu,
+ vcpu->arch.mmio_vmx_offset);
+ int index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;
+
+ if (offset == -1)
+ return;
+
+ val.vval = VCPU_VSX_VR(vcpu, index);
+ val.vsx16val[offset] = gpr16;
+ VCPU_VSX_VR(vcpu, index) = val.vval;
+}
+
+static inline void kvmppc_set_vmx_byte(struct kvm_vcpu *vcpu,
+ u8 gpr8)
+{
+ union kvmppc_one_reg val;
+ int offset = kvmppc_get_vmx_byte_offset(vcpu,
+ vcpu->arch.mmio_vmx_offset);
+ int index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;
+
+ if (offset == -1)
+ return;
- VCPU_VSX_VR(vcpu, index).u[di * 2] = hi;
- VCPU_VSX_VR(vcpu, index).u[di * 2 + 1] = lo;
+ val.vval = VCPU_VSX_VR(vcpu, index);
+ val.vsx8val[offset] = gpr8;
+ VCPU_VSX_VR(vcpu, index) = val.vval;
}
#endif /* CONFIG_ALTIVEC */
@@ -1041,6 +1140,9 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, gpr);
break;
case KVM_MMIO_REG_FPR:
+ if (vcpu->kvm->arch.kvm_ops->giveup_ext)
+ vcpu->kvm->arch.kvm_ops->giveup_ext(vcpu, MSR_FP);
+
VCPU_FPR(vcpu, vcpu->arch.io_gpr & KVM_MMIO_REG_MASK) = gpr;
break;
#ifdef CONFIG_PPC_BOOK3S
@@ -1054,18 +1156,36 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu,
#endif
#ifdef CONFIG_VSX
case KVM_MMIO_REG_VSX:
- if (vcpu->arch.mmio_vsx_copy_type == KVMPPC_VSX_COPY_DWORD)
+ if (vcpu->kvm->arch.kvm_ops->giveup_ext)
+ vcpu->kvm->arch.kvm_ops->giveup_ext(vcpu, MSR_VSX);
+
+ if (vcpu->arch.mmio_copy_type == KVMPPC_VSX_COPY_DWORD)
kvmppc_set_vsr_dword(vcpu, gpr);
- else if (vcpu->arch.mmio_vsx_copy_type == KVMPPC_VSX_COPY_WORD)
+ else if (vcpu->arch.mmio_copy_type == KVMPPC_VSX_COPY_WORD)
kvmppc_set_vsr_word(vcpu, gpr);
- else if (vcpu->arch.mmio_vsx_copy_type ==
+ else if (vcpu->arch.mmio_copy_type ==
KVMPPC_VSX_COPY_DWORD_LOAD_DUMP)
kvmppc_set_vsr_dword_dump(vcpu, gpr);
+ else if (vcpu->arch.mmio_copy_type ==
+ KVMPPC_VSX_COPY_WORD_LOAD_DUMP)
+ kvmppc_set_vsr_word_dump(vcpu, gpr);
break;
#endif
#ifdef CONFIG_ALTIVEC
case KVM_MMIO_REG_VMX:
- kvmppc_set_vmx_dword(vcpu, gpr);
+ if (vcpu->kvm->arch.kvm_ops->giveup_ext)
+ vcpu->kvm->arch.kvm_ops->giveup_ext(vcpu, MSR_VEC);
+
+ if (vcpu->arch.mmio_copy_type == KVMPPC_VMX_COPY_DWORD)
+ kvmppc_set_vmx_dword(vcpu, gpr);
+ else if (vcpu->arch.mmio_copy_type == KVMPPC_VMX_COPY_WORD)
+ kvmppc_set_vmx_word(vcpu, gpr);
+ else if (vcpu->arch.mmio_copy_type ==
+ KVMPPC_VMX_COPY_HWORD)
+ kvmppc_set_vmx_hword(vcpu, gpr);
+ else if (vcpu->arch.mmio_copy_type ==
+ KVMPPC_VMX_COPY_BYTE)
+ kvmppc_set_vmx_byte(vcpu, gpr);
break;
#endif
default:
@@ -1228,7 +1348,7 @@ static inline int kvmppc_get_vsr_data(struct kvm_vcpu *vcpu, int rs, u64 *val)
u32 dword_offset, word_offset;
union kvmppc_one_reg reg;
int vsx_offset = 0;
- int copy_type = vcpu->arch.mmio_vsx_copy_type;
+ int copy_type = vcpu->arch.mmio_copy_type;
int result = 0;
switch (copy_type) {
@@ -1344,14 +1464,16 @@ static int kvmppc_emulate_mmio_vsx_loadstore(struct kvm_vcpu *vcpu,
#endif /* CONFIG_VSX */
#ifdef CONFIG_ALTIVEC
-/* handle quadword load access in two halves */
-int kvmppc_handle_load128_by2x64(struct kvm_run *run, struct kvm_vcpu *vcpu,
- unsigned int rt, int is_default_endian)
+int kvmppc_handle_vmx_load(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ unsigned int rt, unsigned int bytes, int is_default_endian)
{
enum emulation_result emulated = EMULATE_DONE;
+ if (vcpu->arch.mmio_vsx_copy_nums > 2)
+ return EMULATE_FAIL;
+
while (vcpu->arch.mmio_vmx_copy_nums) {
- emulated = __kvmppc_handle_load(run, vcpu, rt, 8,
+ emulated = __kvmppc_handle_load(run, vcpu, rt, bytes,
is_default_endian, 0);
if (emulated != EMULATE_DONE)
@@ -1359,55 +1481,127 @@ int kvmppc_handle_load128_by2x64(struct kvm_run *run, struct kvm_vcpu *vcpu,
vcpu->arch.paddr_accessed += run->mmio.len;
vcpu->arch.mmio_vmx_copy_nums--;
+ vcpu->arch.mmio_vmx_offset++;
}
return emulated;
}
-static inline int kvmppc_get_vmx_data(struct kvm_vcpu *vcpu, int rs, u64 *val)
+int kvmppc_get_vmx_dword(struct kvm_vcpu *vcpu, int index, u64 *val)
{
- vector128 vrs = VCPU_VSX_VR(vcpu, rs);
- u32 di;
- u64 w0, w1;
+ union kvmppc_one_reg reg;
+ int vmx_offset = 0;
+ int result = 0;
- di = 2 - vcpu->arch.mmio_vmx_copy_nums; /* doubleword index */
- if (di > 1)
+ vmx_offset =
+ kvmppc_get_vmx_dword_offset(vcpu, vcpu->arch.mmio_vmx_offset);
+
+ if (vmx_offset == -1)
return -1;
- if (vcpu->arch.mmio_host_swabbed)
- di = 1 - di;
+ reg.vval = VCPU_VSX_VR(vcpu, index);
+ *val = reg.vsxval[vmx_offset];
- w0 = vrs.u[di * 2];
- w1 = vrs.u[di * 2 + 1];
+ return result;
+}
-#ifdef __BIG_ENDIAN
- *val = (w0 << 32) | w1;
-#else
- *val = (w1 << 32) | w0;
-#endif
- return 0;
+int kvmppc_get_vmx_word(struct kvm_vcpu *vcpu, int index, u64 *val)
+{
+ union kvmppc_one_reg reg;
+ int vmx_offset = 0;
+ int result = 0;
+
+ vmx_offset =
+ kvmppc_get_vmx_word_offset(vcpu, vcpu->arch.mmio_vmx_offset);
+
+ if (vmx_offset == -1)
+ return -1;
+
+ reg.vval = VCPU_VSX_VR(vcpu, index);
+ *val = reg.vsx32val[vmx_offset];
+
+ return result;
+}
+
+int kvmppc_get_vmx_hword(struct kvm_vcpu *vcpu, int index, u64 *val)
+{
+ union kvmppc_one_reg reg;
+ int vmx_offset = 0;
+ int result = 0;
+
+ vmx_offset =
+ kvmppc_get_vmx_hword_offset(vcpu, vcpu->arch.mmio_vmx_offset);
+
+ if (vmx_offset == -1)
+ return -1;
+
+ reg.vval = VCPU_VSX_VR(vcpu, index);
+ *val = reg.vsx16val[vmx_offset];
+
+ return result;
}
-/* handle quadword store in two halves */
-int kvmppc_handle_store128_by2x64(struct kvm_run *run, struct kvm_vcpu *vcpu,
- unsigned int rs, int is_default_endian)
+int kvmppc_get_vmx_byte(struct kvm_vcpu *vcpu, int index, u64 *val)
+{
+ union kvmppc_one_reg reg;
+ int vmx_offset = 0;
+ int result = 0;
+
+ vmx_offset =
+ kvmppc_get_vmx_byte_offset(vcpu, vcpu->arch.mmio_vmx_offset);
+
+ if (vmx_offset == -1)
+ return -1;
+
+ reg.vval = VCPU_VSX_VR(vcpu, index);
+ *val = reg.vsx8val[vmx_offset];
+
+ return result;
+}
+
+int kvmppc_handle_vmx_store(struct kvm_run *run, struct kvm_vcpu *vcpu,
+ unsigned int rs, unsigned int bytes, int is_default_endian)
{
u64 val = 0;
+ unsigned int index = rs & KVM_MMIO_REG_MASK;
enum emulation_result emulated = EMULATE_DONE;
+ if (vcpu->arch.mmio_vsx_copy_nums > 2)
+ return EMULATE_FAIL;
+
vcpu->arch.io_gpr = rs;
while (vcpu->arch.mmio_vmx_copy_nums) {
- if (kvmppc_get_vmx_data(vcpu, rs, &val) == -1)
+ switch (vcpu->arch.mmio_copy_type) {
+ case KVMPPC_VMX_COPY_DWORD:
+ if (kvmppc_get_vmx_dword(vcpu, index, &val) == -1)
+ return EMULATE_FAIL;
+
+ break;
+ case KVMPPC_VMX_COPY_WORD:
+ if (kvmppc_get_vmx_word(vcpu, index, &val) == -1)
+ return EMULATE_FAIL;
+ break;
+ case KVMPPC_VMX_COPY_HWORD:
+ if (kvmppc_get_vmx_hword(vcpu, index, &val) == -1)
+ return EMULATE_FAIL;
+ break;
+ case KVMPPC_VMX_COPY_BYTE:
+ if (kvmppc_get_vmx_byte(vcpu, index, &val) == -1)
+ return EMULATE_FAIL;
+ break;
+ default:
return EMULATE_FAIL;
+ }
- emulated = kvmppc_handle_store(run, vcpu, val, 8,
+ emulated = kvmppc_handle_store(run, vcpu, val, bytes,
is_default_endian);
if (emulated != EMULATE_DONE)
break;
vcpu->arch.paddr_accessed += run->mmio.len;
vcpu->arch.mmio_vmx_copy_nums--;
+ vcpu->arch.mmio_vmx_offset++;
}
return emulated;
@@ -1422,11 +1616,11 @@ static int kvmppc_emulate_mmio_vmx_loadstore(struct kvm_vcpu *vcpu,
vcpu->arch.paddr_accessed += run->mmio.len;
if (!vcpu->mmio_is_write) {
- emulated = kvmppc_handle_load128_by2x64(run, vcpu,
- vcpu->arch.io_gpr, 1);
+ emulated = kvmppc_handle_vmx_load(run, vcpu,
+ vcpu->arch.io_gpr, run->mmio.len, 1);
} else {
- emulated = kvmppc_handle_store128_by2x64(run, vcpu,
- vcpu->arch.io_gpr, 1);
+ emulated = kvmppc_handle_vmx_store(run, vcpu,
+ vcpu->arch.io_gpr, run->mmio.len, 1);
}
switch (emulated) {
@@ -1570,8 +1764,10 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
}
#endif
#ifdef CONFIG_ALTIVEC
- if (vcpu->arch.mmio_vmx_copy_nums > 0)
+ if (vcpu->arch.mmio_vmx_copy_nums > 0) {
vcpu->arch.mmio_vmx_copy_nums--;
+ vcpu->arch.mmio_vmx_offset++;
+ }
if (vcpu->arch.mmio_vmx_copy_nums > 0) {
r = kvmppc_emulate_mmio_vmx_loadstore(vcpu, run);
@@ -1784,16 +1980,16 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
void __user *argp = (void __user *)arg;
long r;
- vcpu_load(vcpu);
-
switch (ioctl) {
case KVM_ENABLE_CAP:
{
struct kvm_enable_cap cap;
r = -EFAULT;
+ vcpu_load(vcpu);
if (copy_from_user(&cap, argp, sizeof(cap)))
goto out;
r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
+ vcpu_put(vcpu);
break;
}
@@ -1815,9 +2011,11 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
case KVM_DIRTY_TLB: {
struct kvm_dirty_tlb dirty;
r = -EFAULT;
+ vcpu_load(vcpu);
if (copy_from_user(&dirty, argp, sizeof(dirty)))
goto out;
r = kvm_vcpu_ioctl_dirty_tlb(vcpu, &dirty);
+ vcpu_put(vcpu);
break;
}
#endif
@@ -1826,11 +2024,10 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
}
out:
- vcpu_put(vcpu);
return r;
}
-int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
{
return VM_FAULT_SIGBUS;
}
diff --git a/arch/powerpc/kvm/tm.S b/arch/powerpc/kvm/tm.S
new file mode 100644
index 0000000..90e330f
--- /dev/null
+++ b/arch/powerpc/kvm/tm.S
@@ -0,0 +1,384 @@
+/*
+ * 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.
+ *
+ * Derived from book3s_hv_rmhandlers.S, which is:
+ *
+ * Copyright 2011 Paul Mackerras, IBM Corp. <paulus@au1.ibm.com>
+ *
+ */
+
+#include <asm/reg.h>
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+#include <asm/export.h>
+#include <asm/tm.h>
+#include <asm/cputable.h>
+
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+#define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM)
+
+/*
+ * Save transactional state and TM-related registers.
+ * Called with:
+ * - r3 pointing to the vcpu struct
+ * - r4 points to the MSR with current TS bits:
+ * (For HV KVM, it is VCPU_MSR ; For PR KVM, it is host MSR).
+ * This can modify all checkpointed registers, but
+ * restores r1, r2 before exit.
+ */
+_GLOBAL(__kvmppc_save_tm)
+ mflr r0
+ std r0, PPC_LR_STKOFF(r1)
+
+ /* Turn on TM. */
+ mfmsr r8
+ li r0, 1
+ rldimi r8, r0, MSR_TM_LG, 63-MSR_TM_LG
+ ori r8, r8, MSR_FP
+ oris r8, r8, (MSR_VEC | MSR_VSX)@h
+ mtmsrd r8
+
+ rldicl. r4, r4, 64 - MSR_TS_S_LG, 62
+ beq 1f /* TM not active in guest. */
+
+ std r1, HSTATE_SCRATCH2(r13)
+ std r3, HSTATE_SCRATCH1(r13)
+
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+BEGIN_FTR_SECTION
+ /* Emulation of the treclaim instruction needs TEXASR before treclaim */
+ mfspr r6, SPRN_TEXASR
+ std r6, VCPU_ORIG_TEXASR(r3)
+END_FTR_SECTION_IFSET(CPU_FTR_P9_TM_HV_ASSIST)
+#endif
+
+ /* Clear the MSR RI since r1, r13 are all going to be foobar. */
+ li r5, 0
+ mtmsrd r5, 1
+
+ li r3, TM_CAUSE_KVM_RESCHED
+
+ /* All GPRs are volatile at this point. */
+ TRECLAIM(R3)
+
+ /* Temporarily store r13 and r9 so we have some regs to play with */
+ SET_SCRATCH0(r13)
+ GET_PACA(r13)
+ std r9, PACATMSCRATCH(r13)
+ ld r9, HSTATE_SCRATCH1(r13)
+
+ /* Get a few more GPRs free. */
+ std r29, VCPU_GPRS_TM(29)(r9)
+ std r30, VCPU_GPRS_TM(30)(r9)
+ std r31, VCPU_GPRS_TM(31)(r9)
+
+ /* Save away PPR and DSCR soon so don't run with user values. */
+ mfspr r31, SPRN_PPR
+ HMT_MEDIUM
+ mfspr r30, SPRN_DSCR
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+ ld r29, HSTATE_DSCR(r13)
+ mtspr SPRN_DSCR, r29
+#endif
+
+ /* Save all but r9, r13 & r29-r31 */
+ reg = 0
+ .rept 29
+ .if (reg != 9) && (reg != 13)
+ std reg, VCPU_GPRS_TM(reg)(r9)
+ .endif
+ reg = reg + 1
+ .endr
+ /* ... now save r13 */
+ GET_SCRATCH0(r4)
+ std r4, VCPU_GPRS_TM(13)(r9)
+ /* ... and save r9 */
+ ld r4, PACATMSCRATCH(r13)
+ std r4, VCPU_GPRS_TM(9)(r9)
+
+ /* Reload stack pointer and TOC. */
+ ld r1, HSTATE_SCRATCH2(r13)
+ ld r2, PACATOC(r13)
+
+ /* Set MSR RI now we have r1 and r13 back. */
+ li r5, MSR_RI
+ mtmsrd r5, 1
+
+ /* Save away checkpinted SPRs. */
+ std r31, VCPU_PPR_TM(r9)
+ std r30, VCPU_DSCR_TM(r9)
+ mflr r5
+ mfcr r6
+ mfctr r7
+ mfspr r8, SPRN_AMR
+ mfspr r10, SPRN_TAR
+ mfxer r11
+ std r5, VCPU_LR_TM(r9)
+ stw r6, VCPU_CR_TM(r9)
+ std r7, VCPU_CTR_TM(r9)
+ std r8, VCPU_AMR_TM(r9)
+ std r10, VCPU_TAR_TM(r9)
+ std r11, VCPU_XER_TM(r9)
+
+ /* Restore r12 as trap number. */
+ lwz r12, VCPU_TRAP(r9)
+
+ /* Save FP/VSX. */
+ addi r3, r9, VCPU_FPRS_TM
+ bl store_fp_state
+ addi r3, r9, VCPU_VRS_TM
+ bl store_vr_state
+ mfspr r6, SPRN_VRSAVE
+ stw r6, VCPU_VRSAVE_TM(r9)
+1:
+ /*
+ * We need to save these SPRs after the treclaim so that the software
+ * error code is recorded correctly in the TEXASR. Also the user may
+ * change these outside of a transaction, so they must always be
+ * context switched.
+ */
+ mfspr r7, SPRN_TEXASR
+ std r7, VCPU_TEXASR(r9)
+11:
+ mfspr r5, SPRN_TFHAR
+ mfspr r6, SPRN_TFIAR
+ std r5, VCPU_TFHAR(r9)
+ std r6, VCPU_TFIAR(r9)
+
+ ld r0, PPC_LR_STKOFF(r1)
+ mtlr r0
+ blr
+
+/*
+ * _kvmppc_save_tm_pr() is a wrapper around __kvmppc_save_tm(), so that it can
+ * be invoked from C function by PR KVM only.
+ */
+_GLOBAL(_kvmppc_save_tm_pr)
+ mflr r5
+ std r5, PPC_LR_STKOFF(r1)
+ stdu r1, -SWITCH_FRAME_SIZE(r1)
+ SAVE_NVGPRS(r1)
+
+ /* save MSR since TM/math bits might be impacted
+ * by __kvmppc_save_tm().
+ */
+ mfmsr r5
+ SAVE_GPR(5, r1)
+
+ /* also save DSCR/CR/TAR so that it can be recovered later */
+ mfspr r6, SPRN_DSCR
+ SAVE_GPR(6, r1)
+
+ mfcr r7
+ stw r7, _CCR(r1)
+
+ mfspr r8, SPRN_TAR
+ SAVE_GPR(8, r1)
+
+ bl __kvmppc_save_tm
+
+ REST_GPR(8, r1)
+ mtspr SPRN_TAR, r8
+
+ ld r7, _CCR(r1)
+ mtcr r7
+
+ REST_GPR(6, r1)
+ mtspr SPRN_DSCR, r6
+
+ /* need preserve current MSR's MSR_TS bits */
+ REST_GPR(5, r1)
+ mfmsr r6
+ rldicl r6, r6, 64 - MSR_TS_S_LG, 62
+ rldimi r5, r6, MSR_TS_S_LG, 63 - MSR_TS_T_LG
+ mtmsrd r5
+
+ REST_NVGPRS(r1)
+ addi r1, r1, SWITCH_FRAME_SIZE
+ ld r5, PPC_LR_STKOFF(r1)
+ mtlr r5
+ blr
+
+EXPORT_SYMBOL_GPL(_kvmppc_save_tm_pr);
+
+/*
+ * Restore transactional state and TM-related registers.
+ * Called with:
+ * - r3 pointing to the vcpu struct.
+ * - r4 is the guest MSR with desired TS bits:
+ * For HV KVM, it is VCPU_MSR
+ * For PR KVM, it is provided by caller
+ * This potentially modifies all checkpointed registers.
+ * It restores r1, r2 from the PACA.
+ */
+_GLOBAL(__kvmppc_restore_tm)
+ mflr r0
+ std r0, PPC_LR_STKOFF(r1)
+
+ /* Turn on TM/FP/VSX/VMX so we can restore them. */
+ mfmsr r5
+ li r6, MSR_TM >> 32
+ sldi r6, r6, 32
+ or r5, r5, r6
+ ori r5, r5, MSR_FP
+ oris r5, r5, (MSR_VEC | MSR_VSX)@h
+ mtmsrd r5
+
+ /*
+ * The user may change these outside of a transaction, so they must
+ * always be context switched.
+ */
+ ld r5, VCPU_TFHAR(r3)
+ ld r6, VCPU_TFIAR(r3)
+ ld r7, VCPU_TEXASR(r3)
+ mtspr SPRN_TFHAR, r5
+ mtspr SPRN_TFIAR, r6
+ mtspr SPRN_TEXASR, r7
+
+ mr r5, r4
+ rldicl. r5, r5, 64 - MSR_TS_S_LG, 62
+ beqlr /* TM not active in guest */
+ std r1, HSTATE_SCRATCH2(r13)
+
+ /* Make sure the failure summary is set, otherwise we'll program check
+ * when we trechkpt. It's possible that this might have been not set
+ * on a kvmppc_set_one_reg() call but we shouldn't let this crash the
+ * host.
+ */
+ oris r7, r7, (TEXASR_FS)@h
+ mtspr SPRN_TEXASR, r7
+
+ /*
+ * We need to load up the checkpointed state for the guest.
+ * We need to do this early as it will blow away any GPRs, VSRs and
+ * some SPRs.
+ */
+
+ mr r31, r3
+ addi r3, r31, VCPU_FPRS_TM
+ bl load_fp_state
+ addi r3, r31, VCPU_VRS_TM
+ bl load_vr_state
+ mr r3, r31
+ lwz r7, VCPU_VRSAVE_TM(r3)
+ mtspr SPRN_VRSAVE, r7
+
+ ld r5, VCPU_LR_TM(r3)
+ lwz r6, VCPU_CR_TM(r3)
+ ld r7, VCPU_CTR_TM(r3)
+ ld r8, VCPU_AMR_TM(r3)
+ ld r9, VCPU_TAR_TM(r3)
+ ld r10, VCPU_XER_TM(r3)
+ mtlr r5
+ mtcr r6
+ mtctr r7
+ mtspr SPRN_AMR, r8
+ mtspr SPRN_TAR, r9
+ mtxer r10
+
+ /*
+ * Load up PPR and DSCR values but don't put them in the actual SPRs
+ * till the last moment to avoid running with userspace PPR and DSCR for
+ * too long.
+ */
+ ld r29, VCPU_DSCR_TM(r3)
+ ld r30, VCPU_PPR_TM(r3)
+
+ std r2, PACATMSCRATCH(r13) /* Save TOC */
+
+ /* Clear the MSR RI since r1, r13 are all going to be foobar. */
+ li r5, 0
+ mtmsrd r5, 1
+
+ /* Load GPRs r0-r28 */
+ reg = 0
+ .rept 29
+ ld reg, VCPU_GPRS_TM(reg)(r31)
+ reg = reg + 1
+ .endr
+
+ mtspr SPRN_DSCR, r29
+ mtspr SPRN_PPR, r30
+
+ /* Load final GPRs */
+ ld 29, VCPU_GPRS_TM(29)(r31)
+ ld 30, VCPU_GPRS_TM(30)(r31)
+ ld 31, VCPU_GPRS_TM(31)(r31)
+
+ /* TM checkpointed state is now setup. All GPRs are now volatile. */
+ TRECHKPT
+
+ /* Now let's get back the state we need. */
+ HMT_MEDIUM
+ GET_PACA(r13)
+#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
+ ld r29, HSTATE_DSCR(r13)
+ mtspr SPRN_DSCR, r29
+#endif
+ ld r1, HSTATE_SCRATCH2(r13)
+ ld r2, PACATMSCRATCH(r13)
+
+ /* Set the MSR RI since we have our registers back. */
+ li r5, MSR_RI
+ mtmsrd r5, 1
+ ld r0, PPC_LR_STKOFF(r1)
+ mtlr r0
+ blr
+
+/*
+ * _kvmppc_restore_tm_pr() is a wrapper around __kvmppc_restore_tm(), so that it
+ * can be invoked from C function by PR KVM only.
+ */
+_GLOBAL(_kvmppc_restore_tm_pr)
+ mflr r5
+ std r5, PPC_LR_STKOFF(r1)
+ stdu r1, -SWITCH_FRAME_SIZE(r1)
+ SAVE_NVGPRS(r1)
+
+ /* save MSR to avoid TM/math bits change */
+ mfmsr r5
+ SAVE_GPR(5, r1)
+
+ /* also save DSCR/CR/TAR so that it can be recovered later */
+ mfspr r6, SPRN_DSCR
+ SAVE_GPR(6, r1)
+
+ mfcr r7
+ stw r7, _CCR(r1)
+
+ mfspr r8, SPRN_TAR
+ SAVE_GPR(8, r1)
+
+ bl __kvmppc_restore_tm
+
+ REST_GPR(8, r1)
+ mtspr SPRN_TAR, r8
+
+ ld r7, _CCR(r1)
+ mtcr r7
+
+ REST_GPR(6, r1)
+ mtspr SPRN_DSCR, r6
+
+ /* need preserve current MSR's MSR_TS bits */
+ REST_GPR(5, r1)
+ mfmsr r6
+ rldicl r6, r6, 64 - MSR_TS_S_LG, 62
+ rldimi r5, r6, MSR_TS_S_LG, 63 - MSR_TS_T_LG
+ mtmsrd r5
+
+ REST_NVGPRS(r1)
+ addi r1, r1, SWITCH_FRAME_SIZE
+ ld r5, PPC_LR_STKOFF(r1)
+ mtlr r5
+ blr
+
+EXPORT_SYMBOL_GPL(_kvmppc_restore_tm_pr);
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c
index 94058c2..6aa774a 100644
--- a/arch/powerpc/lib/rheap.c
+++ b/arch/powerpc/lib/rheap.c
@@ -54,7 +54,7 @@ static int grow(rh_info_t * info, int max_blocks)
new_blocks = max_blocks - info->max_blocks;
- block = kmalloc(sizeof(rh_block_t) * max_blocks, GFP_ATOMIC);
+ block = kmalloc_array(max_blocks, sizeof(rh_block_t), GFP_ATOMIC);
if (block == NULL)
return -ENOMEM;
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c
index 7c5f479..8a9a49c 100644
--- a/arch/powerpc/mm/hugetlbpage.c
+++ b/arch/powerpc/mm/hugetlbpage.c
@@ -337,7 +337,8 @@ static void free_hugepd_range(struct mmu_gather *tlb, hugepd_t *hpdp, int pdshif
if (shift >= pdshift)
hugepd_free(tlb, hugepte);
else
- pgtable_free_tlb(tlb, hugepte, pdshift - shift);
+ pgtable_free_tlb(tlb, hugepte,
+ get_hugepd_cache_index(pdshift - shift));
}
static void hugetlb_free_pmd_range(struct mmu_gather *tlb, pud_t *pud,
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index 8cecda4..5c8530d 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -215,7 +215,7 @@ void __init mem_topology_setup(void)
/* Place all memblock_regions in the same node and merge contiguous
* memblock_regions
*/
- memblock_set_node(0, (phys_addr_t)ULLONG_MAX, &memblock.memory, 0);
+ memblock_set_node(0, PHYS_ADDR_MAX, &memblock.memory, 0);
}
void __init initmem_init(void)
diff --git a/arch/powerpc/mm/mmu_context_iommu.c b/arch/powerpc/mm/mmu_context_iommu.c
index 4c615fc..abb4364 100644
--- a/arch/powerpc/mm/mmu_context_iommu.c
+++ b/arch/powerpc/mm/mmu_context_iommu.c
@@ -159,7 +159,7 @@ long mm_iommu_get(struct mm_struct *mm, unsigned long ua, unsigned long entries,
goto unlock_exit;
}
- mem->hpas = vzalloc(entries * sizeof(mem->hpas[0]));
+ mem->hpas = vzalloc(array_size(entries, sizeof(mem->hpas[0])));
if (!mem->hpas) {
kfree(mem);
ret = -ENOMEM;
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 57a5029..0c7e05d 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1316,7 +1316,7 @@ int numa_update_cpu_topology(bool cpus_locked)
if (!weight)
return 0;
- updates = kzalloc(weight * (sizeof(*updates)), GFP_KERNEL);
+ updates = kcalloc(weight, sizeof(*updates), GFP_KERNEL);
if (!updates)
return 0;
diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c
index c1f4ca4..4afbfbb 100644
--- a/arch/powerpc/mm/pgtable-book3s64.c
+++ b/arch/powerpc/mm/pgtable-book3s64.c
@@ -409,6 +409,18 @@ static inline void pgtable_free(void *table, int index)
case PUD_INDEX:
kmem_cache_free(PGT_CACHE(PUD_CACHE_INDEX), table);
break;
+#if defined(CONFIG_PPC_4K_PAGES) && defined(CONFIG_HUGETLB_PAGE)
+ /* 16M hugepd directory at pud level */
+ case HTLB_16M_INDEX:
+ BUILD_BUG_ON(H_16M_CACHE_INDEX <= 0);
+ kmem_cache_free(PGT_CACHE(H_16M_CACHE_INDEX), table);
+ break;
+ /* 16G hugepd directory at the pgd level */
+ case HTLB_16G_INDEX:
+ BUILD_BUG_ON(H_16G_CACHE_INDEX <= 0);
+ kmem_cache_free(PGT_CACHE(H_16G_CACHE_INDEX), table);
+ break;
+#endif
/* We don't free pgd table via RCU callback */
default:
BUG();
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c
index 67a6e86..1135b43 100644
--- a/arch/powerpc/mm/tlb-radix.c
+++ b/arch/powerpc/mm/tlb-radix.c
@@ -689,22 +689,17 @@ EXPORT_SYMBOL(radix__flush_tlb_kernel_range);
static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33;
static unsigned long tlb_local_single_page_flush_ceiling __read_mostly = POWER9_TLB_SETS_RADIX * 2;
-void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
- unsigned long end)
+static inline void __radix__flush_tlb_range(struct mm_struct *mm,
+ unsigned long start, unsigned long end,
+ bool flush_all_sizes)
{
- struct mm_struct *mm = vma->vm_mm;
unsigned long pid;
unsigned int page_shift = mmu_psize_defs[mmu_virtual_psize].shift;
unsigned long page_size = 1UL << page_shift;
unsigned long nr_pages = (end - start) >> page_shift;
bool local, full;
-#ifdef CONFIG_HUGETLB_PAGE
- if (is_vm_hugetlb_page(vma))
- return radix__flush_hugetlb_tlb_range(vma, start, end);
-#endif
-
pid = mm->context.id;
if (unlikely(pid == MMU_NO_CONTEXT))
return;
@@ -738,37 +733,64 @@ is_local:
_tlbie_pid(pid, RIC_FLUSH_TLB);
}
} else {
- bool hflush = false;
+ bool hflush = flush_all_sizes;
+ bool gflush = flush_all_sizes;
unsigned long hstart, hend;
+ unsigned long gstart, gend;
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
- hstart = (start + HPAGE_PMD_SIZE - 1) >> HPAGE_PMD_SHIFT;
- hend = end >> HPAGE_PMD_SHIFT;
- if (hstart < hend) {
- hstart <<= HPAGE_PMD_SHIFT;
- hend <<= HPAGE_PMD_SHIFT;
+ if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
hflush = true;
+
+ if (hflush) {
+ hstart = (start + PMD_SIZE - 1) & PMD_MASK;
+ hend = end & PMD_MASK;
+ if (hstart == hend)
+ hflush = false;
+ }
+
+ if (gflush) {
+ gstart = (start + PUD_SIZE - 1) & PUD_MASK;
+ gend = end & PUD_MASK;
+ if (gstart == gend)
+ gflush = false;
}
-#endif
asm volatile("ptesync": : :"memory");
if (local) {
__tlbiel_va_range(start, end, pid, page_size, mmu_virtual_psize);
if (hflush)
__tlbiel_va_range(hstart, hend, pid,
- HPAGE_PMD_SIZE, MMU_PAGE_2M);
+ PMD_SIZE, MMU_PAGE_2M);
+ if (gflush)
+ __tlbiel_va_range(gstart, gend, pid,
+ PUD_SIZE, MMU_PAGE_1G);
asm volatile("ptesync": : :"memory");
} else {
__tlbie_va_range(start, end, pid, page_size, mmu_virtual_psize);
if (hflush)
__tlbie_va_range(hstart, hend, pid,
- HPAGE_PMD_SIZE, MMU_PAGE_2M);
+ PMD_SIZE, MMU_PAGE_2M);
+ if (gflush)
+ __tlbie_va_range(gstart, gend, pid,
+ PUD_SIZE, MMU_PAGE_1G);
fixup_tlbie();
asm volatile("eieio; tlbsync; ptesync": : :"memory");
}
}
preempt_enable();
}
+
+void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
+ unsigned long end)
+
+{
+#ifdef CONFIG_HUGETLB_PAGE
+ if (is_vm_hugetlb_page(vma))
+ return radix__flush_hugetlb_tlb_range(vma, start, end);
+#endif
+
+ __radix__flush_tlb_range(vma->vm_mm, start, end, false);
+}
EXPORT_SYMBOL(radix__flush_tlb_range);
static int radix_get_mmu_psize(int page_size)
@@ -837,6 +859,8 @@ void radix__tlb_flush(struct mmu_gather *tlb)
int psize = 0;
struct mm_struct *mm = tlb->mm;
int page_size = tlb->page_size;
+ unsigned long start = tlb->start;
+ unsigned long end = tlb->end;
/*
* if page size is not something we understand, do a full mm flush
@@ -847,15 +871,45 @@ void radix__tlb_flush(struct mmu_gather *tlb)
*/
if (tlb->fullmm) {
__flush_all_mm(mm, true);
+#if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE)
+ } else if (mm_tlb_flush_nested(mm)) {
+ /*
+ * If there is a concurrent invalidation that is clearing ptes,
+ * then it's possible this invalidation will miss one of those
+ * cleared ptes and miss flushing the TLB. If this invalidate
+ * returns before the other one flushes TLBs, that can result
+ * in it returning while there are still valid TLBs inside the
+ * range to be invalidated.
+ *
+ * See mm/memory.c:tlb_finish_mmu() for more details.
+ *
+ * The solution to this is ensure the entire range is always
+ * flushed here. The problem for powerpc is that the flushes
+ * are page size specific, so this "forced flush" would not
+ * do the right thing if there are a mix of page sizes in
+ * the range to be invalidated. So use __flush_tlb_range
+ * which invalidates all possible page sizes in the range.
+ *
+ * PWC flush probably is not be required because the core code
+ * shouldn't free page tables in this path, but accounting
+ * for the possibility makes us a bit more robust.
+ *
+ * need_flush_all is an uncommon case because page table
+ * teardown should be done with exclusive locks held (but
+ * after locks are dropped another invalidate could come
+ * in), it could be optimized further if necessary.
+ */
+ if (!tlb->need_flush_all)
+ __radix__flush_tlb_range(mm, start, end, true);
+ else
+ radix__flush_all_mm(mm);
+#endif
} else if ( (psize = radix_get_mmu_psize(page_size)) == -1) {
if (!tlb->need_flush_all)
radix__flush_tlb_mm(mm);
else
radix__flush_all_mm(mm);
} else {
- unsigned long start = tlb->start;
- unsigned long end = tlb->end;
-
if (!tlb->need_flush_all)
radix__flush_tlb_range_psize(mm, start, end, psize);
else
@@ -1043,6 +1097,8 @@ extern void radix_kvm_prefetch_workaround(struct mm_struct *mm)
for (; sib <= cpu_last_thread_sibling(cpu) && !flush; sib++) {
if (sib == cpu)
continue;
+ if (!cpu_possible(sib))
+ continue;
if (paca_ptrs[sib]->kvm_hstate.kvm_vcpu)
flush = true;
}
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index a9636d8..5b061fc 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -566,7 +566,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
if (!bpf_jit_enable)
return;
- addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL);
+ addrs = kcalloc(flen + 1, sizeof(*addrs), GFP_KERNEL);
if (addrs == NULL)
return;
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index f1c9577..380cbf9 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -949,7 +949,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
goto skip_init_ctx;
}
- addrs = kzalloc((flen+1) * sizeof(*addrs), GFP_KERNEL);
+ addrs = kcalloc(flen + 1, sizeof(*addrs), GFP_KERNEL);
if (addrs == NULL) {
fp = org_fp;
goto out_addrs;
diff --git a/arch/powerpc/oprofile/cell/spu_profiler.c b/arch/powerpc/oprofile/cell/spu_profiler.c
index 5182f29..4e099e5 100644
--- a/arch/powerpc/oprofile/cell/spu_profiler.c
+++ b/arch/powerpc/oprofile/cell/spu_profiler.c
@@ -210,8 +210,8 @@ int start_spu_profiling_cycles(unsigned int cycles_reset)
timer.function = profile_spus;
/* Allocate arrays for collecting SPU PC samples */
- samples = kzalloc(SPUS_PER_NODE *
- TRACE_ARRAY_SIZE * sizeof(u32), GFP_KERNEL);
+ samples = kcalloc(SPUS_PER_NODE * TRACE_ARRAY_SIZE, sizeof(u32),
+ GFP_KERNEL);
if (!samples)
return -ENOMEM;
diff --git a/arch/powerpc/platforms/4xx/hsta_msi.c b/arch/powerpc/platforms/4xx/hsta_msi.c
index 9926ad6..1c18f29 100644
--- a/arch/powerpc/platforms/4xx/hsta_msi.c
+++ b/arch/powerpc/platforms/4xx/hsta_msi.c
@@ -156,7 +156,8 @@ static int hsta_msi_probe(struct platform_device *pdev)
if (ret)
goto out;
- ppc4xx_hsta_msi.irq_map = kmalloc(sizeof(int) * irq_count, GFP_KERNEL);
+ ppc4xx_hsta_msi.irq_map = kmalloc_array(irq_count, sizeof(int),
+ GFP_KERNEL);
if (!ppc4xx_hsta_msi.irq_map) {
ret = -ENOMEM;
goto out1;
diff --git a/arch/powerpc/platforms/4xx/msi.c b/arch/powerpc/platforms/4xx/msi.c
index 96aaae6..81b2cbc 100644
--- a/arch/powerpc/platforms/4xx/msi.c
+++ b/arch/powerpc/platforms/4xx/msi.c
@@ -89,7 +89,7 @@ static int ppc4xx_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
if (type == PCI_CAP_ID_MSIX)
pr_debug("ppc4xx msi: MSI-X untested, trying anyway.\n");
- msi_data->msi_virqs = kmalloc((msi_irqs) * sizeof(int), GFP_KERNEL);
+ msi_data->msi_virqs = kmalloc_array(msi_irqs, sizeof(int), GFP_KERNEL);
if (!msi_data->msi_virqs)
return -ENOMEM;
diff --git a/arch/powerpc/platforms/4xx/pci.c b/arch/powerpc/platforms/4xx/pci.c
index 73e6b36..5aca523 100644
--- a/arch/powerpc/platforms/4xx/pci.c
+++ b/arch/powerpc/platforms/4xx/pci.c
@@ -1449,7 +1449,7 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
count = ppc4xx_pciex_hwops->core_init(np);
if (count > 0) {
ppc4xx_pciex_ports =
- kzalloc(count * sizeof(struct ppc4xx_pciex_port),
+ kcalloc(count, sizeof(struct ppc4xx_pciex_port),
GFP_KERNEL);
if (ppc4xx_pciex_ports) {
ppc4xx_pciex_port_count = count;
diff --git a/arch/powerpc/platforms/powernv/opal-sysparam.c b/arch/powerpc/platforms/powernv/opal-sysparam.c
index 6fd4092..9aa87df 100644
--- a/arch/powerpc/platforms/powernv/opal-sysparam.c
+++ b/arch/powerpc/platforms/powernv/opal-sysparam.c
@@ -198,21 +198,21 @@ void __init opal_sys_param_init(void)
goto out_param_buf;
}
- id = kzalloc(sizeof(*id) * count, GFP_KERNEL);
+ id = kcalloc(count, sizeof(*id), GFP_KERNEL);
if (!id) {
pr_err("SYSPARAM: Failed to allocate memory to read parameter "
"id\n");
goto out_param_buf;
}
- size = kzalloc(sizeof(*size) * count, GFP_KERNEL);
+ size = kcalloc(count, sizeof(*size), GFP_KERNEL);
if (!size) {
pr_err("SYSPARAM: Failed to allocate memory to read parameter "
"size\n");
goto out_free_id;
}
- perm = kzalloc(sizeof(*perm) * count, GFP_KERNEL);
+ perm = kcalloc(count, sizeof(*perm), GFP_KERNEL);
if (!perm) {
pr_err("SYSPARAM: Failed to allocate memory to read supported "
"action on the parameter");
@@ -235,7 +235,7 @@ void __init opal_sys_param_init(void)
goto out_free_perm;
}
- attr = kzalloc(sizeof(*attr) * count, GFP_KERNEL);
+ attr = kcalloc(count, sizeof(*attr), GFP_KERNEL);
if (!attr) {
pr_err("SYSPARAM: Failed to allocate memory for parameter "
"attributes\n");
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 1d4e0ef6..353b439 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -544,7 +544,7 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n");
/* Allocate fixups array */
- mpic->fixups = kzalloc(128 * sizeof(*mpic->fixups), GFP_KERNEL);
+ mpic->fixups = kcalloc(128, sizeof(*mpic->fixups), GFP_KERNEL);
BUG_ON(mpic->fixups == NULL);
/* Init spinlock */
@@ -1324,7 +1324,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
if (psrc) {
/* Allocate a bitmap with one bit per interrupt */
unsigned int mapsize = BITS_TO_LONGS(intvec_top + 1);
- mpic->protected = kzalloc(mapsize*sizeof(long), GFP_KERNEL);
+ mpic->protected = kcalloc(mapsize, sizeof(long), GFP_KERNEL);
BUG_ON(mpic->protected == NULL);
for (i = 0; i < psize/sizeof(u32); i++) {
if (psrc[i] > intvec_top)
@@ -1639,8 +1639,9 @@ void __init mpic_init(struct mpic *mpic)
#ifdef CONFIG_PM
/* allocate memory to save mpic state */
- mpic->save_data = kmalloc(mpic->num_sources * sizeof(*mpic->save_data),
- GFP_KERNEL);
+ mpic->save_data = kmalloc_array(mpic->num_sources,
+ sizeof(*mpic->save_data),
+ GFP_KERNEL);
BUG_ON(mpic->save_data == NULL);
#endif
diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c
index 83bcd72..311185b 100644
--- a/arch/powerpc/sysdev/xive/native.c
+++ b/arch/powerpc/sysdev/xive/native.c
@@ -489,7 +489,7 @@ static bool xive_parse_provisioning(struct device_node *np)
if (rc == 0)
return true;
- xive_provision_chips = kzalloc(4 * xive_provision_chip_count,
+ xive_provision_chips = kcalloc(4, xive_provision_chip_count,
GFP_KERNEL);
if (WARN_ON(!xive_provision_chips))
return false;
diff --git a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
index a7dd0e5..137f337 100755
--- a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
+++ b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh
@@ -24,5 +24,4 @@ echo -e "#include <linux/compiler.h>\nnotrace int func() { return 0; }" | \
2> /dev/null | grep -q "_mcount" && \
exit 1
-echo "OK"
exit 0
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 17f19e6..f12680c 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -32,6 +32,7 @@ config RISCV
select HAVE_MEMBLOCK_NODE_MAP
select HAVE_DMA_CONTIGUOUS
select HAVE_GENERIC_DMA_COHERENT
+ select HAVE_PERF_EVENTS
select IRQ_DOMAIN
select NO_BOOTMEM
select RISCV_ISA_A if SMP
@@ -103,9 +104,9 @@ choice
config ARCH_RV32I
bool "RV32I"
select 32BIT
- select GENERIC_ASHLDI3
- select GENERIC_ASHRDI3
- select GENERIC_LSHRDI3
+ select GENERIC_LIB_ASHLDI3
+ select GENERIC_LIB_ASHRDI3
+ select GENERIC_LIB_LSHRDI3
config ARCH_RV64I
bool "RV64I"
@@ -193,6 +194,19 @@ config RISCV_ISA_C
config RISCV_ISA_A
def_bool y
+menu "supported PMU type"
+ depends on PERF_EVENTS
+
+config RISCV_BASE_PMU
+ bool "Base Performance Monitoring Unit"
+ def_bool y
+ help
+ A base PMU that serves as a reference implementation and has limited
+ feature of perf. It can run on any RISC-V machines so serves as the
+ fallback, but this option can also be disable to reduce kernel size.
+
+endmenu
+
endmenu
menu "Kernel type"
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 76e958a..6d4a5f6c 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -71,6 +71,9 @@ KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-relax)
# architectures. It's faster to have GCC emit only aligned accesses.
KBUILD_CFLAGS += $(call cc-option,-mstrict-align)
+# arch specific predefines for sparse
+CHECKFLAGS += -D__riscv -D__riscv_xlen=$(BITS)
+
head-y := arch/riscv/kernel/head.o
core-y += arch/riscv/kernel/ arch/riscv/mm/
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index bca0eee..0732646 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -44,6 +44,7 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_HVC_RISCV_SBI=y
# CONFIG_PTP_1588_CLOCK is not set
CONFIG_DRM=y
CONFIG_DRM_RADEON=y
diff --git a/arch/riscv/include/asm/Kbuild b/arch/riscv/include/asm/Kbuild
index 4286a5f..576ffdca 100644
--- a/arch/riscv/include/asm/Kbuild
+++ b/arch/riscv/include/asm/Kbuild
@@ -25,6 +25,7 @@ generic-y += kdebug.h
generic-y += kmap_types.h
generic-y += kvm_para.h
generic-y += local.h
+generic-y += local64.h
generic-y += mm-arch-hooks.h
generic-y += mman.h
generic-y += module.h
diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h
index efd89a8..8f13074 100644
--- a/arch/riscv/include/asm/cacheflush.h
+++ b/arch/riscv/include/asm/cacheflush.h
@@ -47,7 +47,7 @@ static inline void flush_dcache_page(struct page *page)
#else /* CONFIG_SMP */
-#define flush_icache_all() sbi_remote_fence_i(0)
+#define flush_icache_all() sbi_remote_fence_i(NULL)
void flush_icache_mm(struct mm_struct *mm, bool local);
#endif /* CONFIG_SMP */
diff --git a/arch/riscv/include/asm/perf_event.h b/arch/riscv/include/asm/perf_event.h
new file mode 100644
index 0000000..0e638a0
--- /dev/null
+++ b/arch/riscv/include/asm/perf_event.h
@@ -0,0 +1,84 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 SiFive
+ * Copyright (C) 2018 Andes Technology Corporation
+ *
+ */
+
+#ifndef _ASM_RISCV_PERF_EVENT_H
+#define _ASM_RISCV_PERF_EVENT_H
+
+#include <linux/perf_event.h>
+#include <linux/ptrace.h>
+
+#define RISCV_BASE_COUNTERS 2
+
+/*
+ * The RISCV_MAX_COUNTERS parameter should be specified.
+ */
+
+#ifdef CONFIG_RISCV_BASE_PMU
+#define RISCV_MAX_COUNTERS 2
+#endif
+
+#ifndef RISCV_MAX_COUNTERS
+#error "Please provide a valid RISCV_MAX_COUNTERS for the PMU."
+#endif
+
+/*
+ * These are the indexes of bits in counteren register *minus* 1,
+ * except for cycle. It would be coherent if it can directly mapped
+ * to counteren bit definition, but there is a *time* register at
+ * counteren[1]. Per-cpu structure is scarce resource here.
+ *
+ * According to the spec, an implementation can support counter up to
+ * mhpmcounter31, but many high-end processors has at most 6 general
+ * PMCs, we give the definition to MHPMCOUNTER8 here.
+ */
+#define RISCV_PMU_CYCLE 0
+#define RISCV_PMU_INSTRET 1
+#define RISCV_PMU_MHPMCOUNTER3 2
+#define RISCV_PMU_MHPMCOUNTER4 3
+#define RISCV_PMU_MHPMCOUNTER5 4
+#define RISCV_PMU_MHPMCOUNTER6 5
+#define RISCV_PMU_MHPMCOUNTER7 6
+#define RISCV_PMU_MHPMCOUNTER8 7
+
+#define RISCV_OP_UNSUPP (-EOPNOTSUPP)
+
+struct cpu_hw_events {
+ /* # currently enabled events*/
+ int n_events;
+ /* currently enabled events */
+ struct perf_event *events[RISCV_MAX_COUNTERS];
+ /* vendor-defined PMU data */
+ void *platform;
+};
+
+struct riscv_pmu {
+ struct pmu *pmu;
+
+ /* generic hw/cache events table */
+ const int *hw_events;
+ const int (*cache_events)[PERF_COUNT_HW_CACHE_MAX]
+ [PERF_COUNT_HW_CACHE_OP_MAX]
+ [PERF_COUNT_HW_CACHE_RESULT_MAX];
+ /* method used to map hw/cache events */
+ int (*map_hw_event)(u64 config);
+ int (*map_cache_event)(u64 config);
+
+ /* max generic hw events in map */
+ int max_events;
+ /* number total counters, 2(base) + x(general) */
+ int num_counters;
+ /* the width of the counter */
+ int counter_width;
+
+ /* vendor-defined PMU features */
+ void *platform;
+
+ irqreturn_t (*handle_irq)(int irq_num, void *dev);
+ int irq;
+};
+
+#endif /* _ASM_RISCV_PERF_EVENT_H */
diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
index 7b209ae..85c2d8b 100644
--- a/arch/riscv/include/asm/tlbflush.h
+++ b/arch/riscv/include/asm/tlbflush.h
@@ -49,7 +49,7 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
#include <asm/sbi.h>
-#define flush_tlb_all() sbi_remote_sfence_vma(0, 0, -1)
+#define flush_tlb_all() sbi_remote_sfence_vma(NULL, 0, -1)
#define flush_tlb_page(vma, addr) flush_tlb_range(vma, addr, 0)
#define flush_tlb_range(vma, start, end) \
sbi_remote_sfence_vma(mm_cpumask((vma)->vm_mm)->bits, \
diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h
index 14b0b22..473cfc8 100644
--- a/arch/riscv/include/asm/uaccess.h
+++ b/arch/riscv/include/asm/uaccess.h
@@ -392,19 +392,21 @@ do { \
})
-extern unsigned long __must_check __copy_user(void __user *to,
+extern unsigned long __must_check __asm_copy_to_user(void __user *to,
+ const void *from, unsigned long n);
+extern unsigned long __must_check __asm_copy_from_user(void *to,
const void __user *from, unsigned long n);
static inline unsigned long
raw_copy_from_user(void *to, const void __user *from, unsigned long n)
{
- return __copy_user(to, from, n);
+ return __asm_copy_to_user(to, from, n);
}
static inline unsigned long
raw_copy_to_user(void __user *to, const void *from, unsigned long n)
{
- return __copy_user(to, from, n);
+ return __asm_copy_from_user(to, from, n);
}
extern long strncpy_from_user(char *dest, const char __user *src, long count);
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index 8586dd9..e1274fc 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -39,4 +39,6 @@ obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o
obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o
+obj-$(CONFIG_PERF_EVENTS) += perf_event.o
+
clean:
diff --git a/arch/riscv/kernel/mcount.S b/arch/riscv/kernel/mcount.S
index ce9bdc5..5721624 100644
--- a/arch/riscv/kernel/mcount.S
+++ b/arch/riscv/kernel/mcount.S
@@ -126,5 +126,5 @@ do_trace:
RESTORE_ABI_STATE
ret
ENDPROC(_mcount)
-EXPORT_SYMBOL(_mcount)
#endif
+EXPORT_SYMBOL(_mcount)
diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
index 5dddba3..1d5e9b9 100644
--- a/arch/riscv/kernel/module.c
+++ b/arch/riscv/kernel/module.c
@@ -17,6 +17,17 @@
#include <linux/errno.h>
#include <linux/moduleloader.h>
+static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v)
+{
+ if (v != (u32)v) {
+ pr_err("%s: value %016llx out of range for 32-bit field\n",
+ me->name, v);
+ return -EINVAL;
+ }
+ *location = v;
+ return 0;
+}
+
static int apply_r_riscv_64_rela(struct module *me, u32 *location, Elf_Addr v)
{
*(u64 *)location = v;
@@ -265,6 +276,7 @@ static int apply_r_riscv_sub32_rela(struct module *me, u32 *location,
static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
Elf_Addr v) = {
+ [R_RISCV_32] = apply_r_riscv_32_rela,
[R_RISCV_64] = apply_r_riscv_64_rela,
[R_RISCV_BRANCH] = apply_r_riscv_branch_rela,
[R_RISCV_JAL] = apply_r_riscv_jal_rela,
diff --git a/arch/riscv/kernel/perf_event.c b/arch/riscv/kernel/perf_event.c
new file mode 100644
index 0000000..b0e10c4
--- /dev/null
+++ b/arch/riscv/kernel/perf_event.c
@@ -0,0 +1,485 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2008 Thomas Gleixner <tglx@linutronix.de>
+ * Copyright (C) 2008-2009 Red Hat, Inc., Ingo Molnar
+ * Copyright (C) 2009 Jaswinder Singh Rajput
+ * Copyright (C) 2009 Advanced Micro Devices, Inc., Robert Richter
+ * Copyright (C) 2008-2009 Red Hat, Inc., Peter Zijlstra
+ * Copyright (C) 2009 Intel Corporation, <markus.t.metzger@intel.com>
+ * Copyright (C) 2009 Google, Inc., Stephane Eranian
+ * Copyright 2014 Tilera Corporation. All Rights Reserved.
+ * Copyright (C) 2018 Andes Technology Corporation
+ *
+ * Perf_events support for RISC-V platforms.
+ *
+ * Since the spec. (as of now, Priv-Spec 1.10) does not provide enough
+ * functionality for perf event to fully work, this file provides
+ * the very basic framework only.
+ *
+ * For platform portings, please check Documentations/riscv/pmu.txt.
+ *
+ * The Copyright line includes x86 and tile ones.
+ */
+
+#include <linux/kprobes.h>
+#include <linux/kernel.h>
+#include <linux/kdebug.h>
+#include <linux/mutex.h>
+#include <linux/bitmap.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/perf_event.h>
+#include <linux/atomic.h>
+#include <linux/of.h>
+#include <asm/perf_event.h>
+
+static const struct riscv_pmu *riscv_pmu __read_mostly;
+static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events);
+
+/*
+ * Hardware & cache maps and their methods
+ */
+
+static const int riscv_hw_event_map[] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = RISCV_PMU_CYCLE,
+ [PERF_COUNT_HW_INSTRUCTIONS] = RISCV_PMU_INSTRET,
+ [PERF_COUNT_HW_CACHE_REFERENCES] = RISCV_OP_UNSUPP,
+ [PERF_COUNT_HW_CACHE_MISSES] = RISCV_OP_UNSUPP,
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = RISCV_OP_UNSUPP,
+ [PERF_COUNT_HW_BRANCH_MISSES] = RISCV_OP_UNSUPP,
+ [PERF_COUNT_HW_BUS_CYCLES] = RISCV_OP_UNSUPP,
+};
+
+#define C(x) PERF_COUNT_HW_CACHE_##x
+static const int riscv_cache_event_map[PERF_COUNT_HW_CACHE_MAX]
+[PERF_COUNT_HW_CACHE_OP_MAX]
+[PERF_COUNT_HW_CACHE_RESULT_MAX] = {
+ [C(L1D)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+ [C(L1I)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+ [C(LL)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+ [C(DTLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+ [C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+ [C(BPU)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ [C(OP_PREFETCH)] = {
+ [C(RESULT_ACCESS)] = RISCV_OP_UNSUPP,
+ [C(RESULT_MISS)] = RISCV_OP_UNSUPP,
+ },
+ },
+};
+
+static int riscv_map_hw_event(u64 config)
+{
+ if (config >= riscv_pmu->max_events)
+ return -EINVAL;
+
+ return riscv_pmu->hw_events[config];
+}
+
+int riscv_map_cache_decode(u64 config, unsigned int *type,
+ unsigned int *op, unsigned int *result)
+{
+ return -ENOENT;
+}
+
+static int riscv_map_cache_event(u64 config)
+{
+ unsigned int type, op, result;
+ int err = -ENOENT;
+ int code;
+
+ err = riscv_map_cache_decode(config, &type, &op, &result);
+ if (!riscv_pmu->cache_events || err)
+ return err;
+
+ if (type >= PERF_COUNT_HW_CACHE_MAX ||
+ op >= PERF_COUNT_HW_CACHE_OP_MAX ||
+ result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
+ return -EINVAL;
+
+ code = (*riscv_pmu->cache_events)[type][op][result];
+ if (code == RISCV_OP_UNSUPP)
+ return -EINVAL;
+
+ return code;
+}
+
+/*
+ * Low-level functions: reading/writing counters
+ */
+
+static inline u64 read_counter(int idx)
+{
+ u64 val = 0;
+
+ switch (idx) {
+ case RISCV_PMU_CYCLE:
+ val = csr_read(cycle);
+ break;
+ case RISCV_PMU_INSTRET:
+ val = csr_read(instret);
+ break;
+ default:
+ WARN_ON_ONCE(idx < 0 || idx > RISCV_MAX_COUNTERS);
+ return -EINVAL;
+ }
+
+ return val;
+}
+
+static inline void write_counter(int idx, u64 value)
+{
+ /* currently not supported */
+ WARN_ON_ONCE(1);
+}
+
+/*
+ * pmu->read: read and update the counter
+ *
+ * Other architectures' implementation often have a xxx_perf_event_update
+ * routine, which can return counter values when called in the IRQ, but
+ * return void when being called by the pmu->read method.
+ */
+static void riscv_pmu_read(struct perf_event *event)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ u64 prev_raw_count, new_raw_count;
+ u64 oldval;
+ int idx = hwc->idx;
+ u64 delta;
+
+ do {
+ prev_raw_count = local64_read(&hwc->prev_count);
+ new_raw_count = read_counter(idx);
+
+ oldval = local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+ new_raw_count);
+ } while (oldval != prev_raw_count);
+
+ /*
+ * delta is the value to update the counter we maintain in the kernel.
+ */
+ delta = (new_raw_count - prev_raw_count) &
+ ((1ULL << riscv_pmu->counter_width) - 1);
+ local64_add(delta, &event->count);
+ /*
+ * Something like local64_sub(delta, &hwc->period_left) here is
+ * needed if there is an interrupt for perf.
+ */
+}
+
+/*
+ * State transition functions:
+ *
+ * stop()/start() & add()/del()
+ */
+
+/*
+ * pmu->stop: stop the counter
+ */
+static void riscv_pmu_stop(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+ hwc->state |= PERF_HES_STOPPED;
+
+ if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+ riscv_pmu->pmu->read(event);
+ hwc->state |= PERF_HES_UPTODATE;
+ }
+}
+
+/*
+ * pmu->start: start the event.
+ */
+static void riscv_pmu_start(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+
+ if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+ return;
+
+ if (flags & PERF_EF_RELOAD) {
+ WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+
+ /*
+ * Set the counter to the period to the next interrupt here,
+ * if you have any.
+ */
+ }
+
+ hwc->state = 0;
+ perf_event_update_userpage(event);
+
+ /*
+ * Since we cannot write to counters, this serves as an initialization
+ * to the delta-mechanism in pmu->read(); otherwise, the delta would be
+ * wrong when pmu->read is called for the first time.
+ */
+ local64_set(&hwc->prev_count, read_counter(hwc->idx));
+}
+
+/*
+ * pmu->add: add the event to PMU.
+ */
+static int riscv_pmu_add(struct perf_event *event, int flags)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ struct hw_perf_event *hwc = &event->hw;
+
+ if (cpuc->n_events == riscv_pmu->num_counters)
+ return -ENOSPC;
+
+ /*
+ * We don't have general conunters, so no binding-event-to-counter
+ * process here.
+ *
+ * Indexing using hwc->config generally not works, since config may
+ * contain extra information, but here the only info we have in
+ * hwc->config is the event index.
+ */
+ hwc->idx = hwc->config;
+ cpuc->events[hwc->idx] = event;
+ cpuc->n_events++;
+
+ hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+ if (flags & PERF_EF_START)
+ riscv_pmu->pmu->start(event, PERF_EF_RELOAD);
+
+ return 0;
+}
+
+/*
+ * pmu->del: delete the event from PMU.
+ */
+static void riscv_pmu_del(struct perf_event *event, int flags)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ struct hw_perf_event *hwc = &event->hw;
+
+ cpuc->events[hwc->idx] = NULL;
+ cpuc->n_events--;
+ riscv_pmu->pmu->stop(event, PERF_EF_UPDATE);
+ perf_event_update_userpage(event);
+}
+
+/*
+ * Interrupt: a skeletion for reference.
+ */
+
+static DEFINE_MUTEX(pmc_reserve_mutex);
+
+irqreturn_t riscv_base_pmu_handle_irq(int irq_num, void *dev)
+{
+ return IRQ_NONE;
+}
+
+static int reserve_pmc_hardware(void)
+{
+ int err = 0;
+
+ mutex_lock(&pmc_reserve_mutex);
+ if (riscv_pmu->irq >= 0 && riscv_pmu->handle_irq) {
+ err = request_irq(riscv_pmu->irq, riscv_pmu->handle_irq,
+ IRQF_PERCPU, "riscv-base-perf", NULL);
+ }
+ mutex_unlock(&pmc_reserve_mutex);
+
+ return err;
+}
+
+void release_pmc_hardware(void)
+{
+ mutex_lock(&pmc_reserve_mutex);
+ if (riscv_pmu->irq >= 0)
+ free_irq(riscv_pmu->irq, NULL);
+ mutex_unlock(&pmc_reserve_mutex);
+}
+
+/*
+ * Event Initialization/Finalization
+ */
+
+static atomic_t riscv_active_events = ATOMIC_INIT(0);
+
+static void riscv_event_destroy(struct perf_event *event)
+{
+ if (atomic_dec_return(&riscv_active_events) == 0)
+ release_pmc_hardware();
+}
+
+static int riscv_event_init(struct perf_event *event)
+{
+ struct perf_event_attr *attr = &event->attr;
+ struct hw_perf_event *hwc = &event->hw;
+ int err;
+ int code;
+
+ if (atomic_inc_return(&riscv_active_events) == 1) {
+ err = reserve_pmc_hardware();
+
+ if (err) {
+ pr_warn("PMC hardware not available\n");
+ atomic_dec(&riscv_active_events);
+ return -EBUSY;
+ }
+ }
+
+ switch (event->attr.type) {
+ case PERF_TYPE_HARDWARE:
+ code = riscv_pmu->map_hw_event(attr->config);
+ break;
+ case PERF_TYPE_HW_CACHE:
+ code = riscv_pmu->map_cache_event(attr->config);
+ break;
+ case PERF_TYPE_RAW:
+ return -EOPNOTSUPP;
+ default:
+ return -ENOENT;
+ }
+
+ event->destroy = riscv_event_destroy;
+ if (code < 0) {
+ event->destroy(event);
+ return code;
+ }
+
+ /*
+ * idx is set to -1 because the index of a general event should not be
+ * decided until binding to some counter in pmu->add().
+ *
+ * But since we don't have such support, later in pmu->add(), we just
+ * use hwc->config as the index instead.
+ */
+ hwc->config = code;
+ hwc->idx = -1;
+
+ return 0;
+}
+
+/*
+ * Initialization
+ */
+
+static struct pmu min_pmu = {
+ .name = "riscv-base",
+ .event_init = riscv_event_init,
+ .add = riscv_pmu_add,
+ .del = riscv_pmu_del,
+ .start = riscv_pmu_start,
+ .stop = riscv_pmu_stop,
+ .read = riscv_pmu_read,
+};
+
+static const struct riscv_pmu riscv_base_pmu = {
+ .pmu = &min_pmu,
+ .max_events = ARRAY_SIZE(riscv_hw_event_map),
+ .map_hw_event = riscv_map_hw_event,
+ .hw_events = riscv_hw_event_map,
+ .map_cache_event = riscv_map_cache_event,
+ .cache_events = &riscv_cache_event_map,
+ .counter_width = 63,
+ .num_counters = RISCV_BASE_COUNTERS + 0,
+ .handle_irq = &riscv_base_pmu_handle_irq,
+
+ /* This means this PMU has no IRQ. */
+ .irq = -1,
+};
+
+static const struct of_device_id riscv_pmu_of_ids[] = {
+ {.compatible = "riscv,base-pmu", .data = &riscv_base_pmu},
+ { /* sentinel value */ }
+};
+
+int __init init_hw_perf_events(void)
+{
+ struct device_node *node = of_find_node_by_type(NULL, "pmu");
+ const struct of_device_id *of_id;
+
+ riscv_pmu = &riscv_base_pmu;
+
+ if (node) {
+ of_id = of_match_node(riscv_pmu_of_ids, node);
+
+ if (of_id)
+ riscv_pmu = of_id->data;
+ }
+
+ perf_pmu_register(riscv_pmu->pmu, "cpu", PERF_TYPE_RAW);
+ return 0;
+}
+arch_initcall(init_hw_perf_events);
diff --git a/arch/riscv/kernel/riscv_ksyms.c b/arch/riscv/kernel/riscv_ksyms.c
index 5517342..f247d6d 100644
--- a/arch/riscv/kernel/riscv_ksyms.c
+++ b/arch/riscv/kernel/riscv_ksyms.c
@@ -13,6 +13,7 @@
* Assembly functions that may be used (directly or indirectly) by modules
*/
EXPORT_SYMBOL(__clear_user);
-EXPORT_SYMBOL(__copy_user);
+EXPORT_SYMBOL(__asm_copy_to_user);
+EXPORT_SYMBOL(__asm_copy_from_user);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(memcpy);
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index b99d9dd..81a1952 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -148,7 +148,7 @@ int is_valid_bugaddr(unsigned long pc)
if (pc < PAGE_OFFSET)
return 0;
- if (probe_kernel_address((bug_insn_t __user *)pc, insn))
+ if (probe_kernel_address((bug_insn_t *)pc, insn))
return 0;
return (insn == __BUG_INSN);
}
diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S
index 58fb287..399e6f0 100644
--- a/arch/riscv/lib/uaccess.S
+++ b/arch/riscv/lib/uaccess.S
@@ -13,7 +13,8 @@ _epc:
.previous
.endm
-ENTRY(__copy_user)
+ENTRY(__asm_copy_to_user)
+ENTRY(__asm_copy_from_user)
/* Enable access to user memory */
li t6, SR_SUM
@@ -63,7 +64,8 @@ ENTRY(__copy_user)
addi a0, a0, 1
bltu a1, a3, 5b
j 3b
-ENDPROC(__copy_user)
+ENDPROC(__asm_copy_to_user)
+ENDPROC(__asm_copy_from_user)
ENTRY(__clear_user)
@@ -84,7 +86,7 @@ ENTRY(__clear_user)
bgeu t0, t1, 2f
bltu a0, t0, 4f
1:
- fixup REG_S, zero, (a0), 10f
+ fixup REG_S, zero, (a0), 11f
addi a0, a0, SZREG
bltu a0, t1, 1b
2:
@@ -96,12 +98,12 @@ ENTRY(__clear_user)
li a0, 0
ret
4: /* Edge case: unalignment */
- fixup sb, zero, (a0), 10f
+ fixup sb, zero, (a0), 11f
addi a0, a0, 1
bltu a0, t0, 4b
j 1b
5: /* Edge case: remainder */
- fixup sb, zero, (a0), 10f
+ fixup sb, zero, (a0), 11f
addi a0, a0, 1
bltu a0, a3, 5b
j 3b
@@ -109,9 +111,14 @@ ENDPROC(__clear_user)
.section .fixup,"ax"
.balign 4
+ /* Fixup code for __copy_user(10) and __clear_user(11) */
10:
/* Disable access to user memory */
csrs sstatus, t6
- sub a0, a3, a0
+ mv a0, a2
+ ret
+11:
+ csrs sstatus, t6
+ mv a0, a1
ret
.previous
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index cb6e806..ee6a9c3 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -391,7 +391,7 @@ int appldata_register_ops(struct appldata_ops *ops)
if (ops->size > APPLDATA_MAX_REC_SIZE)
return -EINVAL;
- ops->ctl_table = kzalloc(4 * sizeof(struct ctl_table), GFP_KERNEL);
+ ops->ctl_table = kcalloc(4, sizeof(struct ctl_table), GFP_KERNEL);
if (!ops->ctl_table)
return -ENOMEM;
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index be8cc53..a2945b2 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -239,7 +239,7 @@ static void *page_align_ptr(void *ptr)
static void *diag204_alloc_vbuf(int pages)
{
/* The buffer has to be page aligned! */
- diag204_buf_vmalloc = vmalloc(PAGE_SIZE * (pages + 1));
+ diag204_buf_vmalloc = vmalloc(array_size(PAGE_SIZE, (pages + 1)));
if (!diag204_buf_vmalloc)
return ERR_PTR(-ENOMEM);
diag204_buf = page_align_ptr(diag204_buf_vmalloc);
diff --git a/arch/s390/hypfs/hypfs_diag0c.c b/arch/s390/hypfs/hypfs_diag0c.c
index dce87f1b..cebf051 100644
--- a/arch/s390/hypfs/hypfs_diag0c.c
+++ b/arch/s390/hypfs/hypfs_diag0c.c
@@ -49,7 +49,8 @@ static void *diag0c_store(unsigned int *count)
get_online_cpus();
cpu_count = num_online_cpus();
- cpu_vec = kmalloc(sizeof(*cpu_vec) * num_possible_cpus(), GFP_KERNEL);
+ cpu_vec = kmalloc_array(num_possible_cpus(), sizeof(*cpu_vec),
+ GFP_KERNEL);
if (!cpu_vec)
goto fail_put_online_cpus;
/* Note: Diag 0c needs 8 byte alignment and real storage */
diff --git a/arch/s390/include/asm/css_chars.h b/arch/s390/include/asm/css_chars.h
index 0563fd3..480bb02 100644
--- a/arch/s390/include/asm/css_chars.h
+++ b/arch/s390/include/asm/css_chars.h
@@ -6,36 +6,38 @@
struct css_general_char {
u64 : 12;
- u32 dynio : 1; /* bit 12 */
- u32 : 4;
- u32 eadm : 1; /* bit 17 */
- u32 : 23;
- u32 aif : 1; /* bit 41 */
- u32 : 3;
- u32 mcss : 1; /* bit 45 */
- u32 fcs : 1; /* bit 46 */
- u32 : 1;
- u32 ext_mb : 1; /* bit 48 */
- u32 : 7;
- u32 aif_tdd : 1; /* bit 56 */
- u32 : 1;
- u32 qebsm : 1; /* bit 58 */
- u32 : 2;
- u32 aiv : 1; /* bit 61 */
- u32 : 5;
- u32 aif_osa : 1; /* bit 67 */
- u32 : 12;
- u32 eadm_rf : 1; /* bit 80 */
- u32 : 1;
- u32 cib : 1; /* bit 82 */
- u32 : 5;
- u32 fcx : 1; /* bit 88 */
- u32 : 19;
- u32 alt_ssi : 1; /* bit 108 */
- u32 : 1;
- u32 narf : 1; /* bit 110 */
- u32 : 12;
- u32 util_str : 1;/* bit 123 */
+ u64 dynio : 1; /* bit 12 */
+ u64 : 4;
+ u64 eadm : 1; /* bit 17 */
+ u64 : 23;
+ u64 aif : 1; /* bit 41 */
+ u64 : 3;
+ u64 mcss : 1; /* bit 45 */
+ u64 fcs : 1; /* bit 46 */
+ u64 : 1;
+ u64 ext_mb : 1; /* bit 48 */
+ u64 : 7;
+ u64 aif_tdd : 1; /* bit 56 */
+ u64 : 1;
+ u64 qebsm : 1; /* bit 58 */
+ u64 : 2;
+ u64 aiv : 1; /* bit 61 */
+ u64 : 2;
+
+ u64 : 3;
+ u64 aif_osa : 1; /* bit 67 */
+ u64 : 12;
+ u64 eadm_rf : 1; /* bit 80 */
+ u64 : 1;
+ u64 cib : 1; /* bit 82 */
+ u64 : 5;
+ u64 fcx : 1; /* bit 88 */
+ u64 : 19;
+ u64 alt_ssi : 1; /* bit 108 */
+ u64 : 1;
+ u64 narf : 1; /* bit 110 */
+ u64 : 12;
+ u64 util_str : 1;/* bit 123 */
} __packed;
extern struct css_general_char css_general_characteristics;
diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h
index 99c93d0..4600453 100644
--- a/arch/s390/include/asm/ctl_reg.h
+++ b/arch/s390/include/asm/ctl_reg.h
@@ -10,8 +10,20 @@
#include <linux/const.h>
+#define CR0_CLOCK_COMPARATOR_SIGN _BITUL(63 - 10)
+#define CR0_EMERGENCY_SIGNAL_SUBMASK _BITUL(63 - 49)
+#define CR0_EXTERNAL_CALL_SUBMASK _BITUL(63 - 50)
+#define CR0_CLOCK_COMPARATOR_SUBMASK _BITUL(63 - 52)
+#define CR0_CPU_TIMER_SUBMASK _BITUL(63 - 53)
+#define CR0_SERVICE_SIGNAL_SUBMASK _BITUL(63 - 54)
+#define CR0_UNUSED_56 _BITUL(63 - 56)
+#define CR0_INTERRUPT_KEY_SUBMASK _BITUL(63 - 57)
+#define CR0_MEASUREMENT_ALERT_SUBMASK _BITUL(63 - 58)
+
#define CR2_GUARDED_STORAGE _BITUL(63 - 59)
+#define CR14_UNUSED_32 _BITUL(63 - 32)
+#define CR14_UNUSED_33 _BITUL(63 - 33)
#define CR14_CHANNEL_REPORT_SUBMASK _BITUL(63 - 35)
#define CR14_RECOVERY_SUBMASK _BITUL(63 - 36)
#define CR14_DEGRADATION_SUBMASK _BITUL(63 - 37)
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 81cdb6b..a2188e3 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -812,6 +812,7 @@ struct kvm_arch{
int use_irqchip;
int use_cmma;
int use_pfmfi;
+ int use_skf;
int user_cpu_state_ctrl;
int user_sigp;
int user_stsi;
diff --git a/arch/s390/include/asm/mmu.h b/arch/s390/include/asm/mmu.h
index c639c95..f5ff9db 100644
--- a/arch/s390/include/asm/mmu.h
+++ b/arch/s390/include/asm/mmu.h
@@ -21,7 +21,7 @@ typedef struct {
/* The mmu context uses extended page tables. */
unsigned int has_pgste:1;
/* The mmu context uses storage keys. */
- unsigned int use_skey:1;
+ unsigned int uses_skeys:1;
/* The mmu context uses CMM. */
unsigned int uses_cmm:1;
} mm_context_t;
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h
index 324f6f4..d16bc79 100644
--- a/arch/s390/include/asm/mmu_context.h
+++ b/arch/s390/include/asm/mmu_context.h
@@ -30,7 +30,7 @@ static inline int init_new_context(struct task_struct *tsk,
test_thread_flag(TIF_PGSTE) ||
(current->mm && current->mm->context.alloc_pgste);
mm->context.has_pgste = 0;
- mm->context.use_skey = 0;
+ mm->context.uses_skeys = 0;
mm->context.uses_cmm = 0;
#endif
switch (mm->context.asce_limit) {
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 9809694..5ab6360 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -506,10 +506,10 @@ static inline int mm_alloc_pgste(struct mm_struct *mm)
* faults should no longer be backed by zero pages
*/
#define mm_forbids_zeropage mm_has_pgste
-static inline int mm_use_skey(struct mm_struct *mm)
+static inline int mm_uses_skeys(struct mm_struct *mm)
{
#ifdef CONFIG_PGSTE
- if (mm->context.use_skey)
+ if (mm->context.uses_skeys)
return 1;
#endif
return 0;
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 80e974a..d374f9b 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -194,11 +194,13 @@ static debug_entry_t ***debug_areas_alloc(int pages_per_area, int nr_areas)
debug_entry_t ***areas;
int i, j;
- areas = kmalloc(nr_areas * sizeof(debug_entry_t **), GFP_KERNEL);
+ areas = kmalloc_array(nr_areas, sizeof(debug_entry_t **), GFP_KERNEL);
if (!areas)
goto fail_malloc_areas;
for (i = 0; i < nr_areas; i++) {
- areas[i] = kmalloc(pages_per_area * sizeof(debug_entry_t *), GFP_KERNEL);
+ areas[i] = kmalloc_array(pages_per_area,
+ sizeof(debug_entry_t *),
+ GFP_KERNEL);
if (!areas[i])
goto fail_malloc_areas2;
for (j = 0; j < pages_per_area; j++) {
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c
index 0dc8ac8..d298d3c 100644
--- a/arch/s390/kernel/module.c
+++ b/arch/s390/kernel/module.c
@@ -123,8 +123,8 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
/* Allocate one syminfo structure per symbol. */
me->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym);
- me->arch.syminfo = vmalloc(me->arch.nsyms *
- sizeof(struct mod_arch_syminfo));
+ me->arch.syminfo = vmalloc(array_size(sizeof(struct mod_arch_syminfo),
+ me->arch.nsyms));
if (!me->arch.syminfo)
return -ENOMEM;
symbols = (void *) hdr + symtab->sh_offset;
diff --git a/arch/s390/kernel/perf_cpum_cf_events.c b/arch/s390/kernel/perf_cpum_cf_events.c
index feebb29..d63fb3c 100644
--- a/arch/s390/kernel/perf_cpum_cf_events.c
+++ b/arch/s390/kernel/perf_cpum_cf_events.c
@@ -527,7 +527,7 @@ static __init struct attribute **merge_attr(struct attribute **a,
j++;
j++;
- new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL);
+ new = kmalloc_array(j, sizeof(struct attribute *), GFP_KERNEL);
if (!new)
return NULL;
j = 0;
diff --git a/arch/s390/kernel/sthyi.c b/arch/s390/kernel/sthyi.c
index 80b862e..0859cde 100644
--- a/arch/s390/kernel/sthyi.c
+++ b/arch/s390/kernel/sthyi.c
@@ -315,7 +315,7 @@ static void fill_diag(struct sthyi_sctns *sctns)
if (pages <= 0)
return;
- diag204_buf = vmalloc(PAGE_SIZE * pages);
+ diag204_buf = vmalloc(array_size(pages, PAGE_SIZE));
if (!diag204_buf)
return;
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index f3a1c7c..09abae4 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -285,7 +285,7 @@ static int __init vdso_init(void)
+ PAGE_SIZE - 1) >> PAGE_SHIFT) + 1;
/* Make sure pages are in the correct state */
- vdso32_pagelist = kzalloc(sizeof(struct page *) * (vdso32_pages + 1),
+ vdso32_pagelist = kcalloc(vdso32_pages + 1, sizeof(struct page *),
GFP_KERNEL);
BUG_ON(vdso32_pagelist == NULL);
for (i = 0; i < vdso32_pages - 1; i++) {
@@ -303,7 +303,7 @@ static int __init vdso_init(void)
+ PAGE_SIZE - 1) >> PAGE_SHIFT) + 1;
/* Make sure pages are in the correct state */
- vdso64_pagelist = kzalloc(sizeof(struct page *) * (vdso64_pages + 1),
+ vdso64_pagelist = kcalloc(vdso64_pages + 1, sizeof(struct page *),
GFP_KERNEL);
BUG_ON(vdso64_pagelist == NULL);
for (i = 0; i < vdso64_pages - 1; i++) {
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index 8e2b864..07d30ff 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -847,7 +847,7 @@ int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,
nr_pages = (((ga & ~PAGE_MASK) + len - 1) >> PAGE_SHIFT) + 1;
pages = pages_array;
if (nr_pages > ARRAY_SIZE(pages_array))
- pages = vmalloc(nr_pages * sizeof(unsigned long));
+ pages = vmalloc(array_size(nr_pages, sizeof(unsigned long)));
if (!pages)
return -ENOMEM;
need_ipte_lock = psw_bits(*psw).dat && !asce.r;
diff --git a/arch/s390/kvm/guestdbg.c b/arch/s390/kvm/guestdbg.c
index b5f3e82..394a5f5 100644
--- a/arch/s390/kvm/guestdbg.c
+++ b/arch/s390/kvm/guestdbg.c
@@ -153,7 +153,7 @@ void kvm_s390_patch_guest_per_regs(struct kvm_vcpu *vcpu)
if (guestdbg_sstep_enabled(vcpu)) {
/* disable timer (clock-comparator) interrupts */
- vcpu->arch.sie_block->gcr[0] &= ~0x800ul;
+ vcpu->arch.sie_block->gcr[0] &= ~CR0_CLOCK_COMPARATOR_SUBMASK;
vcpu->arch.sie_block->gcr[9] |= PER_EVENT_IFETCH;
vcpu->arch.sie_block->gcr[10] = 0;
vcpu->arch.sie_block->gcr[11] = -1UL;
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 37d06e0..daa09f8 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -159,7 +159,7 @@ static int psw_interrupts_disabled(struct kvm_vcpu *vcpu)
static int ckc_interrupts_enabled(struct kvm_vcpu *vcpu)
{
if (psw_extint_disabled(vcpu) ||
- !(vcpu->arch.sie_block->gcr[0] & 0x800ul))
+ !(vcpu->arch.sie_block->gcr[0] & CR0_CLOCK_COMPARATOR_SUBMASK))
return 0;
if (guestdbg_enabled(vcpu) && guestdbg_sstep_enabled(vcpu))
/* No timer interrupts when single stepping */
@@ -172,7 +172,7 @@ static int ckc_irq_pending(struct kvm_vcpu *vcpu)
const u64 now = kvm_s390_get_tod_clock_fast(vcpu->kvm);
const u64 ckc = vcpu->arch.sie_block->ckc;
- if (vcpu->arch.sie_block->gcr[0] & 0x0020000000000000ul) {
+ if (vcpu->arch.sie_block->gcr[0] & CR0_CLOCK_COMPARATOR_SIGN) {
if ((s64)ckc >= (s64)now)
return 0;
} else if (ckc >= now) {
@@ -184,7 +184,7 @@ static int ckc_irq_pending(struct kvm_vcpu *vcpu)
static int cpu_timer_interrupts_enabled(struct kvm_vcpu *vcpu)
{
return !psw_extint_disabled(vcpu) &&
- (vcpu->arch.sie_block->gcr[0] & 0x400ul);
+ (vcpu->arch.sie_block->gcr[0] & CR0_CPU_TIMER_SUBMASK);
}
static int cpu_timer_irq_pending(struct kvm_vcpu *vcpu)
@@ -285,15 +285,15 @@ static unsigned long deliverable_irqs(struct kvm_vcpu *vcpu)
active_mask &= ~IRQ_PEND_IO_MASK;
else
active_mask = disable_iscs(vcpu, active_mask);
- if (!(vcpu->arch.sie_block->gcr[0] & 0x2000ul))
+ if (!(vcpu->arch.sie_block->gcr[0] & CR0_EXTERNAL_CALL_SUBMASK))
__clear_bit(IRQ_PEND_EXT_EXTERNAL, &active_mask);
- if (!(vcpu->arch.sie_block->gcr[0] & 0x4000ul))
+ if (!(vcpu->arch.sie_block->gcr[0] & CR0_EMERGENCY_SIGNAL_SUBMASK))
__clear_bit(IRQ_PEND_EXT_EMERGENCY, &active_mask);
- if (!(vcpu->arch.sie_block->gcr[0] & 0x800ul))
+ if (!(vcpu->arch.sie_block->gcr[0] & CR0_CLOCK_COMPARATOR_SUBMASK))
__clear_bit(IRQ_PEND_EXT_CLOCK_COMP, &active_mask);
- if (!(vcpu->arch.sie_block->gcr[0] & 0x400ul))
+ if (!(vcpu->arch.sie_block->gcr[0] & CR0_CPU_TIMER_SUBMASK))
__clear_bit(IRQ_PEND_EXT_CPU_TIMER, &active_mask);
- if (!(vcpu->arch.sie_block->gcr[0] & 0x200ul))
+ if (!(vcpu->arch.sie_block->gcr[0] & CR0_SERVICE_SIGNAL_SUBMASK))
__clear_bit(IRQ_PEND_EXT_SERVICE, &active_mask);
if (psw_mchk_disabled(vcpu))
active_mask &= ~IRQ_PEND_MCHK_MASK;
@@ -1042,7 +1042,7 @@ int kvm_s390_vcpu_has_irq(struct kvm_vcpu *vcpu, int exclude_stop)
/* external call pending and deliverable */
if (kvm_s390_ext_call_pending(vcpu) &&
!psw_extint_disabled(vcpu) &&
- (vcpu->arch.sie_block->gcr[0] & 0x2000ul))
+ (vcpu->arch.sie_block->gcr[0] & CR0_EXTERNAL_CALL_SUBMASK))
return 1;
if (!exclude_stop && kvm_s390_is_stop_irq_pending(vcpu))
@@ -1062,7 +1062,7 @@ static u64 __calculate_sltime(struct kvm_vcpu *vcpu)
u64 cputm, sltime = 0;
if (ckc_interrupts_enabled(vcpu)) {
- if (vcpu->arch.sie_block->gcr[0] & 0x0020000000000000ul) {
+ if (vcpu->arch.sie_block->gcr[0] & CR0_CLOCK_COMPARATOR_SIGN) {
if ((s64)now < (s64)ckc)
sltime = tod_to_ns((s64)ckc - (s64)now);
} else if (now < ckc) {
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 64c9862..3b7a515 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -791,11 +791,21 @@ static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *att
static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu);
-static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr)
+void kvm_s390_vcpu_crypto_reset_all(struct kvm *kvm)
{
struct kvm_vcpu *vcpu;
int i;
+ kvm_s390_vcpu_block_all(kvm);
+
+ kvm_for_each_vcpu(i, vcpu, kvm)
+ kvm_s390_vcpu_crypto_setup(vcpu);
+
+ kvm_s390_vcpu_unblock_all(kvm);
+}
+
+static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr)
+{
if (!test_kvm_facility(kvm, 76))
return -EINVAL;
@@ -832,10 +842,7 @@ static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr)
return -ENXIO;
}
- kvm_for_each_vcpu(i, vcpu, kvm) {
- kvm_s390_vcpu_crypto_setup(vcpu);
- exit_sie(vcpu);
- }
+ kvm_s390_vcpu_crypto_reset_all(kvm);
mutex_unlock(&kvm->lock);
return 0;
}
@@ -1033,8 +1040,8 @@ static int kvm_s390_set_tod(struct kvm *kvm, struct kvm_device_attr *attr)
return ret;
}
-static void kvm_s390_get_tod_clock_ext(struct kvm *kvm,
- struct kvm_s390_vm_tod_clock *gtod)
+static void kvm_s390_get_tod_clock(struct kvm *kvm,
+ struct kvm_s390_vm_tod_clock *gtod)
{
struct kvm_s390_tod_clock_ext htod;
@@ -1043,10 +1050,12 @@ static void kvm_s390_get_tod_clock_ext(struct kvm *kvm,
get_tod_clock_ext((char *)&htod);
gtod->tod = htod.tod + kvm->arch.epoch;
- gtod->epoch_idx = htod.epoch_idx + kvm->arch.epdx;
-
- if (gtod->tod < htod.tod)
- gtod->epoch_idx += 1;
+ gtod->epoch_idx = 0;
+ if (test_kvm_facility(kvm, 139)) {
+ gtod->epoch_idx = htod.epoch_idx + kvm->arch.epdx;
+ if (gtod->tod < htod.tod)
+ gtod->epoch_idx += 1;
+ }
preempt_enable();
}
@@ -1056,12 +1065,7 @@ static int kvm_s390_get_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr)
struct kvm_s390_vm_tod_clock gtod;
memset(&gtod, 0, sizeof(gtod));
-
- if (test_kvm_facility(kvm, 139))
- kvm_s390_get_tod_clock_ext(kvm, &gtod);
- else
- gtod.tod = kvm_s390_get_tod_clock_fast(kvm);
-
+ kvm_s390_get_tod_clock(kvm, &gtod);
if (copy_to_user((void __user *)attr->addr, &gtod, sizeof(gtod)))
return -EFAULT;
@@ -1493,7 +1497,7 @@ static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
return -EINVAL;
/* Is this guest using storage keys? */
- if (!mm_use_skey(current->mm))
+ if (!mm_uses_skeys(current->mm))
return KVM_S390_GET_SKEYS_NONE;
/* Enforce sane limit on memory allocation */
@@ -1725,7 +1729,7 @@ static int kvm_s390_set_cmma_bits(struct kvm *kvm,
if (args->count == 0)
return 0;
- bits = vmalloc(sizeof(*bits) * args->count);
+ bits = vmalloc(array_size(sizeof(*bits), args->count));
if (!bits)
return -ENOMEM;
@@ -1982,10 +1986,10 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
rc = -ENOMEM;
- kvm->arch.use_esca = 0; /* start with basic SCA */
if (!sclp.has_64bscao)
alloc_flags |= GFP_DMA;
rwlock_init(&kvm->arch.sca_lock);
+ /* start with basic SCA */
kvm->arch.sca = (struct bsca_block *) get_zeroed_page(alloc_flags);
if (!kvm->arch.sca)
goto out_err;
@@ -2036,8 +2040,6 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
kvm_s390_crypto_init(kvm);
mutex_init(&kvm->arch.float_int.ais_lock);
- kvm->arch.float_int.simm = 0;
- kvm->arch.float_int.nimm = 0;
spin_lock_init(&kvm->arch.float_int.lock);
for (i = 0; i < FIRQ_LIST_COUNT; i++)
INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]);
@@ -2063,11 +2065,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
kvm->arch.gmap->pfault_enabled = 0;
}
- kvm->arch.css_support = 0;
- kvm->arch.use_irqchip = 0;
kvm->arch.use_pfmfi = sclp.has_pfmfi;
- kvm->arch.epoch = 0;
-
+ kvm->arch.use_skf = sclp.has_skey;
spin_lock_init(&kvm->arch.start_stop_lock);
kvm_s390_vsie_init(kvm);
kvm_s390_gisa_init(kvm);
@@ -2433,8 +2432,12 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
vcpu->arch.sie_block->ckc = 0UL;
vcpu->arch.sie_block->todpr = 0;
memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
- vcpu->arch.sie_block->gcr[0] = 0xE0UL;
- vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
+ vcpu->arch.sie_block->gcr[0] = CR0_UNUSED_56 |
+ CR0_INTERRUPT_KEY_SUBMASK |
+ CR0_MEASUREMENT_ALERT_SUBMASK;
+ vcpu->arch.sie_block->gcr[14] = CR14_UNUSED_32 |
+ CR14_UNUSED_33 |
+ CR14_EXTERNAL_DAMAGE_SUBMASK;
/* make sure the new fpc will be lazily loaded */
save_fpu_regs();
current->thread.fpu.fpc = 0;
@@ -3192,7 +3195,7 @@ static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu)
return 0;
if (kvm_s390_vcpu_has_irq(vcpu, 0))
return 0;
- if (!(vcpu->arch.sie_block->gcr[0] & 0x200ul))
+ if (!(vcpu->arch.sie_block->gcr[0] & CR0_SERVICE_SIGNAL_SUBMASK))
return 0;
if (!vcpu->arch.gmap->pfault_enabled)
return 0;
@@ -3990,7 +3993,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
return r;
}
-int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
{
#ifdef CONFIG_KVM_S390_UCONTROL
if ((vmf->pgoff == KVM_S390_SIE_PAGE_OFFSET)
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 1b5621f..981e3ba 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -410,4 +410,17 @@ static inline int kvm_s390_use_sca_entries(void)
}
void kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
struct mcck_volatile_info *mcck_info);
+
+/**
+ * kvm_s390_vcpu_crypto_reset_all
+ *
+ * Reset the crypto attributes for each vcpu. This can be done while the vcpus
+ * are running as each vcpu will be removed from SIE before resetting the crypt
+ * attributes and restored to SIE afterward.
+ *
+ * Note: The kvm->lock must be held while calling this function
+ *
+ * @kvm: the KVM guest
+ */
+void kvm_s390_vcpu_crypto_reset_all(struct kvm *kvm);
#endif
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index a3bce0e..eb0eb60 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -204,24 +204,28 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
int kvm_s390_skey_check_enable(struct kvm_vcpu *vcpu)
{
- int rc = 0;
+ int rc;
struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block;
trace_kvm_s390_skey_related_inst(vcpu);
- if (!(sie_block->ictl & (ICTL_ISKE | ICTL_SSKE | ICTL_RRBE)) &&
+ /* Already enabled? */
+ if (vcpu->kvm->arch.use_skf &&
+ !(sie_block->ictl & (ICTL_ISKE | ICTL_SSKE | ICTL_RRBE)) &&
!kvm_s390_test_cpuflags(vcpu, CPUSTAT_KSS))
- return rc;
+ return 0;
rc = s390_enable_skey();
VCPU_EVENT(vcpu, 3, "enabling storage keys for guest: %d", rc);
- if (!rc) {
- if (kvm_s390_test_cpuflags(vcpu, CPUSTAT_KSS))
- kvm_s390_clear_cpuflags(vcpu, CPUSTAT_KSS);
- else
- sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE |
- ICTL_RRBE);
- }
- return rc;
+ if (rc)
+ return rc;
+
+ if (kvm_s390_test_cpuflags(vcpu, CPUSTAT_KSS))
+ kvm_s390_clear_cpuflags(vcpu, CPUSTAT_KSS);
+ if (!vcpu->kvm->arch.use_skf)
+ sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
+ else
+ sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE | ICTL_RRBE);
+ return 0;
}
static int try_handle_skey(struct kvm_vcpu *vcpu)
@@ -231,7 +235,7 @@ static int try_handle_skey(struct kvm_vcpu *vcpu)
rc = kvm_s390_skey_check_enable(vcpu);
if (rc)
return rc;
- if (sclp.has_skey) {
+ if (vcpu->kvm->arch.use_skf) {
/* with storage-key facility, SIE interprets it for us */
kvm_s390_retry_instr(vcpu);
VCPU_EVENT(vcpu, 4, "%s", "retrying storage key operation");
diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c
index 969882b..84c89cb 100644
--- a/arch/s390/kvm/vsie.c
+++ b/arch/s390/kvm/vsie.c
@@ -557,7 +557,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
if (test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_64BSCAO))
gpa |= (u64) READ_ONCE(scb_o->scaoh) << 32;
if (gpa) {
- if (!(gpa & ~0x1fffUL))
+ if (gpa < 2 * PAGE_SIZE)
rc = set_validity_icpt(scb_s, 0x0038U);
else if ((gpa & ~0x1fffUL) == kvm_s390_get_prefix(vcpu))
rc = set_validity_icpt(scb_s, 0x0011U);
@@ -578,7 +578,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
gpa = READ_ONCE(scb_o->itdba) & ~0xffUL;
if (gpa && (scb_s->ecb & ECB_TE)) {
- if (!(gpa & ~0x1fffUL)) {
+ if (gpa < 2 * PAGE_SIZE) {
rc = set_validity_icpt(scb_s, 0x0080U);
goto unpin;
}
@@ -594,7 +594,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
gpa = READ_ONCE(scb_o->gvrd) & ~0x1ffUL;
if (gpa && (scb_s->eca & ECA_VX) && !(scb_s->ecd & ECD_HOSTREGMGMT)) {
- if (!(gpa & ~0x1fffUL)) {
+ if (gpa < 2 * PAGE_SIZE) {
rc = set_validity_icpt(scb_s, 0x1310U);
goto unpin;
}
@@ -613,7 +613,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
gpa = READ_ONCE(scb_o->riccbd) & ~0x3fUL;
if (gpa && (scb_s->ecb3 & ECB3_RI)) {
- if (!(gpa & ~0x1fffUL)) {
+ if (gpa < 2 * PAGE_SIZE) {
rc = set_validity_icpt(scb_s, 0x0043U);
goto unpin;
}
@@ -632,7 +632,7 @@ static int pin_blocks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
gpa = READ_ONCE(scb_o->sdnxo) & ~0xfUL;
sdnxc = READ_ONCE(scb_o->sdnxo) & 0xfUL;
- if (!gpa || !(gpa & ~0x1fffUL)) {
+ if (!gpa || gpa < 2 * PAGE_SIZE) {
rc = set_validity_icpt(scb_s, 0x10b0U);
goto unpin;
}
diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c
index 920d408..6ad15d3 100644
--- a/arch/s390/mm/extmem.c
+++ b/arch/s390/mm/extmem.c
@@ -103,7 +103,7 @@ static int scode_set;
static int
dcss_set_subcodes(void)
{
- char *name = kmalloc(8 * sizeof(char), GFP_KERNEL | GFP_DMA);
+ char *name = kmalloc(8, GFP_KERNEL | GFP_DMA);
unsigned long rx, ry;
int rc;
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index 2c55a2b..bc56ec8 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -2184,14 +2184,14 @@ int s390_enable_skey(void)
int rc = 0;
down_write(&mm->mmap_sem);
- if (mm_use_skey(mm))
+ if (mm_uses_skeys(mm))
goto out_up;
- mm->context.use_skey = 1;
+ mm->context.uses_skeys = 1;
for (vma = mm->mmap; vma; vma = vma->vm_next) {
if (ksm_madvise(vma, vma->vm_start, vma->vm_end,
MADV_UNMERGEABLE, &vma->vm_flags)) {
- mm->context.use_skey = 0;
+ mm->context.uses_skeys = 0;
rc = -ENOMEM;
goto out_up;
}
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 4f2b65d..301e466 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -158,7 +158,7 @@ static inline pgste_t pgste_update_all(pte_t pte, pgste_t pgste,
#ifdef CONFIG_PGSTE
unsigned long address, bits, skey;
- if (!mm_use_skey(mm) || pte_val(pte) & _PAGE_INVALID)
+ if (!mm_uses_skeys(mm) || pte_val(pte) & _PAGE_INVALID)
return pgste;
address = pte_val(pte) & PAGE_MASK;
skey = (unsigned long) page_get_storage_key(address);
@@ -180,7 +180,7 @@ static inline void pgste_set_key(pte_t *ptep, pgste_t pgste, pte_t entry,
unsigned long address;
unsigned long nkey;
- if (!mm_use_skey(mm) || pte_val(entry) & _PAGE_INVALID)
+ if (!mm_uses_skeys(mm) || pte_val(entry) & _PAGE_INVALID)
return;
VM_BUG_ON(!(pte_val(*ptep) & _PAGE_INVALID));
address = pte_val(entry) & PAGE_MASK;
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 4d61a08..dd4f3d3 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -77,7 +77,7 @@ config SUPERH32
select PERF_EVENTS
select ARCH_HIBERNATION_POSSIBLE if MMU
select SPARSE_IRQ
- select HAVE_CC_STACKPROTECTOR
+ select HAVE_STACKPROTECTOR
config SUPERH64
def_bool "$(ARCH)" = "sh64"
@@ -687,7 +687,7 @@ config SMP
People using multiprocessor machines who say Y here should also say
Y to "Enhanced Real Time Clock Support", below.
- See also <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO
+ See also <file:Documentation/lockup-watchdogs.txt> and the SMP-HOWTO
available at <http://www.tldp.org/docs.html#howto>.
If you don't know what to do here, say N.
diff --git a/arch/sh/boards/board-sh7785lcr.c b/arch/sh/boards/board-sh7785lcr.c
index d7d232d..3cba60f 100644
--- a/arch/sh/boards/board-sh7785lcr.c
+++ b/arch/sh/boards/board-sh7785lcr.c
@@ -17,7 +17,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
-#include <linux/i2c-pca-platform.h>
+#include <linux/platform_data/i2c-pca-platform.h>
#include <linux/i2c-algo-pca.h>
#include <linux/usb/r8a66597.h>
#include <linux/sh_intc.h>
diff --git a/arch/sh/drivers/dma/dmabrg.c b/arch/sh/drivers/dma/dmabrg.c
index c0dd904..e5a57a1 100644
--- a/arch/sh/drivers/dma/dmabrg.c
+++ b/arch/sh/drivers/dma/dmabrg.c
@@ -154,7 +154,7 @@ static int __init dmabrg_init(void)
unsigned long or;
int ret;
- dmabrg_handlers = kzalloc(10 * sizeof(struct dmabrg_handler),
+ dmabrg_handlers = kcalloc(10, sizeof(struct dmabrg_handler),
GFP_KERNEL);
if (!dmabrg_handlers)
return -ENOMEM;
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
index 382e7ec..3d81a8b 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.c
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -561,7 +561,7 @@ static int __init sh7786_pcie_init(void)
if (unlikely(nr_ports == 0))
return -ENODEV;
- sh7786_pcie_ports = kzalloc(nr_ports * sizeof(struct sh7786_pcie_port),
+ sh7786_pcie_ports = kcalloc(nr_ports, sizeof(struct sh7786_pcie_port),
GFP_KERNEL);
if (unlikely(!sh7786_pcie_ports))
return -ENOMEM;
diff --git a/arch/sh/include/asm/vmlinux.lds.h b/arch/sh/include/asm/vmlinux.lds.h
index f312813..9929556 100644
--- a/arch/sh/include/asm/vmlinux.lds.h
+++ b/arch/sh/include/asm/vmlinux.lds.h
@@ -7,9 +7,9 @@
#ifdef CONFIG_DWARF_UNWINDER
#define DWARF_EH_FRAME \
.eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) { \
- VMLINUX_SYMBOL(__start_eh_frame) = .; \
+ __start_eh_frame = .; \
*(.eh_frame) \
- VMLINUX_SYMBOL(__stop_eh_frame) = .; \
+ __stop_eh_frame = .; \
}
#else
#define DWARF_EH_FRAME
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 68b1a67..4d1bfc8 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -12,7 +12,7 @@
struct kmem_cache *task_xstate_cachep = NULL;
unsigned int xstate_size;
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
#endif
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c
index 9352206..27fddb5 100644
--- a/arch/sh/kernel/process_32.c
+++ b/arch/sh/kernel/process_32.c
@@ -177,7 +177,7 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
{
struct thread_struct *next_t = &next->thread;
-#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
+#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
__stack_chk_guard = next->stack_canary;
#endif
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 9a2b887..0f535de 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -178,7 +178,7 @@ config SMP
Y to "Enhanced Real Time Clock Support", below. The "Advanced Power
Management" code will be disabled if you say Y here.
- See also <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO
+ See also <file:Documentation/lockup-watchdogs.txt> and the SMP-HOWTO
available at <http://www.tldp.org/docs.html#howto>.
If you don't know what to do here, say N.
diff --git a/arch/sparc/kernel/nmi.c b/arch/sparc/kernel/nmi.c
index 048ad78..8babbeb 100644
--- a/arch/sparc/kernel/nmi.c
+++ b/arch/sparc/kernel/nmi.c
@@ -166,7 +166,8 @@ static int __init check_nmi_watchdog(void)
if (!atomic_read(&nmi_active))
return 0;
- prev_nmi_count = kmalloc(nr_cpu_ids * sizeof(unsigned int), GFP_KERNEL);
+ prev_nmi_count = kmalloc_array(nr_cpu_ids, sizeof(unsigned int),
+ GFP_KERNEL);
if (!prev_nmi_count) {
err = -ENOMEM;
goto error;
diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index 7e49bbc9..63baa8a 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -565,7 +565,8 @@ SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type,
}
if (!current_thread_info()->utraps) {
current_thread_info()->utraps =
- kzalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long), GFP_KERNEL);
+ kcalloc(UT_TRAP_INSTRUCTION_31 + 1, sizeof(long),
+ GFP_KERNEL);
if (!current_thread_info()->utraps)
return -ENOMEM;
current_thread_info()->utraps[0] = 1;
@@ -575,8 +576,9 @@ SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type,
unsigned long *p = current_thread_info()->utraps;
current_thread_info()->utraps =
- kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long),
- GFP_KERNEL);
+ kmalloc_array(UT_TRAP_INSTRUCTION_31 + 1,
+ sizeof(long),
+ GFP_KERNEL);
if (!current_thread_info()->utraps) {
current_thread_info()->utraps = p;
return -ENOMEM;
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 8aeb1aa..f396048 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1620,7 +1620,7 @@ static void __init bootmem_init_nonnuma(void)
(top_of_ram - total_ram) >> 20);
init_node_masks_nonnuma();
- memblock_set_node(0, (phys_addr_t)ULLONG_MAX, &memblock.memory, 0);
+ memblock_set_node(0, PHYS_ADDR_MAX, &memblock.memory, 0);
allocate_node_data(0);
node_set_online(0);
}
diff --git a/arch/sparc/net/bpf_jit_comp_32.c b/arch/sparc/net/bpf_jit_comp_32.c
index 3bd8ca9..a5ff886 100644
--- a/arch/sparc/net/bpf_jit_comp_32.c
+++ b/arch/sparc/net/bpf_jit_comp_32.c
@@ -335,7 +335,7 @@ void bpf_jit_compile(struct bpf_prog *fp)
if (!bpf_jit_enable)
return;
- addrs = kmalloc(flen * sizeof(*addrs), GFP_KERNEL);
+ addrs = kmalloc_array(flen, sizeof(*addrs), GFP_KERNEL);
if (addrs == NULL)
return;
diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um
index 3e7f228..20da5a8 100644
--- a/arch/um/Kconfig.um
+++ b/arch/um/Kconfig.um
@@ -80,7 +80,7 @@ config MAGIC_SYSRQ
On UML, this is accomplished by sending a "sysrq" command with
mconsole, followed by the letter for the requested command.
- The keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
+ The keys are documented in <file:Documentation/admin-guide/sysrq.rst>. Don't say Y
unless you really know what this hack does.
config KERNEL_STACK_ORDER
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index dcf5ea2..83c4703 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -1127,9 +1127,9 @@ static int __init ubd_init(void)
return -1;
}
- irq_req_buffer = kmalloc(
- sizeof(struct io_thread_req *) * UBD_REQ_BUFFER_SIZE,
- GFP_KERNEL
+ irq_req_buffer = kmalloc_array(UBD_REQ_BUFFER_SIZE,
+ sizeof(struct io_thread_req *),
+ GFP_KERNEL
);
irq_remainder = 0;
@@ -1137,9 +1137,9 @@ static int __init ubd_init(void)
printk(KERN_ERR "Failed to initialize ubd buffering\n");
return -1;
}
- io_req_buffer = kmalloc(
- sizeof(struct io_thread_req *) * UBD_REQ_BUFFER_SIZE,
- GFP_KERNEL
+ io_req_buffer = kmalloc_array(UBD_REQ_BUFFER_SIZE,
+ sizeof(struct io_thread_req *),
+ GFP_KERNEL
);
io_remainder = 0;
diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index 02168fe..50ee3bb 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -188,7 +188,7 @@ static int get_transport_options(struct arglist *def)
if (strncmp(transport, TRANS_TAP, TRANS_TAP_LEN) == 0)
return (vec_rx | VECTOR_BPF);
if (strncmp(transport, TRANS_RAW, TRANS_RAW_LEN) == 0)
- return (vec_rx | vec_tx);
+ return (vec_rx | vec_tx | VECTOR_QDISC_BYPASS);
return (vec_rx | vec_tx);
}
@@ -504,15 +504,19 @@ static struct vector_queue *create_queue(
result = kmalloc(sizeof(struct vector_queue), GFP_KERNEL);
if (result == NULL)
- goto out_fail;
+ return NULL;
result->max_depth = max_size;
result->dev = vp->dev;
result->mmsg_vector = kmalloc(
(sizeof(struct mmsghdr) * max_size), GFP_KERNEL);
+ if (result->mmsg_vector == NULL)
+ goto out_mmsg_fail;
result->skbuff_vector = kmalloc(
(sizeof(void *) * max_size), GFP_KERNEL);
- if (result->mmsg_vector == NULL || result->skbuff_vector == NULL)
- goto out_fail;
+ if (result->skbuff_vector == NULL)
+ goto out_skb_fail;
+
+ /* further failures can be handled safely by destroy_queue*/
mmsg_vector = result->mmsg_vector;
for (i = 0; i < max_size; i++) {
@@ -527,14 +531,14 @@ static struct vector_queue *create_queue(
result->max_iov_frags = num_extra_frags;
for (i = 0; i < max_size; i++) {
if (vp->header_size > 0)
- iov = kmalloc(
- sizeof(struct iovec) * (3 + num_extra_frags),
- GFP_KERNEL
+ iov = kmalloc_array(3 + num_extra_frags,
+ sizeof(struct iovec),
+ GFP_KERNEL
);
else
- iov = kmalloc(
- sizeof(struct iovec) * (2 + num_extra_frags),
- GFP_KERNEL
+ iov = kmalloc_array(2 + num_extra_frags,
+ sizeof(struct iovec),
+ GFP_KERNEL
);
if (iov == NULL)
goto out_fail;
@@ -563,6 +567,11 @@ static struct vector_queue *create_queue(
result->head = 0;
result->tail = 0;
return result;
+out_skb_fail:
+ kfree(result->mmsg_vector);
+out_mmsg_fail:
+ kfree(result);
+ return NULL;
out_fail:
destroy_queue(result);
return NULL;
@@ -1232,9 +1241,8 @@ static int vector_net_open(struct net_device *dev)
if ((vp->options & VECTOR_QDISC_BYPASS) != 0) {
if (!uml_raw_enable_qdisc_bypass(vp->fds->rx_fd))
- vp->options = vp->options | VECTOR_BPF;
+ vp->options |= VECTOR_BPF;
}
-
if ((vp->options & VECTOR_BPF) != 0)
vp->bpf = uml_vector_default_bpf(vp->fds->rx_fd, dev->dev_addr);
diff --git a/arch/um/drivers/vector_transports.c b/arch/um/drivers/vector_transports.c
index 9065047..77e4ebc 100644
--- a/arch/um/drivers/vector_transports.c
+++ b/arch/um/drivers/vector_transports.c
@@ -120,7 +120,8 @@ static int raw_form_header(uint8_t *header,
skb,
vheader,
virtio_legacy_is_little_endian(),
- false
+ false,
+ 0
);
return 0;
diff --git a/arch/um/include/asm/common.lds.S b/arch/um/include/asm/common.lds.S
index b30d73c..7adb4e6 100644
--- a/arch/um/include/asm/common.lds.S
+++ b/arch/um/include/asm/common.lds.S
@@ -53,12 +53,6 @@
CON_INITCALL
}
- .uml.initcall.init : {
- __uml_initcall_start = .;
- *(.uml.initcall.init)
- __uml_initcall_end = .;
- }
-
SECURITY_INIT
.exitcall : {
diff --git a/arch/um/include/shared/init.h b/arch/um/include/shared/init.h
index b3f5865..c66de43 100644
--- a/arch/um/include/shared/init.h
+++ b/arch/um/include/shared/init.h
@@ -64,14 +64,10 @@ struct uml_param {
int (*setup_func)(char *, int *);
};
-extern initcall_t __uml_initcall_start, __uml_initcall_end;
extern initcall_t __uml_postsetup_start, __uml_postsetup_end;
extern const char *__uml_help_start, *__uml_help_end;
#endif
-#define __uml_initcall(fn) \
- static initcall_t __uml_initcall_##fn __uml_init_call = fn
-
#define __uml_exitcall(fn) \
static exitcall_t __uml_exitcall_##fn __uml_exit_call = fn
@@ -108,7 +104,6 @@ extern struct uml_param __uml_setup_start, __uml_setup_end;
*/
#define __uml_init_setup __used __section(.uml.setup.init)
#define __uml_setup_help __used __section(.uml.help.init)
-#define __uml_init_call __used __section(.uml.initcall.init)
#define __uml_postsetup_call __used __section(.uml.postsetup.init)
#define __uml_exit_call __used __section(.uml.exitcall.exit)
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index 5f970ec..f1fee2b 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -40,17 +40,6 @@ static void set_stklim(void)
}
}
-static __init void do_uml_initcalls(void)
-{
- initcall_t *call;
-
- call = &__uml_initcall_start;
- while (call < &__uml_initcall_end) {
- (*call)();
- call++;
- }
-}
-
static void last_ditch_exit(int sig)
{
uml_cleanup();
@@ -151,7 +140,6 @@ int __init main(int argc, char **argv, char **envp)
scan_elf_aux(envp);
#endif
- do_uml_initcalls();
change_sig(SIGPIPE, 0);
ret = linux_main(argc, argv);
diff --git a/arch/unicore32/include/asm/cacheflush.h b/arch/unicore32/include/asm/cacheflush.h
index 1d9132b..1c8b9f1 100644
--- a/arch/unicore32/include/asm/cacheflush.h
+++ b/arch/unicore32/include/asm/cacheflush.h
@@ -33,7 +33,7 @@
* Start addresses are inclusive and end addresses are exclusive;
* start addresses should be rounded down, end addresses up.
*
- * See Documentation/cachetlb.txt for more information.
+ * See Documentation/core-api/cachetlb.rst for more information.
* Please note that the implementation of these, and the required
* effects are cache-type (VIVT/VIPT/PIPT) specific.
*
diff --git a/arch/unicore32/kernel/pm.c b/arch/unicore32/kernel/pm.c
index 784bc2d..6f8164d 100644
--- a/arch/unicore32/kernel/pm.c
+++ b/arch/unicore32/kernel/pm.c
@@ -109,8 +109,9 @@ static int __init puv3_pm_init(void)
return -EINVAL;
}
- sleep_save = kmalloc(puv3_cpu_pm_fns->save_count
- * sizeof(unsigned long), GFP_KERNEL);
+ sleep_save = kmalloc_array(puv3_cpu_pm_fns->save_count,
+ sizeof(unsigned long),
+ GFP_KERNEL);
if (!sleep_save) {
printk(KERN_ERR "failed to alloc memory for pm save\n");
return -ENOMEM;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 297789a..f1dbb4e 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -130,7 +130,6 @@ config X86
select HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD if X86_64
select HAVE_ARCH_VMAP_STACK if X86_64
select HAVE_ARCH_WITHIN_STACK_FRAMES
- select HAVE_CC_STACKPROTECTOR
select HAVE_CMPXCHG_DOUBLE
select HAVE_CMPXCHG_LOCAL
select HAVE_CONTEXT_TRACKING if X86_64
@@ -182,6 +181,7 @@ config X86
select HAVE_RCU_TABLE_FREE
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RELIABLE_STACKTRACE if X86_64 && UNWINDER_FRAME_POINTER && STACK_VALIDATION
+ select HAVE_STACKPROTECTOR if CC_HAS_SANE_STACKPROTECTOR
select HAVE_STACK_VALIDATION if X86_64
select HAVE_RSEQ
select HAVE_SYSCALL_TRACEPOINTS
@@ -327,7 +327,7 @@ config X86_64_SMP
config X86_32_LAZY_GS
def_bool y
- depends on X86_32 && CC_STACKPROTECTOR_NONE
+ depends on X86_32 && !STACKPROTECTOR
config ARCH_SUPPORTS_UPROBES
def_bool y
@@ -346,6 +346,15 @@ config PGTABLE_LEVELS
default 2
source "init/Kconfig"
+
+config CC_HAS_SANE_STACKPROTECTOR
+ bool
+ default $(success,$(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(CC)) if 64BIT
+ default $(success,$(srctree)/scripts/gcc-x86_32-has-stack-protector.sh $(CC))
+ help
+ We have to make sure stack protector is unconditionally disabled if
+ the compiler produces broken code.
+
source "kernel/Kconfig.freezer"
menu "Processor type and features"
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index f0a6ea2..a08e828 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -258,11 +258,6 @@ archscripts: scripts_basic
archheaders:
$(Q)$(MAKE) $(build)=arch/x86/entry/syscalls all
-archprepare:
-ifeq ($(CONFIG_KEXEC_FILE),y)
- $(Q)$(MAKE) $(build)=arch/x86/purgatory arch/x86/purgatory/kexec-purgatory.c
-endif
-
###
# Kernel objects
@@ -327,7 +322,6 @@ archclean:
$(Q)rm -rf $(objtree)/arch/x86_64
$(Q)$(MAKE) $(clean)=$(boot)
$(Q)$(MAKE) $(clean)=arch/x86/tools
- $(Q)$(MAKE) $(clean)=arch/x86/purgatory
define archhelp
echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)'
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index a8a8642..e57665b 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -118,7 +118,7 @@ __setup_efi_pci(efi_pci_io_protocol_t *pci, struct pci_setup_rom **__rom)
void *romimage;
status = efi_call_proto(efi_pci_io_protocol, attributes, pci,
- EfiPciIoAttributeOperationGet, 0, 0,
+ EfiPciIoAttributeOperationGet, 0ULL,
&attributes);
if (status != EFI_SUCCESS)
return status;
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 9219087..3b2490b 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -164,7 +164,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
if (cached_flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
tracehook_notify_resume(regs);
- rseq_handle_notify_resume(regs);
+ rseq_handle_notify_resume(NULL, regs);
}
if (cached_flags & _TIF_USER_RETURN_NOTIFY)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index bef8e2b..2582881 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -239,7 +239,7 @@ ENTRY(__switch_to_asm)
movl %esp, TASK_threadsp(%eax)
movl TASK_threadsp(%edx), %esp
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
movl TASK_stack_canary(%edx), %ebx
movl %ebx, PER_CPU_VAR(stack_canary)+stack_canary_offset
#endif
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 3166b96..73a522d 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -357,7 +357,7 @@ ENTRY(__switch_to_asm)
movq %rsp, TASK_threadsp(%rdi)
movq TASK_threadsp(%rsi), %rsp
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
movq TASK_stack_canary(%rsi), %rbx
movq %rbx, PER_CPU_VAR(irq_stack_union)+stack_canary_offset
#endif
diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c
index 7782cdb..82ed001 100644
--- a/arch/x86/entry/vsyscall/vsyscall_64.c
+++ b/arch/x86/entry/vsyscall/vsyscall_64.c
@@ -201,7 +201,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
/*
* Handle seccomp. regs->ip must be the original value.
- * See seccomp_send_sigsys and Documentation/prctl/seccomp_filter.txt.
+ * See seccomp_send_sigsys and Documentation/userspace-api/seccomp_filter.rst.
*
* We could optimize the seccomp disabled case, but performance
* here doesn't matter.
diff --git a/arch/x86/events/amd/iommu.c b/arch/x86/events/amd/iommu.c
index 38b5d41..3210fee 100644
--- a/arch/x86/events/amd/iommu.c
+++ b/arch/x86/events/amd/iommu.c
@@ -387,7 +387,7 @@ static __init int _init_events_attrs(void)
while (amd_iommu_v2_event_descs[i].attr.attr.name)
i++;
- attrs = kzalloc(sizeof(struct attribute **) * (i + 1), GFP_KERNEL);
+ attrs = kcalloc(i + 1, sizeof(struct attribute **), GFP_KERNEL);
if (!attrs)
return -ENOMEM;
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 6e461fb..5f4829f 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -1637,7 +1637,7 @@ __init struct attribute **merge_attr(struct attribute **a, struct attribute **b)
j++;
j++;
- new = kmalloc(sizeof(struct attribute *) * j, GFP_KERNEL);
+ new = kmalloc_array(j, sizeof(struct attribute *), GFP_KERNEL);
if (!new)
return NULL;
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index 15b0737..27a4614 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -865,12 +865,10 @@ static void uncore_types_exit(struct intel_uncore_type **types)
static int __init uncore_type_init(struct intel_uncore_type *type, bool setid)
{
struct intel_uncore_pmu *pmus;
- struct attribute_group *attr_group;
- struct attribute **attrs;
size_t size;
int i, j;
- pmus = kzalloc(sizeof(*pmus) * type->num_boxes, GFP_KERNEL);
+ pmus = kcalloc(type->num_boxes, sizeof(*pmus), GFP_KERNEL);
if (!pmus)
return -ENOMEM;
@@ -891,21 +889,24 @@ static int __init uncore_type_init(struct intel_uncore_type *type, bool setid)
0, type->num_counters, 0, 0);
if (type->event_descs) {
+ struct {
+ struct attribute_group group;
+ struct attribute *attrs[];
+ } *attr_group;
for (i = 0; type->event_descs[i].attr.attr.name; i++);
- attr_group = kzalloc(sizeof(struct attribute *) * (i + 1) +
- sizeof(*attr_group), GFP_KERNEL);
+ attr_group = kzalloc(struct_size(attr_group, attrs, i + 1),
+ GFP_KERNEL);
if (!attr_group)
goto err;
- attrs = (struct attribute **)(attr_group + 1);
- attr_group->name = "events";
- attr_group->attrs = attrs;
+ attr_group->group.name = "events";
+ attr_group->group.attrs = attr_group->attrs;
for (j = 0; j < i; j++)
- attrs[j] = &type->event_descs[j].attr.attr;
+ attr_group->attrs[j] = &type->event_descs[j].attr.attr;
- type->events_group = attr_group;
+ type->events_group = &attr_group->group;
}
type->pmu_group = &uncore_pmu_attr_group;
diff --git a/arch/x86/hyperv/mmu.c b/arch/x86/hyperv/mmu.c
index 5f053d7..de27615 100644
--- a/arch/x86/hyperv/mmu.c
+++ b/arch/x86/hyperv/mmu.c
@@ -13,22 +13,6 @@
#define CREATE_TRACE_POINTS
#include <asm/trace/hyperv.h>
-/* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */
-struct hv_flush_pcpu {
- u64 address_space;
- u64 flags;
- u64 processor_mask;
- u64 gva_list[];
-};
-
-/* HvFlushVirtualAddressSpaceEx, HvFlushVirtualAddressListEx hypercalls */
-struct hv_flush_pcpu_ex {
- u64 address_space;
- u64 flags;
- struct hv_vpset hv_vp_set;
- u64 gva_list[];
-};
-
/* Each gva in gva_list encodes up to 4096 pages to flush */
#define HV_TLB_FLUSH_UNIT (4096 * PAGE_SIZE)
@@ -67,8 +51,8 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus,
const struct flush_tlb_info *info)
{
int cpu, vcpu, gva_n, max_gvas;
- struct hv_flush_pcpu **flush_pcpu;
- struct hv_flush_pcpu *flush;
+ struct hv_tlb_flush **flush_pcpu;
+ struct hv_tlb_flush *flush;
u64 status = U64_MAX;
unsigned long flags;
@@ -82,7 +66,7 @@ static void hyperv_flush_tlb_others(const struct cpumask *cpus,
local_irq_save(flags);
- flush_pcpu = (struct hv_flush_pcpu **)
+ flush_pcpu = (struct hv_tlb_flush **)
this_cpu_ptr(hyperv_pcpu_input_arg);
flush = *flush_pcpu;
@@ -152,8 +136,8 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
const struct flush_tlb_info *info)
{
int nr_bank = 0, max_gvas, gva_n;
- struct hv_flush_pcpu_ex **flush_pcpu;
- struct hv_flush_pcpu_ex *flush;
+ struct hv_tlb_flush_ex **flush_pcpu;
+ struct hv_tlb_flush_ex *flush;
u64 status = U64_MAX;
unsigned long flags;
@@ -167,7 +151,7 @@ static void hyperv_flush_tlb_others_ex(const struct cpumask *cpus,
local_irq_save(flags);
- flush_pcpu = (struct hv_flush_pcpu_ex **)
+ flush_pcpu = (struct hv_tlb_flush_ex **)
this_cpu_ptr(hyperv_pcpu_input_arg);
flush = *flush_pcpu;
diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
index 042b5e8..14de043 100644
--- a/arch/x86/include/asm/barrier.h
+++ b/arch/x86/include/asm/barrier.h
@@ -38,7 +38,7 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
{
unsigned long mask;
- asm ("cmp %1,%2; sbb %0,%0;"
+ asm volatile ("cmp %1,%2; sbb %0,%0;"
:"=r" (mask)
:"g"(size),"r" (index)
:"cc");
diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
index 3bfa92c..b8c8926 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -308,6 +308,9 @@ struct ms_hyperv_tsc_page {
/* TSC emulation after migration */
#define HV_X64_MSR_REENLIGHTENMENT_CONTROL 0x40000106
+/* Nested features (CPUID 0x4000000A) EAX */
+#define HV_X64_NESTED_MSR_BITMAP BIT(19)
+
struct hv_reenlightenment_control {
__u64 vector:8;
__u64 reserved1:8;
@@ -678,7 +681,11 @@ struct hv_enlightened_vmcs {
u32 hv_clean_fields;
u32 hv_padding_32;
u32 hv_synthetic_controls;
- u32 hv_enlightenments_control;
+ struct {
+ u32 nested_flush_hypercall:1;
+ u32 msr_bitmap:1;
+ u32 reserved:30;
+ } hv_enlightenments_control;
u32 hv_vp_id;
u64 hv_vm_id;
@@ -734,4 +741,20 @@ struct ipi_arg_ex {
struct hv_vpset vp_set;
};
+/* HvFlushVirtualAddressSpace, HvFlushVirtualAddressList hypercalls */
+struct hv_tlb_flush {
+ u64 address_space;
+ u64 flags;
+ u64 processor_mask;
+ u64 gva_list[];
+};
+
+/* HvFlushVirtualAddressSpaceEx, HvFlushVirtualAddressListEx hypercalls */
+struct hv_tlb_flush_ex {
+ u64 address_space;
+ u64 flags;
+ struct hv_vpset hv_vp_set;
+ u64 gva_list[];
+};
+
#endif
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index b24b1c8..0f82cd9 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -107,11 +107,12 @@ struct x86_emulate_ops {
* @addr: [IN ] Linear address from which to read.
* @val: [OUT] Value read from memory, zero-extended to 'u_long'.
* @bytes: [IN ] Number of bytes to read from memory.
+ * @system:[IN ] Whether the access is forced to be at CPL0.
*/
int (*read_std)(struct x86_emulate_ctxt *ctxt,
unsigned long addr, void *val,
unsigned int bytes,
- struct x86_exception *fault);
+ struct x86_exception *fault, bool system);
/*
* read_phys: Read bytes of standard (non-emulated/special) memory.
@@ -129,10 +130,11 @@ struct x86_emulate_ops {
* @addr: [IN ] Linear address to which to write.
* @val: [OUT] Value write to memory, zero-extended to 'u_long'.
* @bytes: [IN ] Number of bytes to write to memory.
+ * @system:[IN ] Whether the access is forced to be at CPL0.
*/
int (*write_std)(struct x86_emulate_ctxt *ctxt,
unsigned long addr, void *val, unsigned int bytes,
- struct x86_exception *fault);
+ struct x86_exception *fault, bool system);
/*
* fetch: Read bytes of standard (non-emulated/special) memory.
* Used for instruction fetch.
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index f4b2588..c13cd28 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -258,7 +258,8 @@ union kvm_mmu_page_role {
unsigned smep_andnot_wp:1;
unsigned smap_andnot_wp:1;
unsigned ad_disabled:1;
- unsigned :7;
+ unsigned guest_mode:1;
+ unsigned :6;
/*
* This is left at the top of the word so that
@@ -476,6 +477,7 @@ struct kvm_vcpu_hv {
struct kvm_hyperv_exit exit;
struct kvm_vcpu_hv_stimer stimer[HV_SYNIC_STIMER_COUNT];
DECLARE_BITMAP(stimer_pending_bitmap, HV_SYNIC_STIMER_COUNT);
+ cpumask_t tlb_lush;
};
struct kvm_vcpu_arch {
@@ -995,7 +997,7 @@ struct kvm_x86_ops {
void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
void (*hwapic_isr_update)(struct kvm_vcpu *vcpu, int isr);
void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
- void (*set_virtual_x2apic_mode)(struct kvm_vcpu *vcpu, bool set);
+ void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu, hpa_t hpa);
void (*deliver_posted_interrupt)(struct kvm_vcpu *vcpu, int vector);
int (*sync_pir_to_irr)(struct kvm_vcpu *vcpu);
@@ -1277,6 +1279,7 @@ void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu);
int kvm_mmu_load(struct kvm_vcpu *vcpu);
void kvm_mmu_unload(struct kvm_vcpu *vcpu);
void kvm_mmu_sync_roots(struct kvm_vcpu *vcpu);
+void kvm_mmu_free_roots(struct kvm_vcpu *vcpu);
gpa_t translate_nested_gpa(struct kvm_vcpu *vcpu, gpa_t gpa, u32 access,
struct x86_exception *exception);
gpa_t kvm_mmu_gva_to_gpa_read(struct kvm_vcpu *vcpu, gva_t gva,
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 9971921..3cd1431 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -269,7 +269,7 @@ static inline int cpumask_to_vpset(struct hv_vpset *vpset,
return 0;
/*
- * Clear all banks up to the maximum possible bank as hv_flush_pcpu_ex
+ * Clear all banks up to the maximum possible bank as hv_tlb_flush_ex
* structs are not cleared between calls, we risk flushing unneeded
* vCPUs otherwise.
*/
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index e28add6..cfd29ee 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -412,7 +412,7 @@ extern asmlinkage void ignore_sysret(void);
void save_fsgs_for_kvm(void);
#endif
#else /* X86_64 */
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
/*
* Make sure stack canary segment base is cached-aligned:
* "For Intel Atom processors, avoid non zero segment base address
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index 8f09012b..e293c12 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -146,7 +146,7 @@
# define __KERNEL_PERCPU 0
#endif
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
# define __KERNEL_STACK_CANARY (GDT_ENTRY_STACK_CANARY*8)
#else
# define __KERNEL_STACK_CANARY 0
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h
index 371b3a4..8ec97a6 100644
--- a/arch/x86/include/asm/stackprotector.h
+++ b/arch/x86/include/asm/stackprotector.h
@@ -34,7 +34,7 @@
#ifndef _ASM_STACKPROTECTOR_H
#define _ASM_STACKPROTECTOR_H 1
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
#include <asm/tsc.h>
#include <asm/processor.h>
@@ -105,7 +105,7 @@ static inline void load_stack_canary_segment(void)
#endif
}
-#else /* CC_STACKPROTECTOR */
+#else /* STACKPROTECTOR */
#define GDT_STACK_CANARY_INIT
@@ -121,5 +121,5 @@ static inline void load_stack_canary_segment(void)
#endif
}
-#endif /* CC_STACKPROTECTOR */
+#endif /* STACKPROTECTOR */
#endif /* _ASM_STACKPROTECTOR_H */
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 5db8b0b..6aa8499 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -114,6 +114,7 @@
#define VMX_MISC_PREEMPTION_TIMER_RATE_MASK 0x0000001f
#define VMX_MISC_SAVE_EFER_LMA 0x00000020
#define VMX_MISC_ACTIVITY_HLT 0x00000040
+#define VMX_MISC_ZERO_LEN_INS 0x40000000
/* VMFUNC functions */
#define VMX_VMFUNC_EPTP_SWITCHING 0x00000001
@@ -207,7 +208,9 @@ enum vmcs_field {
EPTP_LIST_ADDRESS = 0x00002024,
EPTP_LIST_ADDRESS_HIGH = 0x00002025,
VMREAD_BITMAP = 0x00002026,
+ VMREAD_BITMAP_HIGH = 0x00002027,
VMWRITE_BITMAP = 0x00002028,
+ VMWRITE_BITMAP_HIGH = 0x00002029,
XSS_EXIT_BITMAP = 0x0000202C,
XSS_EXIT_BITMAP_HIGH = 0x0000202D,
TSC_MULTIPLIER = 0x00002032,
@@ -349,11 +352,13 @@ enum vmcs_field {
#define VECTORING_INFO_VALID_MASK INTR_INFO_VALID_MASK
#define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */
+#define INTR_TYPE_RESERVED (1 << 8) /* reserved */
#define INTR_TYPE_NMI_INTR (2 << 8) /* NMI */
#define INTR_TYPE_HARD_EXCEPTION (3 << 8) /* processor exception */
#define INTR_TYPE_SOFT_INTR (4 << 8) /* software interrupt */
#define INTR_TYPE_PRIV_SW_EXCEPTION (5 << 8) /* ICE breakpoint - undocumented */
#define INTR_TYPE_SOFT_EXCEPTION (6 << 8) /* software exception */
+#define INTR_TYPE_OTHER_EVENT (7 << 8) /* other event */
/* GUEST_INTERRUPTIBILITY_INFO flags. */
#define GUEST_INTR_STATE_STI 0x00000001
diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index efaf2d4..d492752 100644
--- a/arch/x86/kernel/apic/x2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/crash_dump.h>
#include <linux/reboot.h>
+#include <linux/memory.h>
#include <asm/uv/uv_mmrs.h>
#include <asm/uv/uv_hub.h>
@@ -392,6 +393,51 @@ extern int uv_hub_info_version(void)
}
EXPORT_SYMBOL(uv_hub_info_version);
+/* Default UV memory block size is 2GB */
+static unsigned long mem_block_size = (2UL << 30);
+
+/* Kernel parameter to specify UV mem block size */
+static int parse_mem_block_size(char *ptr)
+{
+ unsigned long size = memparse(ptr, NULL);
+
+ /* Size will be rounded down by set_block_size() below */
+ mem_block_size = size;
+ return 0;
+}
+early_param("uv_memblksize", parse_mem_block_size);
+
+static __init int adj_blksize(u32 lgre)
+{
+ unsigned long base = (unsigned long)lgre << UV_GAM_RANGE_SHFT;
+ unsigned long size;
+
+ for (size = mem_block_size; size > MIN_MEMORY_BLOCK_SIZE; size >>= 1)
+ if (IS_ALIGNED(base, size))
+ break;
+
+ if (size >= mem_block_size)
+ return 0;
+
+ mem_block_size = size;
+ return 1;
+}
+
+static __init void set_block_size(void)
+{
+ unsigned int order = ffs(mem_block_size);
+
+ if (order) {
+ /* adjust for ffs return of 1..64 */
+ set_memory_block_size_order(order - 1);
+ pr_info("UV: mem_block_size set to 0x%lx\n", mem_block_size);
+ } else {
+ /* bad or zero value, default to 1UL << 31 (2GB) */
+ pr_err("UV: mem_block_size error with 0x%lx\n", mem_block_size);
+ set_memory_block_size_order(31);
+ }
+}
+
/* Build GAM range lookup table: */
static __init void build_uv_gr_table(void)
{
@@ -1180,23 +1226,30 @@ static void __init decode_gam_rng_tbl(unsigned long ptr)
<< UV_GAM_RANGE_SHFT);
int order = 0;
char suffix[] = " KMGTPE";
+ int flag = ' ';
while (size > 9999 && order < sizeof(suffix)) {
size /= 1024;
order++;
}
+ /* adjust max block size to current range start */
+ if (gre->type == 1 || gre->type == 2)
+ if (adj_blksize(lgre))
+ flag = '*';
+
if (!index) {
pr_info("UV: GAM Range Table...\n");
- pr_info("UV: # %20s %14s %5s %4s %5s %3s %2s\n", "Range", "", "Size", "Type", "NASID", "SID", "PN");
+ pr_info("UV: # %20s %14s %6s %4s %5s %3s %2s\n", "Range", "", "Size", "Type", "NASID", "SID", "PN");
}
- pr_info("UV: %2d: 0x%014lx-0x%014lx %5lu%c %3d %04x %02x %02x\n",
+ pr_info("UV: %2d: 0x%014lx-0x%014lx%c %5lu%c %3d %04x %02x %02x\n",
index++,
(unsigned long)lgre << UV_GAM_RANGE_SHFT,
(unsigned long)gre->limit << UV_GAM_RANGE_SHFT,
- size, suffix[order],
+ flag, size, suffix[order],
gre->type, gre->nasid, gre->sockid, gre->pnode);
+ /* update to next range start */
lgre = gre->limit;
if (sock_min > gre->sockid)
sock_min = gre->sockid;
@@ -1427,6 +1480,7 @@ static void __init uv_system_init_hub(void)
build_socket_tables();
build_uv_gr_table();
+ set_block_size();
uv_init_hub_info(&hub_info);
uv_possible_blades = num_possible_nodes();
if (!_node_to_pnode)
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 76417a9..dcb008c 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -32,7 +32,7 @@
void common(void) {
BLANK();
OFFSET(TASK_threadsp, task_struct, thread.sp);
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
OFFSET(TASK_stack_canary, task_struct, stack_canary);
#endif
diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c
index f91ba53..a4a3be3 100644
--- a/arch/x86/kernel/asm-offsets_32.c
+++ b/arch/x86/kernel/asm-offsets_32.c
@@ -50,7 +50,7 @@ void foo(void)
DEFINE(TSS_sysenter_sp0, offsetof(struct cpu_entry_area, tss.x86_tss.sp0) -
offsetofend(struct cpu_entry_area, entry_stack_page.stack));
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
BLANK();
OFFSET(stack_canary_offset, stack_canary, canary);
#endif
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c
index bf51e51..b2dcd16 100644
--- a/arch/x86/kernel/asm-offsets_64.c
+++ b/arch/x86/kernel/asm-offsets_64.c
@@ -69,7 +69,7 @@ int main(void)
OFFSET(TSS_sp1, tss_struct, x86_tss.sp1);
BLANK();
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
DEFINE(stack_canary_offset, offsetof(union irq_stack_union, stack_canary));
BLANK();
#endif
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index cd0fda1..404df26 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -27,6 +27,7 @@
#include <asm/pgtable.h>
#include <asm/set_memory.h>
#include <asm/intel-family.h>
+#include <asm/hypervisor.h>
static void __init spectre_v2_select_mitigation(void);
static void __init ssb_select_mitigation(void);
@@ -664,6 +665,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
if (boot_cpu_has(X86_FEATURE_PTI))
return sprintf(buf, "Mitigation: PTI\n");
+ if (hypervisor_is_type(X86_HYPER_XEN_PV))
+ return sprintf(buf, "Unknown (XEN PV detected, hypervisor mitigation required)\n");
+
break;
case X86_BUG_SPECTRE_V1:
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 38354c6..0c5fcbd 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -671,7 +671,7 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
num_sharing_cache = ((eax >> 14) & 0xfff) + 1;
if (num_sharing_cache) {
- int bits = get_count_order(num_sharing_cache) - 1;
+ int bits = get_count_order(num_sharing_cache);
per_cpu(cpu_llc_id, cpu) = c->apicid >> bits;
}
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 910b47e..eb4cb3e 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1,3 +1,6 @@
+/* cpu_feature_enabled() cannot be used this early */
+#define USE_EARLY_PGTABLE_L5
+
#include <linux/bootmem.h>
#include <linux/linkage.h>
#include <linux/bitops.h>
@@ -1599,7 +1602,7 @@ DEFINE_PER_CPU(unsigned long, cpu_current_top_of_stack) =
(unsigned long)&init_thread_union + THREAD_SIZE;
EXPORT_PER_CPU_SYMBOL(cpu_current_top_of_stack);
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary);
#endif
diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 5bbd06f..f34d89c 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -160,6 +160,11 @@ static struct severity {
SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_INSTR),
USER
),
+ MCESEV(
+ PANIC, "Data load in unrecoverable area of kernel",
+ SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|MCACOD_DATA),
+ KERNEL
+ ),
#endif
MCESEV(
PANIC, "Action required: unknown MCACOD",
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index cd76380..c102ad5 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -772,23 +772,25 @@ EXPORT_SYMBOL_GPL(machine_check_poll);
static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
struct pt_regs *regs)
{
- int i, ret = 0;
char *tmp;
+ int i;
for (i = 0; i < mca_cfg.banks; i++) {
m->status = mce_rdmsrl(msr_ops.status(i));
- if (m->status & MCI_STATUS_VAL) {
- __set_bit(i, validp);
- if (quirk_no_way_out)
- quirk_no_way_out(i, m, regs);
- }
+ if (!(m->status & MCI_STATUS_VAL))
+ continue;
+
+ __set_bit(i, validp);
+ if (quirk_no_way_out)
+ quirk_no_way_out(i, m, regs);
if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) {
+ mce_read_aux(m, i);
*msg = tmp;
- ret = 1;
+ return 1;
}
}
- return ret;
+ return 0;
}
/*
@@ -1205,13 +1207,18 @@ void do_machine_check(struct pt_regs *regs, long error_code)
lmce = m.mcgstatus & MCG_STATUS_LMCES;
/*
+ * Local machine check may already know that we have to panic.
+ * Broadcast machine check begins rendezvous in mce_start()
* Go through all banks in exclusion of the other CPUs. This way we
* don't report duplicated events on shared banks because the first one
- * to see it will clear it. If this is a Local MCE, then no need to
- * perform rendezvous.
+ * to see it will clear it.
*/
- if (!lmce)
+ if (lmce) {
+ if (no_way_out)
+ mce_panic("Fatal local machine check", &m, msg);
+ } else {
order = mce_start(&no_way_out);
+ }
for (i = 0; i < cfg->banks; i++) {
__clear_bit(i, toclear);
@@ -1287,12 +1294,17 @@ void do_machine_check(struct pt_regs *regs, long error_code)
no_way_out = worst >= MCE_PANIC_SEVERITY;
} else {
/*
- * Local MCE skipped calling mce_reign()
- * If we found a fatal error, we need to panic here.
+ * If there was a fatal machine check we should have
+ * already called mce_panic earlier in this function.
+ * Since we re-read the banks, we might have found
+ * something new. Check again to see if we found a
+ * fatal error. We call "mce_severity()" again to
+ * make sure we have the right "msg".
*/
- if (worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3)
- mce_panic("Machine check from unknown source",
- NULL, NULL);
+ if (worst >= MCE_PANIC_SEVERITY && mca_cfg.tolerant < 3) {
+ mce_severity(&m, cfg->tolerant, &msg, true);
+ mce_panic("Local fatal machine check!", &m, msg);
+ }
}
/*
@@ -1457,7 +1469,7 @@ static int __mcheck_cpu_mce_banks_init(void)
int i;
u8 num_banks = mca_cfg.banks;
- mce_banks = kzalloc(num_banks * sizeof(struct mce_bank), GFP_KERNEL);
+ mce_banks = kcalloc(num_banks, sizeof(struct mce_bank), GFP_KERNEL);
if (!mce_banks)
return -ENOMEM;
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index f591b01..dd33c35 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -1384,7 +1384,7 @@ int mce_threshold_create_device(unsigned int cpu)
if (bp)
return 0;
- bp = kzalloc(sizeof(struct threshold_bank *) * mca_cfg.banks,
+ bp = kcalloc(mca_cfg.banks, sizeof(struct threshold_bank *),
GFP_KERNEL);
if (!bp)
return -ENOMEM;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 1c2cfa0..97ccf4c 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -190,8 +190,11 @@ static void save_microcode_patch(void *data, unsigned int size)
p = memdup_patch(data, size);
if (!p)
pr_err("Error allocating buffer %p\n", data);
- else
+ else {
list_replace(&iter->plist, &p->plist);
+ kfree(iter->data);
+ kfree(iter);
+ }
}
}
diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c
index c610f47..4021d38 100644
--- a/arch/x86/kernel/cpu/mtrr/if.c
+++ b/arch/x86/kernel/cpu/mtrr/if.c
@@ -43,7 +43,7 @@ mtrr_file_add(unsigned long base, unsigned long size,
max = num_var_ranges;
if (fcount == NULL) {
- fcount = kzalloc(max * sizeof *fcount, GFP_KERNEL);
+ fcount = kcalloc(max, sizeof(*fcount), GFP_KERNEL);
if (!fcount)
return -ENOMEM;
FILE_FCOUNT(file) = fcount;
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index a21d6ac..8047379 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -44,7 +44,7 @@ static unsigned int __initdata next_early_pgt;
pmdval_t early_pmd_flags = __PAGE_KERNEL_LARGE & ~(_PAGE_GLOBAL | _PAGE_NX);
#ifdef CONFIG_X86_5LEVEL
-unsigned int __pgtable_l5_enabled __initdata;
+unsigned int __pgtable_l5_enabled __ro_after_init;
unsigned int pgdir_shift __ro_after_init = 39;
EXPORT_SYMBOL(pgdir_shift);
unsigned int ptrs_per_p4d __ro_after_init = 1;
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index b59e4fb..abe6df1 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -375,7 +375,7 @@ ENDPROC(startup_32_smp)
*/
__INIT
setup_once:
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
/*
* Configure the stack canary. The linker can't handle this by
* relocation. Manually set base address in stack canary
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index b6be34e..346b248 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -610,7 +610,7 @@ static void hpet_msi_capability_lookup(unsigned int start_timer)
if (!hpet_domain)
return;
- hpet_devs = kzalloc(sizeof(struct hpet_dev) * num_timers, GFP_KERNEL);
+ hpet_devs = kcalloc(num_timers, sizeof(struct hpet_dev), GFP_KERNEL);
if (!hpet_devs)
return;
@@ -966,8 +966,8 @@ int __init hpet_enable(void)
#endif
cfg = hpet_readl(HPET_CFG);
- hpet_boot_cfg = kmalloc((last + 2) * sizeof(*hpet_boot_cfg),
- GFP_KERNEL);
+ hpet_boot_cfg = kmalloc_array(last + 2, sizeof(*hpet_boot_cfg),
+ GFP_KERNEL);
if (hpet_boot_cfg)
*hpet_boot_cfg = cfg;
else
diff --git a/arch/x86/kernel/ksysfs.c b/arch/x86/kernel/ksysfs.c
index 8c1cc08..163ae70 100644
--- a/arch/x86/kernel/ksysfs.c
+++ b/arch/x86/kernel/ksysfs.c
@@ -283,7 +283,7 @@ static int __init create_setup_data_nodes(struct kobject *parent)
if (ret)
goto out_setup_data_kobj;
- kobjp = kmalloc(sizeof(*kobjp) * nr, GFP_KERNEL);
+ kobjp = kmalloc_array(nr, sizeof(*kobjp), GFP_KERNEL);
if (!kobjp) {
ret = -ENOMEM;
goto out_setup_data_kobj;
diff --git a/arch/x86/kernel/quirks.c b/arch/x86/kernel/quirks.c
index 697a4ce..736348e 100644
--- a/arch/x86/kernel/quirks.c
+++ b/arch/x86/kernel/quirks.c
@@ -645,12 +645,19 @@ static void quirk_intel_brickland_xeon_ras_cap(struct pci_dev *pdev)
/* Skylake */
static void quirk_intel_purley_xeon_ras_cap(struct pci_dev *pdev)
{
- u32 capid0;
+ u32 capid0, capid5;
pci_read_config_dword(pdev, 0x84, &capid0);
+ pci_read_config_dword(pdev, 0x98, &capid5);
- if ((capid0 & 0xc0) == 0xc0)
+ /*
+ * CAPID0{7:6} indicate whether this is an advanced RAS SKU
+ * CAPID5{8:5} indicate that various NVDIMM usage modes are
+ * enabled, so memory machine check recovery is also enabled.
+ */
+ if ((capid0 & 0xc0) == 0xc0 || (capid5 & 0x1e0))
static_branch_inc(&mcsafe_key);
+
}
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x0ec3, quirk_intel_brickland_xeon_ras_cap);
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2fc0, quirk_intel_brickland_xeon_ras_cap);
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 445ca11..92a3b31 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -692,7 +692,7 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
* Increment event counter and perform fixup for the pre-signal
* frame.
*/
- rseq_signal_deliver(regs);
+ rseq_signal_deliver(ksig, regs);
/* Set up the stack frame */
if (is_ia32_frame(ksig)) {
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index a535dd6..e6db475 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -835,16 +835,18 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
char *str = (trapnr == X86_TRAP_MF) ? "fpu exception" :
"simd exception";
- if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, SIGFPE) == NOTIFY_STOP)
- return;
cond_local_irq_enable(regs);
if (!user_mode(regs)) {
- if (!fixup_exception(regs, trapnr)) {
- task->thread.error_code = error_code;
- task->thread.trap_nr = trapnr;
+ if (fixup_exception(regs, trapnr))
+ return;
+
+ task->thread.error_code = error_code;
+ task->thread.trap_nr = trapnr;
+
+ if (notify_die(DIE_TRAP, str, regs, error_code,
+ trapnr, SIGFPE) != NOTIFY_STOP)
die(str, regs, error_code);
- }
return;
}
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index f4f30d0..7e042e3 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -203,8 +203,9 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
goto out;
r = -ENOMEM;
if (cpuid->nent) {
- cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) *
- cpuid->nent);
+ cpuid_entries =
+ vmalloc(array_size(sizeof(struct kvm_cpuid_entry),
+ cpuid->nent));
if (!cpuid_entries)
goto out;
r = -EFAULT;
@@ -404,7 +405,8 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
const u32 kvm_cpuid_7_0_ecx_x86_features =
F(AVX512VBMI) | F(LA57) | F(PKU) | 0 /*OSPKE*/ |
F(AVX512_VPOPCNTDQ) | F(UMIP) | F(AVX512_VBMI2) | F(GFNI) |
- F(VAES) | F(VPCLMULQDQ) | F(AVX512_VNNI) | F(AVX512_BITALG);
+ F(VAES) | F(VPCLMULQDQ) | F(AVX512_VNNI) | F(AVX512_BITALG) |
+ F(CLDEMOTE);
/* cpuid 7.0.edx*/
const u32 kvm_cpuid_7_0_edx_x86_features =
@@ -784,7 +786,8 @@ int kvm_dev_ioctl_get_cpuid(struct kvm_cpuid2 *cpuid,
return -EINVAL;
r = -ENOMEM;
- cpuid_entries = vzalloc(sizeof(struct kvm_cpuid_entry2) * cpuid->nent);
+ cpuid_entries = vzalloc(array_size(sizeof(struct kvm_cpuid_entry2),
+ cpuid->nent));
if (!cpuid_entries)
goto out;
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index b3705ae..4c4f426 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -812,6 +812,19 @@ static inline int jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
return assign_eip_near(ctxt, ctxt->_eip + rel);
}
+static int linear_read_system(struct x86_emulate_ctxt *ctxt, ulong linear,
+ void *data, unsigned size)
+{
+ return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, true);
+}
+
+static int linear_write_system(struct x86_emulate_ctxt *ctxt,
+ ulong linear, void *data,
+ unsigned int size)
+{
+ return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, true);
+}
+
static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
struct segmented_address addr,
void *data,
@@ -823,7 +836,7 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
rc = linearize(ctxt, addr, size, false, &linear);
if (rc != X86EMUL_CONTINUE)
return rc;
- return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
+ return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception, false);
}
static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
@@ -837,7 +850,7 @@ static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
rc = linearize(ctxt, addr, size, true, &linear);
if (rc != X86EMUL_CONTINUE)
return rc;
- return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
+ return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception, false);
}
/*
@@ -1496,8 +1509,7 @@ static int read_interrupt_descriptor(struct x86_emulate_ctxt *ctxt,
return emulate_gp(ctxt, index << 3 | 0x2);
addr = dt.address + index * 8;
- return ctxt->ops->read_std(ctxt, addr, desc, sizeof *desc,
- &ctxt->exception);
+ return linear_read_system(ctxt, addr, desc, sizeof *desc);
}
static void get_descriptor_table_ptr(struct x86_emulate_ctxt *ctxt,
@@ -1560,8 +1572,7 @@ static int read_segment_descriptor(struct x86_emulate_ctxt *ctxt,
if (rc != X86EMUL_CONTINUE)
return rc;
- return ctxt->ops->read_std(ctxt, *desc_addr_p, desc, sizeof(*desc),
- &ctxt->exception);
+ return linear_read_system(ctxt, *desc_addr_p, desc, sizeof(*desc));
}
/* allowed just for 8 bytes segments */
@@ -1575,8 +1586,7 @@ static int write_segment_descriptor(struct x86_emulate_ctxt *ctxt,
if (rc != X86EMUL_CONTINUE)
return rc;
- return ctxt->ops->write_std(ctxt, addr, desc, sizeof *desc,
- &ctxt->exception);
+ return linear_write_system(ctxt, addr, desc, sizeof *desc);
}
static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
@@ -1737,8 +1747,7 @@ static int __load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
return ret;
}
} else if (ctxt->mode == X86EMUL_MODE_PROT64) {
- ret = ctxt->ops->read_std(ctxt, desc_addr+8, &base3,
- sizeof(base3), &ctxt->exception);
+ ret = linear_read_system(ctxt, desc_addr+8, &base3, sizeof(base3));
if (ret != X86EMUL_CONTINUE)
return ret;
if (emul_is_noncanonical_address(get_desc_base(&seg_desc) |
@@ -2051,11 +2060,11 @@ static int __emulate_int_real(struct x86_emulate_ctxt *ctxt, int irq)
eip_addr = dt.address + (irq << 2);
cs_addr = dt.address + (irq << 2) + 2;
- rc = ops->read_std(ctxt, cs_addr, &cs, 2, &ctxt->exception);
+ rc = linear_read_system(ctxt, cs_addr, &cs, 2);
if (rc != X86EMUL_CONTINUE)
return rc;
- rc = ops->read_std(ctxt, eip_addr, &eip, 2, &ctxt->exception);
+ rc = linear_read_system(ctxt, eip_addr, &eip, 2);
if (rc != X86EMUL_CONTINUE)
return rc;
@@ -2919,12 +2928,12 @@ static bool emulator_io_port_access_allowed(struct x86_emulate_ctxt *ctxt,
#ifdef CONFIG_X86_64
base |= ((u64)base3) << 32;
#endif
- r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL);
+ r = ops->read_std(ctxt, base + 102, &io_bitmap_ptr, 2, NULL, true);
if (r != X86EMUL_CONTINUE)
return false;
if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg))
return false;
- r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL);
+ r = ops->read_std(ctxt, base + io_bitmap_ptr + port/8, &perm, 2, NULL, true);
if (r != X86EMUL_CONTINUE)
return false;
if ((perm >> bit_idx) & mask)
@@ -3053,35 +3062,30 @@ static int task_switch_16(struct x86_emulate_ctxt *ctxt,
u16 tss_selector, u16 old_tss_sel,
ulong old_tss_base, struct desc_struct *new_desc)
{
- const struct x86_emulate_ops *ops = ctxt->ops;
struct tss_segment_16 tss_seg;
int ret;
u32 new_tss_base = get_desc_base(new_desc);
- ret = ops->read_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg,
- &ctxt->exception);
+ ret = linear_read_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg);
if (ret != X86EMUL_CONTINUE)
return ret;
save_state_to_tss16(ctxt, &tss_seg);
- ret = ops->write_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg,
- &ctxt->exception);
+ ret = linear_write_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = ops->read_std(ctxt, new_tss_base, &tss_seg, sizeof tss_seg,
- &ctxt->exception);
+ ret = linear_read_system(ctxt, new_tss_base, &tss_seg, sizeof tss_seg);
if (ret != X86EMUL_CONTINUE)
return ret;
if (old_tss_sel != 0xffff) {
tss_seg.prev_task_link = old_tss_sel;
- ret = ops->write_std(ctxt, new_tss_base,
- &tss_seg.prev_task_link,
- sizeof tss_seg.prev_task_link,
- &ctxt->exception);
+ ret = linear_write_system(ctxt, new_tss_base,
+ &tss_seg.prev_task_link,
+ sizeof tss_seg.prev_task_link);
if (ret != X86EMUL_CONTINUE)
return ret;
}
@@ -3197,38 +3201,34 @@ static int task_switch_32(struct x86_emulate_ctxt *ctxt,
u16 tss_selector, u16 old_tss_sel,
ulong old_tss_base, struct desc_struct *new_desc)
{
- const struct x86_emulate_ops *ops = ctxt->ops;
struct tss_segment_32 tss_seg;
int ret;
u32 new_tss_base = get_desc_base(new_desc);
u32 eip_offset = offsetof(struct tss_segment_32, eip);
u32 ldt_sel_offset = offsetof(struct tss_segment_32, ldt_selector);
- ret = ops->read_std(ctxt, old_tss_base, &tss_seg, sizeof tss_seg,
- &ctxt->exception);
+ ret = linear_read_system(ctxt, old_tss_base, &tss_seg, sizeof tss_seg);
if (ret != X86EMUL_CONTINUE)
return ret;
save_state_to_tss32(ctxt, &tss_seg);
/* Only GP registers and segment selectors are saved */
- ret = ops->write_std(ctxt, old_tss_base + eip_offset, &tss_seg.eip,
- ldt_sel_offset - eip_offset, &ctxt->exception);
+ ret = linear_write_system(ctxt, old_tss_base + eip_offset, &tss_seg.eip,
+ ldt_sel_offset - eip_offset);
if (ret != X86EMUL_CONTINUE)
return ret;
- ret = ops->read_std(ctxt, new_tss_base, &tss_seg, sizeof tss_seg,
- &ctxt->exception);
+ ret = linear_read_system(ctxt, new_tss_base, &tss_seg, sizeof tss_seg);
if (ret != X86EMUL_CONTINUE)
return ret;
if (old_tss_sel != 0xffff) {
tss_seg.prev_task_link = old_tss_sel;
- ret = ops->write_std(ctxt, new_tss_base,
- &tss_seg.prev_task_link,
- sizeof tss_seg.prev_task_link,
- &ctxt->exception);
+ ret = linear_write_system(ctxt, new_tss_base,
+ &tss_seg.prev_task_link,
+ sizeof tss_seg.prev_task_link);
if (ret != X86EMUL_CONTINUE)
return ret;
}
@@ -4189,7 +4189,9 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt)
maxphyaddr = eax & 0xff;
else
maxphyaddr = 36;
- rsvd = rsvd_bits(maxphyaddr, 62);
+ rsvd = rsvd_bits(maxphyaddr, 63);
+ if (ctxt->ops->get_cr(ctxt, 4) & X86_CR4_PCIDE)
+ rsvd &= ~CR3_PCID_INVD;
}
if (new_val & rsvd)
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
index 46ff64d..af8caf96 100644
--- a/arch/x86/kvm/hyperv.c
+++ b/arch/x86/kvm/hyperv.c
@@ -1242,6 +1242,121 @@ int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
return kvm_hv_get_msr(vcpu, msr, pdata);
}
+static __always_inline int get_sparse_bank_no(u64 valid_bank_mask, int bank_no)
+{
+ int i = 0, j;
+
+ if (!(valid_bank_mask & BIT_ULL(bank_no)))
+ return -1;
+
+ for (j = 0; j < bank_no; j++)
+ if (valid_bank_mask & BIT_ULL(j))
+ i++;
+
+ return i;
+}
+
+static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa,
+ u16 rep_cnt, bool ex)
+{
+ struct kvm *kvm = current_vcpu->kvm;
+ struct kvm_vcpu_hv *hv_current = &current_vcpu->arch.hyperv;
+ struct hv_tlb_flush_ex flush_ex;
+ struct hv_tlb_flush flush;
+ struct kvm_vcpu *vcpu;
+ unsigned long vcpu_bitmap[BITS_TO_LONGS(KVM_MAX_VCPUS)] = {0};
+ unsigned long valid_bank_mask = 0;
+ u64 sparse_banks[64];
+ int sparse_banks_len, i;
+ bool all_cpus;
+
+ if (!ex) {
+ if (unlikely(kvm_read_guest(kvm, ingpa, &flush, sizeof(flush))))
+ return HV_STATUS_INVALID_HYPERCALL_INPUT;
+
+ trace_kvm_hv_flush_tlb(flush.processor_mask,
+ flush.address_space, flush.flags);
+
+ sparse_banks[0] = flush.processor_mask;
+ all_cpus = flush.flags & HV_FLUSH_ALL_PROCESSORS;
+ } else {
+ if (unlikely(kvm_read_guest(kvm, ingpa, &flush_ex,
+ sizeof(flush_ex))))
+ return HV_STATUS_INVALID_HYPERCALL_INPUT;
+
+ trace_kvm_hv_flush_tlb_ex(flush_ex.hv_vp_set.valid_bank_mask,
+ flush_ex.hv_vp_set.format,
+ flush_ex.address_space,
+ flush_ex.flags);
+
+ valid_bank_mask = flush_ex.hv_vp_set.valid_bank_mask;
+ all_cpus = flush_ex.hv_vp_set.format !=
+ HV_GENERIC_SET_SPARSE_4K;
+
+ sparse_banks_len = bitmap_weight(&valid_bank_mask, 64) *
+ sizeof(sparse_banks[0]);
+
+ if (!sparse_banks_len && !all_cpus)
+ goto ret_success;
+
+ if (!all_cpus &&
+ kvm_read_guest(kvm,
+ ingpa + offsetof(struct hv_tlb_flush_ex,
+ hv_vp_set.bank_contents),
+ sparse_banks,
+ sparse_banks_len))
+ return HV_STATUS_INVALID_HYPERCALL_INPUT;
+ }
+
+ cpumask_clear(&hv_current->tlb_lush);
+
+ kvm_for_each_vcpu(i, vcpu, kvm) {
+ struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv;
+ int bank = hv->vp_index / 64, sbank = 0;
+
+ if (!all_cpus) {
+ /* Banks >64 can't be represented */
+ if (bank >= 64)
+ continue;
+
+ /* Non-ex hypercalls can only address first 64 vCPUs */
+ if (!ex && bank)
+ continue;
+
+ if (ex) {
+ /*
+ * Check is the bank of this vCPU is in sparse
+ * set and get the sparse bank number.
+ */
+ sbank = get_sparse_bank_no(valid_bank_mask,
+ bank);
+
+ if (sbank < 0)
+ continue;
+ }
+
+ if (!(sparse_banks[sbank] & BIT_ULL(hv->vp_index % 64)))
+ continue;
+ }
+
+ /*
+ * vcpu->arch.cr3 may not be up-to-date for running vCPUs so we
+ * can't analyze it here, flush TLB regardless of the specified
+ * address space.
+ */
+ __set_bit(i, vcpu_bitmap);
+ }
+
+ kvm_make_vcpus_request_mask(kvm,
+ KVM_REQ_TLB_FLUSH | KVM_REQUEST_NO_WAKEUP,
+ vcpu_bitmap, &hv_current->tlb_lush);
+
+ret_success:
+ /* We always do full TLB flush, set rep_done = rep_cnt. */
+ return (u64)HV_STATUS_SUCCESS |
+ ((u64)rep_cnt << HV_HYPERCALL_REP_COMP_OFFSET);
+}
+
bool kvm_hv_hypercall_enabled(struct kvm *kvm)
{
return READ_ONCE(kvm->arch.hyperv.hv_hypercall) & HV_X64_MSR_HYPERCALL_ENABLE;
@@ -1315,7 +1430,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
{
u64 param, ingpa, outgpa, ret = HV_STATUS_SUCCESS;
uint16_t code, rep_idx, rep_cnt;
- bool fast, longmode;
+ bool fast, longmode, rep;
/*
* hypercall generates UD from non zero cpl and real mode
@@ -1345,31 +1460,34 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
#endif
code = param & 0xffff;
- fast = (param >> 16) & 0x1;
- rep_cnt = (param >> 32) & 0xfff;
- rep_idx = (param >> 48) & 0xfff;
+ fast = !!(param & HV_HYPERCALL_FAST_BIT);
+ rep_cnt = (param >> HV_HYPERCALL_REP_COMP_OFFSET) & 0xfff;
+ rep_idx = (param >> HV_HYPERCALL_REP_START_OFFSET) & 0xfff;
+ rep = !!(rep_cnt || rep_idx);
trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa);
- /* Hypercall continuation is not supported yet */
- if (rep_cnt || rep_idx) {
- ret = HV_STATUS_INVALID_HYPERCALL_CODE;
- goto out;
- }
-
switch (code) {
case HVCALL_NOTIFY_LONG_SPIN_WAIT:
+ if (unlikely(rep)) {
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+ break;
+ }
kvm_vcpu_on_spin(vcpu, true);
break;
case HVCALL_SIGNAL_EVENT:
+ if (unlikely(rep)) {
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+ break;
+ }
ret = kvm_hvcall_signal_event(vcpu, fast, ingpa);
if (ret != HV_STATUS_INVALID_PORT_ID)
break;
/* maybe userspace knows this conn_id: fall through */
case HVCALL_POST_MESSAGE:
/* don't bother userspace if it has no way to handle it */
- if (!vcpu_to_synic(vcpu)->active) {
- ret = HV_STATUS_INVALID_HYPERCALL_CODE;
+ if (unlikely(rep || !vcpu_to_synic(vcpu)->active)) {
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
break;
}
vcpu->run->exit_reason = KVM_EXIT_HYPERV;
@@ -1380,12 +1498,39 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
vcpu->arch.complete_userspace_io =
kvm_hv_hypercall_complete_userspace;
return 0;
+ case HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST:
+ if (unlikely(fast || !rep_cnt || rep_idx)) {
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+ break;
+ }
+ ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, false);
+ break;
+ case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE:
+ if (unlikely(fast || rep)) {
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+ break;
+ }
+ ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, false);
+ break;
+ case HVCALL_FLUSH_VIRTUAL_ADDRESS_LIST_EX:
+ if (unlikely(fast || !rep_cnt || rep_idx)) {
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+ break;
+ }
+ ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, true);
+ break;
+ case HVCALL_FLUSH_VIRTUAL_ADDRESS_SPACE_EX:
+ if (unlikely(fast || rep)) {
+ ret = HV_STATUS_INVALID_HYPERCALL_INPUT;
+ break;
+ }
+ ret = kvm_hv_flush_tlb(vcpu, ingpa, rep_cnt, true);
+ break;
default:
ret = HV_STATUS_INVALID_HYPERCALL_CODE;
break;
}
-out:
return kvm_hv_hypercall_complete(vcpu, ret);
}
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 3773c46..b5cd846 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2002,13 +2002,11 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
}
}
- if ((old_value ^ value) & X2APIC_ENABLE) {
- if (value & X2APIC_ENABLE) {
- kvm_apic_set_x2apic_id(apic, vcpu->vcpu_id);
- kvm_x86_ops->set_virtual_x2apic_mode(vcpu, true);
- } else
- kvm_x86_ops->set_virtual_x2apic_mode(vcpu, false);
- }
+ if (((old_value ^ value) & X2APIC_ENABLE) && (value & X2APIC_ENABLE))
+ kvm_apic_set_x2apic_id(apic, vcpu->vcpu_id);
+
+ if ((old_value ^ value) & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE))
+ kvm_x86_ops->set_virtual_apic_mode(vcpu);
apic->base_address = apic->vcpu->arch.apic_base &
MSR_IA32_APICBASE_BASE;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index edce055..ed0ed39 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -16,6 +16,13 @@
#define APIC_BUS_CYCLE_NS 1
#define APIC_BUS_FREQUENCY (1000000000ULL / APIC_BUS_CYCLE_NS)
+enum lapic_mode {
+ LAPIC_MODE_DISABLED = 0,
+ LAPIC_MODE_INVALID = X2APIC_ENABLE,
+ LAPIC_MODE_XAPIC = MSR_IA32_APICBASE_ENABLE,
+ LAPIC_MODE_X2APIC = MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE,
+};
+
struct kvm_timer {
struct hrtimer timer;
s64 period; /* unit: ns */
@@ -89,6 +96,7 @@ u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
+enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu);
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
@@ -220,4 +228,10 @@ void kvm_lapic_switch_to_hv_timer(struct kvm_vcpu *vcpu);
void kvm_lapic_expired_hv_timer(struct kvm_vcpu *vcpu);
bool kvm_lapic_hv_timer_in_use(struct kvm_vcpu *vcpu);
void kvm_lapic_restart_hv_timer(struct kvm_vcpu *vcpu);
+
+static inline enum lapic_mode kvm_apic_mode(u64 apic_base)
+{
+ return apic_base & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
+}
+
#endif
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index d634f033..d594690 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -222,7 +222,6 @@ static const u64 shadow_acc_track_saved_bits_mask = PT64_EPT_READABLE_MASK |
static const u64 shadow_acc_track_saved_bits_shift = PT64_SECOND_AVAIL_BITS_SHIFT;
static void mmu_spte_set(u64 *sptep, u64 spte);
-static void mmu_free_roots(struct kvm_vcpu *vcpu);
void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask, u64 mmio_value)
{
@@ -3343,51 +3342,48 @@ out_unlock:
return RET_PF_RETRY;
}
-
-static void mmu_free_roots(struct kvm_vcpu *vcpu)
+static void mmu_free_root_page(struct kvm *kvm, hpa_t *root_hpa,
+ struct list_head *invalid_list)
{
- int i;
struct kvm_mmu_page *sp;
- LIST_HEAD(invalid_list);
- if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
+ if (!VALID_PAGE(*root_hpa))
return;
- if (vcpu->arch.mmu.shadow_root_level >= PT64_ROOT_4LEVEL &&
- (vcpu->arch.mmu.root_level >= PT64_ROOT_4LEVEL ||
- vcpu->arch.mmu.direct_map)) {
- hpa_t root = vcpu->arch.mmu.root_hpa;
+ sp = page_header(*root_hpa & PT64_BASE_ADDR_MASK);
+ --sp->root_count;
+ if (!sp->root_count && sp->role.invalid)
+ kvm_mmu_prepare_zap_page(kvm, sp, invalid_list);
- spin_lock(&vcpu->kvm->mmu_lock);
- sp = page_header(root);
- --sp->root_count;
- if (!sp->root_count && sp->role.invalid) {
- kvm_mmu_prepare_zap_page(vcpu->kvm, sp, &invalid_list);
- kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
- }
- spin_unlock(&vcpu->kvm->mmu_lock);
- vcpu->arch.mmu.root_hpa = INVALID_PAGE;
+ *root_hpa = INVALID_PAGE;
+}
+
+void kvm_mmu_free_roots(struct kvm_vcpu *vcpu)
+{
+ int i;
+ LIST_HEAD(invalid_list);
+ struct kvm_mmu *mmu = &vcpu->arch.mmu;
+
+ if (!VALID_PAGE(mmu->root_hpa))
return;
- }
spin_lock(&vcpu->kvm->mmu_lock);
- for (i = 0; i < 4; ++i) {
- hpa_t root = vcpu->arch.mmu.pae_root[i];
- if (root) {
- root &= PT64_BASE_ADDR_MASK;
- sp = page_header(root);
- --sp->root_count;
- if (!sp->root_count && sp->role.invalid)
- kvm_mmu_prepare_zap_page(vcpu->kvm, sp,
- &invalid_list);
- }
- vcpu->arch.mmu.pae_root[i] = INVALID_PAGE;
+ if (mmu->shadow_root_level >= PT64_ROOT_4LEVEL &&
+ (mmu->root_level >= PT64_ROOT_4LEVEL || mmu->direct_map)) {
+ mmu_free_root_page(vcpu->kvm, &mmu->root_hpa, &invalid_list);
+ } else {
+ for (i = 0; i < 4; ++i)
+ if (mmu->pae_root[i] != 0)
+ mmu_free_root_page(vcpu->kvm, &mmu->pae_root[i],
+ &invalid_list);
+ mmu->root_hpa = INVALID_PAGE;
}
+
kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
spin_unlock(&vcpu->kvm->mmu_lock);
- vcpu->arch.mmu.root_hpa = INVALID_PAGE;
}
+EXPORT_SYMBOL_GPL(kvm_mmu_free_roots);
static int mmu_check_root(struct kvm_vcpu *vcpu, gfn_t root_gfn)
{
@@ -3720,7 +3716,6 @@ static int handle_mmio_page_fault(struct kvm_vcpu *vcpu, u64 addr, bool direct)
*/
return RET_PF_RETRY;
}
-EXPORT_SYMBOL_GPL(handle_mmio_page_fault);
static bool page_fault_handle_page_track(struct kvm_vcpu *vcpu,
u32 error_code, gfn_t gfn)
@@ -3812,6 +3807,14 @@ static bool try_async_pf(struct kvm_vcpu *vcpu, bool prefault, gfn_t gfn,
struct kvm_memory_slot *slot;
bool async;
+ /*
+ * Don't expose private memslots to L2.
+ */
+ if (is_guest_mode(vcpu) && !kvm_is_visible_gfn(vcpu->kvm, gfn)) {
+ *pfn = KVM_PFN_NOSLOT;
+ return false;
+ }
+
slot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
async = false;
*pfn = __gfn_to_pfn_memslot(slot, gfn, false, &async, write, writable);
@@ -3951,7 +3954,7 @@ static void nonpaging_init_context(struct kvm_vcpu *vcpu,
void kvm_mmu_new_cr3(struct kvm_vcpu *vcpu)
{
- mmu_free_roots(vcpu);
+ kvm_mmu_free_roots(vcpu);
}
static unsigned long get_cr3(struct kvm_vcpu *vcpu)
@@ -4473,6 +4476,7 @@ static void init_kvm_tdp_mmu(struct kvm_vcpu *vcpu)
struct kvm_mmu *context = &vcpu->arch.mmu;
context->base_role.word = 0;
+ context->base_role.guest_mode = is_guest_mode(vcpu);
context->base_role.smm = is_smm(vcpu);
context->base_role.ad_disabled = (shadow_accessed_mask == 0);
context->page_fault = tdp_page_fault;
@@ -4539,6 +4543,7 @@ void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu)
= smep && !is_write_protection(vcpu);
context->base_role.smap_andnot_wp
= smap && !is_write_protection(vcpu);
+ context->base_role.guest_mode = is_guest_mode(vcpu);
context->base_role.smm = is_smm(vcpu);
reset_shadow_zero_bits_mask(vcpu, context);
}
@@ -4564,7 +4569,7 @@ void kvm_init_shadow_ept_mmu(struct kvm_vcpu *vcpu, bool execonly,
context->root_hpa = INVALID_PAGE;
context->direct_map = false;
context->base_role.ad_disabled = !accessed_dirty;
-
+ context->base_role.guest_mode = 1;
update_permission_bitmask(vcpu, context, true);
update_pkru_bitmask(vcpu, context, true);
update_last_nonleaf_level(vcpu, context);
@@ -4664,7 +4669,7 @@ EXPORT_SYMBOL_GPL(kvm_mmu_load);
void kvm_mmu_unload(struct kvm_vcpu *vcpu)
{
- mmu_free_roots(vcpu);
+ kvm_mmu_free_roots(vcpu);
WARN_ON(VALID_PAGE(vcpu->arch.mmu.root_hpa));
}
EXPORT_SYMBOL_GPL(kvm_mmu_unload);
@@ -4825,6 +4830,7 @@ static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
mask.smep_andnot_wp = 1;
mask.smap_andnot_wp = 1;
mask.smm = 1;
+ mask.guest_mode = 1;
mask.ad_disabled = 1;
/*
diff --git a/arch/x86/kvm/page_track.c b/arch/x86/kvm/page_track.c
index 01c1371..3052a59 100644
--- a/arch/x86/kvm/page_track.c
+++ b/arch/x86/kvm/page_track.c
@@ -40,8 +40,9 @@ 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] = kvzalloc(npages *
- sizeof(*slot->arch.gfn_track[i]), GFP_KERNEL);
+ slot->arch.gfn_track[i] =
+ kvcalloc(npages, sizeof(*slot->arch.gfn_track[i]),
+ GFP_KERNEL);
if (!slot->arch.gfn_track[i])
goto track_free;
}
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 950ec50..f059a73 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1001,7 +1001,9 @@ static int svm_cpu_init(int cpu)
if (svm_sev_enabled()) {
r = -ENOMEM;
- sd->sev_vmcbs = kmalloc((max_sev_asid + 1) * sizeof(void *), GFP_KERNEL);
+ sd->sev_vmcbs = kmalloc_array(max_sev_asid + 1,
+ sizeof(void *),
+ GFP_KERNEL);
if (!sd->sev_vmcbs)
goto err_1;
}
@@ -1768,7 +1770,10 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,
unsigned long npages, npinned, size;
unsigned long locked, lock_limit;
struct page **pages;
- int first, last;
+ unsigned long first, last;
+
+ if (ulen == 0 || uaddr + ulen < uaddr)
+ return NULL;
/* Calculate number of pages. */
first = (uaddr & PAGE_MASK) >> PAGE_SHIFT;
@@ -1855,13 +1860,13 @@ static void __unregister_enc_region_locked(struct kvm *kvm,
static struct kvm *svm_vm_alloc(void)
{
- struct kvm_svm *kvm_svm = kzalloc(sizeof(struct kvm_svm), GFP_KERNEL);
+ struct kvm_svm *kvm_svm = vzalloc(sizeof(struct kvm_svm));
return &kvm_svm->kvm;
}
static void svm_vm_free(struct kvm *kvm)
{
- kfree(to_kvm_svm(kvm));
+ vfree(to_kvm_svm(kvm));
}
static void sev_vm_destroy(struct kvm *kvm)
@@ -5062,7 +5067,7 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
set_cr_intercept(svm, INTERCEPT_CR8_WRITE);
}
-static void svm_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
+static void svm_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
{
return;
}
@@ -6949,6 +6954,9 @@ static int svm_register_enc_region(struct kvm *kvm,
if (!sev_guest(kvm))
return -ENOTTY;
+ if (range->addr > ULONG_MAX || range->size > ULONG_MAX)
+ return -EINVAL;
+
region = kzalloc(sizeof(*region), GFP_KERNEL);
if (!region)
return -ENOMEM;
@@ -7100,7 +7108,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
.enable_nmi_window = enable_nmi_window,
.enable_irq_window = enable_irq_window,
.update_cr8_intercept = update_cr8_intercept,
- .set_virtual_x2apic_mode = svm_set_virtual_x2apic_mode,
+ .set_virtual_apic_mode = svm_set_virtual_apic_mode,
.get_enable_apicv = svm_get_enable_apicv,
.refresh_apicv_exec_ctrl = svm_refresh_apicv_exec_ctrl,
.load_eoi_exitmap = svm_load_eoi_exitmap,
diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
index 9807c31..0f99768 100644
--- a/arch/x86/kvm/trace.h
+++ b/arch/x86/kvm/trace.h
@@ -1367,6 +1367,57 @@ TRACE_EVENT(kvm_hv_timer_state,
__entry->vcpu_id,
__entry->hv_timer_in_use)
);
+
+/*
+ * Tracepoint for kvm_hv_flush_tlb.
+ */
+TRACE_EVENT(kvm_hv_flush_tlb,
+ TP_PROTO(u64 processor_mask, u64 address_space, u64 flags),
+ TP_ARGS(processor_mask, address_space, flags),
+
+ TP_STRUCT__entry(
+ __field(u64, processor_mask)
+ __field(u64, address_space)
+ __field(u64, flags)
+ ),
+
+ TP_fast_assign(
+ __entry->processor_mask = processor_mask;
+ __entry->address_space = address_space;
+ __entry->flags = flags;
+ ),
+
+ TP_printk("processor_mask 0x%llx address_space 0x%llx flags 0x%llx",
+ __entry->processor_mask, __entry->address_space,
+ __entry->flags)
+);
+
+/*
+ * Tracepoint for kvm_hv_flush_tlb_ex.
+ */
+TRACE_EVENT(kvm_hv_flush_tlb_ex,
+ TP_PROTO(u64 valid_bank_mask, u64 format, u64 address_space, u64 flags),
+ TP_ARGS(valid_bank_mask, format, address_space, flags),
+
+ TP_STRUCT__entry(
+ __field(u64, valid_bank_mask)
+ __field(u64, format)
+ __field(u64, address_space)
+ __field(u64, flags)
+ ),
+
+ TP_fast_assign(
+ __entry->valid_bank_mask = valid_bank_mask;
+ __entry->format = format;
+ __entry->address_space = address_space;
+ __entry->flags = flags;
+ ),
+
+ TP_printk("valid_bank_mask 0x%llx format 0x%llx "
+ "address_space 0x%llx flags 0x%llx",
+ __entry->valid_bank_mask, __entry->format,
+ __entry->address_space, __entry->flags)
+);
#endif /* _TRACE_KVM_H */
#undef TRACE_INCLUDE_PATH
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 40aa292..1689f43 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -242,7 +242,11 @@ struct shared_msr_entry {
* underlying hardware which will be used to run L2.
* This structure is packed to ensure that its layout is identical across
* machines (necessary for live migration).
- * If there are changes in this struct, VMCS12_REVISION must be changed.
+ *
+ * IMPORTANT: Changing the layout of existing fields in this structure
+ * will break save/restore compatibility with older kvm releases. When
+ * adding new fields, either use space in the reserved padding* arrays
+ * or add the new fields to the end of the structure.
*/
typedef u64 natural_width;
struct __packed vmcs12 {
@@ -265,17 +269,14 @@ struct __packed vmcs12 {
u64 virtual_apic_page_addr;
u64 apic_access_addr;
u64 posted_intr_desc_addr;
- u64 vm_function_control;
u64 ept_pointer;
u64 eoi_exit_bitmap0;
u64 eoi_exit_bitmap1;
u64 eoi_exit_bitmap2;
u64 eoi_exit_bitmap3;
- u64 eptp_list_address;
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;
@@ -288,7 +289,12 @@ struct __packed vmcs12 {
u64 host_ia32_pat;
u64 host_ia32_efer;
u64 host_ia32_perf_global_ctrl;
- u64 padding64[8]; /* room for future expansion */
+ u64 vmread_bitmap;
+ u64 vmwrite_bitmap;
+ u64 vm_function_control;
+ u64 eptp_list_address;
+ u64 pml_address;
+ u64 padding64[3]; /* room for future expansion */
/*
* To allow migration of L1 (complete with its L2 guests) between
* machines of different natural widths (32 or 64 bit), we cannot have
@@ -397,7 +403,6 @@ 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;
@@ -405,12 +410,172 @@ struct __packed vmcs12 {
u16 host_fs_selector;
u16 host_gs_selector;
u16 host_tr_selector;
+ u16 guest_pml_index;
};
/*
+ * For save/restore compatibility, the vmcs12 field offsets must not change.
+ */
+#define CHECK_OFFSET(field, loc) \
+ BUILD_BUG_ON_MSG(offsetof(struct vmcs12, field) != (loc), \
+ "Offset of " #field " in struct vmcs12 has changed.")
+
+static inline void vmx_check_vmcs12_offsets(void) {
+ CHECK_OFFSET(revision_id, 0);
+ CHECK_OFFSET(abort, 4);
+ CHECK_OFFSET(launch_state, 8);
+ CHECK_OFFSET(io_bitmap_a, 40);
+ CHECK_OFFSET(io_bitmap_b, 48);
+ CHECK_OFFSET(msr_bitmap, 56);
+ CHECK_OFFSET(vm_exit_msr_store_addr, 64);
+ CHECK_OFFSET(vm_exit_msr_load_addr, 72);
+ CHECK_OFFSET(vm_entry_msr_load_addr, 80);
+ CHECK_OFFSET(tsc_offset, 88);
+ CHECK_OFFSET(virtual_apic_page_addr, 96);
+ CHECK_OFFSET(apic_access_addr, 104);
+ CHECK_OFFSET(posted_intr_desc_addr, 112);
+ CHECK_OFFSET(ept_pointer, 120);
+ CHECK_OFFSET(eoi_exit_bitmap0, 128);
+ CHECK_OFFSET(eoi_exit_bitmap1, 136);
+ CHECK_OFFSET(eoi_exit_bitmap2, 144);
+ CHECK_OFFSET(eoi_exit_bitmap3, 152);
+ CHECK_OFFSET(xss_exit_bitmap, 160);
+ CHECK_OFFSET(guest_physical_address, 168);
+ CHECK_OFFSET(vmcs_link_pointer, 176);
+ CHECK_OFFSET(guest_ia32_debugctl, 184);
+ CHECK_OFFSET(guest_ia32_pat, 192);
+ CHECK_OFFSET(guest_ia32_efer, 200);
+ CHECK_OFFSET(guest_ia32_perf_global_ctrl, 208);
+ CHECK_OFFSET(guest_pdptr0, 216);
+ CHECK_OFFSET(guest_pdptr1, 224);
+ CHECK_OFFSET(guest_pdptr2, 232);
+ CHECK_OFFSET(guest_pdptr3, 240);
+ CHECK_OFFSET(guest_bndcfgs, 248);
+ CHECK_OFFSET(host_ia32_pat, 256);
+ CHECK_OFFSET(host_ia32_efer, 264);
+ CHECK_OFFSET(host_ia32_perf_global_ctrl, 272);
+ CHECK_OFFSET(vmread_bitmap, 280);
+ CHECK_OFFSET(vmwrite_bitmap, 288);
+ CHECK_OFFSET(vm_function_control, 296);
+ CHECK_OFFSET(eptp_list_address, 304);
+ CHECK_OFFSET(pml_address, 312);
+ CHECK_OFFSET(cr0_guest_host_mask, 344);
+ CHECK_OFFSET(cr4_guest_host_mask, 352);
+ CHECK_OFFSET(cr0_read_shadow, 360);
+ CHECK_OFFSET(cr4_read_shadow, 368);
+ CHECK_OFFSET(cr3_target_value0, 376);
+ CHECK_OFFSET(cr3_target_value1, 384);
+ CHECK_OFFSET(cr3_target_value2, 392);
+ CHECK_OFFSET(cr3_target_value3, 400);
+ CHECK_OFFSET(exit_qualification, 408);
+ CHECK_OFFSET(guest_linear_address, 416);
+ CHECK_OFFSET(guest_cr0, 424);
+ CHECK_OFFSET(guest_cr3, 432);
+ CHECK_OFFSET(guest_cr4, 440);
+ CHECK_OFFSET(guest_es_base, 448);
+ CHECK_OFFSET(guest_cs_base, 456);
+ CHECK_OFFSET(guest_ss_base, 464);
+ CHECK_OFFSET(guest_ds_base, 472);
+ CHECK_OFFSET(guest_fs_base, 480);
+ CHECK_OFFSET(guest_gs_base, 488);
+ CHECK_OFFSET(guest_ldtr_base, 496);
+ CHECK_OFFSET(guest_tr_base, 504);
+ CHECK_OFFSET(guest_gdtr_base, 512);
+ CHECK_OFFSET(guest_idtr_base, 520);
+ CHECK_OFFSET(guest_dr7, 528);
+ CHECK_OFFSET(guest_rsp, 536);
+ CHECK_OFFSET(guest_rip, 544);
+ CHECK_OFFSET(guest_rflags, 552);
+ CHECK_OFFSET(guest_pending_dbg_exceptions, 560);
+ CHECK_OFFSET(guest_sysenter_esp, 568);
+ CHECK_OFFSET(guest_sysenter_eip, 576);
+ CHECK_OFFSET(host_cr0, 584);
+ CHECK_OFFSET(host_cr3, 592);
+ CHECK_OFFSET(host_cr4, 600);
+ CHECK_OFFSET(host_fs_base, 608);
+ CHECK_OFFSET(host_gs_base, 616);
+ CHECK_OFFSET(host_tr_base, 624);
+ CHECK_OFFSET(host_gdtr_base, 632);
+ CHECK_OFFSET(host_idtr_base, 640);
+ CHECK_OFFSET(host_ia32_sysenter_esp, 648);
+ CHECK_OFFSET(host_ia32_sysenter_eip, 656);
+ CHECK_OFFSET(host_rsp, 664);
+ CHECK_OFFSET(host_rip, 672);
+ CHECK_OFFSET(pin_based_vm_exec_control, 744);
+ CHECK_OFFSET(cpu_based_vm_exec_control, 748);
+ CHECK_OFFSET(exception_bitmap, 752);
+ CHECK_OFFSET(page_fault_error_code_mask, 756);
+ CHECK_OFFSET(page_fault_error_code_match, 760);
+ CHECK_OFFSET(cr3_target_count, 764);
+ CHECK_OFFSET(vm_exit_controls, 768);
+ CHECK_OFFSET(vm_exit_msr_store_count, 772);
+ CHECK_OFFSET(vm_exit_msr_load_count, 776);
+ CHECK_OFFSET(vm_entry_controls, 780);
+ CHECK_OFFSET(vm_entry_msr_load_count, 784);
+ CHECK_OFFSET(vm_entry_intr_info_field, 788);
+ CHECK_OFFSET(vm_entry_exception_error_code, 792);
+ CHECK_OFFSET(vm_entry_instruction_len, 796);
+ CHECK_OFFSET(tpr_threshold, 800);
+ CHECK_OFFSET(secondary_vm_exec_control, 804);
+ CHECK_OFFSET(vm_instruction_error, 808);
+ CHECK_OFFSET(vm_exit_reason, 812);
+ CHECK_OFFSET(vm_exit_intr_info, 816);
+ CHECK_OFFSET(vm_exit_intr_error_code, 820);
+ CHECK_OFFSET(idt_vectoring_info_field, 824);
+ CHECK_OFFSET(idt_vectoring_error_code, 828);
+ CHECK_OFFSET(vm_exit_instruction_len, 832);
+ CHECK_OFFSET(vmx_instruction_info, 836);
+ CHECK_OFFSET(guest_es_limit, 840);
+ CHECK_OFFSET(guest_cs_limit, 844);
+ CHECK_OFFSET(guest_ss_limit, 848);
+ CHECK_OFFSET(guest_ds_limit, 852);
+ CHECK_OFFSET(guest_fs_limit, 856);
+ CHECK_OFFSET(guest_gs_limit, 860);
+ CHECK_OFFSET(guest_ldtr_limit, 864);
+ CHECK_OFFSET(guest_tr_limit, 868);
+ CHECK_OFFSET(guest_gdtr_limit, 872);
+ CHECK_OFFSET(guest_idtr_limit, 876);
+ CHECK_OFFSET(guest_es_ar_bytes, 880);
+ CHECK_OFFSET(guest_cs_ar_bytes, 884);
+ CHECK_OFFSET(guest_ss_ar_bytes, 888);
+ CHECK_OFFSET(guest_ds_ar_bytes, 892);
+ CHECK_OFFSET(guest_fs_ar_bytes, 896);
+ CHECK_OFFSET(guest_gs_ar_bytes, 900);
+ CHECK_OFFSET(guest_ldtr_ar_bytes, 904);
+ CHECK_OFFSET(guest_tr_ar_bytes, 908);
+ CHECK_OFFSET(guest_interruptibility_info, 912);
+ CHECK_OFFSET(guest_activity_state, 916);
+ CHECK_OFFSET(guest_sysenter_cs, 920);
+ CHECK_OFFSET(host_ia32_sysenter_cs, 924);
+ CHECK_OFFSET(vmx_preemption_timer_value, 928);
+ CHECK_OFFSET(virtual_processor_id, 960);
+ CHECK_OFFSET(posted_intr_nv, 962);
+ CHECK_OFFSET(guest_es_selector, 964);
+ CHECK_OFFSET(guest_cs_selector, 966);
+ CHECK_OFFSET(guest_ss_selector, 968);
+ CHECK_OFFSET(guest_ds_selector, 970);
+ CHECK_OFFSET(guest_fs_selector, 972);
+ CHECK_OFFSET(guest_gs_selector, 974);
+ CHECK_OFFSET(guest_ldtr_selector, 976);
+ CHECK_OFFSET(guest_tr_selector, 978);
+ CHECK_OFFSET(guest_intr_status, 980);
+ CHECK_OFFSET(host_es_selector, 982);
+ CHECK_OFFSET(host_cs_selector, 984);
+ CHECK_OFFSET(host_ss_selector, 986);
+ CHECK_OFFSET(host_ds_selector, 988);
+ CHECK_OFFSET(host_fs_selector, 990);
+ CHECK_OFFSET(host_gs_selector, 992);
+ CHECK_OFFSET(host_tr_selector, 994);
+ CHECK_OFFSET(guest_pml_index, 996);
+}
+
+/*
* VMCS12_REVISION is an arbitrary id that should be changed if the content or
* layout of struct vmcs12 is changed. MSR_IA32_VMX_BASIC returns this id, and
* VMPTRLD verifies that the VMCS region that L1 is loading contains this id.
+ *
+ * IMPORTANT: Changing this value will break save/restore compatibility with
+ * older kvm releases.
*/
#define VMCS12_REVISION 0x11e57ed0
@@ -481,7 +646,8 @@ struct nested_vmx {
bool sync_shadow_vmcs;
bool dirty_vmcs12;
- bool change_vmcs01_virtual_x2apic_mode;
+ bool change_vmcs01_virtual_apic_mode;
+
/* L2 must run next, and mustn't decide to exit to L1. */
bool nested_run_pending;
@@ -761,6 +927,7 @@ static const unsigned short vmcs_field_to_offset_table[] = {
FIELD64(VM_EXIT_MSR_STORE_ADDR, vm_exit_msr_store_addr),
FIELD64(VM_EXIT_MSR_LOAD_ADDR, vm_exit_msr_load_addr),
FIELD64(VM_ENTRY_MSR_LOAD_ADDR, vm_entry_msr_load_addr),
+ FIELD64(PML_ADDRESS, pml_address),
FIELD64(TSC_OFFSET, tsc_offset),
FIELD64(VIRTUAL_APIC_PAGE_ADDR, virtual_apic_page_addr),
FIELD64(APIC_ACCESS_ADDR, apic_access_addr),
@@ -772,10 +939,11 @@ static const unsigned short vmcs_field_to_offset_table[] = {
FIELD64(EOI_EXIT_BITMAP2, eoi_exit_bitmap2),
FIELD64(EOI_EXIT_BITMAP3, eoi_exit_bitmap3),
FIELD64(EPTP_LIST_ADDRESS, eptp_list_address),
+ FIELD64(VMREAD_BITMAP, vmread_bitmap),
+ FIELD64(VMWRITE_BITMAP, vmwrite_bitmap),
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),
@@ -1089,6 +1257,16 @@ static inline u16 evmcs_read16(unsigned long field)
return *(u16 *)((char *)current_evmcs + offset);
}
+static inline void evmcs_touch_msr_bitmap(void)
+{
+ if (unlikely(!current_evmcs))
+ return;
+
+ if (current_evmcs->hv_enlightenments_control.msr_bitmap)
+ current_evmcs->hv_clean_fields &=
+ ~HV_VMX_ENLIGHTENED_CLEAN_FIELD_MSR_BITMAP;
+}
+
static void evmcs_load(u64 phys_addr)
{
struct hv_vp_assist_page *vp_ap =
@@ -1173,6 +1351,7 @@ static inline u32 evmcs_read32(unsigned long field) { return 0; }
static inline u16 evmcs_read16(unsigned long field) { return 0; }
static inline void evmcs_load(u64 phys_addr) {}
static inline void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf) {}
+static inline void evmcs_touch_msr_bitmap(void) {}
#endif /* IS_ENABLED(CONFIG_HYPERV) */
static inline bool is_exception_n(u32 intr_info, u8 vector)
@@ -1393,6 +1572,11 @@ static inline bool cpu_has_vmx_invept_global(void)
return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT;
}
+static inline bool cpu_has_vmx_invvpid_individual_addr(void)
+{
+ return vmx_capability.vpid & VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT;
+}
+
static inline bool cpu_has_vmx_invvpid_single(void)
{
return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT;
@@ -1510,6 +1694,28 @@ static inline unsigned nested_cpu_vmx_misc_cr3_count(struct kvm_vcpu *vcpu)
return vmx_misc_cr3_count(to_vmx(vcpu)->nested.msrs.misc_low);
}
+/*
+ * Do the virtual VMX capability MSRs specify that L1 can use VMWRITE
+ * to modify any valid field of the VMCS, or are the VM-exit
+ * information fields read-only?
+ */
+static inline bool nested_cpu_has_vmwrite_any_field(struct kvm_vcpu *vcpu)
+{
+ return to_vmx(vcpu)->nested.msrs.misc_low &
+ MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS;
+}
+
+static inline bool nested_cpu_has_zero_length_injection(struct kvm_vcpu *vcpu)
+{
+ return to_vmx(vcpu)->nested.msrs.misc_low & VMX_MISC_ZERO_LEN_INS;
+}
+
+static inline bool nested_cpu_supports_monitor_trap_flag(struct kvm_vcpu *vcpu)
+{
+ return to_vmx(vcpu)->nested.msrs.procbased_ctls_high &
+ CPU_BASED_MONITOR_TRAP_FLAG;
+}
+
static inline bool nested_cpu_has(struct vmcs12 *vmcs12, u32 bit)
{
return vmcs12->cpu_based_vm_exec_control & bit;
@@ -3127,6 +3333,7 @@ static void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, bool apicv)
msrs->misc_high);
msrs->misc_low &= VMX_MISC_SAVE_EFER_LMA;
msrs->misc_low |=
+ MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS |
VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE |
VMX_MISC_ACTIVITY_HLT;
msrs->misc_high = 0;
@@ -3300,6 +3507,15 @@ static int vmx_restore_vmx_misc(struct vcpu_vmx *vmx, u64 data)
vmx->nested.msrs.misc_low = data;
vmx->nested.msrs.misc_high = data >> 32;
+
+ /*
+ * If L1 has read-only VM-exit information fields, use the
+ * less permissive vmx_vmwrite_bitmap to specify write
+ * permissions for the shadow VMCS.
+ */
+ if (enable_shadow_vmcs && !nested_cpu_has_vmwrite_any_field(&vmx->vcpu))
+ vmcs_write64(VMWRITE_BITMAP, __pa(vmx_vmwrite_bitmap));
+
return 0;
}
@@ -3354,6 +3570,13 @@ static int vmx_set_vmx_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
+ /*
+ * Don't allow changes to the VMX capability MSRs while the vCPU
+ * is in VMX operation.
+ */
+ if (vmx->nested.vmxon)
+ return -EBUSY;
+
switch (msr_index) {
case MSR_IA32_VMX_BASIC:
return vmx_restore_vmx_basic(vmx, data);
@@ -4216,6 +4439,15 @@ static int alloc_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)
if (!loaded_vmcs->msr_bitmap)
goto out_vmcs;
memset(loaded_vmcs->msr_bitmap, 0xff, PAGE_SIZE);
+
+ if (IS_ENABLED(CONFIG_HYPERV) &&
+ static_branch_unlikely(&enable_evmcs) &&
+ (ms_hyperv.nested_features & HV_X64_NESTED_MSR_BITMAP)) {
+ struct hv_enlightened_vmcs *evmcs =
+ (struct hv_enlightened_vmcs *)loaded_vmcs->vmcs;
+
+ evmcs->hv_enlightenments_control.msr_bitmap = 1;
+ }
}
return 0;
@@ -5329,6 +5561,9 @@ static void __always_inline vmx_disable_intercept_for_msr(unsigned long *msr_bit
if (!cpu_has_vmx_msr_bitmap())
return;
+ if (static_branch_unlikely(&enable_evmcs))
+ evmcs_touch_msr_bitmap();
+
/*
* See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
* have the write-low and read-high bitmap offsets the wrong way round.
@@ -5364,6 +5599,9 @@ static void __always_inline vmx_enable_intercept_for_msr(unsigned long *msr_bitm
if (!cpu_has_vmx_msr_bitmap())
return;
+ if (static_branch_unlikely(&enable_evmcs))
+ evmcs_touch_msr_bitmap();
+
/*
* See Intel PRM Vol. 3, 20.6.9 (MSR-Bitmap Address). Early manuals
* have the write-low and read-high bitmap offsets the wrong way round.
@@ -5946,8 +6184,14 @@ static void vmx_vcpu_setup(struct vcpu_vmx *vmx)
int i;
if (enable_shadow_vmcs) {
+ /*
+ * At vCPU creation, "VMWRITE to any supported field
+ * in the VMCS" is supported, so use the more
+ * permissive vmx_vmread_bitmap to specify both read
+ * and write permissions for the shadow VMCS.
+ */
vmcs_write64(VMREAD_BITMAP, __pa(vmx_vmread_bitmap));
- vmcs_write64(VMWRITE_BITMAP, __pa(vmx_vmwrite_bitmap));
+ vmcs_write64(VMWRITE_BITMAP, __pa(vmx_vmread_bitmap));
}
if (cpu_has_vmx_msr_bitmap())
vmcs_write64(MSR_BITMAP, __pa(vmx->vmcs01.msr_bitmap));
@@ -7588,8 +7832,7 @@ static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer)
vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva))
return 1;
- if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, vmpointer,
- sizeof(*vmpointer), &e)) {
+ if (kvm_read_guest_virt(vcpu, gva, vmpointer, sizeof(*vmpointer), &e)) {
kvm_inject_page_fault(vcpu, &e);
return 1;
}
@@ -7670,6 +7913,12 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
return 1;
}
+ /* CPL=0 must be checked manually. */
+ if (vmx_get_cpl(vcpu)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
if (vmx->nested.vmxon) {
nested_vmx_failValid(vcpu, VMXERR_VMXON_IN_VMX_ROOT_OPERATION);
return kvm_skip_emulated_instruction(vcpu);
@@ -7729,6 +7978,11 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
*/
static int nested_vmx_check_permission(struct kvm_vcpu *vcpu)
{
+ if (vmx_get_cpl(vcpu)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 0;
+ }
+
if (!to_vmx(vcpu)->nested.vmxon) {
kvm_queue_exception(vcpu, UD_VECTOR);
return 0;
@@ -7928,23 +8182,42 @@ static inline int vmcs12_write_any(struct kvm_vcpu *vcpu,
}
+/*
+ * Copy the writable VMCS shadow fields back to the VMCS12, in case
+ * they have been modified by the L1 guest. Note that the "read-only"
+ * VM-exit information fields are actually writable if the vCPU is
+ * configured to support "VMWRITE to any supported field in the VMCS."
+ */
static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)
{
- int i;
+ const u16 *fields[] = {
+ shadow_read_write_fields,
+ shadow_read_only_fields
+ };
+ const int max_fields[] = {
+ max_shadow_read_write_fields,
+ max_shadow_read_only_fields
+ };
+ int i, q;
unsigned long field;
u64 field_value;
struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;
- const u16 *fields = shadow_read_write_fields;
- const int num_fields = max_shadow_read_write_fields;
preempt_disable();
vmcs_load(shadow_vmcs);
- for (i = 0; i < num_fields; i++) {
- field = fields[i];
- field_value = __vmcs_readl(field);
- vmcs12_write_any(&vmx->vcpu, field, field_value);
+ for (q = 0; q < ARRAY_SIZE(fields); q++) {
+ for (i = 0; i < max_fields[q]; i++) {
+ field = fields[q][i];
+ field_value = __vmcs_readl(field);
+ vmcs12_write_any(&vmx->vcpu, field, field_value);
+ }
+ /*
+ * Skip the VM-exit information fields if they are read-only.
+ */
+ if (!nested_cpu_has_vmwrite_any_field(&vmx->vcpu))
+ break;
}
vmcs_clear(shadow_vmcs);
@@ -8029,9 +8302,9 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
if (get_vmx_mem_address(vcpu, exit_qualification,
vmx_instruction_info, true, &gva))
return 1;
- /* _system ok, as hardware has verified cpl=0 */
- kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva,
- &field_value, (is_long_mode(vcpu) ? 8 : 4), NULL);
+ /* _system ok, nested_vmx_check_permission has verified cpl=0 */
+ kvm_write_guest_virt_system(vcpu, gva, &field_value,
+ (is_long_mode(vcpu) ? 8 : 4), NULL);
}
nested_vmx_succeed(vcpu);
@@ -8069,8 +8342,8 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)
if (get_vmx_mem_address(vcpu, exit_qualification,
vmx_instruction_info, false, &gva))
return 1;
- if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva,
- &field_value, (is_64_bit_mode(vcpu) ? 8 : 4), &e)) {
+ if (kvm_read_guest_virt(vcpu, gva, &field_value,
+ (is_64_bit_mode(vcpu) ? 8 : 4), &e)) {
kvm_inject_page_fault(vcpu, &e);
return 1;
}
@@ -8078,7 +8351,12 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)
field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
- if (vmcs_field_readonly(field)) {
+ /*
+ * If the vCPU supports "VMWRITE to any supported field in the
+ * VMCS," then the "read-only" fields are actually read/write.
+ */
+ if (vmcs_field_readonly(field) &&
+ !nested_cpu_has_vmwrite_any_field(vcpu)) {
nested_vmx_failValid(vcpu,
VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT);
return kvm_skip_emulated_instruction(vcpu);
@@ -8189,10 +8467,10 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu)
if (get_vmx_mem_address(vcpu, exit_qualification,
vmx_instruction_info, true, &vmcs_gva))
return 1;
- /* ok to use *_system, as hardware has verified cpl=0 */
- if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva,
- (void *)&to_vmx(vcpu)->nested.current_vmptr,
- sizeof(u64), &e)) {
+ /* *_system ok, nested_vmx_check_permission has verified cpl=0 */
+ if (kvm_write_guest_virt_system(vcpu, vmcs_gva,
+ (void *)&to_vmx(vcpu)->nested.current_vmptr,
+ sizeof(u64), &e)) {
kvm_inject_page_fault(vcpu, &e);
return 1;
}
@@ -8239,8 +8517,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
vmx_instruction_info, false, &gva))
return 1;
- if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &operand,
- sizeof(operand), &e)) {
+ if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
kvm_inject_page_fault(vcpu, &e);
return 1;
}
@@ -8304,8 +8581,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
vmx_instruction_info, false, &gva))
return 1;
- if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &operand,
- sizeof(operand), &e)) {
+ if (kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e)) {
kvm_inject_page_fault(vcpu, &e);
return 1;
}
@@ -8317,12 +8593,19 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
switch (type) {
case VMX_VPID_EXTENT_INDIVIDUAL_ADDR:
- if (is_noncanonical_address(operand.gla, vcpu)) {
+ if (!operand.vpid ||
+ is_noncanonical_address(operand.gla, vcpu)) {
nested_vmx_failValid(vcpu,
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
return kvm_skip_emulated_instruction(vcpu);
}
- /* fall through */
+ if (cpu_has_vmx_invvpid_individual_addr() &&
+ vmx->nested.vpid02) {
+ __invvpid(VMX_VPID_EXTENT_INDIVIDUAL_ADDR,
+ vmx->nested.vpid02, operand.gla);
+ } else
+ __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
+ break;
case VMX_VPID_EXTENT_SINGLE_CONTEXT:
case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL:
if (!operand.vpid) {
@@ -8330,15 +8613,16 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
return kvm_skip_emulated_instruction(vcpu);
}
+ __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
break;
case VMX_VPID_EXTENT_ALL_CONTEXT:
+ __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
break;
default:
WARN_ON_ONCE(1);
return kvm_skip_emulated_instruction(vcpu);
}
- __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
nested_vmx_succeed(vcpu);
return kvm_skip_emulated_instruction(vcpu);
@@ -8842,11 +9126,13 @@ static bool nested_vmx_exit_reflected(struct kvm_vcpu *vcpu, u32 exit_reason)
case EXIT_REASON_TPR_BELOW_THRESHOLD:
return nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW);
case EXIT_REASON_APIC_ACCESS:
- return nested_cpu_has2(vmcs12,
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
case EXIT_REASON_APIC_WRITE:
case EXIT_REASON_EOI_INDUCED:
- /* apic_write and eoi_induced should exit unconditionally. */
+ /*
+ * The controls for "virtualize APIC accesses," "APIC-
+ * register virtualization," and "virtual-interrupt
+ * delivery" only come from vmcs12.
+ */
return true;
case EXIT_REASON_EPT_VIOLATION:
/*
@@ -9253,31 +9539,43 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu, int tpr, int irr)
vmcs_write32(TPR_THRESHOLD, irr);
}
-static void vmx_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
+static void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
{
u32 sec_exec_control;
+ if (!lapic_in_kernel(vcpu))
+ return;
+
/* Postpone execution until vmcs01 is the current VMCS. */
if (is_guest_mode(vcpu)) {
- to_vmx(vcpu)->nested.change_vmcs01_virtual_x2apic_mode = true;
+ to_vmx(vcpu)->nested.change_vmcs01_virtual_apic_mode = true;
return;
}
- if (!cpu_has_vmx_virtualize_x2apic_mode())
- return;
-
if (!cpu_need_tpr_shadow(vcpu))
return;
sec_exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+ sec_exec_control &= ~(SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE);
- if (set) {
- sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
- sec_exec_control |= SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
- } else {
- sec_exec_control &= ~SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
- sec_exec_control |= SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
- vmx_flush_tlb(vcpu, true);
+ switch (kvm_get_apic_mode(vcpu)) {
+ case LAPIC_MODE_INVALID:
+ WARN_ONCE(true, "Invalid local APIC state");
+ case LAPIC_MODE_DISABLED:
+ break;
+ case LAPIC_MODE_XAPIC:
+ if (flexpriority_enabled) {
+ sec_exec_control |=
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES;
+ vmx_flush_tlb(vcpu, true);
+ }
+ break;
+ case LAPIC_MODE_X2APIC:
+ if (cpu_has_vmx_virtualize_x2apic_mode())
+ sec_exec_control |=
+ SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE;
+ break;
}
vmcs_write32(SECONDARY_VM_EXEC_CONTROL, sec_exec_control);
@@ -9286,24 +9584,7 @@ static void vmx_set_virtual_x2apic_mode(struct kvm_vcpu *vcpu, bool set)
static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu, hpa_t hpa)
{
- struct vcpu_vmx *vmx = to_vmx(vcpu);
-
- /*
- * Currently we do not handle the nested case where L2 has an
- * APIC access page of its own; that page is still pinned.
- * Hence, we skip the case where the VCPU is in guest mode _and_
- * L1 prepared an APIC access page for L2.
- *
- * For the case where L1 and L2 share the same APIC access page
- * (flexpriority=Y but SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES clear
- * in the vmcs12), this function will only update either the vmcs01
- * or the vmcs02. If the former, the vmcs02 will be updated by
- * prepare_vmcs02. If the latter, the vmcs01 will be updated in
- * the next L2->L1 exit.
- */
- if (!is_guest_mode(vcpu) ||
- !nested_cpu_has2(get_vmcs12(&vmx->vcpu),
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
+ if (!is_guest_mode(vcpu)) {
vmcs_write64(APIC_ACCESS_ADDR, hpa);
vmx_flush_tlb(vcpu, true);
}
@@ -9943,13 +10224,13 @@ STACK_FRAME_NON_STANDARD(vmx_vcpu_run);
static struct kvm *vmx_vm_alloc(void)
{
- struct kvm_vmx *kvm_vmx = kzalloc(sizeof(struct kvm_vmx), GFP_KERNEL);
+ struct kvm_vmx *kvm_vmx = vzalloc(sizeof(struct kvm_vmx));
return &kvm_vmx->kvm;
}
static void vmx_vm_free(struct kvm *kvm)
{
- kfree(to_kvm_vmx(kvm));
+ vfree(to_kvm_vmx(kvm));
}
static void vmx_switch_vmcs(struct kvm_vcpu *vcpu, struct loaded_vmcs *vmcs)
@@ -10387,11 +10668,6 @@ static void nested_get_vmcs12_pages(struct kvm_vcpu *vcpu,
vmcs_clear_bits(SECONDARY_VM_EXEC_CONTROL,
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
}
- } else if (!(nested_cpu_has_virt_x2apic_mode(vmcs12)) &&
- cpu_need_virtualize_apic_accesses(&vmx->vcpu)) {
- vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,
- SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES);
- kvm_vcpu_reload_apic_access_page(vcpu);
}
if (nested_cpu_has(vmcs12, CPU_BASED_TPR_SHADOW)) {
@@ -10871,8 +11147,7 @@ static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool ne
return 0;
}
-static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
- bool from_vmentry)
+static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -11006,13 +11281,13 @@ static void prepare_vmcs02_full(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
* is assigned to entry_failure_code on failure.
*/
static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
- bool from_vmentry, u32 *entry_failure_code)
+ u32 *entry_failure_code)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
u32 exec_control, vmcs12_exec_ctrl;
if (vmx->nested.dirty_vmcs12) {
- prepare_vmcs02_full(vcpu, vmcs12, from_vmentry);
+ prepare_vmcs02_full(vcpu, vmcs12);
vmx->nested.dirty_vmcs12 = false;
}
@@ -11032,7 +11307,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
* HOST_FS_BASE, HOST_GS_BASE.
*/
- if (from_vmentry &&
+ if (vmx->nested.nested_run_pending &&
(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS)) {
kvm_set_dr(vcpu, 7, vmcs12->guest_dr7);
vmcs_write64(GUEST_IA32_DEBUGCTL, vmcs12->guest_ia32_debugctl);
@@ -11040,7 +11315,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
kvm_set_dr(vcpu, 7, vcpu->arch.dr7);
vmcs_write64(GUEST_IA32_DEBUGCTL, vmx->nested.vmcs01_debugctl);
}
- if (from_vmentry) {
+ if (vmx->nested.nested_run_pending) {
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
vmcs12->vm_entry_intr_info_field);
vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE,
@@ -11172,7 +11447,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
~VM_ENTRY_IA32E_MODE) |
(vmcs_config.vmentry_ctrl & ~VM_ENTRY_IA32E_MODE));
- if (from_vmentry &&
+ if (vmx->nested.nested_run_pending &&
(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_PAT)) {
vmcs_write64(GUEST_IA32_PAT, vmcs12->guest_ia32_pat);
vcpu->arch.pat = vmcs12->guest_ia32_pat;
@@ -11197,7 +11472,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
if (nested_cpu_has_vpid(vmcs12) && vmx->nested.vpid02) {
if (vmcs12->virtual_processor_id != vmx->nested.last_vpid) {
vmx->nested.last_vpid = vmcs12->virtual_processor_id;
- __vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02, true);
+ __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
}
} else {
vmx_flush_tlb(vcpu, true);
@@ -11240,7 +11515,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
vmx_set_cr4(vcpu, vmcs12->guest_cr4);
vmcs_writel(CR4_READ_SHADOW, nested_read_cr4(vmcs12));
- if (from_vmentry &&
+ if (vmx->nested.nested_run_pending &&
(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_IA32_EFER))
vcpu->arch.efer = vmcs12->guest_ia32_efer;
else if (vmcs12->vm_entry_controls & VM_ENTRY_IA32E_MODE)
@@ -11356,6 +11631,62 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
!nested_cr3_valid(vcpu, vmcs12->host_cr3))
return VMXERR_ENTRY_INVALID_HOST_STATE_FIELD;
+ /*
+ * From the Intel SDM, volume 3:
+ * Fields relevant to VM-entry event injection must be set properly.
+ * These fields are the VM-entry interruption-information field, the
+ * VM-entry exception error code, and the VM-entry instruction length.
+ */
+ if (vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK) {
+ u32 intr_info = vmcs12->vm_entry_intr_info_field;
+ u8 vector = intr_info & INTR_INFO_VECTOR_MASK;
+ u32 intr_type = intr_info & INTR_INFO_INTR_TYPE_MASK;
+ bool has_error_code = intr_info & INTR_INFO_DELIVER_CODE_MASK;
+ bool should_have_error_code;
+ bool urg = nested_cpu_has2(vmcs12,
+ SECONDARY_EXEC_UNRESTRICTED_GUEST);
+ bool prot_mode = !urg || vmcs12->guest_cr0 & X86_CR0_PE;
+
+ /* VM-entry interruption-info field: interruption type */
+ if (intr_type == INTR_TYPE_RESERVED ||
+ (intr_type == INTR_TYPE_OTHER_EVENT &&
+ !nested_cpu_supports_monitor_trap_flag(vcpu)))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ /* VM-entry interruption-info field: vector */
+ if ((intr_type == INTR_TYPE_NMI_INTR && vector != NMI_VECTOR) ||
+ (intr_type == INTR_TYPE_HARD_EXCEPTION && vector > 31) ||
+ (intr_type == INTR_TYPE_OTHER_EVENT && vector != 0))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ /* VM-entry interruption-info field: deliver error code */
+ should_have_error_code =
+ intr_type == INTR_TYPE_HARD_EXCEPTION && prot_mode &&
+ x86_exception_has_error_code(vector);
+ if (has_error_code != should_have_error_code)
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ /* VM-entry exception error code */
+ if (has_error_code &&
+ vmcs12->vm_entry_exception_error_code & GENMASK(31, 15))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ /* VM-entry interruption-info field: reserved bits */
+ if (intr_info & INTR_INFO_RESVD_BITS_MASK)
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
+ /* VM-entry instruction length */
+ switch (intr_type) {
+ case INTR_TYPE_SOFT_EXCEPTION:
+ case INTR_TYPE_SOFT_INTR:
+ case INTR_TYPE_PRIV_SW_EXCEPTION:
+ if ((vmcs12->vm_entry_instruction_len > 15) ||
+ (vmcs12->vm_entry_instruction_len == 0 &&
+ !nested_cpu_has_zero_length_injection(vcpu)))
+ return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+ }
+ }
+
return 0;
}
@@ -11418,7 +11749,7 @@ static int check_vmentry_postreqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
return 0;
}
-static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry)
+static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
@@ -11438,7 +11769,7 @@ static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry)
vcpu->arch.tsc_offset += vmcs12->tsc_offset;
r = EXIT_REASON_INVALID_STATE;
- if (prepare_vmcs02(vcpu, vmcs12, from_vmentry, &exit_qual))
+ if (prepare_vmcs02(vcpu, vmcs12, &exit_qual))
goto fail;
nested_get_vmcs12_pages(vcpu, vmcs12);
@@ -11540,20 +11871,22 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)
* the nested entry.
*/
- ret = enter_vmx_non_root_mode(vcpu, true);
- if (ret)
+ vmx->nested.nested_run_pending = 1;
+ ret = enter_vmx_non_root_mode(vcpu);
+ if (ret) {
+ vmx->nested.nested_run_pending = 0;
return ret;
+ }
/*
* If we're entering a halted L2 vcpu and the L2 vcpu won't be woken
* by event injection, halt vcpu.
*/
if ((vmcs12->guest_activity_state == GUEST_ACTIVITY_HLT) &&
- !(vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK))
+ !(vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK)) {
+ vmx->nested.nested_run_pending = 0;
return kvm_vcpu_halt(vcpu);
-
- vmx->nested.nested_run_pending = 1;
-
+ }
return 1;
out:
@@ -11925,12 +12258,20 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
load_vmcs12_mmu_host_state(vcpu, vmcs12);
- if (enable_vpid) {
- /*
- * Trivially support vpid by letting L2s share their parent
- * L1's vpid. TODO: move to a more elaborate solution, giving
- * each L2 its own vpid and exposing the vpid feature to L1.
- */
+ /*
+ * If vmcs01 don't use VPID, CPU flushes TLB on every
+ * VMEntry/VMExit. Thus, no need to flush TLB.
+ *
+ * If vmcs12 uses VPID, TLB entries populated by L2 are
+ * tagged with vmx->nested.vpid02 while L1 entries are tagged
+ * with vmx->vpid. Thus, no need to flush TLB.
+ *
+ * Therefore, flush TLB only in case vmcs01 uses VPID and
+ * vmcs12 don't use VPID as in this case L1 & L2 TLB entries
+ * are both tagged with vmx->vpid.
+ */
+ if (enable_vpid &&
+ !(nested_cpu_has_vpid(vmcs12) && to_vmx(vcpu)->nested.vpid02)) {
vmx_flush_tlb(vcpu, true);
}
@@ -12069,10 +12410,9 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,
if (kvm_has_tsc_control)
decache_tsc_multiplier(vmx);
- if (vmx->nested.change_vmcs01_virtual_x2apic_mode) {
- vmx->nested.change_vmcs01_virtual_x2apic_mode = false;
- vmx_set_virtual_x2apic_mode(vcpu,
- vcpu->arch.apic_base & X2APIC_ENABLE);
+ if (vmx->nested.change_vmcs01_virtual_apic_mode) {
+ vmx->nested.change_vmcs01_virtual_apic_mode = false;
+ vmx_set_virtual_apic_mode(vcpu);
} else if (!nested_cpu_has_ept(vmcs12) &&
nested_cpu_has2(vmcs12,
SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
@@ -12236,7 +12576,7 @@ static inline int u64_shl_div_u64(u64 a, unsigned int shift,
static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
{
struct vcpu_vmx *vmx;
- u64 tscl, guest_tscl, delta_tsc;
+ u64 tscl, guest_tscl, delta_tsc, lapic_timer_advance_cycles;
if (kvm_mwait_in_guest(vcpu->kvm))
return -EOPNOTSUPP;
@@ -12245,6 +12585,12 @@ static int vmx_set_hv_timer(struct kvm_vcpu *vcpu, u64 guest_deadline_tsc)
tscl = rdtsc();
guest_tscl = kvm_read_l1_tsc(vcpu, tscl);
delta_tsc = max(guest_deadline_tsc, guest_tscl) - guest_tscl;
+ lapic_timer_advance_cycles = nsec_to_cycles(vcpu, lapic_timer_advance_ns);
+
+ if (delta_tsc > lapic_timer_advance_cycles)
+ delta_tsc -= lapic_timer_advance_cycles;
+ else
+ delta_tsc = 0;
/* Convert to host delta tsc if tsc scaling is enabled */
if (vcpu->arch.tsc_scaling_ratio != kvm_default_tsc_scaling_ratio &&
@@ -12615,7 +12961,7 @@ static int vmx_pre_leave_smm(struct kvm_vcpu *vcpu, u64 smbase)
if (vmx->nested.smm.guest_mode) {
vcpu->arch.hflags &= ~HF_SMM_MASK;
- ret = enter_vmx_non_root_mode(vcpu, false);
+ ret = enter_vmx_non_root_mode(vcpu);
vcpu->arch.hflags |= HF_SMM_MASK;
if (ret)
return ret;
@@ -12700,7 +13046,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
.enable_nmi_window = enable_nmi_window,
.enable_irq_window = enable_irq_window,
.update_cr8_intercept = update_cr8_intercept,
- .set_virtual_x2apic_mode = vmx_set_virtual_x2apic_mode,
+ .set_virtual_apic_mode = vmx_set_virtual_apic_mode,
.set_apic_access_page_addr = vmx_set_apic_access_page_addr,
.get_enable_apicv = vmx_get_enable_apicv,
.refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
@@ -12812,6 +13158,7 @@ static int __init vmx_init(void)
rcu_assign_pointer(crash_vmclear_loaded_vmcss,
crash_vmclear_local_loaded_vmcss);
#endif
+ vmx_check_vmcs12_offsets();
return 0;
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 71e7cda..0046aa7 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -138,6 +138,7 @@ module_param(tsc_tolerance_ppm, uint, S_IRUGO | S_IWUSR);
/* lapic timer advance (tscdeadline mode only) in nanoseconds */
unsigned int __read_mostly lapic_timer_advance_ns = 0;
module_param(lapic_timer_advance_ns, uint, S_IRUGO | S_IWUSR);
+EXPORT_SYMBOL_GPL(lapic_timer_advance_ns);
static bool __read_mostly vector_hashing = true;
module_param(vector_hashing, bool, S_IRUGO);
@@ -318,23 +319,27 @@ u64 kvm_get_apic_base(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_get_apic_base);
+enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu)
+{
+ return kvm_apic_mode(kvm_get_apic_base(vcpu));
+}
+EXPORT_SYMBOL_GPL(kvm_get_apic_mode);
+
int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
{
- u64 old_state = vcpu->arch.apic_base &
- (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
- u64 new_state = msr_info->data &
- (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
+ enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
+ enum lapic_mode new_mode = kvm_apic_mode(msr_info->data);
u64 reserved_bits = ((~0ULL) << cpuid_maxphyaddr(vcpu)) | 0x2ff |
(guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
- if ((msr_info->data & reserved_bits) || new_state == X2APIC_ENABLE)
- return 1;
- if (!msr_info->host_initiated &&
- ((new_state == MSR_IA32_APICBASE_ENABLE &&
- old_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE)) ||
- (new_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE) &&
- old_state == 0)))
+ if ((msr_info->data & reserved_bits) != 0 || new_mode == LAPIC_MODE_INVALID)
return 1;
+ if (!msr_info->host_initiated) {
+ if (old_mode == LAPIC_MODE_X2APIC && new_mode == LAPIC_MODE_XAPIC)
+ return 1;
+ if (old_mode == LAPIC_MODE_DISABLED && new_mode == LAPIC_MODE_X2APIC)
+ return 1;
+ }
kvm_lapic_set_base(vcpu, msr_info->data);
return 0;
@@ -856,7 +861,7 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
}
if (is_long_mode(vcpu) &&
- (cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 62)))
+ (cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 63)))
return 1;
else if (is_pae(vcpu) && is_paging(vcpu) &&
!load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3))
@@ -1761,7 +1766,7 @@ static int do_monotonic_boot(s64 *t, u64 *tsc_timestamp)
return mode;
}
-static int do_realtime(struct timespec *ts, u64 *tsc_timestamp)
+static int do_realtime(struct timespec64 *ts, u64 *tsc_timestamp)
{
struct pvclock_gtod_data *gtod = &pvclock_gtod_data;
unsigned long seq;
@@ -1794,7 +1799,7 @@ static bool kvm_get_time_and_clockread(s64 *kernel_ns, u64 *tsc_timestamp)
}
/* returns true if host is using TSC based clocksource */
-static bool kvm_get_walltime_and_clockread(struct timespec *ts,
+static bool kvm_get_walltime_and_clockread(struct timespec64 *ts,
u64 *tsc_timestamp)
{
/* checked again under seqlock below */
@@ -2868,6 +2873,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
case KVM_CAP_HYPERV_SYNIC2:
case KVM_CAP_HYPERV_VP_INDEX:
case KVM_CAP_HYPERV_EVENTFD:
+ case KVM_CAP_HYPERV_TLBFLUSH:
case KVM_CAP_PCI_SEGMENT:
case KVM_CAP_DEBUGREGS:
case KVM_CAP_X86_ROBUST_SINGLESTEP:
@@ -2894,7 +2900,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
r = KVM_CLOCK_TSC_STABLE;
break;
case KVM_CAP_X86_DISABLE_EXITS:
- r |= KVM_X86_DISABLE_EXITS_HTL | KVM_X86_DISABLE_EXITS_PAUSE;
+ r |= KVM_X86_DISABLE_EXITS_HLT | KVM_X86_DISABLE_EXITS_PAUSE;
if(kvm_can_mwait_in_guest())
r |= KVM_X86_DISABLE_EXITS_MWAIT;
break;
@@ -3962,7 +3968,7 @@ out_nofree:
return r;
}
-int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
{
return VM_FAULT_SIGBUS;
}
@@ -4248,7 +4254,7 @@ split_irqchip_unlock:
if ((cap->args[0] & KVM_X86_DISABLE_EXITS_MWAIT) &&
kvm_can_mwait_in_guest())
kvm->arch.mwait_in_guest = true;
- if (cap->args[0] & KVM_X86_DISABLE_EXITS_HTL)
+ if (cap->args[0] & KVM_X86_DISABLE_EXITS_HLT)
kvm->arch.hlt_in_guest = true;
if (cap->args[0] & KVM_X86_DISABLE_EXITS_PAUSE)
kvm->arch.pause_in_guest = true;
@@ -4787,11 +4793,10 @@ static int kvm_fetch_guest_virt(struct x86_emulate_ctxt *ctxt,
return X86EMUL_CONTINUE;
}
-int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
+int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
gva_t addr, void *val, unsigned int bytes,
struct x86_exception *exception)
{
- struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
@@ -4799,12 +4804,17 @@ int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
}
EXPORT_SYMBOL_GPL(kvm_read_guest_virt);
-static int kvm_read_guest_virt_system(struct x86_emulate_ctxt *ctxt,
- gva_t addr, void *val, unsigned int bytes,
- struct x86_exception *exception)
+static int emulator_read_std(struct x86_emulate_ctxt *ctxt,
+ gva_t addr, void *val, unsigned int bytes,
+ struct x86_exception *exception, bool system)
{
struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
- return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, exception);
+ u32 access = 0;
+
+ if (!system && kvm_x86_ops->get_cpl(vcpu) == 3)
+ access |= PFERR_USER_MASK;
+
+ return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access, exception);
}
static int kvm_read_guest_phys_system(struct x86_emulate_ctxt *ctxt,
@@ -4816,18 +4826,16 @@ static int kvm_read_guest_phys_system(struct x86_emulate_ctxt *ctxt,
return r < 0 ? X86EMUL_IO_NEEDED : X86EMUL_CONTINUE;
}
-int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
- gva_t addr, void *val,
- unsigned int bytes,
- struct x86_exception *exception)
+static int kvm_write_guest_virt_helper(gva_t addr, void *val, unsigned int bytes,
+ struct kvm_vcpu *vcpu, u32 access,
+ struct x86_exception *exception)
{
- struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
void *data = val;
int r = X86EMUL_CONTINUE;
while (bytes) {
gpa_t gpa = vcpu->arch.walk_mmu->gva_to_gpa(vcpu, addr,
- PFERR_WRITE_MASK,
+ access,
exception);
unsigned offset = addr & (PAGE_SIZE-1);
unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset);
@@ -4848,6 +4856,27 @@ int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
out:
return r;
}
+
+static int emulator_write_std(struct x86_emulate_ctxt *ctxt, gva_t addr, void *val,
+ unsigned int bytes, struct x86_exception *exception,
+ bool system)
+{
+ struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt);
+ u32 access = PFERR_WRITE_MASK;
+
+ if (!system && kvm_x86_ops->get_cpl(vcpu) == 3)
+ access |= PFERR_USER_MASK;
+
+ return kvm_write_guest_virt_helper(addr, val, bytes, vcpu,
+ access, exception);
+}
+
+int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu, gva_t addr, void *val,
+ unsigned int bytes, struct x86_exception *exception)
+{
+ return kvm_write_guest_virt_helper(addr, val, bytes, vcpu,
+ PFERR_WRITE_MASK, exception);
+}
EXPORT_SYMBOL_GPL(kvm_write_guest_virt_system);
int handle_ud(struct kvm_vcpu *vcpu)
@@ -4858,8 +4887,8 @@ int handle_ud(struct kvm_vcpu *vcpu)
struct x86_exception e;
if (force_emulation_prefix &&
- kvm_read_guest_virt(&vcpu->arch.emulate_ctxt,
- kvm_get_linear_rip(vcpu), sig, sizeof(sig), &e) == 0 &&
+ kvm_read_guest_virt(vcpu, kvm_get_linear_rip(vcpu),
+ sig, sizeof(sig), &e) == 0 &&
memcmp(sig, "\xf\xbkvm", sizeof(sig)) == 0) {
kvm_rip_write(vcpu, kvm_rip_read(vcpu) + sizeof(sig));
emul_type = 0;
@@ -5600,8 +5629,8 @@ static int emulator_pre_leave_smm(struct x86_emulate_ctxt *ctxt, u64 smbase)
static const struct x86_emulate_ops emulate_ops = {
.read_gpr = emulator_read_gpr,
.write_gpr = emulator_write_gpr,
- .read_std = kvm_read_guest_virt_system,
- .write_std = kvm_write_guest_virt_system,
+ .read_std = emulator_read_std,
+ .write_std = emulator_write_std,
.read_phys = kvm_read_guest_phys_system,
.fetch = kvm_fetch_guest_virt,
.read_emulated = emulator_read_emulated,
@@ -6617,7 +6646,7 @@ static int kvm_pv_clock_pairing(struct kvm_vcpu *vcpu, gpa_t paddr,
unsigned long clock_type)
{
struct kvm_clock_pairing clock_pairing;
- struct timespec ts;
+ struct timespec64 ts;
u64 cycle;
int ret;
@@ -8538,7 +8567,7 @@ int kvm_arch_hardware_setup(void)
/*
* Make sure the user can only configure tsc_khz values that
* fit into a signed integer.
- * A min value is not calculated needed because it will always
+ * A min value is not calculated because it will always
* be 1 on all machines.
*/
u64 max = min(0x7fffffffULL,
@@ -8871,13 +8900,14 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
slot->base_gfn, level) + 1;
slot->arch.rmap[i] =
- kvzalloc(lpages * sizeof(*slot->arch.rmap[i]), GFP_KERNEL);
+ kvcalloc(lpages, sizeof(*slot->arch.rmap[i]),
+ GFP_KERNEL);
if (!slot->arch.rmap[i])
goto out_free;
if (i == 0)
continue;
- linfo = kvzalloc(lpages * sizeof(*linfo), GFP_KERNEL);
+ linfo = kvcalloc(lpages, sizeof(*linfo), GFP_KERNEL);
if (!linfo)
goto out_free;
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index c9492f7..257f276 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -110,6 +110,15 @@ static inline bool is_la57_mode(struct kvm_vcpu *vcpu)
#endif
}
+static inline bool x86_exception_has_error_code(unsigned int vector)
+{
+ static u32 exception_has_error_code = BIT(DF_VECTOR) | BIT(TS_VECTOR) |
+ BIT(NP_VECTOR) | BIT(SS_VECTOR) | BIT(GP_VECTOR) |
+ BIT(PF_VECTOR) | BIT(AC_VECTOR);
+
+ return (1U << vector) & exception_has_error_code;
+}
+
static inline bool mmu_is_nested(struct kvm_vcpu *vcpu)
{
return vcpu->arch.walk_mmu == &vcpu->arch.nested_mmu;
@@ -247,11 +256,11 @@ int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip);
void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr);
u64 get_kvmclock_ns(struct kvm *kvm);
-int kvm_read_guest_virt(struct x86_emulate_ctxt *ctxt,
+int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
gva_t addr, void *val, unsigned int bytes,
struct x86_exception *exception);
-int kvm_write_guest_virt_system(struct x86_emulate_ctxt *ctxt,
+int kvm_write_guest_virt_system(struct kvm_vcpu *vcpu,
gva_t addr, void *val, unsigned int bytes,
struct x86_exception *exception);
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index fec82b5..cee58a9 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -706,7 +706,9 @@ void __init init_mem_mapping(void)
*/
int devmem_is_allowed(unsigned long pagenr)
{
- if (page_is_ram(pagenr)) {
+ if (region_intersects(PFN_PHYS(pagenr), PAGE_SIZE,
+ IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE)
+ != REGION_DISJOINT) {
/*
* For disallowed memory regions in the low 1MB range,
* request that the page be shown as all zeros.
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index c893c6a..979e0a0 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -692,7 +692,7 @@ void __init initmem_init(void)
high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
#endif
- memblock_set_node(0, (phys_addr_t)ULLONG_MAX, &memblock.memory, 0);
+ memblock_set_node(0, PHYS_ADDR_MAX, &memblock.memory, 0);
sparse_memory_present_with_active_regions(0);
#ifdef CONFIG_FLATMEM
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 17383f9..a688617 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -742,7 +742,7 @@ kernel_physical_mapping_init(unsigned long paddr_start,
#ifndef CONFIG_NUMA
void __init initmem_init(void)
{
- memblock_set_node(0, (phys_addr_t)ULLONG_MAX, &memblock.memory, 0);
+ memblock_set_node(0, PHYS_ADDR_MAX, &memblock.memory, 0);
}
#endif
@@ -1350,16 +1350,28 @@ int kern_addr_valid(unsigned long addr)
/* Amount of ram needed to start using large blocks */
#define MEM_SIZE_FOR_LARGE_BLOCK (64UL << 30)
+/* Adjustable memory block size */
+static unsigned long set_memory_block_size;
+int __init set_memory_block_size_order(unsigned int order)
+{
+ unsigned long size = 1UL << order;
+
+ if (size > MEM_SIZE_FOR_LARGE_BLOCK || size < MIN_MEMORY_BLOCK_SIZE)
+ return -EINVAL;
+
+ set_memory_block_size = size;
+ return 0;
+}
+
static unsigned long probe_memory_block_size(void)
{
unsigned long boot_mem_end = max_pfn << PAGE_SHIFT;
unsigned long bz;
- /* If this is UV system, always set 2G block size */
- if (is_uv_system()) {
- bz = MAX_BLOCK_SIZE;
+ /* If memory block size has been set, then use it */
+ bz = set_memory_block_size;
+ if (bz)
goto done;
- }
/* Use regular block if RAM is smaller than MEM_SIZE_FOR_LARGE_BLOCK */
if (boot_mem_end < MEM_SIZE_FOR_LARGE_BLOCK) {
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 8fca446..2580cd2 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1107,7 +1107,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
extra_pass = true;
goto skip_init_addrs;
}
- addrs = kmalloc(prog->len * sizeof(*addrs), GFP_KERNEL);
+ addrs = kmalloc_array(prog->len, sizeof(*addrs), GFP_KERNEL);
if (!addrs) {
prog = orig_prog;
goto out_addrs;
diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c
index 0cc04e3..5579987 100644
--- a/arch/x86/net/bpf_jit_comp32.c
+++ b/arch/x86/net/bpf_jit_comp32.c
@@ -2345,7 +2345,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
prog = tmp;
}
- addrs = kmalloc(prog->len * sizeof(*addrs), GFP_KERNEL);
+ addrs = kmalloc_array(prog->len, sizeof(*addrs), GFP_KERNEL);
if (!addrs) {
prog = orig_prog;
goto out;
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 9542a746..9112d1c 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -168,7 +168,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
if (type == PCI_CAP_ID_MSI && nvec > 1)
return 1;
- v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL);
+ v = kcalloc(max(1, nvec), sizeof(int), GFP_KERNEL);
if (!v)
return -ENOMEM;
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index b96d382..ca446da 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -2142,7 +2142,7 @@ static int __init init_per_cpu(int nuvhubs, int base_part_pnode)
if (is_uv3_hub() || is_uv2_hub() || is_uv1_hub())
timeout_us = calculate_destination_timeout();
- vp = kmalloc(nuvhubs * sizeof(struct uvhub_desc), GFP_KERNEL);
+ vp = kmalloc_array(nuvhubs, sizeof(struct uvhub_desc), GFP_KERNEL);
uvhub_descs = (struct uvhub_desc *)vp;
memset(uvhub_descs, 0, nuvhubs * sizeof(struct uvhub_desc));
uvhub_mask = kzalloc((nuvhubs+7)/8, GFP_KERNEL);
diff --git a/arch/x86/platform/uv/uv_time.c b/arch/x86/platform/uv/uv_time.c
index b082d71..a36b368 100644
--- a/arch/x86/platform/uv/uv_time.c
+++ b/arch/x86/platform/uv/uv_time.c
@@ -158,7 +158,7 @@ static __init int uv_rtc_allocate_timers(void)
{
int cpu;
- blade_info = kzalloc(uv_possible_blades * sizeof(void *), GFP_KERNEL);
+ blade_info = kcalloc(uv_possible_blades, sizeof(void *), GFP_KERNEL);
if (!blade_info)
return -ENOMEM;
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index c9081c6..3b53185 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -65,6 +65,13 @@ __read_mostly int xen_have_vector_callback;
EXPORT_SYMBOL_GPL(xen_have_vector_callback);
/*
+ * NB: needs to live in .data because it's used by xen_prepare_pvh which runs
+ * before clearing the bss.
+ */
+uint32_t xen_start_flags __attribute__((section(".data"))) = 0;
+EXPORT_SYMBOL(xen_start_flags);
+
+/*
* Point at some empty memory to start with. We map the real shared_info
* page as soon as fixmap is up and running.
*/
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 357969a..8d4e2e1 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1203,6 +1203,7 @@ asmlinkage __visible void __init xen_start_kernel(void)
return;
xen_domain_type = XEN_PV_DOMAIN;
+ xen_start_flags = xen_start_info->flags;
xen_setup_features();
diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c
index aa1c6a68..c85d1a8 100644
--- a/arch/x86/xen/enlighten_pvh.c
+++ b/arch/x86/xen/enlighten_pvh.c
@@ -97,6 +97,7 @@ void __init xen_prepare_pvh(void)
}
xen_pvh = 1;
+ xen_start_flags = pvh_start_info.flags;
msr = cpuid_ebx(xen_cpuid_base() + 2);
pfn = __pa(hypercall_page);
diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c
index 2e20ae2f..e3b18ad 100644
--- a/arch/x86/xen/smp_pv.c
+++ b/arch/x86/xen/smp_pv.c
@@ -32,6 +32,7 @@
#include <xen/interface/vcpu.h>
#include <xen/interface/xenpmu.h>
+#include <asm/spec-ctrl.h>
#include <asm/xen/interface.h>
#include <asm/xen/hypercall.h>
@@ -70,6 +71,8 @@ static void cpu_bringup(void)
cpu_data(cpu).x86_max_cores = 1;
set_cpu_sibling_map(cpu);
+ speculative_store_bypass_ht_init();
+
xen_setup_cpu_clockevents();
notify_cpu_starting(cpu);
@@ -250,6 +253,8 @@ static void __init xen_pv_smp_prepare_cpus(unsigned int max_cpus)
}
set_cpu_sibling_map(0);
+ speculative_store_bypass_ht_init();
+
xen_pmu_init(0);
if (xen_smp_intr_init(0) || xen_smp_intr_init_pv(0))
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 17df3322..d575e87 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -17,7 +17,6 @@ config XTENSA
select GENERIC_SCHED_CLOCK
select GENERIC_STRNCPY_FROM_USER if KASAN
select HAVE_ARCH_KASAN if MMU
- select HAVE_CC_STACKPROTECTOR
select HAVE_DEBUG_KMEMLEAK
select HAVE_DMA_CONTIGUOUS
select HAVE_EXIT_THREAD
@@ -28,6 +27,7 @@ config XTENSA
select HAVE_MEMBLOCK
select HAVE_OPROFILE
select HAVE_PERF_EVENTS
+ select HAVE_STACKPROTECTOR
select IRQ_DOMAIN
select MODULES_USE_ELF_RELA
select NO_BOOTMEM
diff --git a/arch/xtensa/include/asm/cacheflush.h b/arch/xtensa/include/asm/cacheflush.h
index 397d6a1..a0d50be 100644
--- a/arch/xtensa/include/asm/cacheflush.h
+++ b/arch/xtensa/include/asm/cacheflush.h
@@ -88,7 +88,7 @@ static inline void __invalidate_icache_page_alias(unsigned long virt,
*
* Pages can get remapped. Because this might change the 'color' of that page,
* we have to flush the cache before the PTE is changed.
- * (see also Documentation/cachetlb.txt)
+ * (see also Documentation/core-api/cachetlb.rst)
*/
#if defined(CONFIG_MMU) && \
@@ -152,7 +152,7 @@ void local_flush_cache_page(struct vm_area_struct *vma,
__invalidate_icache_range(start,(end) - (start)); \
} while (0)
-/* This is not required, see Documentation/cachetlb.txt */
+/* This is not required, see Documentation/core-api/cachetlb.rst */
#define flush_icache_page(vma,page) do { } while (0)
#define flush_dcache_mmap_lock(mapping) do { } while (0)
diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c
index 022cf91..67904f5 100644
--- a/arch/xtensa/kernel/asm-offsets.c
+++ b/arch/xtensa/kernel/asm-offsets.c
@@ -76,7 +76,7 @@ int main(void)
DEFINE(TASK_PID, offsetof (struct task_struct, pid));
DEFINE(TASK_THREAD, offsetof (struct task_struct, thread));
DEFINE(TASK_THREAD_INFO, offsetof (struct task_struct, stack));
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
DEFINE(TASK_STACK_CANARY, offsetof(struct task_struct, stack_canary));
#endif
DEFINE(TASK_STRUCT_SIZE, sizeof (struct task_struct));
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 5caff07..9cbc380 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1971,7 +1971,7 @@ ENTRY(_switch_to)
s32i a1, a2, THREAD_SP # save stack pointer
#endif
-#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
+#if defined(CONFIG_STACKPROTECTOR) && !defined(CONFIG_SMP)
movi a6, __stack_chk_guard
l32i a8, a3, TASK_STACK_CANARY
s32i a8, a6, 0
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 8dd0593..483dcfb 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -58,7 +58,7 @@ void (*pm_power_off)(void) = NULL;
EXPORT_SYMBOL(pm_power_off);
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
#include <linux/stackprotector.h>
unsigned long __stack_chk_guard __read_mostly;
EXPORT_SYMBOL(__stack_chk_guard);
diff --git a/block/Kconfig b/block/Kconfig
index 28ec557..eb50fd4 100644
--- a/block/Kconfig
+++ b/block/Kconfig
@@ -114,7 +114,7 @@ config BLK_DEV_THROTTLING
one needs to mount and use blkio cgroup controller for creating
cgroups and specifying per device IO rate policies.
- See Documentation/cgroups/blkio-controller.txt for more information.
+ See Documentation/cgroup-v1/blkio-controller.txt for more information.
config BLK_DEV_THROTTLING_LOW
bool "Block throttling .low limit interface support (EXPERIMENTAL)"
diff --git a/block/bio.c b/block/bio.c
index db9a40e..67eff5e 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1807,9 +1807,6 @@ again:
if (!bio_integrity_endio(bio))
return;
- if (WARN_ONCE(bio->bi_next, "driver left bi_next not NULL"))
- bio->bi_next = NULL;
-
/*
* Need to have a real endio function for chained bios, otherwise
* various corner cases will break (like stacking block devices that
@@ -2091,7 +2088,8 @@ static int __init init_bio(void)
{
bio_slab_max = 2;
bio_slab_nr = 0;
- bio_slabs = kzalloc(bio_slab_max * sizeof(struct bio_slab), GFP_KERNEL);
+ bio_slabs = kcalloc(bio_slab_max, sizeof(struct bio_slab),
+ GFP_KERNEL);
if (!bio_slabs)
panic("bio: can't allocate bios\n");
diff --git a/block/blk-core.c b/block/blk-core.c
index cf0ee76..afd2596 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -273,10 +273,6 @@ static void req_bio_endio(struct request *rq, struct bio *bio,
bio_advance(bio, nbytes);
/* don't actually finish bio if it's part of flush sequence */
- /*
- * XXX this code looks suspicious - it's not consistent with advancing
- * req->bio in caller
- */
if (bio->bi_iter.bi_size == 0 && !(rq->rq_flags & RQF_FLUSH_SEQ))
bio_endio(bio);
}
@@ -3081,10 +3077,8 @@ bool blk_update_request(struct request *req, blk_status_t error,
struct bio *bio = req->bio;
unsigned bio_bytes = min(bio->bi_iter.bi_size, nr_bytes);
- if (bio_bytes == bio->bi_iter.bi_size) {
+ if (bio_bytes == bio->bi_iter.bi_size)
req->bio = bio->bi_next;
- bio->bi_next = NULL;
- }
/* Completion has already been traced */
bio_clear_flag(bio, BIO_TRACE_COMPLETION);
diff --git a/block/blk-flush.c b/block/blk-flush.c
index 058abdb..ce41f66 100644
--- a/block/blk-flush.c
+++ b/block/blk-flush.c
@@ -169,9 +169,11 @@ static bool blk_flush_complete_seq(struct request *rq,
struct request_queue *q = rq->q;
struct list_head *pending = &fq->flush_queue[fq->flush_pending_idx];
bool queued = false, kicked;
+ unsigned int cmd_flags;
BUG_ON(rq->flush.seq & seq);
rq->flush.seq |= seq;
+ cmd_flags = rq->cmd_flags;
if (likely(!error))
seq = blk_flush_cur_seq(rq);
@@ -212,7 +214,7 @@ static bool blk_flush_complete_seq(struct request *rq,
BUG();
}
- kicked = blk_kick_flush(q, fq, rq->cmd_flags);
+ kicked = blk_kick_flush(q, fq, cmd_flags);
return kicked | queued;
}
diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c
index ffa6223..1c4532e 100644
--- a/block/blk-mq-debugfs.c
+++ b/block/blk-mq-debugfs.c
@@ -356,7 +356,7 @@ static const char *const blk_mq_rq_state_name_array[] = {
static const char *blk_mq_rq_state_name(enum mq_rq_state rq_state)
{
- if (WARN_ON_ONCE((unsigned int)rq_state >
+ if (WARN_ON_ONCE((unsigned int)rq_state >=
ARRAY_SIZE(blk_mq_rq_state_name_array)))
return "(?)";
return blk_mq_rq_state_name_array[rq_state];
diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c
index 70356a2a..09b2ee6 100644
--- a/block/blk-mq-tag.c
+++ b/block/blk-mq-tag.c
@@ -311,35 +311,6 @@ void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset,
}
EXPORT_SYMBOL(blk_mq_tagset_busy_iter);
-int blk_mq_tagset_iter(struct blk_mq_tag_set *set, void *data,
- int (fn)(void *, struct request *))
-{
- int i, j, ret = 0;
-
- if (WARN_ON_ONCE(!fn))
- goto out;
-
- for (i = 0; i < set->nr_hw_queues; i++) {
- struct blk_mq_tags *tags = set->tags[i];
-
- if (!tags)
- continue;
-
- for (j = 0; j < tags->nr_tags; j++) {
- if (!tags->static_rqs[j])
- continue;
-
- ret = fn(data, tags->static_rqs[j]);
- if (ret)
- goto out;
- }
- }
-
-out:
- return ret;
-}
-EXPORT_SYMBOL_GPL(blk_mq_tagset_iter);
-
void blk_mq_queue_tag_busy_iter(struct request_queue *q, busy_iter_fn *fn,
void *priv)
{
diff --git a/block/blk-mq.c b/block/blk-mq.c
index d2de0a7..b429d51 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -671,6 +671,7 @@ static void __blk_mq_requeue_request(struct request *rq)
if (blk_mq_request_started(rq)) {
WRITE_ONCE(rq->state, MQ_RQ_IDLE);
+ rq->rq_flags &= ~RQF_TIMED_OUT;
if (q->dma_drain_size && blk_rq_bytes(rq))
rq->nr_phys_segments--;
}
@@ -770,6 +771,7 @@ EXPORT_SYMBOL(blk_mq_tag_to_rq);
static void blk_mq_rq_timed_out(struct request *req, bool reserved)
{
+ req->rq_flags |= RQF_TIMED_OUT;
if (req->q->mq_ops->timeout) {
enum blk_eh_timer_return ret;
@@ -788,6 +790,8 @@ static bool blk_mq_req_expired(struct request *rq, unsigned long *next)
if (blk_mq_rq_state(rq) != MQ_RQ_IN_FLIGHT)
return false;
+ if (rq->rq_flags & RQF_TIMED_OUT)
+ return false;
deadline = blk_rq_deadline(rq);
if (time_after_eq(jiffies, deadline))
@@ -1903,7 +1907,7 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set,
if (!tags)
return NULL;
- tags->rqs = kzalloc_node(nr_tags * sizeof(struct request *),
+ tags->rqs = kcalloc_node(nr_tags, sizeof(struct request *),
GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
node);
if (!tags->rqs) {
@@ -1911,9 +1915,9 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set,
return NULL;
}
- tags->static_rqs = kzalloc_node(nr_tags * sizeof(struct request *),
- GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
- node);
+ tags->static_rqs = kcalloc_node(nr_tags, sizeof(struct request *),
+ GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
+ node);
if (!tags->static_rqs) {
kfree(tags->rqs);
blk_mq_free_tags(tags);
@@ -2349,7 +2353,6 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q)
mutex_lock(&set->tag_list_lock);
list_del_rcu(&q->tag_set_list);
- INIT_LIST_HEAD(&q->tag_set_list);
if (list_is_singular(&set->tag_list)) {
/* just transitioned to unshared */
set->flags &= ~BLK_MQ_F_TAG_SHARED;
@@ -2357,8 +2360,8 @@ static void blk_mq_del_queue_tag_set(struct request_queue *q)
blk_mq_update_tag_set_depth(set, false);
}
mutex_unlock(&set->tag_list_lock);
-
synchronize_rcu();
+ INIT_LIST_HEAD(&q->tag_set_list);
}
static void blk_mq_add_queue_tag_set(struct blk_mq_tag_set *set,
@@ -2522,7 +2525,7 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
/* init q->mq_kobj and sw queues' kobjects */
blk_mq_sysfs_init(q);
- q->queue_hw_ctx = kzalloc_node(nr_cpu_ids * sizeof(*(q->queue_hw_ctx)),
+ q->queue_hw_ctx = kcalloc_node(nr_cpu_ids, sizeof(*(q->queue_hw_ctx)),
GFP_KERNEL, set->numa_node);
if (!q->queue_hw_ctx)
goto err_percpu;
@@ -2741,14 +2744,14 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
if (set->nr_hw_queues > nr_cpu_ids)
set->nr_hw_queues = nr_cpu_ids;
- set->tags = kzalloc_node(nr_cpu_ids * sizeof(struct blk_mq_tags *),
+ set->tags = kcalloc_node(nr_cpu_ids, sizeof(struct blk_mq_tags *),
GFP_KERNEL, set->numa_node);
if (!set->tags)
return -ENOMEM;
ret = -ENOMEM;
- set->mq_map = kzalloc_node(sizeof(*set->mq_map) * nr_cpu_ids,
- GFP_KERNEL, set->numa_node);
+ set->mq_map = kcalloc_node(nr_cpu_ids, sizeof(*set->mq_map),
+ GFP_KERNEL, set->numa_node);
if (!set->mq_map)
goto out_free_tags;
diff --git a/block/blk-softirq.c b/block/blk-softirq.c
index 01e2b35..15c1f5e 100644
--- a/block/blk-softirq.c
+++ b/block/blk-softirq.c
@@ -144,6 +144,7 @@ do_local:
local_irq_restore(flags);
}
+EXPORT_SYMBOL(__blk_complete_request);
/**
* blk_complete_request - end I/O on a request
diff --git a/block/blk-tag.c b/block/blk-tag.c
index 09f19c6..fbc153a 100644
--- a/block/blk-tag.c
+++ b/block/blk-tag.c
@@ -99,12 +99,12 @@ init_tag_map(struct request_queue *q, struct blk_queue_tag *tags, int depth)
__func__, depth);
}
- tag_index = kzalloc(depth * sizeof(struct request *), GFP_ATOMIC);
+ tag_index = kcalloc(depth, sizeof(struct request *), GFP_ATOMIC);
if (!tag_index)
goto fail;
nr_ulongs = ALIGN(depth, BITS_PER_LONG) / BITS_PER_LONG;
- tag_map = kzalloc(nr_ulongs * sizeof(unsigned long), GFP_ATOMIC);
+ tag_map = kcalloc(nr_ulongs, sizeof(unsigned long), GFP_ATOMIC);
if (!tag_map)
goto fail;
@@ -188,7 +188,6 @@ int blk_queue_init_tags(struct request_queue *q, int depth,
*/
q->queue_tags = tags;
queue_flag_set_unlocked(QUEUE_FLAG_QUEUED, q);
- INIT_LIST_HEAD(&q->tag_busy_list);
return 0;
}
EXPORT_SYMBOL(blk_queue_init_tags);
@@ -374,27 +373,6 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq)
rq->tag = tag;
bqt->tag_index[tag] = rq;
blk_start_request(rq);
- list_add(&rq->queuelist, &q->tag_busy_list);
return 0;
}
EXPORT_SYMBOL(blk_queue_start_tag);
-
-/**
- * blk_queue_invalidate_tags - invalidate all pending tags
- * @q: the request queue for the device
- *
- * Description:
- * Hardware conditions may dictate a need to stop all pending requests.
- * In this case, we will safely clear the block side of the tag queue and
- * readd all requests to the request queue in the right order.
- **/
-void blk_queue_invalidate_tags(struct request_queue *q)
-{
- struct list_head *tmp, *n;
-
- lockdep_assert_held(q->queue_lock);
-
- list_for_each_safe(tmp, n, &q->tag_busy_list)
- blk_requeue_request(q, list_entry_rq(tmp));
-}
-EXPORT_SYMBOL(blk_queue_invalidate_tags);
diff --git a/block/blk-timeout.c b/block/blk-timeout.c
index 4b8a48d..f2cfd56 100644
--- a/block/blk-timeout.c
+++ b/block/blk-timeout.c
@@ -210,6 +210,7 @@ void blk_add_timer(struct request *req)
if (!req->timeout)
req->timeout = q->rq_timeout;
+ req->rq_flags &= ~RQF_TIMED_OUT;
blk_rq_set_deadline(req, jiffies + req->timeout);
/*
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index 3d08dc84..5100091 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -331,8 +331,8 @@ int blkdev_report_zones_ioctl(struct block_device *bdev, fmode_t mode,
if (rep.nr_zones > INT_MAX / sizeof(struct blk_zone))
return -ERANGE;
- zones = kvmalloc(rep.nr_zones * sizeof(struct blk_zone),
- GFP_KERNEL | __GFP_ZERO);
+ zones = kvmalloc_array(rep.nr_zones, sizeof(struct blk_zone),
+ GFP_KERNEL | __GFP_ZERO);
if (!zones)
return -ENOMEM;
diff --git a/block/bsg.c b/block/bsg.c
index 132e657..66602c4 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -693,6 +693,8 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
struct bsg_device *bd;
unsigned char buf[32];
+ lockdep_assert_held(&bsg_mutex);
+
if (!blk_get_queue(rq))
return ERR_PTR(-ENXIO);
@@ -707,14 +709,12 @@ static struct bsg_device *bsg_add_device(struct inode *inode,
bsg_set_block(bd, file);
atomic_set(&bd->ref_count, 1);
- mutex_lock(&bsg_mutex);
hlist_add_head(&bd->dev_list, bsg_dev_idx_hash(iminor(inode)));
strncpy(bd->name, dev_name(rq->bsg_dev.class_dev), sizeof(bd->name) - 1);
bsg_dbg(bd, "bound to <%s>, max queue %d\n",
format_dev_t(buf, inode->i_rdev), bd->max_queue);
- mutex_unlock(&bsg_mutex);
return bd;
}
@@ -722,7 +722,7 @@ static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q)
{
struct bsg_device *bd;
- mutex_lock(&bsg_mutex);
+ lockdep_assert_held(&bsg_mutex);
hlist_for_each_entry(bd, bsg_dev_idx_hash(minor), dev_list) {
if (bd->queue == q) {
@@ -732,7 +732,6 @@ static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q)
}
bd = NULL;
found:
- mutex_unlock(&bsg_mutex);
return bd;
}
@@ -746,17 +745,18 @@ static struct bsg_device *bsg_get_device(struct inode *inode, struct file *file)
*/
mutex_lock(&bsg_mutex);
bcd = idr_find(&bsg_minor_idr, iminor(inode));
- mutex_unlock(&bsg_mutex);
- if (!bcd)
- return ERR_PTR(-ENODEV);
+ if (!bcd) {
+ bd = ERR_PTR(-ENODEV);
+ goto out_unlock;
+ }
bd = __bsg_get_device(iminor(inode), bcd->queue);
- if (bd)
- return bd;
-
- bd = bsg_add_device(inode, bcd->queue, file);
+ if (!bd)
+ bd = bsg_add_device(inode, bcd->queue, file);
+out_unlock:
+ mutex_unlock(&bsg_mutex);
return bd;
}
diff --git a/block/partitions/check.c b/block/partitions/check.c
index 720145c..ffe408f 100644
--- a/block/partitions/check.c
+++ b/block/partitions/check.c
@@ -122,7 +122,7 @@ static struct parsed_partitions *allocate_partitions(struct gendisk *hd)
return NULL;
nr = disk_max_parts(hd);
- state->parts = vzalloc(nr * sizeof(state->parts[0]));
+ state->parts = vzalloc(array_size(nr, sizeof(state->parts[0])));
if (!state->parts) {
kfree(state);
return NULL;
diff --git a/block/partitions/ldm.c b/block/partitions/ldm.c
index 2a365c7..0417937 100644
--- a/block/partitions/ldm.c
+++ b/block/partitions/ldm.c
@@ -378,7 +378,7 @@ static bool ldm_validate_tocblocks(struct parsed_partitions *state,
BUG_ON(!state || !ldb);
ph = &ldb->ph;
tb[0] = &ldb->toc;
- tb[1] = kmalloc(sizeof(*tb[1]) * 3, GFP_KERNEL);
+ tb[1] = kmalloc_array(3, sizeof(*tb[1]), GFP_KERNEL);
if (!tb[1]) {
ldm_crit("Out of memory.");
goto err;
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 945f4b8..e0de4dd 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -877,7 +877,7 @@ static size_t response_get_string(const struct parsed_resp *resp, int n,
return 0;
}
- if (n > resp->num) {
+ if (n >= resp->num) {
pr_debug("Response has %d tokens. Can't access %d\n",
resp->num, n);
return 0;
@@ -916,7 +916,7 @@ static u64 response_get_u64(const struct parsed_resp *resp, int n)
return 0;
}
- if (n > resp->num) {
+ if (n >= resp->num) {
pr_debug("Response has %d tokens. Can't access %d\n",
resp->num, n);
return 0;
diff --git a/certs/Kconfig b/certs/Kconfig
index 5f7663d..c94e93d 100644
--- a/certs/Kconfig
+++ b/certs/Kconfig
@@ -13,7 +13,7 @@ config MODULE_SIG_KEY
If this option is unchanged from its default "certs/signing_key.pem",
then the kernel will automatically generate the private key and
- certificate as described in Documentation/module-signing.txt
+ certificate as described in Documentation/admin-guide/module-signing.rst
config SYSTEM_TRUSTED_KEYRING
bool "Provide system-wide ring of trusted keys"
diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c
index 330cf9f..825524f 100644
--- a/crypto/algif_aead.c
+++ b/crypto/algif_aead.c
@@ -255,8 +255,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg,
processed - as);
if (!areq->tsgl_entries)
areq->tsgl_entries = 1;
- areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) *
- areq->tsgl_entries,
+ areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
+ areq->tsgl_entries),
GFP_KERNEL);
if (!areq->tsgl) {
err = -ENOMEM;
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 15cf3c5..4c04eb9 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -100,7 +100,8 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg,
areq->tsgl_entries = af_alg_count_tsgl(sk, len, 0);
if (!areq->tsgl_entries)
areq->tsgl_entries = 1;
- areq->tsgl = sock_kmalloc(sk, sizeof(*areq->tsgl) * areq->tsgl_entries,
+ areq->tsgl = sock_kmalloc(sk, array_size(sizeof(*areq->tsgl),
+ areq->tsgl_entries),
GFP_KERNEL);
if (!areq->tsgl) {
err = -ENOMEM;
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index 39aecad..26539e9 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -1,6 +1,6 @@
/* Asymmetric public-key cryptography key type
*
- * See Documentation/security/asymmetric-keys.txt
+ * See Documentation/crypto/asymmetric-keys.txt
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
diff --git a/crypto/asymmetric_keys/signature.c b/crypto/asymmetric_keys/signature.c
index 11b7ba17..2819831 100644
--- a/crypto/asymmetric_keys/signature.c
+++ b/crypto/asymmetric_keys/signature.c
@@ -1,6 +1,6 @@
/* Signature verification with an asymmetric key
*
- * See Documentation/security/asymmetric-keys.txt
+ * See Documentation/crypto/asymmetric-keys.txt
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
diff --git a/crypto/morus640.c b/crypto/morus640.c
index 9fbcde3..5eede37 100644
--- a/crypto/morus640.c
+++ b/crypto/morus640.c
@@ -274,8 +274,9 @@ static void crypto_morus640_decrypt_chunk(struct morus640_state *state, u8 *dst,
union morus640_block_in tail;
memcpy(tail.bytes, src, size);
+ memset(tail.bytes + size, 0, MORUS640_BLOCK_SIZE - size);
- crypto_morus640_load_a(&m, src);
+ crypto_morus640_load_a(&m, tail.bytes);
crypto_morus640_core(state, &m);
crypto_morus640_store_a(tail.bytes, &m);
memset(tail.bytes + size, 0, MORUS640_BLOCK_SIZE - size);
diff --git a/crypto/sha3_generic.c b/crypto/sha3_generic.c
index 264ec12..7f6735d 100644
--- a/crypto/sha3_generic.c
+++ b/crypto/sha3_generic.c
@@ -152,7 +152,7 @@ static SHA3_INLINE void keccakf_round(u64 st[25])
st[24] ^= bc[ 4];
}
-static void __optimize("O3") keccakf(u64 st[25])
+static void keccakf(u64 st[25])
{
int round;
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index d1d9984..11e4535 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -603,7 +603,8 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
goto out_nooutbuf;
/* avoid "the frame size is larger than 1024 bytes" compiler warning */
- sg = kmalloc(sizeof(*sg) * 8 * (diff_dst ? 4 : 2), GFP_KERNEL);
+ sg = kmalloc(array3_size(sizeof(*sg), 8, (diff_dst ? 4 : 2)),
+ GFP_KERNEL);
if (!sg)
goto out_nosg;
sgout = &sg[16];
diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c
index cb6ac5c..f8fecfe 100644
--- a/drivers/acpi/acpi_lpss.c
+++ b/drivers/acpi/acpi_lpss.c
@@ -22,6 +22,7 @@
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/pwm.h>
+#include <linux/suspend.h>
#include <linux/delay.h>
#include "internal.h"
@@ -233,11 +234,13 @@ static const struct lpss_device_desc lpt_sdio_dev_desc = {
static const struct lpss_device_desc byt_pwm_dev_desc = {
.flags = LPSS_SAVE_CTX,
+ .prv_offset = 0x800,
.setup = byt_pwm_setup,
};
static const struct lpss_device_desc bsw_pwm_dev_desc = {
.flags = LPSS_SAVE_CTX | LPSS_NO_D3_DELAY,
+ .prv_offset = 0x800,
.setup = bsw_pwm_setup,
};
@@ -944,9 +947,10 @@ static void lpss_iosf_exit_d3_state(void)
mutex_unlock(&lpss_iosf_mutex);
}
-static int acpi_lpss_suspend(struct device *dev, bool wakeup)
+static int acpi_lpss_suspend(struct device *dev, bool runtime)
{
struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+ bool wakeup = runtime || device_may_wakeup(dev);
int ret;
if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
@@ -959,13 +963,14 @@ static int acpi_lpss_suspend(struct device *dev, bool wakeup)
* wrong status for devices being about to be powered off. See
* lpss_iosf_enter_d3_state() for further information.
*/
- if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available())
+ if ((runtime || !pm_suspend_via_firmware()) &&
+ lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available())
lpss_iosf_enter_d3_state();
return ret;
}
-static int acpi_lpss_resume(struct device *dev)
+static int acpi_lpss_resume(struct device *dev, bool runtime)
{
struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
int ret;
@@ -974,7 +979,8 @@ static int acpi_lpss_resume(struct device *dev)
* This call is kept first to be in symmetry with
* acpi_lpss_runtime_suspend() one.
*/
- if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available())
+ if ((runtime || !pm_resume_via_firmware()) &&
+ lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available())
lpss_iosf_exit_d3_state();
ret = acpi_dev_resume(dev);
@@ -998,12 +1004,12 @@ static int acpi_lpss_suspend_late(struct device *dev)
return 0;
ret = pm_generic_suspend_late(dev);
- return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev));
+ return ret ? ret : acpi_lpss_suspend(dev, false);
}
static int acpi_lpss_resume_early(struct device *dev)
{
- int ret = acpi_lpss_resume(dev);
+ int ret = acpi_lpss_resume(dev, false);
return ret ? ret : pm_generic_resume_early(dev);
}
@@ -1018,7 +1024,7 @@ static int acpi_lpss_runtime_suspend(struct device *dev)
static int acpi_lpss_runtime_resume(struct device *dev)
{
- int ret = acpi_lpss_resume(dev);
+ int ret = acpi_lpss_resume(dev, true);
return ret ? ret : pm_generic_runtime_resume(dev);
}
diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c
index 88cd949..eaa60c9 100644
--- a/drivers/acpi/acpi_platform.c
+++ b/drivers/acpi/acpi_platform.c
@@ -82,7 +82,7 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev,
if (count < 0) {
return NULL;
} else if (count > 0) {
- resources = kzalloc(count * sizeof(struct resource),
+ resources = kcalloc(count, sizeof(struct resource),
GFP_KERNEL);
if (!resources) {
dev_err(&adev->dev, "No memory for resources\n");
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index 2f2e737..f0b5226 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -832,8 +832,9 @@ int acpi_video_get_levels(struct acpi_device *device,
* in order to account for buggy BIOS which don't export the first two
* special levels (see below)
*/
- br->levels = kmalloc((obj->package.count + ACPI_VIDEO_FIRST_LEVEL) *
- sizeof(*br->levels), GFP_KERNEL);
+ br->levels = kmalloc_array(obj->package.count + ACPI_VIDEO_FIRST_LEVEL,
+ sizeof(*br->levels),
+ GFP_KERNEL);
if (!br->levels) {
result = -ENOMEM;
goto out_free;
diff --git a/drivers/acpi/acpica/dbnames.c b/drivers/acpi/acpica/dbnames.c
index dc94de9..992bd7b 100644
--- a/drivers/acpi/acpica/dbnames.c
+++ b/drivers/acpi/acpica/dbnames.c
@@ -322,6 +322,7 @@ acpi_db_walk_and_match_name(acpi_handle obj_handle,
acpi_os_printf("Could Not get pathname for object %p\n",
obj_handle);
} else {
+ info.count = 0;
info.owner_id = ACPI_OWNER_ID_MAX;
info.debug_level = ACPI_UINT32_MAX;
info.display_type = ACPI_DISPLAY_SUMMARY | ACPI_DISPLAY_SHORT;
diff --git a/drivers/acpi/acpica/dbobject.c b/drivers/acpi/acpica/dbobject.c
index 58c3253..a1c76bf 100644
--- a/drivers/acpi/acpica/dbobject.c
+++ b/drivers/acpi/acpica/dbobject.c
@@ -35,6 +35,15 @@ void
acpi_db_dump_method_info(acpi_status status, struct acpi_walk_state *walk_state)
{
struct acpi_thread_state *thread;
+ struct acpi_namespace_node *node;
+
+ node = walk_state->method_node;
+
+ /* There are no locals or arguments for the module-level code case */
+
+ if (node == acpi_gbl_root_node) {
+ return;
+ }
/* Ignore control codes, they are not errors */
@@ -384,8 +393,14 @@ void acpi_db_decode_locals(struct acpi_walk_state *walk_state)
struct acpi_namespace_node *node;
u8 display_locals = FALSE;
- obj_desc = walk_state->method_desc;
node = walk_state->method_node;
+ obj_desc = walk_state->method_desc;
+
+ /* There are no locals for the module-level code case */
+
+ if (node == acpi_gbl_root_node) {
+ return;
+ }
if (!node) {
acpi_os_printf
@@ -452,6 +467,12 @@ void acpi_db_decode_arguments(struct acpi_walk_state *walk_state)
node = walk_state->method_node;
obj_desc = walk_state->method_desc;
+ /* There are no arguments for the module-level code case */
+
+ if (node == acpi_gbl_root_node) {
+ return;
+ }
+
if (!node) {
acpi_os_printf
("No method node (Executing subtree for buffer or opregion)\n");
diff --git a/drivers/acpi/acpica/dsdebug.c b/drivers/acpi/acpica/dsdebug.c
index 70a2fca..9d33f0b 100644
--- a/drivers/acpi/acpica/dsdebug.c
+++ b/drivers/acpi/acpica/dsdebug.c
@@ -162,9 +162,15 @@ acpi_ds_dump_method_stack(acpi_status status,
op->common.next = NULL;
#ifdef ACPI_DISASSEMBLER
- acpi_os_printf("Failed at ");
- acpi_dm_disassemble(next_walk_state, op,
- ACPI_UINT32_MAX);
+ if (walk_state->method_node !=
+ acpi_gbl_root_node) {
+
+ /* More verbose if not module-level code */
+
+ acpi_os_printf("Failed at ");
+ acpi_dm_disassemble(next_walk_state, op,
+ ACPI_UINT32_MAX);
+ }
#endif
op->common.next = next;
}
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index f85c6f3..2373a74 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -490,6 +490,17 @@ acpi_status acpi_ex_unload_table(union acpi_operand_object *ddb_handle)
ACPI_WARNING((AE_INFO, "Received request to unload an ACPI table"));
/*
+ * May 2018: Unload is no longer supported for the following reasons:
+ * 1) A correct implementation on some hosts may not be possible.
+ * 2) Other ACPI implementations do not correctly/fully support it.
+ * 3) It requires host device driver support which does not exist.
+ * (To properly support namespace unload out from underneath.)
+ * 4) This AML operator has never been seen in the field.
+ */
+ ACPI_EXCEPTION((AE_INFO, AE_NOT_IMPLEMENTED,
+ "AML Unload operator is not supported"));
+
+ /*
* Validate the handle
* Although the handle is partially validated in acpi_ex_reconfiguration()
* when it calls acpi_ex_resolve_operands(), the handle is more completely
diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c
index 4bdbd1d..90ccffc 100644
--- a/drivers/acpi/acpica/nsdump.c
+++ b/drivers/acpi/acpica/nsdump.c
@@ -170,6 +170,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle,
}
type = this_node->type;
+ info->count++;
/* Check if the owner matches */
@@ -639,6 +640,7 @@ acpi_ns_dump_objects(acpi_object_type type,
return;
}
+ info.count = 0;
info.debug_level = ACPI_LV_TABLES;
info.owner_id = owner_id;
info.display_type = display_type;
@@ -649,6 +651,7 @@ acpi_ns_dump_objects(acpi_object_type type,
acpi_ns_dump_one_object, NULL,
(void *)&info, NULL);
+ acpi_os_printf("\nNamespace node count: %u\n\n", info.count);
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
}
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c
index 68422af..bc5f059 100644
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -515,6 +515,22 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
+ if (walk_state->opcode == AML_SCOPE_OP) {
+ /*
+ * If the scope op fails to parse, skip the body of the
+ * scope op because the parse failure indicates that the
+ * device may not exist.
+ */
+ walk_state->parser_state.aml =
+ walk_state->aml + 1;
+ walk_state->parser_state.aml =
+ acpi_ps_get_next_package_end
+ (&walk_state->parser_state);
+ walk_state->aml =
+ walk_state->parser_state.aml;
+ ACPI_ERROR((AE_INFO,
+ "Skipping Scope block"));
+ }
continue;
}
@@ -557,7 +573,40 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
-
+ if ((walk_state->control_state) &&
+ ((walk_state->control_state->control.
+ opcode == AML_IF_OP)
+ || (walk_state->control_state->control.
+ opcode == AML_WHILE_OP))) {
+ /*
+ * If the if/while op fails to parse, we will skip parsing
+ * the body of the op.
+ */
+ parser_state->aml =
+ walk_state->control_state->control.
+ aml_predicate_start + 1;
+ parser_state->aml =
+ acpi_ps_get_next_package_end
+ (parser_state);
+ walk_state->aml = parser_state->aml;
+
+ ACPI_ERROR((AE_INFO,
+ "Skipping While/If block"));
+ if (*walk_state->aml == AML_ELSE_OP) {
+ ACPI_ERROR((AE_INFO,
+ "Skipping Else block"));
+ walk_state->parser_state.aml =
+ walk_state->aml + 1;
+ walk_state->parser_state.aml =
+ acpi_ps_get_next_package_end
+ (parser_state);
+ walk_state->aml =
+ parser_state->aml;
+ }
+ ACPI_FREE(acpi_ut_pop_generic_state
+ (&walk_state->control_state));
+ }
+ op = NULL;
continue;
}
}
diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c
index 7d9d015..3138e7a 100644
--- a/drivers/acpi/acpica/psobject.c
+++ b/drivers/acpi/acpica/psobject.c
@@ -12,6 +12,7 @@
#include "acparser.h"
#include "amlcode.h"
#include "acconvert.h"
+#include "acnamesp.h"
#define _COMPONENT ACPI_PARSER
ACPI_MODULE_NAME("psobject")
@@ -549,6 +550,21 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
do {
if (*op) {
+ /*
+ * These Opcodes need to be removed from the namespace because they
+ * get created even if these opcodes cannot be created due to
+ * errors.
+ */
+ if (((*op)->common.aml_opcode == AML_REGION_OP)
+ || ((*op)->common.aml_opcode ==
+ AML_DATA_REGION_OP)) {
+ acpi_ns_delete_children((*op)->common.
+ node);
+ acpi_ns_remove_node((*op)->common.node);
+ (*op)->common.node = NULL;
+ acpi_ps_delete_parse_tree(*op);
+ }
+
status2 =
acpi_ps_complete_this_op(walk_state, *op);
if (ACPI_FAILURE(status2)) {
@@ -574,6 +590,20 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
#endif
walk_state->prev_op = NULL;
walk_state->prev_arg_types = walk_state->arg_types;
+
+ if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) {
+ /*
+ * There was something that went wrong while executing code at the
+ * module-level. We need to skip parsing whatever caused the
+ * error and keep going. One runtime error during the table load
+ * should not cause the entire table to not be loaded. This is
+ * because there could be correct AML beyond the parts that caused
+ * the runtime error.
+ */
+ ACPI_ERROR((AE_INFO,
+ "Ignore error and continue table load"));
+ return_ACPI_STATUS(AE_OK);
+ }
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c
index e0a442b..bd6af8c 100644
--- a/drivers/acpi/acpica/pswalk.c
+++ b/drivers/acpi/acpica/pswalk.c
@@ -25,22 +25,48 @@ ACPI_MODULE_NAME("pswalk")
* DESCRIPTION: Delete a portion of or an entire parse tree.
*
******************************************************************************/
+#include "amlcode.h"
void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root)
{
union acpi_parse_object *op = subtree_root;
union acpi_parse_object *next = NULL;
union acpi_parse_object *parent = NULL;
+ u32 level = 0;
ACPI_FUNCTION_TRACE_PTR(ps_delete_parse_tree, subtree_root);
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE_TREES, " root %p\n", subtree_root));
+
/* Visit all nodes in the subtree */
while (op) {
-
- /* Check if we are not ascending */
-
if (op != parent) {
+ /* This is the descending case */
+
+ if (ACPI_IS_DEBUG_ENABLED
+ (ACPI_LV_PARSE_TREES, _COMPONENT)) {
+
+ /* This debug option will print the entire parse tree */
+
+ acpi_os_printf(" %*.s%s %p", (level * 4),
+ " ",
+ acpi_ps_get_opcode_name(op->
+ common.
+ aml_opcode),
+ op);
+
+ if (op->named.aml_opcode == AML_INT_NAMEPATH_OP) {
+ acpi_os_printf(" %4.4s",
+ op->common.value.string);
+ }
+ if (op->named.aml_opcode == AML_STRING_OP) {
+ acpi_os_printf(" %s",
+ op->common.value.string);
+ }
+ acpi_os_printf("\n");
+ }
+
/* Look for an argument or child of the current op */
next = acpi_ps_get_arg(op, 0);
@@ -49,6 +75,7 @@ void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root)
/* Still going downward in tree (Op is not completed yet) */
op = next;
+ level++;
continue;
}
}
@@ -69,6 +96,7 @@ void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root)
if (next) {
op = next;
} else {
+ level--;
op = parent;
}
}
diff --git a/drivers/acpi/acpica/uterror.c b/drivers/acpi/acpica/uterror.c
index 12d4a0f..5a64dda 100644
--- a/drivers/acpi/acpica/uterror.c
+++ b/drivers/acpi/acpica/uterror.c
@@ -182,20 +182,20 @@ acpi_ut_prefixed_namespace_error(const char *module_name,
switch (lookup_status) {
case AE_ALREADY_EXISTS:
- acpi_os_printf(ACPI_MSG_BIOS_ERROR);
+ acpi_os_printf("\n" ACPI_MSG_BIOS_ERROR);
message = "Failure creating";
break;
case AE_NOT_FOUND:
- acpi_os_printf(ACPI_MSG_BIOS_ERROR);
- message = "Failure looking up";
+ acpi_os_printf("\n" ACPI_MSG_BIOS_ERROR);
+ message = "Could not resolve";
break;
default:
- acpi_os_printf(ACPI_MSG_ERROR);
- message = "Failure looking up";
+ acpi_os_printf("\n" ACPI_MSG_ERROR);
+ message = "Failure resolving";
break;
}
diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c
index 1b415fa..64b63c8 100644
--- a/drivers/acpi/acpica/utosi.c
+++ b/drivers/acpi/acpica/utosi.c
@@ -69,6 +69,7 @@ static struct acpi_interface_info acpi_default_supported_interfaces[] = {
{"Windows 2015", NULL, 0, ACPI_OSI_WIN_10}, /* Windows 10 - Added 03/2015 */
{"Windows 2016", NULL, 0, ACPI_OSI_WIN_10_RS1}, /* Windows 10 version 1607 - Added 12/2017 */
{"Windows 2017", NULL, 0, ACPI_OSI_WIN_10_RS2}, /* Windows 10 version 1703 - Added 12/2017 */
+ {"Windows 2017.2", NULL, 0, ACPI_OSI_WIN_10_RS3}, /* Windows 10 version 1709 - Added 02/2018 */
/* Feature Group Strings */
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 9bff853..3c5ea7c 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -524,7 +524,8 @@ retry:
pr_warn(FW_WARN "too many record IDs!\n");
return 0;
}
- new_entries = kvmalloc(new_size * sizeof(entries[0]), GFP_KERNEL);
+ new_entries = kvmalloc_array(new_size, sizeof(entries[0]),
+ GFP_KERNEL);
if (!new_entries)
return -ENOMEM;
memcpy(new_entries, entries,
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c
index 9cb7411..b1e9f81 100644
--- a/drivers/acpi/apei/hest.c
+++ b/drivers/acpi/apei/hest.c
@@ -195,7 +195,8 @@ static int __init hest_ghes_dev_register(unsigned int ghes_count)
struct ghes_arr ghes_arr;
ghes_arr.count = 0;
- ghes_arr.ghes_devs = kmalloc(sizeof(void *) * ghes_count, GFP_KERNEL);
+ ghes_arr.ghes_devs = kmalloc_array(ghes_count, sizeof(void *),
+ GFP_KERNEL);
if (!ghes_arr.ghes_devs)
return -ENOMEM;
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index bb94cf0..442a9e2 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -2037,6 +2037,17 @@ static inline void acpi_ec_query_exit(void)
}
}
+static const struct dmi_system_id acpi_ec_no_wakeup[] = {
+ {
+ .ident = "Thinkpad X1 Carbon 6th",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "20KGS3JF01"),
+ },
+ },
+ { },
+};
+
int __init acpi_ec_init(void)
{
int result;
@@ -2047,6 +2058,15 @@ int __init acpi_ec_init(void)
if (result)
return result;
+ /*
+ * Disable EC wakeup on following systems to prevent periodic
+ * wakeup from EC GPE.
+ */
+ if (dmi_check_system(acpi_ec_no_wakeup)) {
+ ec_no_wakeup = true;
+ pr_debug("Disabling EC wakeup on suspend-to-idle\n");
+ }
+
/* Drivers must be started after acpi_ec_query_init() */
dsdt_fail = acpi_bus_register_driver(&acpi_ec_driver);
/*
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index 3563103..fe0183d 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -298,8 +298,8 @@ static int acpi_fan_get_fps(struct acpi_device *device)
}
fan->fps_count = obj->package.count - 1; /* minus revision field */
- fan->fps = devm_kzalloc(&device->dev,
- fan->fps_count * sizeof(struct acpi_fan_fps),
+ fan->fps = devm_kcalloc(&device->dev,
+ fan->fps_count, sizeof(struct acpi_fan_fps),
GFP_KERNEL);
if (!fan->fps) {
dev_err(&device->dev, "Not enough memory\n");
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index b87252b..d15814e 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1082,9 +1082,10 @@ static int __nfit_mem_init(struct acpi_nfit_desc *acpi_desc,
continue;
nfit_mem->nfit_flush = nfit_flush;
flush = nfit_flush->flush;
- nfit_mem->flush_wpq = devm_kzalloc(acpi_desc->dev,
- flush->hint_count
- * sizeof(struct resource), GFP_KERNEL);
+ nfit_mem->flush_wpq = devm_kcalloc(acpi_desc->dev,
+ flush->hint_count,
+ sizeof(struct resource),
+ GFP_KERNEL);
if (!nfit_mem->flush_wpq)
return -ENOMEM;
for (i = 0; i < flush->hint_count; i++) {
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index a651ab3..a303fd0 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -343,8 +343,9 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
pr->performance->state_count = pss->package.count;
pr->performance->states =
- kmalloc(sizeof(struct acpi_processor_px) * pss->package.count,
- GFP_KERNEL);
+ kmalloc_array(pss->package.count,
+ sizeof(struct acpi_processor_px),
+ GFP_KERNEL);
if (!pr->performance->states) {
result = -ENOMEM;
goto end;
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index 7f9aff4..fbc936c 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -534,8 +534,9 @@ static int acpi_processor_get_throttling_states(struct acpi_processor *pr)
pr->throttling.state_count = tss->package.count;
pr->throttling.states_tss =
- kmalloc(sizeof(struct acpi_processor_tx_tss) * tss->package.count,
- GFP_KERNEL);
+ kmalloc_array(tss->package.count,
+ sizeof(struct acpi_processor_tx_tss),
+ GFP_KERNEL);
if (!pr->throttling.states_tss) {
result = -ENOMEM;
goto end;
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index 4fc59c3..41324f0 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -857,12 +857,12 @@ void acpi_irq_stats_init(void)
num_gpes = acpi_current_gpe_count;
num_counters = num_gpes + ACPI_NUM_FIXED_EVENTS + NUM_COUNTERS_EXTRA;
- all_attrs = kzalloc(sizeof(struct attribute *) * (num_counters + 1),
+ all_attrs = kcalloc(num_counters + 1, sizeof(struct attribute *),
GFP_KERNEL);
if (all_attrs == NULL)
return;
- all_counters = kzalloc(sizeof(struct event_counter) * (num_counters),
+ all_counters = kcalloc(num_counters, sizeof(struct event_counter),
GFP_KERNEL);
if (all_counters == NULL)
goto fail;
@@ -871,7 +871,7 @@ void acpi_irq_stats_init(void)
if (ACPI_FAILURE(status))
goto fail;
- counter_attrs = kzalloc(sizeof(struct kobj_attribute) * (num_counters),
+ counter_attrs = kcalloc(num_counters, sizeof(struct kobj_attribute),
GFP_KERNEL);
if (counter_attrs == NULL)
goto fail;
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 4f382d5..2628806 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -692,8 +692,8 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc,
}
}
#endif
- alloc->pages = kzalloc(sizeof(alloc->pages[0]) *
- ((vma->vm_end - vma->vm_start) / PAGE_SIZE),
+ alloc->pages = kcalloc((vma->vm_end - vma->vm_start) / PAGE_SIZE,
+ sizeof(alloc->pages[0]),
GFP_KERNEL);
if (alloc->pages == NULL) {
ret = -ENOMEM;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index c41b9eea..27d15ed 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6987,7 +6987,7 @@ static void __init ata_parse_force_param(void)
if (*p == ',')
size++;
- ata_force_tbl = kzalloc(sizeof(ata_force_tbl[0]) * size, GFP_KERNEL);
+ ata_force_tbl = kcalloc(size, sizeof(ata_force_tbl[0]), GFP_KERNEL);
if (!ata_force_tbl) {
printk(KERN_WARNING "ata: failed to extend force table, "
"libata.force ignored\n");
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 85aa761..2ae1799 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -340,7 +340,7 @@ static int sata_pmp_init_links (struct ata_port *ap, int nr_ports)
int i, err;
if (!pmp_link) {
- pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS,
+ pmp_link = kcalloc(SATA_PMP_MAX_PORTS, sizeof(pmp_link[0]),
GFP_NOIO);
if (!pmp_link)
return -ENOMEM;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index ce5019d..6a91d04 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -5054,6 +5054,18 @@ int ata_sas_port_init(struct ata_port *ap)
}
EXPORT_SYMBOL_GPL(ata_sas_port_init);
+int ata_sas_tport_add(struct device *parent, struct ata_port *ap)
+{
+ return ata_tport_add(parent, ap);
+}
+EXPORT_SYMBOL_GPL(ata_sas_tport_add);
+
+void ata_sas_tport_delete(struct ata_port *ap)
+{
+ ata_tport_delete(ap);
+}
+EXPORT_SYMBOL_GPL(ata_sas_tport_delete);
+
/**
* ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc
* @ap: SATA port to destroy
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index cddf96f..73ba8e1 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -4114,13 +4114,13 @@ static int mv_platform_probe(struct platform_device *pdev)
if (!host || !hpriv)
return -ENOMEM;
- hpriv->port_clks = devm_kzalloc(&pdev->dev,
- sizeof(struct clk *) * n_ports,
+ hpriv->port_clks = devm_kcalloc(&pdev->dev,
+ n_ports, sizeof(struct clk *),
GFP_KERNEL);
if (!hpriv->port_clks)
return -ENOMEM;
- hpriv->port_phys = devm_kzalloc(&pdev->dev,
- sizeof(struct phy *) * n_ports,
+ hpriv->port_phys = devm_kcalloc(&pdev->dev,
+ n_ports, sizeof(struct phy *),
GFP_KERNEL);
if (!hpriv->port_phys)
return -ENOMEM;
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index 6ebc4e4..99a3811 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -2094,7 +2094,8 @@ static int fore200e_alloc_rx_buf(struct fore200e *fore200e)
DPRINTK(2, "rx buffers %d / %d are being allocated\n", scheme, magn);
/* allocate the array of receive buffers */
- buffer = bsq->buffer = kzalloc(nbr * sizeof(struct buffer), GFP_KERNEL);
+ buffer = bsq->buffer = kcalloc(nbr, sizeof(struct buffer),
+ GFP_KERNEL);
if (buffer == NULL)
return -ENOMEM;
diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c
index be07660..ff81a57 100644
--- a/drivers/atm/iphase.c
+++ b/drivers/atm/iphase.c
@@ -1618,7 +1618,7 @@ static int rx_init(struct atm_dev *dev)
skb_queue_head_init(&iadev->rx_dma_q);
iadev->rx_free_desc_qhead = NULL;
- iadev->rx_open = kzalloc(4 * iadev->num_vc, GFP_KERNEL);
+ iadev->rx_open = kcalloc(4, iadev->num_vc, GFP_KERNEL);
if (!iadev->rx_open) {
printk(KERN_ERR DEV_LABEL "itf %d couldn't get free page\n",
dev->number);
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 0df1a1c..1728301 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -1291,7 +1291,8 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
card->using_dma = 1;
if (1) { /* All known FPGA versions so far */
card->dma_alignment = 3;
- card->dma_bounce = kmalloc(card->nr_ports * BUF_SIZE, GFP_KERNEL);
+ card->dma_bounce = kmalloc_array(card->nr_ports,
+ BUF_SIZE, GFP_KERNEL);
if (!card->dma_bounce) {
dev_warn(&card->dev->dev, "Failed to allocate DMA bounce buffers\n");
err = -ENOMEM;
diff --git a/drivers/auxdisplay/cfag12864b.c b/drivers/auxdisplay/cfag12864b.c
index 6bd2f65..7eebae7 100644
--- a/drivers/auxdisplay/cfag12864b.c
+++ b/drivers/auxdisplay/cfag12864b.c
@@ -333,8 +333,8 @@ static int __init cfag12864b_init(void)
goto none;
}
- cfag12864b_cache = kmalloc(sizeof(unsigned char) *
- CFAG12864B_SIZE, GFP_KERNEL);
+ cfag12864b_cache = kmalloc(CFAG12864B_SIZE,
+ GFP_KERNEL);
if (cfag12864b_cache == NULL) {
printk(KERN_ERR CFAG12864B_NAME ": ERROR: "
"can't alloc cache buffer (%i bytes)\n",
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index b074f24..704f442 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -8,10 +8,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \
topology.o container.o property.o cacheinfo.o \
devcon.o
obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
-obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
obj-y += power/
-obj-$(CONFIG_HAS_DMA) += dma-mapping.o
-obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o
obj-$(CONFIG_ISA_BUS_API) += isa.o
obj-y += firmware_loader/
obj-$(CONFIG_NUMA) += node.o
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 36622b5..df3e1a4 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -236,6 +236,13 @@ struct device_link *device_link_add(struct device *consumer,
link->rpm_active = true;
}
pm_runtime_new_link(consumer);
+ /*
+ * If the link is being added by the consumer driver at probe
+ * time, balance the decrementation of the supplier's runtime PM
+ * usage counter after consumer probe in driver_probe_device().
+ */
+ if (consumer->links.status == DL_DEV_PROBING)
+ pm_runtime_get_noresume(supplier);
}
get_device(supplier);
link->supplier = supplier;
@@ -255,12 +262,12 @@ struct device_link *device_link_add(struct device *consumer,
switch (consumer->links.status) {
case DL_DEV_PROBING:
/*
- * Balance the decrementation of the supplier's
- * runtime PM usage counter after consumer probe
- * in driver_probe_device().
+ * Some callers expect the link creation during
+ * consumer driver probe to resume the supplier
+ * even without DL_FLAG_RPM_ACTIVE.
*/
if (flags & DL_FLAG_PM_RUNTIME)
- pm_runtime_get_sync(supplier);
+ pm_runtime_resume(supplier);
link->status = DL_STATE_CONSUMER_PROBE;
break;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index fb4e2df..1435d72 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -580,7 +580,7 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
drv->bus->name, __func__, dev_name(dev), drv->name);
- pm_runtime_resume_suppliers(dev);
+ pm_runtime_get_suppliers(dev);
if (dev->parent)
pm_runtime_get_sync(dev->parent);
@@ -591,6 +591,7 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
if (dev->parent)
pm_runtime_put(dev->parent);
+ pm_runtime_put_suppliers(dev);
return ret;
}
diff --git a/drivers/base/firmware_loader/fallback.c b/drivers/base/firmware_loader/fallback.c
index b676a99..7f73274 100644
--- a/drivers/base/firmware_loader/fallback.c
+++ b/drivers/base/firmware_loader/fallback.c
@@ -403,7 +403,7 @@ static int fw_realloc_pages(struct fw_sysfs *fw_sysfs, int min_size)
fw_priv->page_array_size * 2);
struct page **new_pages;
- new_pages = vmalloc(new_array_size * sizeof(void *));
+ new_pages = vmalloc(array_size(new_array_size, sizeof(void *)));
if (!new_pages) {
fw_load_abort(fw_sysfs);
return -ENOMEM;
diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c
index 7ae62b6..df41b47 100644
--- a/drivers/base/power/common.c
+++ b/drivers/base/power/common.c
@@ -117,13 +117,50 @@ int dev_pm_domain_attach(struct device *dev, bool power_on)
EXPORT_SYMBOL_GPL(dev_pm_domain_attach);
/**
+ * dev_pm_domain_attach_by_id - Associate a device with one of its PM domains.
+ * @dev: The device used to lookup the PM domain.
+ * @index: The index of the PM domain.
+ *
+ * As @dev may only be attached to a single PM domain, the backend PM domain
+ * provider creates a virtual device to attach instead. If attachment succeeds,
+ * the ->detach() callback in the struct dev_pm_domain are assigned by the
+ * corresponding backend attach function, as to deal with detaching of the
+ * created virtual device.
+ *
+ * This function should typically be invoked by a driver during the probe phase,
+ * in case its device requires power management through multiple PM domains. The
+ * driver may benefit from using the received device, to configure device-links
+ * towards its original device. Depending on the use-case and if needed, the
+ * links may be dynamically changed by the driver, which allows it to control
+ * the power to the PM domains independently from each other.
+ *
+ * Callers must ensure proper synchronization of this function with power
+ * management callbacks.
+ *
+ * Returns the virtual created device when successfully attached to its PM
+ * domain, NULL in case @dev don't need a PM domain, else an ERR_PTR().
+ * Note that, to detach the returned virtual device, the driver shall call
+ * dev_pm_domain_detach() on it, typically during the remove phase.
+ */
+struct device *dev_pm_domain_attach_by_id(struct device *dev,
+ unsigned int index)
+{
+ if (dev->pm_domain)
+ return ERR_PTR(-EEXIST);
+
+ return genpd_dev_pm_attach_by_id(dev, index);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_attach_by_id);
+
+/**
* dev_pm_domain_detach - Detach a device from its PM domain.
* @dev: Device to detach.
* @power_off: Used to indicate whether we should power off the device.
*
- * This functions will reverse the actions from dev_pm_domain_attach() and thus
- * try to detach the @dev from its PM domain. Typically it should be invoked
- * from subsystem level code during the remove phase.
+ * This functions will reverse the actions from dev_pm_domain_attach() and
+ * dev_pm_domain_attach_by_id(), thus it detaches @dev from its PM domain.
+ * Typically it should be invoked during the remove phase, either from
+ * subsystem level code or from drivers.
*
* Callers must ensure proper synchronization of this function with power
* management callbacks.
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 6f403d6..4925af5 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -2171,6 +2171,15 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
}
EXPORT_SYMBOL_GPL(of_genpd_remove_last);
+static void genpd_release_dev(struct device *dev)
+{
+ kfree(dev);
+}
+
+static struct bus_type genpd_bus_type = {
+ .name = "genpd",
+};
+
/**
* genpd_dev_pm_detach - Detach a device from its PM domain.
* @dev: Device to detach.
@@ -2208,6 +2217,10 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off)
/* Check if PM domain can be powered off after removing this device. */
genpd_queue_power_off_work(pd);
+
+ /* Unregister the device if it was created by genpd. */
+ if (dev->bus == &genpd_bus_type)
+ device_unregister(dev);
}
static void genpd_dev_pm_sync(struct device *dev)
@@ -2221,32 +2234,17 @@ static void genpd_dev_pm_sync(struct device *dev)
genpd_queue_power_off_work(pd);
}
-/**
- * genpd_dev_pm_attach - Attach a device to its PM domain using DT.
- * @dev: Device to attach.
- *
- * Parse device's OF node to find a PM domain specifier. If such is found,
- * attaches the device to retrieved pm_domain ops.
- *
- * Returns 1 on successfully attached PM domain, 0 when the device don't need a
- * PM domain or a negative error code in case of failures. Note that if a
- * power-domain exists for the device, but it cannot be found or turned on,
- * then return -EPROBE_DEFER to ensure that the device is not probed and to
- * re-try again later.
- */
-int genpd_dev_pm_attach(struct device *dev)
+static int __genpd_dev_pm_attach(struct device *dev, struct device_node *np,
+ unsigned int index)
{
struct of_phandle_args pd_args;
struct generic_pm_domain *pd;
int ret;
- if (!dev->of_node)
- return 0;
-
- ret = of_parse_phandle_with_args(dev->of_node, "power-domains",
- "#power-domain-cells", 0, &pd_args);
+ ret = of_parse_phandle_with_args(np, "power-domains",
+ "#power-domain-cells", index, &pd_args);
if (ret < 0)
- return 0;
+ return ret;
mutex_lock(&gpd_list_lock);
pd = genpd_get_from_provider(&pd_args);
@@ -2282,8 +2280,98 @@ int genpd_dev_pm_attach(struct device *dev)
return ret ? -EPROBE_DEFER : 1;
}
+
+/**
+ * genpd_dev_pm_attach - Attach a device to its PM domain using DT.
+ * @dev: Device to attach.
+ *
+ * Parse device's OF node to find a PM domain specifier. If such is found,
+ * attaches the device to retrieved pm_domain ops.
+ *
+ * Returns 1 on successfully attached PM domain, 0 when the device don't need a
+ * PM domain or when multiple power-domains exists for it, else a negative error
+ * code. Note that if a power-domain exists for the device, but it cannot be
+ * found or turned on, then return -EPROBE_DEFER to ensure that the device is
+ * not probed and to re-try again later.
+ */
+int genpd_dev_pm_attach(struct device *dev)
+{
+ if (!dev->of_node)
+ return 0;
+
+ /*
+ * Devices with multiple PM domains must be attached separately, as we
+ * can only attach one PM domain per device.
+ */
+ if (of_count_phandle_with_args(dev->of_node, "power-domains",
+ "#power-domain-cells") != 1)
+ return 0;
+
+ return __genpd_dev_pm_attach(dev, dev->of_node, 0);
+}
EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
+/**
+ * genpd_dev_pm_attach_by_id - Associate a device with one of its PM domains.
+ * @dev: The device used to lookup the PM domain.
+ * @index: The index of the PM domain.
+ *
+ * Parse device's OF node to find a PM domain specifier at the provided @index.
+ * If such is found, creates a virtual device and attaches it to the retrieved
+ * pm_domain ops. To deal with detaching of the virtual device, the ->detach()
+ * callback in the struct dev_pm_domain are assigned to genpd_dev_pm_detach().
+ *
+ * Returns the created virtual device if successfully attached PM domain, NULL
+ * when the device don't need a PM domain, else an ERR_PTR() in case of
+ * failures. If a power-domain exists for the device, but cannot be found or
+ * turned on, then ERR_PTR(-EPROBE_DEFER) is returned to ensure that the device
+ * is not probed and to re-try again later.
+ */
+struct device *genpd_dev_pm_attach_by_id(struct device *dev,
+ unsigned int index)
+{
+ struct device *genpd_dev;
+ int num_domains;
+ int ret;
+
+ if (!dev->of_node)
+ return NULL;
+
+ /* Deal only with devices using multiple PM domains. */
+ num_domains = of_count_phandle_with_args(dev->of_node, "power-domains",
+ "#power-domain-cells");
+ if (num_domains < 2 || index >= num_domains)
+ return NULL;
+
+ /* Allocate and register device on the genpd bus. */
+ genpd_dev = kzalloc(sizeof(*genpd_dev), GFP_KERNEL);
+ if (!genpd_dev)
+ return ERR_PTR(-ENOMEM);
+
+ dev_set_name(genpd_dev, "genpd:%u:%s", index, dev_name(dev));
+ genpd_dev->bus = &genpd_bus_type;
+ genpd_dev->release = genpd_release_dev;
+
+ ret = device_register(genpd_dev);
+ if (ret) {
+ kfree(genpd_dev);
+ return ERR_PTR(ret);
+ }
+
+ /* Try to attach the device to the PM domain at the specified index. */
+ ret = __genpd_dev_pm_attach(genpd_dev, dev->of_node, index);
+ if (ret < 1) {
+ device_unregister(genpd_dev);
+ return ret ? ERR_PTR(ret) : NULL;
+ }
+
+ pm_runtime_set_active(genpd_dev);
+ pm_runtime_enable(genpd_dev);
+
+ return genpd_dev;
+}
+EXPORT_SYMBOL_GPL(genpd_dev_pm_attach_by_id);
+
static const struct of_device_id idle_state_match[] = {
{ .compatible = "domain-idle-state", },
{ }
@@ -2443,6 +2531,12 @@ unlock:
}
EXPORT_SYMBOL_GPL(of_genpd_opp_to_performance_state);
+static int __init genpd_bus_init(void)
+{
+ return bus_register(&genpd_bus_type);
+}
+core_initcall(genpd_bus_init);
+
#endif /* CONFIG_PM_GENERIC_DOMAINS_OF */
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index c6030f1..beb85c3 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -1563,16 +1563,37 @@ void pm_runtime_clean_up_links(struct device *dev)
}
/**
- * pm_runtime_resume_suppliers - Resume supplier devices.
+ * pm_runtime_get_suppliers - Resume and reference-count supplier devices.
* @dev: Consumer device.
*/
-void pm_runtime_resume_suppliers(struct device *dev)
+void pm_runtime_get_suppliers(struct device *dev)
{
+ struct device_link *link;
int idx;
idx = device_links_read_lock();
- rpm_get_suppliers(dev);
+ list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
+ if (link->flags & DL_FLAG_PM_RUNTIME)
+ pm_runtime_get_sync(link->supplier);
+
+ device_links_read_unlock(idx);
+}
+
+/**
+ * pm_runtime_put_suppliers - Drop references to supplier devices.
+ * @dev: Consumer device.
+ */
+void pm_runtime_put_suppliers(struct device *dev)
+{
+ struct device_link *link;
+ int idx;
+
+ idx = device_links_read_lock();
+
+ list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
+ if (link->flags & DL_FLAG_PM_RUNTIME)
+ pm_runtime_put(link->supplier);
device_links_read_unlock(idx);
}
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index 0f651ef..d713738 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -353,7 +353,7 @@ static ssize_t wakeup_count_show(struct device *dev,
spin_lock_irq(&dev->power.lock);
if (dev->power.wakeup) {
- count = dev->power.wakeup->event_count;
+ count = dev->power.wakeup->wakeup_count;
enabled = true;
}
spin_unlock_irq(&dev->power.lock);
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index 6ca77d6..f651806 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -5719,8 +5719,8 @@ static bool DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller,
Controller->CombinedStatusBufferLength = NewStatusBufferLength;
return true;
}
- NewStatusBuffer = kmalloc(2 * Controller->CombinedStatusBufferLength,
- GFP_ATOMIC);
+ NewStatusBuffer = kmalloc_array(2, Controller->CombinedStatusBufferLength,
+ GFP_ATOMIC);
if (NewStatusBuffer == NULL)
{
DAC960_Warning("Unable to expand Combined Status Buffer - Truncating\n",
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 7655d61..a80809b 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -511,7 +511,8 @@ static void drbd_calc_cpu_mask(cpumask_var_t *cpu_mask)
{
unsigned int *resources_per_cpu, min_index = ~0;
- resources_per_cpu = kzalloc(nr_cpu_ids * sizeof(*resources_per_cpu), GFP_KERNEL);
+ resources_per_cpu = kcalloc(nr_cpu_ids, sizeof(*resources_per_cpu),
+ GFP_KERNEL);
if (resources_per_cpu) {
struct drbd_resource *resource;
unsigned int cpu, min = ~0;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 21e6d1b..d6b6f43 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -524,7 +524,8 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
__rq_for_each_bio(bio, rq)
segments += bio_segments(bio);
- bvec = kmalloc(sizeof(struct bio_vec) * segments, GFP_NOIO);
+ bvec = kmalloc_array(segments, sizeof(struct bio_vec),
+ GFP_NOIO);
if (!bvec)
return -EIO;
cmd->bvec = bvec;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 3b7083b..74a0556 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -76,6 +76,7 @@ struct link_dead_args {
#define NBD_HAS_CONFIG_REF 4
#define NBD_BOUND 5
#define NBD_DESTROY_ON_DISCONNECT 6
+#define NBD_DISCONNECT_ON_CLOSE 7
struct nbd_config {
u32 flags;
@@ -138,6 +139,7 @@ static void nbd_config_put(struct nbd_device *nbd);
static void nbd_connect_reply(struct genl_info *info, int index);
static int nbd_genl_status(struct sk_buff *skb, struct genl_info *info);
static void nbd_dead_link_work(struct work_struct *work);
+static void nbd_disconnect_and_put(struct nbd_device *nbd);
static inline struct device *nbd_to_dev(struct nbd_device *nbd)
{
@@ -1305,6 +1307,12 @@ out:
static void nbd_release(struct gendisk *disk, fmode_t mode)
{
struct nbd_device *nbd = disk->private_data;
+ struct block_device *bdev = bdget_disk(disk, 0);
+
+ if (test_bit(NBD_DISCONNECT_ON_CLOSE, &nbd->config->runtime_flags) &&
+ bdev->bd_openers == 0)
+ nbd_disconnect_and_put(nbd);
+
nbd_config_put(nbd);
nbd_put(nbd);
}
@@ -1705,6 +1713,10 @@ again:
&config->runtime_flags);
put_dev = true;
}
+ if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) {
+ set_bit(NBD_DISCONNECT_ON_CLOSE,
+ &config->runtime_flags);
+ }
}
if (info->attrs[NBD_ATTR_SOCKETS]) {
@@ -1749,6 +1761,17 @@ out:
return ret;
}
+static void nbd_disconnect_and_put(struct nbd_device *nbd)
+{
+ mutex_lock(&nbd->config_lock);
+ nbd_disconnect(nbd);
+ nbd_clear_sock(nbd);
+ mutex_unlock(&nbd->config_lock);
+ if (test_and_clear_bit(NBD_HAS_CONFIG_REF,
+ &nbd->config->runtime_flags))
+ nbd_config_put(nbd);
+}
+
static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
{
struct nbd_device *nbd;
@@ -1781,13 +1804,7 @@ static int nbd_genl_disconnect(struct sk_buff *skb, struct genl_info *info)
nbd_put(nbd);
return 0;
}
- mutex_lock(&nbd->config_lock);
- nbd_disconnect(nbd);
- nbd_clear_sock(nbd);
- mutex_unlock(&nbd->config_lock);
- if (test_and_clear_bit(NBD_HAS_CONFIG_REF,
- &nbd->config->runtime_flags))
- nbd_config_put(nbd);
+ nbd_disconnect_and_put(nbd);
nbd_config_put(nbd);
nbd_put(nbd);
return 0;
@@ -1798,7 +1815,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
struct nbd_device *nbd = NULL;
struct nbd_config *config;
int index;
- int ret = -EINVAL;
+ int ret = 0;
bool put_dev = false;
if (!netlink_capable(skb, CAP_SYS_ADMIN))
@@ -1838,6 +1855,7 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
!nbd->task_recv) {
dev_err(nbd_to_dev(nbd),
"not configured, cannot reconfigure\n");
+ ret = -EINVAL;
goto out;
}
@@ -1862,6 +1880,14 @@ static int nbd_genl_reconfigure(struct sk_buff *skb, struct genl_info *info)
&config->runtime_flags))
refcount_inc(&nbd->refs);
}
+
+ if (flags & NBD_CFLAG_DISCONNECT_ON_CLOSE) {
+ set_bit(NBD_DISCONNECT_ON_CLOSE,
+ &config->runtime_flags);
+ } else {
+ clear_bit(NBD_DISCONNECT_ON_CLOSE,
+ &config->runtime_flags);
+ }
}
if (info->attrs[NBD_ATTR_SOCKETS]) {
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c
index 2bdadd7..042c778 100644
--- a/drivers/block/null_blk.c
+++ b/drivers/block/null_blk.c
@@ -1365,7 +1365,7 @@ static blk_qc_t null_queue_bio(struct request_queue *q, struct bio *bio)
static enum blk_eh_timer_return null_rq_timed_out_fn(struct request *rq)
{
pr_info("null: rq %p timed out\n", rq);
- blk_mq_complete_request(rq);
+ __blk_complete_request(rq);
return BLK_EH_DONE;
}
@@ -1575,12 +1575,12 @@ static int setup_commands(struct nullb_queue *nq)
struct nullb_cmd *cmd;
int i, tag_size;
- nq->cmds = kzalloc(nq->queue_depth * sizeof(*cmd), GFP_KERNEL);
+ nq->cmds = kcalloc(nq->queue_depth, sizeof(*cmd), GFP_KERNEL);
if (!nq->cmds)
return -ENOMEM;
tag_size = ALIGN(nq->queue_depth, BITS_PER_LONG) / BITS_PER_LONG;
- nq->tag_map = kzalloc(tag_size * sizeof(unsigned long), GFP_KERNEL);
+ nq->tag_map = kcalloc(tag_size, sizeof(unsigned long), GFP_KERNEL);
if (!nq->tag_map) {
kfree(nq->cmds);
return -ENOMEM;
@@ -1598,8 +1598,9 @@ static int setup_commands(struct nullb_queue *nq)
static int setup_queues(struct nullb *nullb)
{
- nullb->queues = kzalloc(nullb->dev->submit_queues *
- sizeof(struct nullb_queue), GFP_KERNEL);
+ nullb->queues = kcalloc(nullb->dev->submit_queues,
+ sizeof(struct nullb_queue),
+ GFP_KERNEL);
if (!nullb->queues)
return -ENOMEM;
diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
index 8fa4533..1e3d5de 100644
--- a/drivers/block/ps3vram.c
+++ b/drivers/block/ps3vram.c
@@ -407,8 +407,9 @@ static int ps3vram_cache_init(struct ps3_system_bus_device *dev)
priv->cache.page_count = CACHE_PAGE_COUNT;
priv->cache.page_size = CACHE_PAGE_SIZE;
- priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) *
- CACHE_PAGE_COUNT, GFP_KERNEL);
+ priv->cache.tags = kcalloc(CACHE_PAGE_COUNT,
+ sizeof(struct ps3vram_tag),
+ GFP_KERNEL);
if (!priv->cache.tags)
return -ENOMEM;
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index af35404..fa0729c 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -2339,6 +2339,7 @@ static bool is_zero_bvecs(struct bio_vec *bvecs, u32 bytes)
static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
{
unsigned int num_osd_ops = obj_req->osd_req->r_num_ops;
+ int ret;
dout("%s obj_req %p bytes %u\n", __func__, obj_req, bytes);
rbd_assert(obj_req->osd_req->r_ops[0].op == CEPH_OSD_OP_STAT);
@@ -2353,6 +2354,11 @@ static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
if (!obj_req->osd_req)
return -ENOMEM;
+ ret = osd_req_op_cls_init(obj_req->osd_req, 0, CEPH_OSD_OP_CALL, "rbd",
+ "copyup");
+ if (ret)
+ return ret;
+
/*
* Only send non-zero copyup data to save some I/O and network
* bandwidth -- zero copyup data is equivalent to the object not
@@ -2362,9 +2368,6 @@ static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
dout("%s obj_req %p detected zeroes\n", __func__, obj_req);
bytes = 0;
}
-
- osd_req_op_cls_init(obj_req->osd_req, 0, CEPH_OSD_OP_CALL, "rbd",
- "copyup");
osd_req_op_cls_request_data_bvecs(obj_req->osd_req, 0,
obj_req->copyup_bvecs,
obj_req->copyup_bvec_count,
@@ -3397,7 +3400,6 @@ static void cancel_tasks_sync(struct rbd_device *rbd_dev)
{
dout("%s rbd_dev %p\n", __func__, rbd_dev);
- cancel_delayed_work_sync(&rbd_dev->watch_dwork);
cancel_work_sync(&rbd_dev->acquired_lock_work);
cancel_work_sync(&rbd_dev->released_lock_work);
cancel_delayed_work_sync(&rbd_dev->lock_dwork);
@@ -3415,6 +3417,7 @@ static void rbd_unregister_watch(struct rbd_device *rbd_dev)
rbd_dev->watch_state = RBD_WATCH_STATE_UNREGISTERED;
mutex_unlock(&rbd_dev->watch_mutex);
+ cancel_delayed_work_sync(&rbd_dev->watch_dwork);
ceph_osdc_flush_notifies(&rbd_dev->rbd_client->client->osdc);
}
diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c
index 09537be..b7d7191 100644
--- a/drivers/block/rsxx/core.c
+++ b/drivers/block/rsxx/core.c
@@ -873,7 +873,8 @@ static int rsxx_pci_probe(struct pci_dev *dev,
dev_info(CARD_TO_DEV(card),
"Failed reading the number of DMA targets\n");
- card->ctrl = kzalloc(card->n_targets * sizeof(*card->ctrl), GFP_KERNEL);
+ card->ctrl = kcalloc(card->n_targets, sizeof(*card->ctrl),
+ GFP_KERNEL);
if (!card->ctrl) {
st = -ENOMEM;
goto failed_dma_setup;
diff --git a/drivers/block/rsxx/dma.c b/drivers/block/rsxx/dma.c
index beaccf1..8fbc1bf 100644
--- a/drivers/block/rsxx/dma.c
+++ b/drivers/block/rsxx/dma.c
@@ -1038,7 +1038,7 @@ int rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card)
struct rsxx_dma *dma;
struct list_head *issued_dmas;
- issued_dmas = kzalloc(sizeof(*issued_dmas) * card->n_targets,
+ issued_dmas = kcalloc(card->n_targets, sizeof(*issued_dmas),
GFP_KERNEL);
if (!issued_dmas)
return -ENOMEM;
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 66412eed..a4bc74e 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -139,7 +139,8 @@ static int xen_blkif_alloc_rings(struct xen_blkif *blkif)
{
unsigned int r;
- blkif->rings = kzalloc(blkif->nr_rings * sizeof(struct xen_blkif_ring), GFP_KERNEL);
+ blkif->rings = kcalloc(blkif->nr_rings, sizeof(struct xen_blkif_ring),
+ GFP_KERNEL);
if (!blkif->rings)
return -ENOMEM;
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index ae00a82..b5cedcc 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -1906,7 +1906,9 @@ static int negotiate_mq(struct blkfront_info *info)
if (!info->nr_rings)
info->nr_rings = 1;
- info->rinfo = kzalloc(sizeof(struct blkfront_ring_info) * info->nr_rings, GFP_KERNEL);
+ info->rinfo = kcalloc(info->nr_rings,
+ sizeof(struct blkfront_ring_info),
+ GFP_KERNEL);
if (!info->rinfo) {
xenbus_dev_fatal(info->xbdev, -ENOMEM, "allocating ring_info structure");
return -ENOMEM;
@@ -2216,15 +2218,18 @@ static int blkfront_setup_indirect(struct blkfront_ring_info *rinfo)
}
for (i = 0; i < BLK_RING_SIZE(info); i++) {
- rinfo->shadow[i].grants_used = kzalloc(
- sizeof(rinfo->shadow[i].grants_used[0]) * grants,
- GFP_NOIO);
- rinfo->shadow[i].sg = kzalloc(sizeof(rinfo->shadow[i].sg[0]) * psegs, GFP_NOIO);
- if (info->max_indirect_segments)
- rinfo->shadow[i].indirect_grants = kzalloc(
- sizeof(rinfo->shadow[i].indirect_grants[0]) *
- INDIRECT_GREFS(grants),
+ rinfo->shadow[i].grants_used =
+ kcalloc(grants,
+ sizeof(rinfo->shadow[i].grants_used[0]),
GFP_NOIO);
+ rinfo->shadow[i].sg = kcalloc(psegs,
+ sizeof(rinfo->shadow[i].sg[0]),
+ GFP_NOIO);
+ if (info->max_indirect_segments)
+ rinfo->shadow[i].indirect_grants =
+ kcalloc(INDIRECT_GREFS(grants),
+ sizeof(rinfo->shadow[i].indirect_grants[0]),
+ GFP_NOIO);
if ((rinfo->shadow[i].grants_used == NULL) ||
(rinfo->shadow[i].sg == NULL) ||
(info->max_indirect_segments &&
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 8f9130a..d0c5bc4 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -197,8 +197,9 @@ static int z2_open(struct block_device *bdev, fmode_t mode)
vaddr = (unsigned long)z_remap_nocache_nonser(paddr, size);
#endif
z2ram_map =
- kmalloc((size/Z2RAM_CHUNKSIZE)*sizeof(z2ram_map[0]),
- GFP_KERNEL);
+ kmalloc_array(size / Z2RAM_CHUNKSIZE,
+ sizeof(z2ram_map[0]),
+ GFP_KERNEL);
if ( z2ram_map == NULL )
{
printk( KERN_ERR DEVICE_NAME
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index da51293..7436b2d 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -898,7 +898,7 @@ static bool zram_meta_alloc(struct zram *zram, u64 disksize)
size_t num_pages;
num_pages = disksize >> PAGE_SHIFT;
- zram->table = vzalloc(num_pages * sizeof(*zram->table));
+ zram->table = vzalloc(array_size(num_pages, sizeof(*zram->table)));
if (!zram->table)
return false;
diff --git a/drivers/bluetooth/hci_nokia.c b/drivers/bluetooth/hci_nokia.c
index 14d159e..2dc33e6 100644
--- a/drivers/bluetooth/hci_nokia.c
+++ b/drivers/bluetooth/hci_nokia.c
@@ -29,7 +29,7 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
-#include <linux/unaligned/le_struct.h>
+#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index 6dc177b..d1c0b60 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -33,7 +33,6 @@ config HISILICON_LPC
bool "Support for ISA I/O space on HiSilicon Hip06/7"
depends on ARM64 && (ARCH_HISI || COMPILE_TEST)
select INDIRECT_PIO
- select MFD_CORE if ACPI
help
Driver to enable I/O access to devices attached to the Low Pin
Count bus on the HiSilicon Hip06/7 SoC.
diff --git a/drivers/bus/arm-cci.c b/drivers/bus/arm-cci.c
index 443e4c3..b8184a9 100644
--- a/drivers/bus/arm-cci.c
+++ b/drivers/bus/arm-cci.c
@@ -371,8 +371,6 @@ asmlinkage void __naked cci_enable_port_for_self(void)
[sizeof_struct_cpu_port] "i" (sizeof(struct cpu_port)),
[sizeof_struct_ace_port] "i" (sizeof(struct cci_ace_port)),
[offsetof_port_phys] "i" (offsetof(struct cci_ace_port, phys)) );
-
- unreachable();
}
/**
diff --git a/drivers/bus/fsl-mc/fsl-mc-allocator.c b/drivers/bus/fsl-mc/fsl-mc-allocator.c
index fb1442b..e906ecfe 100644
--- a/drivers/bus/fsl-mc/fsl-mc-allocator.c
+++ b/drivers/bus/fsl-mc/fsl-mc-allocator.c
@@ -354,8 +354,8 @@ int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
if (error < 0)
return error;
- irq_resources = devm_kzalloc(&mc_bus_dev->dev,
- sizeof(*irq_resources) * irq_count,
+ irq_resources = devm_kcalloc(&mc_bus_dev->dev,
+ irq_count, sizeof(*irq_resources),
GFP_KERNEL);
if (!irq_resources) {
error = -ENOMEM;
@@ -455,7 +455,7 @@ int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
return -ENOSPC;
}
- irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
+ irqs = devm_kcalloc(&mc_dev->dev, irq_count, sizeof(irqs[0]),
GFP_KERNEL);
if (!irqs)
return -ENOMEM;
diff --git a/drivers/bus/hisi_lpc.c b/drivers/bus/hisi_lpc.c
index 2d4611e..d5f8545 100644
--- a/drivers/bus/hisi_lpc.c
+++ b/drivers/bus/hisi_lpc.c
@@ -11,12 +11,12 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/logic_pio.h>
-#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
+#include <linux/serial_8250.h>
#include <linux/slab.h>
#define DRV_NAME "hisi-lpc"
@@ -341,15 +341,6 @@ static const struct logic_pio_host_ops hisi_lpc_ops = {
};
#ifdef CONFIG_ACPI
-#define MFD_CHILD_NAME_PREFIX DRV_NAME"-"
-#define MFD_CHILD_NAME_LEN (ACPI_ID_LEN + sizeof(MFD_CHILD_NAME_PREFIX) - 1)
-
-struct hisi_lpc_mfd_cell {
- struct mfd_cell_acpi_match acpi_match;
- char name[MFD_CHILD_NAME_LEN];
- char pnpid[ACPI_ID_LEN];
-};
-
static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev,
struct acpi_device *host,
struct resource *res)
@@ -368,7 +359,7 @@ static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev,
}
/*
- * hisi_lpc_acpi_set_io_res - set the resources for a child's MFD
+ * hisi_lpc_acpi_set_io_res - set the resources for a child
* @child: the device node to be updated the I/O resource
* @hostdev: the device node associated with host controller
* @res: double pointer to be set to the address of translated resources
@@ -452,78 +443,122 @@ static int hisi_lpc_acpi_set_io_res(struct device *child,
return 0;
}
+static int hisi_lpc_acpi_remove_subdev(struct device *dev, void *unused)
+{
+ platform_device_unregister(to_platform_device(dev));
+ return 0;
+}
+
+struct hisi_lpc_acpi_cell {
+ const char *hid;
+ const char *name;
+ void *pdata;
+ size_t pdata_size;
+};
+
/*
* hisi_lpc_acpi_probe - probe children for ACPI FW
* @hostdev: LPC host device pointer
*
* Returns 0 when successful, and a negative value for failure.
*
- * Scan all child devices and create a per-device MFD with
- * logical PIO translated IO resources.
+ * Create a platform device per child, fixing up the resources
+ * from bus addresses to Logical PIO addresses.
+ *
*/
static int hisi_lpc_acpi_probe(struct device *hostdev)
{
struct acpi_device *adev = ACPI_COMPANION(hostdev);
- struct hisi_lpc_mfd_cell *hisi_lpc_mfd_cells;
- struct mfd_cell *mfd_cells;
struct acpi_device *child;
- int size, ret, count = 0, cell_num = 0;
-
- list_for_each_entry(child, &adev->children, node)
- cell_num++;
-
- /* allocate the mfd cell and companion ACPI info, one per child */
- size = sizeof(*mfd_cells) + sizeof(*hisi_lpc_mfd_cells);
- mfd_cells = devm_kcalloc(hostdev, cell_num, size, GFP_KERNEL);
- if (!mfd_cells)
- return -ENOMEM;
+ int ret;
- hisi_lpc_mfd_cells = (struct hisi_lpc_mfd_cell *)&mfd_cells[cell_num];
/* Only consider the children of the host */
list_for_each_entry(child, &adev->children, node) {
- struct mfd_cell *mfd_cell = &mfd_cells[count];
- struct hisi_lpc_mfd_cell *hisi_lpc_mfd_cell =
- &hisi_lpc_mfd_cells[count];
- struct mfd_cell_acpi_match *acpi_match =
- &hisi_lpc_mfd_cell->acpi_match;
- char *name = hisi_lpc_mfd_cell[count].name;
- char *pnpid = hisi_lpc_mfd_cell[count].pnpid;
- struct mfd_cell_acpi_match match = {
- .pnpid = pnpid,
+ const char *hid = acpi_device_hid(child);
+ const struct hisi_lpc_acpi_cell *cell;
+ struct platform_device *pdev;
+ const struct resource *res;
+ bool found = false;
+ int num_res;
+
+ ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev, &res,
+ &num_res);
+ if (ret) {
+ dev_warn(hostdev, "set resource fail (%d)\n", ret);
+ goto fail;
+ }
+
+ cell = (struct hisi_lpc_acpi_cell []){
+ /* ipmi */
+ {
+ .hid = "IPI0001",
+ .name = "hisi-lpc-ipmi",
+ },
+ /* 8250-compatible uart */
+ {
+ .hid = "HISI1031",
+ .name = "serial8250",
+ .pdata = (struct plat_serial8250_port []) {
+ {
+ .iobase = res->start,
+ .uartclk = 1843200,
+ .iotype = UPIO_PORT,
+ .flags = UPF_BOOT_AUTOCONF,
+ },
+ {}
+ },
+ .pdata_size = 2 *
+ sizeof(struct plat_serial8250_port),
+ },
+ {}
};
- /*
- * For any instances of this host controller (Hip06 and Hip07
- * are the only chipsets), we would not have multiple slaves
- * with the same HID. And in any system we would have just one
- * controller active. So don't worrry about MFD name clashes.
- */
- snprintf(name, MFD_CHILD_NAME_LEN, MFD_CHILD_NAME_PREFIX"%s",
- acpi_device_hid(child));
- snprintf(pnpid, ACPI_ID_LEN, "%s", acpi_device_hid(child));
-
- memcpy(acpi_match, &match, sizeof(*acpi_match));
- mfd_cell->name = name;
- mfd_cell->acpi_match = acpi_match;
-
- ret = hisi_lpc_acpi_set_io_res(&child->dev, &adev->dev,
- &mfd_cell->resources,
- &mfd_cell->num_resources);
- if (ret) {
- dev_warn(&child->dev, "set resource fail (%d)\n", ret);
- return ret;
+ for (; cell && cell->name; cell++) {
+ if (!strcmp(cell->hid, hid)) {
+ found = true;
+ break;
+ }
}
- count++;
- }
- ret = mfd_add_devices(hostdev, PLATFORM_DEVID_NONE,
- mfd_cells, cell_num, NULL, 0, NULL);
- if (ret) {
- dev_err(hostdev, "failed to add mfd cells (%d)\n", ret);
- return ret;
+ if (!found) {
+ dev_warn(hostdev,
+ "could not find cell for child device (%s)\n",
+ hid);
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO);
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ pdev->dev.parent = hostdev;
+ ACPI_COMPANION_SET(&pdev->dev, child);
+
+ ret = platform_device_add_resources(pdev, res, num_res);
+ if (ret)
+ goto fail;
+
+ ret = platform_device_add_data(pdev, cell->pdata,
+ cell->pdata_size);
+ if (ret)
+ goto fail;
+
+ ret = platform_device_add(pdev);
+ if (ret)
+ goto fail;
+
+ acpi_device_set_enumerated(child);
}
return 0;
+
+fail:
+ device_for_each_child(hostdev, NULL,
+ hisi_lpc_acpi_remove_subdev);
+ return ret;
}
static const struct acpi_device_id hisi_lpc_acpi_match[] = {
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 7cd2fd0..1cc2962 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
+#include <linux/reset.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
@@ -32,10 +33,18 @@ static const char * const reg_names[] = { "rev", "sysc", "syss", };
enum sysc_clocks {
SYSC_FCK,
SYSC_ICK,
+ SYSC_OPTFCK0,
+ SYSC_OPTFCK1,
+ SYSC_OPTFCK2,
+ SYSC_OPTFCK3,
+ SYSC_OPTFCK4,
+ SYSC_OPTFCK5,
+ SYSC_OPTFCK6,
+ SYSC_OPTFCK7,
SYSC_MAX_CLOCKS,
};
-static const char * const clock_names[] = { "fck", "ick", };
+static const char * const clock_names[SYSC_ICK + 1] = { "fck", "ick", };
#define SYSC_IDLEMODE_MASK 3
#define SYSC_CLOCKACTIVITY_MASK 3
@@ -48,6 +57,8 @@ static const char * const clock_names[] = { "fck", "ick", };
* @module_va: virtual address of the interconnect target module
* @offsets: register offsets from module base
* @clocks: clocks used by the interconnect target module
+ * @clock_roles: clock role names for the found clocks
+ * @nr_clocks: number of clocks used by the interconnect target module
* @legacy_mode: configured for legacy mode if set
* @cap: interconnect target module capabilities
* @cfg: interconnect target module configuration
@@ -61,7 +72,10 @@ struct sysc {
u32 module_size;
void __iomem *module_va;
int offsets[SYSC_MAX_REGS];
- struct clk *clocks[SYSC_MAX_CLOCKS];
+ struct clk **clocks;
+ const char **clock_roles;
+ int nr_clocks;
+ struct reset_control *rsts;
const char *legacy_mode;
const struct sysc_capabilities *cap;
struct sysc_config cfg;
@@ -88,6 +102,11 @@ static u32 sysc_read(struct sysc *ddata, int offset)
return readl_relaxed(ddata->module_va + offset);
}
+static bool sysc_opt_clks_needed(struct sysc *ddata)
+{
+ return !!(ddata->cfg.quirks & SYSC_QUIRK_OPT_CLKS_NEEDED);
+}
+
static u32 sysc_read_revision(struct sysc *ddata)
{
int offset = ddata->offsets[SYSC_REVISION];
@@ -98,21 +117,28 @@ static u32 sysc_read_revision(struct sysc *ddata)
return sysc_read(ddata, offset);
}
-static int sysc_get_one_clock(struct sysc *ddata,
- enum sysc_clocks index)
+static int sysc_get_one_clock(struct sysc *ddata, const char *name)
{
- const char *name;
- int error;
+ int error, i, index = -ENODEV;
+
+ if (!strncmp(clock_names[SYSC_FCK], name, 3))
+ index = SYSC_FCK;
+ else if (!strncmp(clock_names[SYSC_ICK], name, 3))
+ index = SYSC_ICK;
+
+ if (index < 0) {
+ for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
+ if (!ddata->clocks[i]) {
+ index = i;
+ break;
+ }
+ }
+ }
- switch (index) {
- case SYSC_FCK:
- break;
- case SYSC_ICK:
- break;
- default:
- return -EINVAL;
+ if (index < 0) {
+ dev_err(ddata->dev, "clock %s not added\n", name);
+ return index;
}
- name = clock_names[index];
ddata->clocks[index] = devm_clk_get(ddata->dev, name);
if (IS_ERR(ddata->clocks[index])) {
@@ -138,10 +164,50 @@ static int sysc_get_one_clock(struct sysc *ddata,
static int sysc_get_clocks(struct sysc *ddata)
{
- int i, error;
+ struct device_node *np = ddata->dev->of_node;
+ struct property *prop;
+ const char *name;
+ int nr_fck = 0, nr_ick = 0, i, error = 0;
- for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
- error = sysc_get_one_clock(ddata, i);
+ ddata->clock_roles = devm_kzalloc(ddata->dev,
+ sizeof(*ddata->clock_roles) *
+ SYSC_MAX_CLOCKS,
+ GFP_KERNEL);
+ if (!ddata->clock_roles)
+ return -ENOMEM;
+
+ of_property_for_each_string(np, "clock-names", prop, name) {
+ if (!strncmp(clock_names[SYSC_FCK], name, 3))
+ nr_fck++;
+ if (!strncmp(clock_names[SYSC_ICK], name, 3))
+ nr_ick++;
+ ddata->clock_roles[ddata->nr_clocks] = name;
+ ddata->nr_clocks++;
+ }
+
+ if (ddata->nr_clocks < 1)
+ return 0;
+
+ if (ddata->nr_clocks > SYSC_MAX_CLOCKS) {
+ dev_err(ddata->dev, "too many clocks for %pOF\n", np);
+
+ return -EINVAL;
+ }
+
+ if (nr_fck > 1 || nr_ick > 1) {
+ dev_err(ddata->dev, "max one fck and ick for %pOF\n", np);
+
+ return -EINVAL;
+ }
+
+ ddata->clocks = devm_kzalloc(ddata->dev,
+ sizeof(*ddata->clocks) * ddata->nr_clocks,
+ GFP_KERNEL);
+ if (!ddata->clocks)
+ return -ENOMEM;
+
+ for (i = 0; i < ddata->nr_clocks; i++) {
+ error = sysc_get_one_clock(ddata, ddata->clock_roles[i]);
if (error && error != -ENOENT)
return error;
}
@@ -150,6 +216,42 @@ static int sysc_get_clocks(struct sysc *ddata)
}
/**
+ * sysc_init_resets - reset module on init
+ * @ddata: device driver data
+ *
+ * A module can have both OCP softreset control and external rstctrl.
+ * If more complicated rstctrl resets are needed, please handle these
+ * directly from the child device driver and map only the module reset
+ * for the parent interconnect target module device.
+ *
+ * Automatic reset of the module on init can be skipped with the
+ * "ti,no-reset-on-init" device tree property.
+ */
+static int sysc_init_resets(struct sysc *ddata)
+{
+ int error;
+
+ ddata->rsts =
+ devm_reset_control_array_get_optional_exclusive(ddata->dev);
+ if (IS_ERR(ddata->rsts))
+ return PTR_ERR(ddata->rsts);
+
+ if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
+ goto deassert;
+
+ error = reset_control_assert(ddata->rsts);
+ if (error)
+ return error;
+
+deassert:
+ error = reset_control_deassert(ddata->rsts);
+ if (error)
+ return error;
+
+ return 0;
+}
+
+/**
* sysc_parse_and_check_child_range - parses module IO region from ranges
* @ddata: device driver data
*
@@ -533,9 +635,13 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev)
goto idled;
}
- for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
+ for (i = 0; i < ddata->nr_clocks; i++) {
if (IS_ERR_OR_NULL(ddata->clocks[i]))
continue;
+
+ if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
+ break;
+
clk_disable(ddata->clocks[i]);
}
@@ -572,9 +678,13 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev)
goto awake;
}
- for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
+ for (i = 0; i < ddata->nr_clocks; i++) {
if (IS_ERR_OR_NULL(ddata->clocks[i]))
continue;
+
+ if (i >= SYSC_OPTFCK0 && !sysc_opt_clks_needed(ddata))
+ break;
+
error = clk_enable(ddata->clocks[i]);
if (error)
return error;
@@ -590,23 +700,103 @@ awake:
static int sysc_suspend(struct device *dev)
{
struct sysc *ddata;
+ int error;
ddata = dev_get_drvdata(dev);
+ if (ddata->cfg.quirks & (SYSC_QUIRK_RESOURCE_PROVIDER |
+ SYSC_QUIRK_LEGACY_IDLE))
+ return 0;
+
if (!ddata->enabled)
return 0;
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
+ error = pm_runtime_put_sync_suspend(dev);
+ if (error < 0) {
+ dev_warn(ddata->dev, "%s not idle %i %s\n",
+ __func__, error,
+ ddata->name ? ddata->name : "");
+
+ return 0;
+ }
+
ddata->needs_resume = true;
- return sysc_runtime_suspend(dev);
+ return 0;
}
static int sysc_resume(struct device *dev)
{
struct sysc *ddata;
+ int error;
+
+ ddata = dev_get_drvdata(dev);
+
+ if (ddata->cfg.quirks & (SYSC_QUIRK_RESOURCE_PROVIDER |
+ SYSC_QUIRK_LEGACY_IDLE))
+ return 0;
+
+ if (ddata->needs_resume) {
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
+ error = pm_runtime_get_sync(dev);
+ if (error < 0) {
+ dev_err(ddata->dev, "%s error %i %s\n",
+ __func__, error,
+ ddata->name ? ddata->name : "");
+
+ return error;
+ }
+
+ ddata->needs_resume = false;
+ }
+
+ return 0;
+}
+
+static int sysc_noirq_suspend(struct device *dev)
+{
+ struct sysc *ddata;
ddata = dev_get_drvdata(dev);
+
+ if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
+ return 0;
+
+ if (!(ddata->cfg.quirks & SYSC_QUIRK_RESOURCE_PROVIDER))
+ return 0;
+
+ if (!ddata->enabled)
+ return 0;
+
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
+ ddata->needs_resume = true;
+
+ return sysc_runtime_suspend(dev);
+}
+
+static int sysc_noirq_resume(struct device *dev)
+{
+ struct sysc *ddata;
+
+ ddata = dev_get_drvdata(dev);
+
+ if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE)
+ return 0;
+
+ if (!(ddata->cfg.quirks & SYSC_QUIRK_RESOURCE_PROVIDER))
+ return 0;
+
if (ddata->needs_resume) {
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
ddata->needs_resume = false;
return sysc_runtime_resume(dev);
@@ -618,6 +808,7 @@ static int sysc_resume(struct device *dev)
static const struct dev_pm_ops sysc_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(sysc_suspend, sysc_resume)
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sysc_noirq_suspend, sysc_noirq_resume)
SET_RUNTIME_PM_OPS(sysc_runtime_suspend,
sysc_runtime_resume,
NULL)
@@ -649,9 +840,29 @@ struct sysc_revision_quirk {
}
static const struct sysc_revision_quirk sysc_revision_quirks[] = {
+ /* These need to use noirq_suspend */
+ SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+ SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff,
+ SYSC_QUIRK_RESOURCE_PROVIDER),
+
/* These drivers need to be fixed to not use pm_runtime_irq_safe() */
SYSC_QUIRK("gpio", 0, 0, 0x10, 0x114, 0x50600801, 0xffffffff,
- SYSC_QUIRK_LEGACY_IDLE),
+ SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET),
SYSC_QUIRK("mmu", 0, 0, 0x10, 0x14, 0x00000020, 0xffffffff,
SYSC_QUIRK_LEGACY_IDLE),
SYSC_QUIRK("mmu", 0, 0, 0x10, 0x14, 0x00000030, 0xffffffff,
@@ -664,8 +875,40 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_QUIRK_LEGACY_IDLE),
SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff,
SYSC_QUIRK_LEGACY_IDLE),
+ /* Some timers on omap4 and later */
+ SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffffffff,
+ SYSC_QUIRK_LEGACY_IDLE),
SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
SYSC_QUIRK_LEGACY_IDLE),
+ /* Uarts on omap4 and later */
+ SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffffffff,
+ SYSC_QUIRK_LEGACY_IDLE),
+
+ /* These devices don't yet suspend properly without legacy setting */
+ SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffffffff,
+ SYSC_QUIRK_LEGACY_IDLE),
+ SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xffffffff,
+ SYSC_QUIRK_LEGACY_IDLE),
+ SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0d00, 0xffffffff,
+ SYSC_QUIRK_LEGACY_IDLE),
+
+#ifdef DEBUG
+ SYSC_QUIRK("aess", 0, 0, 0x10, -1, 0x40000000, 0xffffffff, 0),
+ SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0),
+ SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, 0),
+ SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0),
+ SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0),
+ SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0),
+ SYSC_QUIRK("mcbsp", 0, -1, 0x8c, -1, 0, 0, 0),
+ SYSC_QUIRK("mailbox", 0, 0, 0x10, -1, 0x00000400, 0xffffffff, 0),
+ SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40000902, 0xffffffff, 0),
+ SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40002903, 0xffffffff, 0),
+ SYSC_QUIRK("spinlock", 0, 0, 0x10, -1, 0x50020000, 0xffffffff, 0),
+ SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0),
+ SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0),
+ SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
+ 0xffffffff, 0),
+#endif
};
static void sysc_init_revision_quirks(struct sysc *ddata)
@@ -716,6 +959,7 @@ static int sysc_init_module(struct sysc *ddata)
return 0;
}
+
ddata->revision = sysc_read_revision(ddata);
pm_runtime_put_sync(ddata->dev);
@@ -811,29 +1055,58 @@ static int sysc_init_syss_mask(struct sysc *ddata)
}
/*
- * Many child device drivers need to have fck available to get the clock
- * rate for device internal configuration.
+ * Many child device drivers need to have fck and opt clocks available
+ * to get the clock rate for device internal configuration etc.
*/
-static int sysc_child_add_fck(struct sysc *ddata,
- struct device *child)
+static int sysc_child_add_named_clock(struct sysc *ddata,
+ struct device *child,
+ const char *name)
{
- struct clk *fck;
+ struct clk *clk;
struct clk_lookup *l;
- const char *name = clock_names[SYSC_FCK];
+ int error = 0;
- if (IS_ERR_OR_NULL(ddata->clocks[SYSC_FCK]))
+ if (!name)
return 0;
- fck = clk_get(child, name);
- if (!IS_ERR(fck)) {
- clk_put(fck);
+ clk = clk_get(child, name);
+ if (!IS_ERR(clk)) {
+ clk_put(clk);
return -EEXIST;
}
- l = clkdev_create(ddata->clocks[SYSC_FCK], name, dev_name(child));
+ clk = clk_get(ddata->dev, name);
+ if (IS_ERR(clk))
+ return -ENODEV;
+
+ l = clkdev_create(clk, name, dev_name(child));
+ if (!l)
+ error = -ENOMEM;
+
+ clk_put(clk);
+
+ return error;
+}
+
+static int sysc_child_add_clocks(struct sysc *ddata,
+ struct device *child)
+{
+ int i, error;
+
+ for (i = 0; i < ddata->nr_clocks; i++) {
+ error = sysc_child_add_named_clock(ddata,
+ child,
+ ddata->clock_roles[i]);
+ if (error && error != -EEXIST) {
+ dev_err(ddata->dev, "could not add child clock %s: %i\n",
+ ddata->clock_roles[i], error);
+
+ return error;
+ }
+ }
- return l ? 0 : -ENODEV;
+ return 0;
}
static struct device_type sysc_device_type = {
@@ -891,18 +1164,33 @@ static int sysc_child_suspend_noirq(struct device *dev)
ddata = sysc_child_to_parent(dev);
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
error = pm_generic_suspend_noirq(dev);
- if (error)
+ if (error) {
+ dev_err(dev, "%s error at %i: %i\n",
+ __func__, __LINE__, error);
+
return error;
+ }
if (!pm_runtime_status_suspended(dev)) {
error = pm_generic_runtime_suspend(dev);
- if (error)
+ if (error) {
+ dev_err(dev, "%s error at %i: %i\n",
+ __func__, __LINE__, error);
+
return error;
+ }
error = sysc_runtime_suspend(ddata->dev);
- if (error)
+ if (error) {
+ dev_err(dev, "%s error at %i: %i\n",
+ __func__, __LINE__, error);
+
return error;
+ }
ddata->child_needs_resume = true;
}
@@ -917,6 +1205,9 @@ static int sysc_child_resume_noirq(struct device *dev)
ddata = sysc_child_to_parent(dev);
+ dev_dbg(ddata->dev, "%s %s\n", __func__,
+ ddata->name ? ddata->name : "");
+
if (ddata->child_needs_resume) {
ddata->child_needs_resume = false;
@@ -983,10 +1274,9 @@ static int sysc_notifier_call(struct notifier_block *nb,
switch (event) {
case BUS_NOTIFY_ADD_DEVICE:
- error = sysc_child_add_fck(ddata, dev);
- if (error && error != -EEXIST)
- dev_warn(ddata->dev, "could not add %s fck: %i\n",
- dev_name(dev), error);
+ error = sysc_child_add_clocks(ddata, dev);
+ if (error)
+ return error;
sysc_legacy_idle_quirk(ddata, dev);
break;
default:
@@ -1314,6 +1604,11 @@ static void ti_sysc_idle(struct work_struct *work)
pm_runtime_put_sync(ddata->dev);
}
+static const struct of_device_id sysc_match_table[] = {
+ { .compatible = "simple-bus", },
+ { /* sentinel */ },
+};
+
static int sysc_probe(struct platform_device *pdev)
{
struct ti_sysc_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -1359,8 +1654,11 @@ static int sysc_probe(struct platform_device *pdev)
if (error)
goto unprepare;
- pm_runtime_enable(ddata->dev);
+ error = sysc_init_resets(ddata);
+ if (error)
+ return error;
+ pm_runtime_enable(ddata->dev);
error = sysc_init_module(ddata);
if (error)
goto unprepare;
@@ -1375,8 +1673,8 @@ static int sysc_probe(struct platform_device *pdev)
sysc_show_registers(ddata);
ddata->dev->type = &sysc_device_type;
- error = of_platform_populate(ddata->dev->of_node,
- NULL, pdata ? pdata->auxdata : NULL,
+ error = of_platform_populate(ddata->dev->of_node, sysc_match_table,
+ pdata ? pdata->auxdata : NULL,
ddata->dev);
if (error)
goto err;
@@ -1391,6 +1689,9 @@ static int sysc_probe(struct platform_device *pdev)
pm_runtime_put(&pdev->dev);
}
+ if (!of_get_available_child_count(ddata->dev->of_node))
+ reset_control_assert(ddata->rsts);
+
return 0;
err:
@@ -1420,6 +1721,7 @@ static int sysc_remove(struct platform_device *pdev)
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+ reset_control_assert(ddata->rsts);
unprepare:
sysc_unprepare(ddata);
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 9adc8c3..a78b8e7 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -2132,7 +2132,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf,
*/
nr = nframes;
do {
- cgc.buffer = kmalloc(CD_FRAMESIZE_RAW * nr, GFP_KERNEL);
+ cgc.buffer = kmalloc_array(nr, CD_FRAMESIZE_RAW, GFP_KERNEL);
if (cgc.buffer)
break;
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 410c30c..212f447 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -81,7 +81,7 @@ config PRINTER
corresponding drivers into the kernel.
To compile this driver as a module, choose M here and read
- <file:Documentation/parport.txt>. The module will be called lp.
+ <file:Documentation/admin-guide/parport.rst>. The module will be called lp.
If you have several parallel ports, you can specify which ports to
use with the "lp" kernel command line option. (Try "man bootparam"
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index b450544..6914e4f 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -85,7 +85,8 @@ static int amd_create_gatt_pages(int nr_tables)
int retval = 0;
int i;
- tables = kzalloc((nr_tables + 1) * sizeof(struct amd_page_map *),GFP_KERNEL);
+ tables = kcalloc(nr_tables + 1, sizeof(struct amd_page_map *),
+ GFP_KERNEL);
if (tables == NULL)
return -ENOMEM;
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index 88b4cbe..20bf5f7 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -108,7 +108,8 @@ static int ati_create_gatt_pages(int nr_tables)
int retval = 0;
int i;
- tables = kzalloc((nr_tables + 1) * sizeof(struct ati_page_map *),GFP_KERNEL);
+ tables = kcalloc(nr_tables + 1, sizeof(struct ati_page_map *),
+ GFP_KERNEL);
if (tables == NULL)
return -ENOMEM;
diff --git a/drivers/char/agp/compat_ioctl.c b/drivers/char/agp/compat_ioctl.c
index 2053f70..52ffe17 100644
--- a/drivers/char/agp/compat_ioctl.c
+++ b/drivers/char/agp/compat_ioctl.c
@@ -98,11 +98,15 @@ static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user
if (ureserve.seg_count >= 16384)
return -EINVAL;
- usegment = kmalloc(sizeof(*usegment) * ureserve.seg_count, GFP_KERNEL);
+ usegment = kmalloc_array(ureserve.seg_count,
+ sizeof(*usegment),
+ GFP_KERNEL);
if (!usegment)
return -ENOMEM;
- ksegment = kmalloc(sizeof(*ksegment) * kreserve.seg_count, GFP_KERNEL);
+ ksegment = kmalloc_array(kreserve.seg_count,
+ sizeof(*ksegment),
+ GFP_KERNEL);
if (!ksegment) {
kfree(usegment);
return -ENOMEM;
diff --git a/drivers/char/agp/isoch.c b/drivers/char/agp/isoch.c
index fc8e1bc..31c374b 100644
--- a/drivers/char/agp/isoch.c
+++ b/drivers/char/agp/isoch.c
@@ -93,7 +93,8 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
* We'll work with an array of isoch_data's (one for each
* device in dev_list) throughout this function.
*/
- if ((master = kmalloc(ndevs * sizeof(*master), GFP_KERNEL)) == NULL) {
+ master = kmalloc_array(ndevs, sizeof(*master), GFP_KERNEL);
+ if (master == NULL) {
ret = -ENOMEM;
goto get_out;
}
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c
index 3051c73..e7d5bdc 100644
--- a/drivers/char/agp/sgi-agp.c
+++ b/drivers/char/agp/sgi-agp.c
@@ -280,9 +280,9 @@ static int agp_sgi_init(void)
else
return 0;
- sgi_tioca_agp_bridges = kmalloc(tioca_gart_found *
- sizeof(struct agp_bridge_data *),
- GFP_KERNEL);
+ sgi_tioca_agp_bridges = kmalloc_array(tioca_gart_found,
+ sizeof(struct agp_bridge_data *),
+ GFP_KERNEL);
if (!sgi_tioca_agp_bridges)
return -ENOMEM;
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 4dbdd3b..7729414 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -96,7 +96,7 @@ static int serverworks_create_gatt_pages(int nr_tables)
int retval = 0;
int i;
- tables = kzalloc((nr_tables + 1) * sizeof(struct serverworks_page_map *),
+ tables = kcalloc(nr_tables + 1, sizeof(struct serverworks_page_map *),
GFP_KERNEL);
if (tables == NULL)
return -ENOMEM;
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 79d8c84..31fcd043 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -402,7 +402,9 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
if (table == NULL)
return -ENOMEM;
- uninorth_priv.pages_arr = kmalloc((1 << page_order) * sizeof(struct page*), GFP_KERNEL);
+ uninorth_priv.pages_arr = kmalloc_array(1 << page_order,
+ sizeof(struct page *),
+ GFP_KERNEL);
if (uninorth_priv.pages_arr == NULL)
goto enomem;
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 91bb98c..aaf9e5a 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -516,11 +516,18 @@ EXPORT_SYMBOL_GPL(hwrng_register);
void hwrng_unregister(struct hwrng *rng)
{
+ int err;
+
mutex_lock(&rng_mutex);
list_del(&rng->list);
- if (current_rng == rng)
- enable_best_rng();
+ if (current_rng == rng) {
+ err = enable_best_rng();
+ if (err) {
+ drop_current_rng();
+ cur_rng_set_by_user = 0;
+ }
+ }
if (list_empty(&rng_list)) {
mutex_unlock(&rng_mutex);
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 22f634e..18e4650 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -1757,7 +1757,8 @@ static unsigned short *ssif_address_list(void)
list_for_each_entry(info, &ssif_infos, link)
count++;
- address_list = kzalloc(sizeof(*address_list) * (count + 1), GFP_KERNEL);
+ address_list = kcalloc(count + 1, sizeof(*address_list),
+ GFP_KERNEL);
if (!address_list)
return NULL;
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index 293167c..fd6eec8 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -321,7 +321,8 @@ static int __init raw_init(void)
max_raw_minors = MAX_RAW_MINORS;
}
- raw_devices = vzalloc(sizeof(struct raw_device_data) * max_raw_minors);
+ raw_devices = vzalloc(array_size(max_raw_minors,
+ sizeof(struct raw_device_data)));
if (!raw_devices) {
printk(KERN_ERR "Not enough memory for raw device structures\n");
ret = -ENOMEM;
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 96c77c8..d31b090 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -980,7 +980,7 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
goto out;
}
- chip->cc_attrs_tbl = devm_kzalloc(&chip->dev, 4 * nr_commands,
+ chip->cc_attrs_tbl = devm_kcalloc(&chip->dev, 4, nr_commands,
GFP_KERNEL);
rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY);
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 2108551..17084cf 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -433,8 +433,7 @@ static struct port_buffer *alloc_buf(struct virtio_device *vdev, size_t buf_size
* Allocate buffer and the sg list. The sg list array is allocated
* directly after the port_buffer struct.
*/
- buf = kmalloc(sizeof(*buf) + sizeof(struct scatterlist) * pages,
- GFP_KERNEL);
+ buf = kmalloc(struct_size(buf, sg, pages), GFP_KERNEL);
if (!buf)
goto fail;
@@ -1892,13 +1891,14 @@ static int init_vqs(struct ports_device *portdev)
nr_ports = portdev->max_nr_ports;
nr_queues = use_multiport(portdev) ? (nr_ports + 1) * 2 : 2;
- vqs = kmalloc(nr_queues * sizeof(struct virtqueue *), GFP_KERNEL);
- io_callbacks = kmalloc(nr_queues * sizeof(vq_callback_t *), GFP_KERNEL);
- io_names = kmalloc(nr_queues * sizeof(char *), GFP_KERNEL);
- portdev->in_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
- GFP_KERNEL);
- portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *),
- GFP_KERNEL);
+ vqs = kmalloc_array(nr_queues, sizeof(struct virtqueue *), GFP_KERNEL);
+ io_callbacks = kmalloc_array(nr_queues, sizeof(vq_callback_t *),
+ GFP_KERNEL);
+ io_names = kmalloc_array(nr_queues, sizeof(char *), GFP_KERNEL);
+ portdev->in_vqs = kmalloc_array(nr_ports, sizeof(struct virtqueue *),
+ GFP_KERNEL);
+ portdev->out_vqs = kmalloc_array(nr_ports, sizeof(struct virtqueue *),
+ GFP_KERNEL);
if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs ||
!portdev->out_vqs) {
err = -ENOMEM;
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 9e0b2f2..7bef066 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -734,7 +734,7 @@ static void bcm2835_pll_debug_init(struct clk_hw *hw,
const struct bcm2835_pll_data *data = pll->data;
struct debugfs_reg32 *regs;
- regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL);
+ regs = devm_kcalloc(cprman->dev, 7, sizeof(*regs), GFP_KERNEL);
if (!regs)
return;
@@ -865,7 +865,7 @@ static void bcm2835_pll_divider_debug_init(struct clk_hw *hw,
const struct bcm2835_pll_divider_data *data = divider->data;
struct debugfs_reg32 *regs;
- regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL);
+ regs = devm_kcalloc(cprman->dev, 7, sizeof(*regs), GFP_KERNEL);
if (!regs)
return;
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index a24a6af..9760b52 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -6,7 +6,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * Standard functionality for the common clock API. See Documentation/clk.txt
+ * Standard functionality for the common clock API. See Documentation/driver-api/clk.rst
*/
#include <linux/clk.h>
@@ -2747,7 +2747,7 @@ static int __clk_core_init(struct clk_core *core)
goto out;
}
- /* check that clk_ops are sane. See Documentation/clk.txt */
+ /* check that clk_ops are sane. See Documentation/driver-api/clk.rst */
if (core->ops->set_rate &&
!((core->ops->round_rate || core->ops->determine_rate) &&
core->ops->recalc_rate)) {
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
index 5421923..502bcbb 100644
--- a/drivers/clk/ingenic/cgu.h
+++ b/drivers/clk/ingenic/cgu.h
@@ -194,7 +194,7 @@ struct ingenic_cgu {
/**
* struct ingenic_clk - private data for a clock
- * @hw: see Documentation/clk.txt
+ * @hw: see Documentation/driver-api/clk.rst
* @cgu: a pointer to the CGU data
* @idx: the index of this clock in cgu->clock_info
*/
diff --git a/drivers/clk/renesas/clk-r8a7740.c b/drivers/clk/renesas/clk-r8a7740.c
index d074f8e..a7a30d2 100644
--- a/drivers/clk/renesas/clk-r8a7740.c
+++ b/drivers/clk/renesas/clk-r8a7740.c
@@ -161,7 +161,7 @@ static void __init r8a7740_cpg_clocks_init(struct device_node *np)
}
cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
- clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL);
+ clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
if (cpg == NULL || clks == NULL) {
/* We're leaking memory on purpose, there's no point in cleaning
* up as the system won't boot anyway.
diff --git a/drivers/clk/renesas/clk-r8a7779.c b/drivers/clk/renesas/clk-r8a7779.c
index 27fbfaf..5adcca4 100644
--- a/drivers/clk/renesas/clk-r8a7779.c
+++ b/drivers/clk/renesas/clk-r8a7779.c
@@ -138,7 +138,7 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
}
cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
- clks = kzalloc(CPG_NUM_CLOCKS * sizeof(*clks), GFP_KERNEL);
+ clks = kcalloc(CPG_NUM_CLOCKS, sizeof(*clks), GFP_KERNEL);
if (cpg == NULL || clks == NULL) {
/* We're leaking memory on purpose, there's no point in cleaning
* up as the system won't boot anyway.
diff --git a/drivers/clk/renesas/clk-rcar-gen2.c b/drivers/clk/renesas/clk-rcar-gen2.c
index ee32a02..bccd62f 100644
--- a/drivers/clk/renesas/clk-rcar-gen2.c
+++ b/drivers/clk/renesas/clk-rcar-gen2.c
@@ -417,7 +417,7 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
}
cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
- clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL);
+ clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
if (cpg == NULL || clks == NULL) {
/* We're leaking memory on purpose, there's no point in cleaning
* up as the system won't boot anyway.
diff --git a/drivers/clk/renesas/clk-rz.c b/drivers/clk/renesas/clk-rz.c
index 67dd712..ac2f86d 100644
--- a/drivers/clk/renesas/clk-rz.c
+++ b/drivers/clk/renesas/clk-rz.c
@@ -97,7 +97,7 @@ static void __init rz_cpg_clocks_init(struct device_node *np)
return;
cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
- clks = kzalloc(num_clks * sizeof(*clks), GFP_KERNEL);
+ clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
BUG_ON(!cpg || !clks);
cpg->data.clks = clks;
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index 14819d9..a79d819 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -874,7 +874,7 @@ static void __init st_of_create_quadfs_fsynths(
return;
clk_data->clk_num = QUADFS_MAX_CHAN;
- clk_data->clks = kzalloc(QUADFS_MAX_CHAN * sizeof(struct clk *),
+ clk_data->clks = kcalloc(QUADFS_MAX_CHAN, sizeof(struct clk *),
GFP_KERNEL);
if (!clk_data->clks) {
diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c
index 25bda48..7a7106d 100644
--- a/drivers/clk/st/clkgen-pll.c
+++ b/drivers/clk/st/clkgen-pll.c
@@ -738,7 +738,7 @@ static void __init clkgen_c32_pll_setup(struct device_node *np,
return;
clk_data->clk_num = num_odfs;
- clk_data->clks = kzalloc(clk_data->clk_num * sizeof(struct clk *),
+ clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
GFP_KERNEL);
if (!clk_data->clks)
diff --git a/drivers/clk/sunxi/clk-usb.c b/drivers/clk/sunxi/clk-usb.c
index fe0c3d1..917fc27 100644
--- a/drivers/clk/sunxi/clk-usb.c
+++ b/drivers/clk/sunxi/clk-usb.c
@@ -122,7 +122,7 @@ static void __init sunxi_usb_clk_setup(struct device_node *node,
if (!clk_data)
return;
- clk_data->clks = kzalloc((qty+1) * sizeof(struct clk *), GFP_KERNEL);
+ clk_data->clks = kcalloc(qty + 1, sizeof(struct clk *), GFP_KERNEL);
if (!clk_data->clks) {
kfree(clk_data);
return;
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
index 593d76a..ffaf17f7 100644
--- a/drivers/clk/tegra/clk.c
+++ b/drivers/clk/tegra/clk.c
@@ -216,14 +216,15 @@ struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
if (WARN_ON(banks > ARRAY_SIZE(periph_regs)))
return NULL;
- periph_clk_enb_refcnt = kzalloc(32 * banks *
- sizeof(*periph_clk_enb_refcnt), GFP_KERNEL);
+ periph_clk_enb_refcnt = kcalloc(32 * banks,
+ sizeof(*periph_clk_enb_refcnt),
+ GFP_KERNEL);
if (!periph_clk_enb_refcnt)
return NULL;
periph_banks = banks;
- clks = kzalloc(num * sizeof(struct clk *), GFP_KERNEL);
+ clks = kcalloc(num, sizeof(struct clk *), GFP_KERNEL);
if (!clks)
kfree(periph_clk_enb_refcnt);
diff --git a/drivers/clk/ti/adpll.c b/drivers/clk/ti/adpll.c
index d6036c7..688e403 100644
--- a/drivers/clk/ti/adpll.c
+++ b/drivers/clk/ti/adpll.c
@@ -501,8 +501,9 @@ static int ti_adpll_init_dco(struct ti_adpll_data *d)
const char *postfix;
int width, err;
- d->outputs.clks = devm_kzalloc(d->dev, sizeof(struct clk *) *
+ d->outputs.clks = devm_kcalloc(d->dev,
MAX_ADPLL_OUTPUTS,
+ sizeof(struct clk *),
GFP_KERNEL);
if (!d->outputs.clks)
return -ENOMEM;
@@ -915,8 +916,9 @@ static int ti_adpll_probe(struct platform_device *pdev)
if (err)
return err;
- d->clocks = devm_kzalloc(d->dev, sizeof(struct ti_adpll_clock) *
+ d->clocks = devm_kcalloc(d->dev,
TI_ADPLL_NR_CLOCKS,
+ sizeof(struct ti_adpll_clock),
GFP_KERNEL);
if (!d->clocks)
return -ENOMEM;
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
index 9498e93..61c126a 100644
--- a/drivers/clk/ti/apll.c
+++ b/drivers/clk/ti/apll.c
@@ -206,7 +206,7 @@ static void __init of_dra7_apll_setup(struct device_node *node)
goto cleanup;
}
- parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL);
+ parent_names = kcalloc(init->num_parents, sizeof(char *), GFP_KERNEL);
if (!parent_names)
goto cleanup;
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index aaa277d..ccfb4d9 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -366,7 +366,7 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
num_dividers = i;
- tmp = kzalloc(sizeof(*tmp) * (valid_div + 1), GFP_KERNEL);
+ tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL);
if (!tmp)
return -ENOMEM;
@@ -496,7 +496,7 @@ __init ti_clk_get_div_table(struct device_node *node)
return ERR_PTR(-EINVAL);
}
- table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL);
+ table = kcalloc(valid_div + 1, sizeof(*table), GFP_KERNEL);
if (!table)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 7d33ca9..dc86d07 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -309,7 +309,7 @@ static void __init of_ti_dpll_setup(struct device_node *node,
goto cleanup;
}
- parent_names = kzalloc(sizeof(char *) * init->num_parents, GFP_KERNEL);
+ parent_names = kcalloc(init->num_parents, sizeof(char *), GFP_KERNEL);
if (!parent_names)
goto cleanup;
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 70b3cf8..bbbf37c 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -1000,7 +1000,7 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
/* Allocate and setup the channels. */
cmt->num_channels = hweight8(cmt->hw_channels);
- cmt->channels = kzalloc(cmt->num_channels * sizeof(*cmt->channels),
+ cmt->channels = kcalloc(cmt->num_channels, sizeof(*cmt->channels),
GFP_KERNEL);
if (cmt->channels == NULL) {
ret = -ENOMEM;
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c
index 53aa7e9..6812e09 100644
--- a/drivers/clocksource/sh_mtu2.c
+++ b/drivers/clocksource/sh_mtu2.c
@@ -418,7 +418,7 @@ static int sh_mtu2_setup(struct sh_mtu2_device *mtu,
/* Allocate and setup the channels. */
mtu->num_channels = 3;
- mtu->channels = kzalloc(sizeof(*mtu->channels) * mtu->num_channels,
+ mtu->channels = kcalloc(mtu->num_channels, sizeof(*mtu->channels),
GFP_KERNEL);
if (mtu->channels == NULL) {
ret = -ENOMEM;
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c
index 31d8816..c74a6c54 100644
--- a/drivers/clocksource/sh_tmu.c
+++ b/drivers/clocksource/sh_tmu.c
@@ -569,7 +569,7 @@ static int sh_tmu_setup(struct sh_tmu_device *tmu, struct platform_device *pdev)
}
/* Allocate and setup the channels. */
- tmu->channels = kzalloc(sizeof(*tmu->channels) * tmu->num_channels,
+ tmu->channels = kcalloc(tmu->num_channels, sizeof(*tmu->channels),
GFP_KERNEL);
if (tmu->channels == NULL) {
ret = -ENOMEM;
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index e5cdc3a..2717f88 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -304,8 +304,10 @@ static int __init stm32_timer_init(struct device_node *node)
to->private_data = kzalloc(sizeof(struct stm32_timer_private),
GFP_KERNEL);
- if (!to->private_data)
+ if (!to->private_data) {
+ ret = -ENOMEM;
goto deinit;
+ }
rstc = of_reset_control_get(node, NULL);
if (!IS_ERR(rstc)) {
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index c7ce928..52f5f1a 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -125,7 +125,7 @@ config ARM_OMAP2PLUS_CPUFREQ
default ARCH_OMAP2PLUS
config ARM_QCOM_CPUFREQ_KRYO
- bool "Qualcomm Kryo based CPUFreq"
+ tristate "Qualcomm Kryo based CPUFreq"
depends on ARM64
depends on QCOM_QFPROM
depends on QCOM_SMEM
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 9449657..b61f4ec 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -465,8 +465,8 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
return result;
}
-unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy,
- unsigned int target_freq)
+static unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy,
+ unsigned int target_freq)
{
struct acpi_cpufreq_data *data = policy->driver_data;
struct acpi_processor_performance *perf;
@@ -759,8 +759,8 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
goto err_unreg;
}
- freq_table = kzalloc(sizeof(*freq_table) *
- (perf->state_count+1), GFP_KERNEL);
+ freq_table = kcalloc(perf->state_count + 1, sizeof(*freq_table),
+ GFP_KERNEL);
if (!freq_table) {
result = -ENOMEM;
goto err_unreg;
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index 1d7ef5f..cf62a1f 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -280,7 +280,7 @@ static int merge_cluster_tables(void)
for (i = 0; i < MAX_CLUSTERS; i++)
count += get_table_count(freq_table[i]);
- table = kzalloc(sizeof(*table) * count, GFP_KERNEL);
+ table = kcalloc(count, sizeof(*table), GFP_KERNEL);
if (!table)
return -ENOMEM;
diff --git a/drivers/cpufreq/bmips-cpufreq.c b/drivers/cpufreq/bmips-cpufreq.c
index 1653151..56a4ebb 100644
--- a/drivers/cpufreq/bmips-cpufreq.c
+++ b/drivers/cpufreq/bmips-cpufreq.c
@@ -71,7 +71,7 @@ bmips_cpufreq_get_freq_table(const struct cpufreq_policy *policy)
cpu_freq = htp_freq_to_cpu_freq(priv->clk_mult);
- table = kmalloc((priv->max_freqs + 1) * sizeof(*table), GFP_KERNEL);
+ table = kmalloc_array(priv->max_freqs + 1, sizeof(*table), GFP_KERNEL);
if (!table)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/cpufreq/brcmstb-avs-cpufreq.c b/drivers/cpufreq/brcmstb-avs-cpufreq.c
index b07559b..e6f9cbe 100644
--- a/drivers/cpufreq/brcmstb-avs-cpufreq.c
+++ b/drivers/cpufreq/brcmstb-avs-cpufreq.c
@@ -410,7 +410,7 @@ brcm_avs_get_freq_table(struct device *dev, struct private_data *priv)
if (ret)
return ERR_PTR(ret);
- table = devm_kzalloc(dev, (AVS_PSTATE_MAX + 1) * sizeof(*table),
+ table = devm_kcalloc(dev, AVS_PSTATE_MAX + 1, sizeof(*table),
GFP_KERNEL);
if (!table)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index 3464580..a9d3eec 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -313,7 +313,8 @@ static int __init cppc_cpufreq_init(void)
if (acpi_disabled)
return -ENODEV;
- all_cpu_data = kzalloc(sizeof(void *) * num_possible_cpus(), GFP_KERNEL);
+ all_cpu_data = kcalloc(num_possible_cpus(), sizeof(void *),
+ GFP_KERNEL);
if (!all_cpu_data)
return -ENOMEM;
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index 871bf9c..1d50e97 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -165,7 +165,7 @@ unsigned int dbs_update(struct cpufreq_policy *policy)
* calls, so the previous load value can be used then.
*/
load = j_cdbs->prev_load;
- } else if (unlikely(time_elapsed > 2 * sampling_rate &&
+ } else if (unlikely((int)idle_time > 2 * sampling_rate &&
j_cdbs->prev_load)) {
/*
* If the CPU had gone completely idle and a task has
@@ -185,10 +185,8 @@ unsigned int dbs_update(struct cpufreq_policy *policy)
* clear prev_load to guarantee that the load will be
* computed again next time.
*
- * Detecting this situation is easy: the governor's
- * utilization update handler would not have run during
- * CPU-idle periods. Hence, an unusually large
- * 'time_elapsed' (as compared to the sampling rate)
+ * Detecting this situation is easy: an unusually large
+ * 'idle_time' (as compared to the sampling rate)
* indicates this scenario.
*/
load = j_cdbs->prev_load;
@@ -217,8 +215,8 @@ unsigned int dbs_update(struct cpufreq_policy *policy)
j_cdbs->prev_load = load;
}
- if (time_elapsed > 2 * sampling_rate) {
- unsigned int periods = time_elapsed / sampling_rate;
+ if (unlikely((int)idle_time > 2 * sampling_rate)) {
+ unsigned int periods = idle_time / sampling_rate;
if (periods < idle_periods)
idle_periods = periods;
diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c
index 7974a2f..dd5440d 100644
--- a/drivers/cpufreq/ia64-acpi-cpufreq.c
+++ b/drivers/cpufreq/ia64-acpi-cpufreq.c
@@ -241,8 +241,8 @@ acpi_cpufreq_cpu_init (
}
/* alloc freq_table */
- freq_table = kzalloc(sizeof(*freq_table) *
- (data->acpi_data.state_count + 1),
+ freq_table = kcalloc(data->acpi_data.state_count + 1,
+ sizeof(*freq_table),
GFP_KERNEL);
if (!freq_table) {
result = -ENOMEM;
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 83cf631..8b3c2a7 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -266,6 +266,8 @@ put_node:
}
#define OCOTP_CFG3_6UL_SPEED_696MHZ 0x2
+#define OCOTP_CFG3_6ULL_SPEED_792MHZ 0x2
+#define OCOTP_CFG3_6ULL_SPEED_900MHZ 0x3
static void imx6ul_opp_check_speed_grading(struct device *dev)
{
@@ -287,16 +289,30 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)
* Speed GRADING[1:0] defines the max speed of ARM:
* 2b'00: Reserved;
* 2b'01: 528000000Hz;
- * 2b'10: 696000000Hz;
- * 2b'11: Reserved;
+ * 2b'10: 696000000Hz on i.MX6UL, 792000000Hz on i.MX6ULL;
+ * 2b'11: 900000000Hz on i.MX6ULL only;
* We need to set the max speed of ARM according to fuse map.
*/
val = readl_relaxed(base + OCOTP_CFG3);
val >>= OCOTP_CFG3_SPEED_SHIFT;
val &= 0x3;
- if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
- if (dev_pm_opp_disable(dev, 696000000))
- dev_warn(dev, "failed to disable 696MHz OPP\n");
+
+ if (of_machine_is_compatible("fsl,imx6ul")) {
+ if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
+ if (dev_pm_opp_disable(dev, 696000000))
+ dev_warn(dev, "failed to disable 696MHz OPP\n");
+ }
+
+ if (of_machine_is_compatible("fsl,imx6ull")) {
+ if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
+ if (dev_pm_opp_disable(dev, 792000000))
+ dev_warn(dev, "failed to disable 792MHz OPP\n");
+
+ if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
+ if (dev_pm_opp_disable(dev, 900000000))
+ dev_warn(dev, "failed to disable 900MHz OPP\n");
+ }
+
iounmap(base);
put_node:
of_node_put(np);
@@ -356,7 +372,8 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
goto put_reg;
}
- if (of_machine_is_compatible("fsl,imx6ul"))
+ if (of_machine_is_compatible("fsl,imx6ul") ||
+ of_machine_is_compatible("fsl,imx6ull"))
imx6ul_opp_check_speed_grading(cpu_dev);
else
imx6q_opp_check_speed_grading(cpu_dev);
@@ -377,7 +394,8 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
}
/* Make imx6_soc_volt array's size same as arm opp number */
- imx6_soc_volt = devm_kzalloc(cpu_dev, sizeof(*imx6_soc_volt) * num, GFP_KERNEL);
+ imx6_soc_volt = devm_kcalloc(cpu_dev, num, sizeof(*imx6_soc_volt),
+ GFP_KERNEL);
if (imx6_soc_volt == NULL) {
ret = -ENOMEM;
goto free_freq_table;
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 08960a5..ece120d 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -221,6 +221,11 @@ struct global_params {
* preference/bias
* @epp_saved: Saved EPP/EPB during system suspend or CPU offline
* operation
+ * @hwp_req_cached: Cached value of the last HWP Request MSR
+ * @hwp_cap_cached: Cached value of the last HWP Capabilities MSR
+ * @last_io_update: Last time when IO wake flag was set
+ * @sched_flags: Store scheduler flags for possible cross CPU update
+ * @hwp_boost_min: Last HWP boosted min performance
*
* This structure stores per CPU instance data for all CPUs.
*/
@@ -253,6 +258,11 @@ struct cpudata {
s16 epp_policy;
s16 epp_default;
s16 epp_saved;
+ u64 hwp_req_cached;
+ u64 hwp_cap_cached;
+ u64 last_io_update;
+ unsigned int sched_flags;
+ u32 hwp_boost_min;
};
static struct cpudata **all_cpu_data;
@@ -284,7 +294,9 @@ struct pstate_funcs {
static struct pstate_funcs pstate_funcs __read_mostly;
static int hwp_active __read_mostly;
+static int hwp_mode_bdw __read_mostly;
static bool per_cpu_limits __read_mostly;
+static bool hwp_boost __read_mostly;
static struct cpufreq_driver *intel_pstate_driver __read_mostly;
@@ -689,6 +701,7 @@ static void intel_pstate_get_hwp_max(unsigned int cpu, int *phy_max,
u64 cap;
rdmsrl_on_cpu(cpu, MSR_HWP_CAPABILITIES, &cap);
+ WRITE_ONCE(all_cpu_data[cpu]->hwp_cap_cached, cap);
if (global.no_turbo)
*current_max = HWP_GUARANTEED_PERF(cap);
else
@@ -763,6 +776,7 @@ update_epp:
intel_pstate_set_epb(cpu, epp);
}
skip_epp:
+ WRITE_ONCE(cpu_data->hwp_req_cached, value);
wrmsrl_on_cpu(cpu, MSR_HWP_REQUEST, value);
}
@@ -1020,6 +1034,30 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b,
return count;
}
+static ssize_t show_hwp_dynamic_boost(struct kobject *kobj,
+ struct attribute *attr, char *buf)
+{
+ return sprintf(buf, "%u\n", hwp_boost);
+}
+
+static ssize_t store_hwp_dynamic_boost(struct kobject *a, struct attribute *b,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+
+ ret = kstrtouint(buf, 10, &input);
+ if (ret)
+ return ret;
+
+ mutex_lock(&intel_pstate_driver_lock);
+ hwp_boost = !!input;
+ intel_pstate_update_policies();
+ mutex_unlock(&intel_pstate_driver_lock);
+
+ return count;
+}
+
show_one(max_perf_pct, max_perf_pct);
show_one(min_perf_pct, min_perf_pct);
@@ -1029,6 +1067,7 @@ define_one_global_rw(max_perf_pct);
define_one_global_rw(min_perf_pct);
define_one_global_ro(turbo_pct);
define_one_global_ro(num_pstates);
+define_one_global_rw(hwp_dynamic_boost);
static struct attribute *intel_pstate_attributes[] = {
&status.attr,
@@ -1069,6 +1108,11 @@ static void __init intel_pstate_sysfs_expose_params(void)
rc = sysfs_create_file(intel_pstate_kobject, &min_perf_pct.attr);
WARN_ON(rc);
+ if (hwp_active) {
+ rc = sysfs_create_file(intel_pstate_kobject,
+ &hwp_dynamic_boost.attr);
+ WARN_ON(rc);
+ }
}
/************************** sysfs end ************************/
@@ -1370,7 +1414,15 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
cpu->pstate.turbo_pstate = pstate_funcs.get_turbo();
cpu->pstate.scaling = pstate_funcs.get_scaling();
cpu->pstate.max_freq = cpu->pstate.max_pstate * cpu->pstate.scaling;
- cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
+
+ if (hwp_active && !hwp_mode_bdw) {
+ unsigned int phy_max, current_max;
+
+ intel_pstate_get_hwp_max(cpu->cpu, &phy_max, &current_max);
+ cpu->pstate.turbo_freq = phy_max * cpu->pstate.scaling;
+ } else {
+ cpu->pstate.turbo_freq = cpu->pstate.turbo_pstate * cpu->pstate.scaling;
+ }
if (pstate_funcs.get_aperf_mperf_shift)
cpu->aperf_mperf_shift = pstate_funcs.get_aperf_mperf_shift();
@@ -1381,6 +1433,116 @@ static void intel_pstate_get_cpu_pstates(struct cpudata *cpu)
intel_pstate_set_min_pstate(cpu);
}
+/*
+ * Long hold time will keep high perf limits for long time,
+ * which negatively impacts perf/watt for some workloads,
+ * like specpower. 3ms is based on experiements on some
+ * workoads.
+ */
+static int hwp_boost_hold_time_ns = 3 * NSEC_PER_MSEC;
+
+static inline void intel_pstate_hwp_boost_up(struct cpudata *cpu)
+{
+ u64 hwp_req = READ_ONCE(cpu->hwp_req_cached);
+ u32 max_limit = (hwp_req & 0xff00) >> 8;
+ u32 min_limit = (hwp_req & 0xff);
+ u32 boost_level1;
+
+ /*
+ * Cases to consider (User changes via sysfs or boot time):
+ * If, P0 (Turbo max) = P1 (Guaranteed max) = min:
+ * No boost, return.
+ * If, P0 (Turbo max) > P1 (Guaranteed max) = min:
+ * Should result in one level boost only for P0.
+ * If, P0 (Turbo max) = P1 (Guaranteed max) > min:
+ * Should result in two level boost:
+ * (min + p1)/2 and P1.
+ * If, P0 (Turbo max) > P1 (Guaranteed max) > min:
+ * Should result in three level boost:
+ * (min + p1)/2, P1 and P0.
+ */
+
+ /* If max and min are equal or already at max, nothing to boost */
+ if (max_limit == min_limit || cpu->hwp_boost_min >= max_limit)
+ return;
+
+ if (!cpu->hwp_boost_min)
+ cpu->hwp_boost_min = min_limit;
+
+ /* level at half way mark between min and guranteed */
+ boost_level1 = (HWP_GUARANTEED_PERF(cpu->hwp_cap_cached) + min_limit) >> 1;
+
+ if (cpu->hwp_boost_min < boost_level1)
+ cpu->hwp_boost_min = boost_level1;
+ else if (cpu->hwp_boost_min < HWP_GUARANTEED_PERF(cpu->hwp_cap_cached))
+ cpu->hwp_boost_min = HWP_GUARANTEED_PERF(cpu->hwp_cap_cached);
+ else if (cpu->hwp_boost_min == HWP_GUARANTEED_PERF(cpu->hwp_cap_cached) &&
+ max_limit != HWP_GUARANTEED_PERF(cpu->hwp_cap_cached))
+ cpu->hwp_boost_min = max_limit;
+ else
+ return;
+
+ hwp_req = (hwp_req & ~GENMASK_ULL(7, 0)) | cpu->hwp_boost_min;
+ wrmsrl(MSR_HWP_REQUEST, hwp_req);
+ cpu->last_update = cpu->sample.time;
+}
+
+static inline void intel_pstate_hwp_boost_down(struct cpudata *cpu)
+{
+ if (cpu->hwp_boost_min) {
+ bool expired;
+
+ /* Check if we are idle for hold time to boost down */
+ expired = time_after64(cpu->sample.time, cpu->last_update +
+ hwp_boost_hold_time_ns);
+ if (expired) {
+ wrmsrl(MSR_HWP_REQUEST, cpu->hwp_req_cached);
+ cpu->hwp_boost_min = 0;
+ }
+ }
+ cpu->last_update = cpu->sample.time;
+}
+
+static inline void intel_pstate_update_util_hwp_local(struct cpudata *cpu,
+ u64 time)
+{
+ cpu->sample.time = time;
+
+ if (cpu->sched_flags & SCHED_CPUFREQ_IOWAIT) {
+ bool do_io = false;
+
+ cpu->sched_flags = 0;
+ /*
+ * Set iowait_boost flag and update time. Since IO WAIT flag
+ * is set all the time, we can't just conclude that there is
+ * some IO bound activity is scheduled on this CPU with just
+ * one occurrence. If we receive at least two in two
+ * consecutive ticks, then we treat as boost candidate.
+ */
+ if (time_before64(time, cpu->last_io_update + 2 * TICK_NSEC))
+ do_io = true;
+
+ cpu->last_io_update = time;
+
+ if (do_io)
+ intel_pstate_hwp_boost_up(cpu);
+
+ } else {
+ intel_pstate_hwp_boost_down(cpu);
+ }
+}
+
+static inline void intel_pstate_update_util_hwp(struct update_util_data *data,
+ u64 time, unsigned int flags)
+{
+ struct cpudata *cpu = container_of(data, struct cpudata, update_util);
+
+ cpu->sched_flags |= flags;
+
+ if (smp_processor_id() == cpu->cpu)
+ intel_pstate_update_util_hwp_local(cpu, time);
+}
+
static inline void intel_pstate_calc_avg_perf(struct cpudata *cpu)
{
struct sample *sample = &cpu->sample;
@@ -1641,6 +1803,12 @@ static const struct x86_cpu_id intel_pstate_cpu_ee_disable_ids[] = {
{}
};
+static const struct x86_cpu_id intel_pstate_hwp_boost_ids[] = {
+ ICPU(INTEL_FAM6_SKYLAKE_X, core_funcs),
+ ICPU(INTEL_FAM6_SKYLAKE_DESKTOP, core_funcs),
+ {}
+};
+
static int intel_pstate_init_cpu(unsigned int cpunum)
{
struct cpudata *cpu;
@@ -1671,6 +1839,10 @@ static int intel_pstate_init_cpu(unsigned int cpunum)
intel_pstate_disable_ee(cpunum);
intel_pstate_hwp_enable(cpu);
+
+ id = x86_match_cpu(intel_pstate_hwp_boost_ids);
+ if (id)
+ hwp_boost = true;
}
intel_pstate_get_cpu_pstates(cpu);
@@ -1684,7 +1856,7 @@ static void intel_pstate_set_update_util_hook(unsigned int cpu_num)
{
struct cpudata *cpu = all_cpu_data[cpu_num];
- if (hwp_active)
+ if (hwp_active && !hwp_boost)
return;
if (cpu->update_util_set)
@@ -1693,7 +1865,9 @@ static void intel_pstate_set_update_util_hook(unsigned int cpu_num)
/* Prevent intel_pstate_update_util() from using stale data. */
cpu->sample.time = 0;
cpufreq_add_update_util_hook(cpu_num, &cpu->update_util,
- intel_pstate_update_util);
+ (hwp_active ?
+ intel_pstate_update_util_hwp :
+ intel_pstate_update_util));
cpu->update_util_set = true;
}
@@ -1805,8 +1979,16 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy)
intel_pstate_set_update_util_hook(policy->cpu);
}
- if (hwp_active)
+ if (hwp_active) {
+ /*
+ * When hwp_boost was active before and dynamically it
+ * was turned off, in that case we need to clear the
+ * update util hook.
+ */
+ if (!hwp_boost)
+ intel_pstate_clear_update_util_hook(policy->cpu);
intel_pstate_hwp_set(policy->cpu);
+ }
mutex_unlock(&intel_pstate_limits_lock);
@@ -2294,28 +2476,36 @@ static inline bool intel_pstate_has_acpi_ppc(void) { return false; }
static inline void intel_pstate_request_control_from_smm(void) {}
#endif /* CONFIG_ACPI */
+#define INTEL_PSTATE_HWP_BROADWELL 0x01
+
+#define ICPU_HWP(model, hwp_mode) \
+ { X86_VENDOR_INTEL, 6, model, X86_FEATURE_HWP, hwp_mode }
+
static const struct x86_cpu_id hwp_support_ids[] __initconst = {
- { X86_VENDOR_INTEL, 6, X86_MODEL_ANY, X86_FEATURE_HWP },
+ ICPU_HWP(INTEL_FAM6_BROADWELL_X, INTEL_PSTATE_HWP_BROADWELL),
+ ICPU_HWP(INTEL_FAM6_BROADWELL_XEON_D, INTEL_PSTATE_HWP_BROADWELL),
+ ICPU_HWP(X86_MODEL_ANY, 0),
{}
};
static int __init intel_pstate_init(void)
{
+ const struct x86_cpu_id *id;
int rc;
if (no_load)
return -ENODEV;
- if (x86_match_cpu(hwp_support_ids)) {
+ id = x86_match_cpu(hwp_support_ids);
+ if (id) {
copy_cpu_funcs(&core_funcs);
if (!no_hwp) {
hwp_active++;
+ hwp_mode_bdw = id->driver_data;
intel_pstate.attr = hwp_cpufreq_attrs;
goto hwp_cpu_matched;
}
} else {
- const struct x86_cpu_id *id;
-
id = x86_match_cpu(intel_pstate_cpu_ids);
if (!id)
return -ENODEV;
@@ -2339,7 +2529,7 @@ hwp_cpu_matched:
pr_info("Intel P-state driver initializing\n");
- all_cpu_data = vzalloc(sizeof(void *) * num_possible_cpus());
+ all_cpu_data = vzalloc(array_size(sizeof(void *), num_possible_cpus()));
if (!all_cpu_data)
return -ENOMEM;
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index 61a4c5b..279bd9e 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -474,8 +474,8 @@ static int longhaul_get_ranges(void)
return -EINVAL;
}
- longhaul_table = kzalloc((numscales + 1) * sizeof(*longhaul_table),
- GFP_KERNEL);
+ longhaul_table = kcalloc(numscales + 1, sizeof(*longhaul_table),
+ GFP_KERNEL);
if (!longhaul_table)
return -ENOMEM;
diff --git a/drivers/cpufreq/pxa3xx-cpufreq.c b/drivers/cpufreq/pxa3xx-cpufreq.c
index 7acc7fa..9daa2cc 100644
--- a/drivers/cpufreq/pxa3xx-cpufreq.c
+++ b/drivers/cpufreq/pxa3xx-cpufreq.c
@@ -93,7 +93,7 @@ static int setup_freqs_table(struct cpufreq_policy *policy,
struct cpufreq_frequency_table *table;
int i;
- table = kzalloc((num + 1) * sizeof(*table), GFP_KERNEL);
+ table = kcalloc(num + 1, sizeof(*table), GFP_KERNEL);
if (table == NULL)
return -ENOMEM;
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c b/drivers/cpufreq/qcom-cpufreq-kryo.c
index d049fe4..01bddac 100644
--- a/drivers/cpufreq/qcom-cpufreq-kryo.c
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -42,6 +42,8 @@ enum _msm8996_version {
NUM_OF_MSM8996_VERSIONS,
};
+struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev;
+
static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
{
size_t len;
@@ -74,7 +76,6 @@ static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
{
struct opp_table *opp_tables[NR_CPUS] = {0};
- struct platform_device *cpufreq_dt_pdev;
enum _msm8996_version msm8996_version;
struct nvmem_cell *speedbin_nvmem;
struct device_node *np;
@@ -115,6 +116,8 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
speedbin = nvmem_cell_read(speedbin_nvmem, &len);
nvmem_cell_put(speedbin_nvmem);
+ if (IS_ERR(speedbin))
+ return PTR_ERR(speedbin);
switch (msm8996_version) {
case MSM8996_V3:
@@ -127,6 +130,7 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
BUG();
break;
}
+ kfree(speedbin);
for_each_possible_cpu(cpu) {
cpu_dev = get_cpu_device(cpu);
@@ -162,8 +166,15 @@ free_opp:
return ret;
}
+static int qcom_cpufreq_kryo_remove(struct platform_device *pdev)
+{
+ platform_device_unregister(cpufreq_dt_pdev);
+ return 0;
+}
+
static struct platform_driver qcom_cpufreq_kryo_driver = {
.probe = qcom_cpufreq_kryo_probe,
+ .remove = qcom_cpufreq_kryo_remove,
.driver = {
.name = "qcom-cpufreq-kryo",
},
@@ -198,8 +209,9 @@ static int __init qcom_cpufreq_kryo_init(void)
if (unlikely(ret < 0))
return ret;
- ret = PTR_ERR_OR_ZERO(platform_device_register_simple(
- "qcom-cpufreq-kryo", -1, NULL, 0));
+ kryo_cpufreq_pdev = platform_device_register_simple(
+ "qcom-cpufreq-kryo", -1, NULL, 0);
+ ret = PTR_ERR_OR_ZERO(kryo_cpufreq_pdev);
if (0 == ret)
return 0;
@@ -208,5 +220,12 @@ static int __init qcom_cpufreq_kryo_init(void)
}
module_init(qcom_cpufreq_kryo_init);
+static void __init qcom_cpufreq_kryo_exit(void)
+{
+ platform_device_unregister(kryo_cpufreq_pdev);
+ platform_driver_unregister(&qcom_cpufreq_kryo_driver);
+}
+module_exit(qcom_cpufreq_kryo_exit);
+
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Kryo CPUfreq driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c
index 909bd6e..3b291a2 100644
--- a/drivers/cpufreq/s3c24xx-cpufreq.c
+++ b/drivers/cpufreq/s3c24xx-cpufreq.c
@@ -562,7 +562,7 @@ static int s3c_cpufreq_build_freq(void)
size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0);
size++;
- ftab = kzalloc(sizeof(*ftab) * size, GFP_KERNEL);
+ ftab = kcalloc(size, sizeof(*ftab), GFP_KERNEL);
if (!ftab)
return -ENOMEM;
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index b4dbc774..50b1551 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -117,7 +117,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
return -ENODEV;
}
- ret = handle->perf_ops->add_opps_to_device(handle, cpu_dev);
+ ret = handle->perf_ops->device_opps_add(handle, cpu_dev);
if (ret) {
dev_warn(cpu_dev, "failed to add opps to the device\n");
return ret;
@@ -164,7 +164,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
/* SCMI allows DVFS request for any domain from any CPU */
policy->dvfs_possible_from_any_cpu = true;
- latency = handle->perf_ops->get_transition_latency(handle, cpu_dev);
+ latency = handle->perf_ops->transition_latency_get(handle, cpu_dev);
if (!latency)
latency = CPUFREQ_ETERNAL;
diff --git a/drivers/cpufreq/sfi-cpufreq.c b/drivers/cpufreq/sfi-cpufreq.c
index 9767afe..9787704 100644
--- a/drivers/cpufreq/sfi-cpufreq.c
+++ b/drivers/cpufreq/sfi-cpufreq.c
@@ -95,8 +95,8 @@ static int __init sfi_cpufreq_init(void)
if (ret)
return ret;
- freq_table = kzalloc(sizeof(*freq_table) *
- (num_freq_table_entries + 1), GFP_KERNEL);
+ freq_table = kcalloc(num_freq_table_entries + 1, sizeof(*freq_table),
+ GFP_KERNEL);
if (!freq_table) {
ret = -ENOMEM;
goto err_free_array;
diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
index 195f27f..4074e26 100644
--- a/drivers/cpufreq/spear-cpufreq.c
+++ b/drivers/cpufreq/spear-cpufreq.c
@@ -195,7 +195,7 @@ static int spear_cpufreq_probe(struct platform_device *pdev)
cnt = prop->length / sizeof(u32);
val = prop->value;
- freq_tbl = kzalloc(sizeof(*freq_tbl) * (cnt + 1), GFP_KERNEL);
+ freq_tbl = kcalloc(cnt + 1, sizeof(*freq_tbl), GFP_KERNEL);
if (!freq_tbl) {
ret = -ENOMEM;
goto out_put_node;
diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
index 6ba709b..3f0e2a1 100644
--- a/drivers/cpufreq/ti-cpufreq.c
+++ b/drivers/cpufreq/ti-cpufreq.c
@@ -217,7 +217,7 @@ static int ti_cpufreq_probe(struct platform_device *pdev)
if (!match)
return -ENODEV;
- opp_data = kzalloc(sizeof(*opp_data), GFP_KERNEL);
+ opp_data = devm_kzalloc(&pdev->dev, sizeof(*opp_data), GFP_KERNEL);
if (!opp_data)
return -ENOMEM;
@@ -226,8 +226,7 @@ static int ti_cpufreq_probe(struct platform_device *pdev)
opp_data->cpu_dev = get_cpu_device(0);
if (!opp_data->cpu_dev) {
pr_err("%s: Failed to get device for CPU0\n", __func__);
- ret = ENODEV;
- goto free_opp_data;
+ return -ENODEV;
}
opp_data->opp_node = dev_pm_opp_of_get_opp_desc_node(opp_data->cpu_dev);
@@ -285,8 +284,6 @@ register_cpufreq_dt:
fail_put_node:
of_node_put(opp_data->opp_node);
-free_opp_data:
- kfree(opp_data);
return ret;
}
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 9cb234c..05981cc 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -141,11 +141,11 @@ static void crypto4xx_hw_init(struct crypto4xx_device *dev)
int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size)
{
- ctx->sa_in = kzalloc(size * 4, GFP_ATOMIC);
+ ctx->sa_in = kcalloc(size, 4, GFP_ATOMIC);
if (ctx->sa_in == NULL)
return -ENOMEM;
- ctx->sa_out = kzalloc(size * 4, GFP_ATOMIC);
+ ctx->sa_out = kcalloc(size, 4, GFP_ATOMIC);
if (ctx->sa_out == NULL) {
kfree(ctx->sa_in);
ctx->sa_in = NULL;
@@ -180,8 +180,8 @@ static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev)
if (!dev->pdr)
return -ENOMEM;
- dev->pdr_uinfo = kzalloc(sizeof(struct pd_uinfo) * PPC4XX_NUM_PD,
- GFP_KERNEL);
+ dev->pdr_uinfo = kcalloc(PPC4XX_NUM_PD, sizeof(struct pd_uinfo),
+ GFP_KERNEL);
if (!dev->pdr_uinfo) {
dma_free_coherent(dev->core_dev->device,
sizeof(struct ce_pd) * PPC4XX_NUM_PD,
diff --git a/drivers/crypto/cavium/nitrox/nitrox_isr.c b/drivers/crypto/cavium/nitrox/nitrox_isr.c
index dbead5f..ee0d70b 100644
--- a/drivers/crypto/cavium/nitrox/nitrox_isr.c
+++ b/drivers/crypto/cavium/nitrox/nitrox_isr.c
@@ -254,7 +254,7 @@ static int nitrox_enable_msix(struct nitrox_device *ndev)
* Entry 192: NPS_CORE_INT_ACTIVE
*/
nr_entries = (ndev->nr_queues * NR_RING_VECTORS) + 1;
- entries = kzalloc_node(nr_entries * sizeof(struct msix_entry),
+ entries = kcalloc_node(nr_entries, sizeof(struct msix_entry),
GFP_KERNEL, ndev->node);
if (!entries)
return -ENOMEM;
diff --git a/drivers/crypto/chelsio/chtls/chtls_io.c b/drivers/crypto/chelsio/chtls/chtls_io.c
index 51fc682..afebbd8 100644
--- a/drivers/crypto/chelsio/chtls/chtls_io.c
+++ b/drivers/crypto/chelsio/chtls/chtls_io.c
@@ -240,7 +240,7 @@ static int tls_copy_ivs(struct sock *sk, struct sk_buff *skb)
}
/* generate the IVs */
- ivs = kmalloc(number_of_ivs * CIPHER_BLOCK_SIZE, GFP_ATOMIC);
+ ivs = kmalloc_array(CIPHER_BLOCK_SIZE, number_of_ivs, GFP_ATOMIC);
if (!ivs)
return -ENOMEM;
get_random_bytes(ivs, number_of_ivs * CIPHER_BLOCK_SIZE);
@@ -1548,15 +1548,14 @@ skip_copy:
tp->urg_data = 0;
if ((avail + offset) >= skb->len) {
- if (likely(skb))
- chtls_free_skb(sk, skb);
- buffers_freed++;
if (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_TLS_HDR) {
tp->copied_seq += skb->len;
hws->rcvpld = skb->hdr_len;
} else {
tp->copied_seq += hws->rcvpld;
}
+ chtls_free_skb(sk, skb);
+ buffers_freed++;
hws->copied_seq = 0;
if (copied >= target &&
!skb_peek(&sk->sk_receive_queue))
diff --git a/drivers/crypto/inside-secure/safexcel_hash.c b/drivers/crypto/inside-secure/safexcel_hash.c
index d138d6b..c77b0e1 100644
--- a/drivers/crypto/inside-secure/safexcel_hash.c
+++ b/drivers/crypto/inside-secure/safexcel_hash.c
@@ -922,7 +922,7 @@ int safexcel_hmac_setkey(const char *alg, const u8 *key, unsigned int keylen,
crypto_ahash_clear_flags(tfm, ~0);
blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
- ipad = kzalloc(2 * blocksize, GFP_KERNEL);
+ ipad = kcalloc(2, blocksize, GFP_KERNEL);
if (!ipad) {
ret = -ENOMEM;
goto free_request;
diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c
index f81fa4a..a4aa681 100644
--- a/drivers/crypto/marvell/cesa.c
+++ b/drivers/crypto/marvell/cesa.c
@@ -471,7 +471,7 @@ static int mv_cesa_probe(struct platform_device *pdev)
sram_size = CESA_SA_MIN_SRAM_SIZE;
cesa->sram_size = sram_size;
- cesa->engines = devm_kzalloc(dev, caps->nengines * sizeof(*engines),
+ cesa->engines = devm_kcalloc(dev, caps->nengines, sizeof(*engines),
GFP_KERNEL);
if (!cesa->engines)
return -ENOMEM;
diff --git a/drivers/crypto/marvell/hash.c b/drivers/crypto/marvell/hash.c
index e61b085..e34d80b 100644
--- a/drivers/crypto/marvell/hash.c
+++ b/drivers/crypto/marvell/hash.c
@@ -1198,7 +1198,7 @@ static int mv_cesa_ahmac_setkey(const char *hash_alg_name,
blocksize = crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
- ipad = kzalloc(2 * blocksize, GFP_KERNEL);
+ ipad = kcalloc(2, blocksize, GFP_KERNEL);
if (!ipad) {
ret = -ENOMEM;
goto free_req;
diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c
index 80e9c84..ab6235b 100644
--- a/drivers/crypto/n2_core.c
+++ b/drivers/crypto/n2_core.c
@@ -1919,12 +1919,12 @@ static int grab_global_resources(void)
goto out_hvapi_release;
err = -ENOMEM;
- cpu_to_cwq = kzalloc(sizeof(struct spu_queue *) * NR_CPUS,
+ cpu_to_cwq = kcalloc(NR_CPUS, sizeof(struct spu_queue *),
GFP_KERNEL);
if (!cpu_to_cwq)
goto out_queue_cache_destroy;
- cpu_to_mau = kzalloc(sizeof(struct spu_queue *) * NR_CPUS,
+ cpu_to_mau = kcalloc(NR_CPUS, sizeof(struct spu_queue *),
GFP_KERNEL);
if (!cpu_to_mau)
goto out_free_cwq_table;
diff --git a/drivers/crypto/qat/qat_common/adf_isr.c b/drivers/crypto/qat/qat_common/adf_isr.c
index 06d4901..cd1cdf5 100644
--- a/drivers/crypto/qat/qat_common/adf_isr.c
+++ b/drivers/crypto/qat/qat_common/adf_isr.c
@@ -238,7 +238,7 @@ static int adf_isr_alloc_msix_entry_table(struct adf_accel_dev *accel_dev)
if (!accel_dev->pf.vf_info)
msix_num_entries += hw_data->num_banks;
- entries = kzalloc_node(msix_num_entries * sizeof(*entries),
+ entries = kcalloc_node(msix_num_entries, sizeof(*entries),
GFP_KERNEL, dev_to_node(&GET_DEV(accel_dev)));
if (!entries)
return -ENOMEM;
diff --git a/drivers/crypto/qat/qat_common/qat_uclo.c b/drivers/crypto/qat/qat_common/qat_uclo.c
index 98d22c2..6bd8f6a 100644
--- a/drivers/crypto/qat/qat_common/qat_uclo.c
+++ b/drivers/crypto/qat/qat_common/qat_uclo.c
@@ -1162,8 +1162,9 @@ static int qat_uclo_map_suof(struct icp_qat_fw_loader_handle *handle,
suof_handle->img_table.num_simgs = suof_ptr->num_chunks - 1;
if (suof_handle->img_table.num_simgs != 0) {
- suof_img_hdr = kzalloc(suof_handle->img_table.num_simgs *
- sizeof(img_header), GFP_KERNEL);
+ suof_img_hdr = kcalloc(suof_handle->img_table.num_simgs,
+ sizeof(img_header),
+ GFP_KERNEL);
if (!suof_img_hdr)
return -ENOMEM;
suof_handle->img_table.simg_hdr = suof_img_hdr;
diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c
index 981e456..cdc96f1 100644
--- a/drivers/crypto/stm32/stm32-hash.c
+++ b/drivers/crypto/stm32/stm32-hash.c
@@ -970,8 +970,9 @@ static int stm32_hash_export(struct ahash_request *req, void *out)
while (!(stm32_hash_read(hdev, HASH_SR) & HASH_SR_DATA_INPUT_READY))
cpu_relax();
- rctx->hw_context = kmalloc(sizeof(u32) * (3 + HASH_CSR_REGISTER_NUMBER),
- GFP_KERNEL);
+ rctx->hw_context = kmalloc_array(3 + HASH_CSR_REGISTER_NUMBER,
+ sizeof(u32),
+ GFP_KERNEL);
preg = rctx->hw_context;
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index 7cebf0a..cf14f09 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -3393,8 +3393,10 @@ static int talitos_probe(struct platform_device *ofdev)
}
}
- priv->chan = devm_kzalloc(dev, sizeof(struct talitos_channel) *
- priv->num_channels, GFP_KERNEL);
+ priv->chan = devm_kcalloc(dev,
+ priv->num_channels,
+ sizeof(struct talitos_channel),
+ GFP_KERNEL);
if (!priv->chan) {
dev_err(dev, "failed to allocate channel management space\n");
err = -ENOMEM;
@@ -3411,9 +3413,10 @@ static int talitos_probe(struct platform_device *ofdev)
spin_lock_init(&priv->chan[i].head_lock);
spin_lock_init(&priv->chan[i].tail_lock);
- priv->chan[i].fifo = devm_kzalloc(dev,
- sizeof(struct talitos_request) *
- priv->fifo_len, GFP_KERNEL);
+ priv->chan[i].fifo = devm_kcalloc(dev,
+ priv->fifo_len,
+ sizeof(struct talitos_request),
+ GFP_KERNEL);
if (!priv->chan[i].fifo) {
dev_err(dev, "failed to allocate request fifo %d\n", i);
err = -ENOMEM;
diff --git a/drivers/crypto/virtio/virtio_crypto_algs.c b/drivers/crypto/virtio/virtio_crypto_algs.c
index ba190cf..af6a908 100644
--- a/drivers/crypto/virtio/virtio_crypto_algs.c
+++ b/drivers/crypto/virtio/virtio_crypto_algs.c
@@ -371,7 +371,7 @@ __virtio_crypto_ablkcipher_do_req(struct virtio_crypto_sym_request *vc_sym_req,
/* Why 3? outhdr + iv + inhdr */
sg_total = src_nents + dst_nents + 3;
- sgs = kzalloc_node(sg_total * sizeof(*sgs), GFP_ATOMIC,
+ sgs = kcalloc_node(sg_total, sizeof(*sgs), GFP_ATOMIC,
dev_to_node(&vcrypto->vdev->dev));
if (!sgs)
return -ENOMEM;
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index fe2af6a..0b5b3ab 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -628,14 +628,15 @@ struct devfreq *devfreq_add_device(struct device *dev,
goto err_dev;
}
- devfreq->trans_table = devm_kzalloc(&devfreq->dev,
- sizeof(unsigned int) *
- devfreq->profile->max_state *
- devfreq->profile->max_state,
- GFP_KERNEL);
- devfreq->time_in_state = devm_kzalloc(&devfreq->dev,
- sizeof(unsigned long) *
+ devfreq->trans_table =
+ devm_kzalloc(&devfreq->dev,
+ array3_size(sizeof(unsigned int),
+ devfreq->profile->max_state,
+ devfreq->profile->max_state),
+ GFP_KERNEL);
+ devfreq->time_in_state = devm_kcalloc(&devfreq->dev,
devfreq->profile->max_state,
+ sizeof(unsigned long),
GFP_KERNEL);
devfreq->last_stat_updated = jiffies;
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index d96e3dc..3cd6a18 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -518,7 +518,7 @@ static int of_get_devfreq_events(struct device_node *np,
event_ops = exynos_bus_get_ops(np);
count = of_get_child_count(events_np);
- desc = devm_kzalloc(dev, sizeof(*desc) * count, GFP_KERNEL);
+ desc = devm_kcalloc(dev, count, sizeof(*desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
info->num_events = count;
diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c
index 7a67b83..d91cbbe 100644
--- a/drivers/dma/bestcomm/bestcomm.c
+++ b/drivers/dma/bestcomm/bestcomm.c
@@ -87,7 +87,8 @@ bcom_task_alloc(int bd_count, int bd_size, int priv_size)
/* Init the BDs, if needed */
if (bd_count) {
- tsk->cookie = kmalloc(sizeof(void*) * bd_count, GFP_KERNEL);
+ tsk->cookie = kmalloc_array(bd_count, sizeof(void *),
+ GFP_KERNEL);
if (!tsk->cookie)
goto error;
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index b451354..08ba847 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -38,7 +38,7 @@
* Each device has a channels list, which runs unlocked but is never modified
* once the device is registered, it's just setup by the driver.
*
- * See Documentation/dmaengine.txt for more details
+ * See Documentation/driver-api/dmaengine for more details
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c
index 7792a91..4fa4c06 100644
--- a/drivers/dma/ioat/init.c
+++ b/drivers/dma/ioat/init.c
@@ -322,10 +322,10 @@ static int ioat_dma_self_test(struct ioatdma_device *ioat_dma)
unsigned long tmo;
unsigned long flags;
- src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
+ src = kzalloc(IOAT_TEST_SIZE, GFP_KERNEL);
if (!src)
return -ENOMEM;
- dest = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL);
+ dest = kzalloc(IOAT_TEST_SIZE, GFP_KERNEL);
if (!dest) {
kfree(src);
return -ENOMEM;
diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c
index ed76044..bbff52b 100644
--- a/drivers/dma/ipu/ipu_idmac.c
+++ b/drivers/dma/ipu/ipu_idmac.c
@@ -910,7 +910,8 @@ out:
/* Called with ichan->chan_mutex held */
static int idmac_desc_alloc(struct idmac_channel *ichan, int n)
{
- struct idmac_tx_desc *desc = vmalloc(n * sizeof(struct idmac_tx_desc));
+ struct idmac_tx_desc *desc =
+ vmalloc(array_size(n, sizeof(struct idmac_tx_desc)));
struct idmac *idmac = to_idmac(ichan->dma_chan.device);
if (!desc)
diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c
index 26b6745..fa31ccc 100644
--- a/drivers/dma/k3dma.c
+++ b/drivers/dma/k3dma.c
@@ -848,8 +848,8 @@ static int k3_dma_probe(struct platform_device *op)
return -ENOMEM;
/* init phy channel */
- d->phy = devm_kzalloc(&op->dev,
- d->dma_channels * sizeof(struct k3_dma_phy), GFP_KERNEL);
+ d->phy = devm_kcalloc(&op->dev,
+ d->dma_channels, sizeof(struct k3_dma_phy), GFP_KERNEL);
if (d->phy == NULL)
return -ENOMEM;
@@ -879,8 +879,8 @@ static int k3_dma_probe(struct platform_device *op)
d->slave.copy_align = DMAENGINE_ALIGN_8_BYTES;
/* init virtual channel */
- d->chans = devm_kzalloc(&op->dev,
- d->dma_requests * sizeof(struct k3_dma_chan), GFP_KERNEL);
+ d->chans = devm_kcalloc(&op->dev,
+ d->dma_requests, sizeof(struct k3_dma_chan), GFP_KERNEL);
if (d->chans == NULL)
return -ENOMEM;
diff --git a/drivers/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c
index 94d7bd7..68dd797 100644
--- a/drivers/dma/mic_x100_dma.c
+++ b/drivers/dma/mic_x100_dma.c
@@ -385,7 +385,8 @@ static int mic_dma_alloc_desc_ring(struct mic_dma_chan *ch)
if (dma_mapping_error(dev, ch->desc_ring_micpa))
goto map_error;
- ch->tx_array = vzalloc(MIC_DMA_DESC_RX_SIZE * sizeof(*ch->tx_array));
+ ch->tx_array = vzalloc(array_size(MIC_DMA_DESC_RX_SIZE,
+ sizeof(*ch->tx_array)));
if (!ch->tx_array)
goto tx_error;
return 0;
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 1993889..969534c 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -777,11 +777,11 @@ static int mv_chan_memcpy_self_test(struct mv_xor_chan *mv_chan)
struct dmaengine_unmap_data *unmap;
int err = 0;
- src = kmalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL);
+ src = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!src)
return -ENOMEM;
- dest = kzalloc(sizeof(u8) * PAGE_SIZE, GFP_KERNEL);
+ dest = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!dest) {
kfree(src);
return -ENOMEM;
diff --git a/drivers/dma/mv_xor_v2.c b/drivers/dma/mv_xor_v2.c
index 3548caa..c6589cc 100644
--- a/drivers/dma/mv_xor_v2.c
+++ b/drivers/dma/mv_xor_v2.c
@@ -809,8 +809,9 @@ static int mv_xor_v2_probe(struct platform_device *pdev)
}
/* alloc memory for the SW descriptors */
- xor_dev->sw_desq = devm_kzalloc(&pdev->dev, sizeof(*sw_desc) *
- MV_XOR_V2_DESC_NUM, GFP_KERNEL);
+ xor_dev->sw_desq = devm_kcalloc(&pdev->dev,
+ MV_XOR_V2_DESC_NUM, sizeof(*sw_desc),
+ GFP_KERNEL);
if (!xor_dev->sw_desq) {
ret = -ENOMEM;
goto free_hw_desq;
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 6237069..defcdde 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -1866,7 +1866,7 @@ static int dmac_alloc_threads(struct pl330_dmac *pl330)
int i;
/* Allocate 1 Manager and 'chans' Channel threads */
- pl330->channels = kzalloc((1 + chans) * sizeof(*thrd),
+ pl330->channels = kcalloc(1 + chans, sizeof(*thrd),
GFP_KERNEL);
if (!pl330->channels)
return -ENOMEM;
@@ -2990,7 +2990,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
pl330->num_peripherals = num_chan;
- pl330->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
+ pl330->peripherals = kcalloc(num_chan, sizeof(*pch), GFP_KERNEL);
if (!pl330->peripherals) {
ret = -ENOMEM;
goto probe_err2;
diff --git a/drivers/dma/s3c24xx-dma.c b/drivers/dma/s3c24xx-dma.c
index cd92d69..7056fe7 100644
--- a/drivers/dma/s3c24xx-dma.c
+++ b/drivers/dma/s3c24xx-dma.c
@@ -1223,9 +1223,9 @@ static int s3c24xx_dma_probe(struct platform_device *pdev)
if (IS_ERR(s3cdma->base))
return PTR_ERR(s3cdma->base);
- s3cdma->phy_chans = devm_kzalloc(&pdev->dev,
- sizeof(struct s3c24xx_dma_phy) *
- pdata->num_phy_channels,
+ s3cdma->phy_chans = devm_kcalloc(&pdev->dev,
+ pdata->num_phy_channels,
+ sizeof(struct s3c24xx_dma_phy),
GFP_KERNEL);
if (!s3cdma->phy_chans)
return -ENOMEM;
diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index 12fa48e..6b5626e 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -1045,8 +1045,9 @@ EXPORT_SYMBOL(shdma_cleanup);
static int __init shdma_enter(void)
{
- shdma_slave_used = kzalloc(DIV_ROUND_UP(slave_num, BITS_PER_LONG) *
- sizeof(long), GFP_KERNEL);
+ shdma_slave_used = kcalloc(DIV_ROUND_UP(slave_num, BITS_PER_LONG),
+ sizeof(long),
+ GFP_KERNEL);
if (!shdma_slave_used)
return -ENOMEM;
return 0;
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index f146458..c74a88b 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -471,7 +471,7 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan)
if (ret < 0)
return ret;
- chan->sw_desc_pool = kzalloc(sizeof(*desc) * ZYNQMP_DMA_NUM_DESCS,
+ chan->sw_desc_pool = kcalloc(ZYNQMP_DMA_NUM_DESCS, sizeof(*desc),
GFP_KERNEL);
if (!chan->sw_desc_pool)
return -ENOMEM;
diff --git a/drivers/dma/zx_dma.c b/drivers/dma/zx_dma.c
index 2bb6953..2571bc7 100644
--- a/drivers/dma/zx_dma.c
+++ b/drivers/dma/zx_dma.c
@@ -798,8 +798,8 @@ static int zx_dma_probe(struct platform_device *op)
return -ENOMEM;
/* init phy channel */
- d->phy = devm_kzalloc(&op->dev,
- d->dma_channels * sizeof(struct zx_dma_phy), GFP_KERNEL);
+ d->phy = devm_kcalloc(&op->dev,
+ d->dma_channels, sizeof(struct zx_dma_phy), GFP_KERNEL);
if (!d->phy)
return -ENOMEM;
@@ -834,8 +834,8 @@ static int zx_dma_probe(struct platform_device *op)
d->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
/* init virtual channel */
- d->chans = devm_kzalloc(&op->dev,
- d->dma_requests * sizeof(struct zx_dma_chan), GFP_KERNEL);
+ d->chans = devm_kcalloc(&op->dev,
+ d->dma_requests, sizeof(struct zx_dma_chan), GFP_KERNEL);
if (!d->chans)
return -ENOMEM;
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 329cb96..18aeabb 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -3451,7 +3451,7 @@ static int __init amd64_edac_init(void)
opstate_init();
err = -ENOMEM;
- ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL);
+ ecc_stngs = kcalloc(amd_nb_num(), sizeof(ecc_stngs[0]), GFP_KERNEL);
if (!ecc_stngs)
goto err_free;
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 4d0ea35..8ed4dd9 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -461,7 +461,7 @@ static struct i7core_dev *alloc_i7core_dev(u8 socket,
if (!i7core_dev)
return NULL;
- i7core_dev->pdev = kzalloc(sizeof(*i7core_dev->pdev) * table->n_devs,
+ i7core_dev->pdev = kcalloc(table->n_devs, sizeof(*i7core_dev->pdev),
GFP_KERNEL);
if (!i7core_dev->pdev) {
kfree(i7core_dev);
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
index 8bff5fd..af83ad5 100644
--- a/drivers/extcon/extcon.c
+++ b/drivers/extcon/extcon.c
@@ -1126,8 +1126,9 @@ int extcon_dev_register(struct extcon_dev *edev)
char *str;
struct extcon_cable *cable;
- edev->cables = kzalloc(sizeof(struct extcon_cable) *
- edev->max_supported, GFP_KERNEL);
+ edev->cables = kcalloc(edev->max_supported,
+ sizeof(struct extcon_cable),
+ GFP_KERNEL);
if (!edev->cables) {
ret = -ENOMEM;
goto err_sysfs_alloc;
@@ -1136,7 +1137,7 @@ int extcon_dev_register(struct extcon_dev *edev)
cable = &edev->cables[index];
snprintf(buf, 10, "cable.%d", index);
- str = kzalloc(sizeof(char) * (strlen(buf) + 1),
+ str = kzalloc(strlen(buf) + 1,
GFP_KERNEL);
if (!str) {
for (index--; index >= 0; index--) {
@@ -1177,15 +1178,17 @@ int extcon_dev_register(struct extcon_dev *edev)
for (index = 0; edev->mutually_exclusive[index]; index++)
;
- edev->attrs_muex = kzalloc(sizeof(struct attribute *) *
- (index + 1), GFP_KERNEL);
+ edev->attrs_muex = kcalloc(index + 1,
+ sizeof(struct attribute *),
+ GFP_KERNEL);
if (!edev->attrs_muex) {
ret = -ENOMEM;
goto err_muex;
}
- edev->d_attrs_muex = kzalloc(sizeof(struct device_attribute) *
- index, GFP_KERNEL);
+ edev->d_attrs_muex = kcalloc(index,
+ sizeof(struct device_attribute),
+ GFP_KERNEL);
if (!edev->d_attrs_muex) {
ret = -ENOMEM;
kfree(edev->attrs_muex);
@@ -1194,7 +1197,7 @@ int extcon_dev_register(struct extcon_dev *edev)
for (index = 0; edev->mutually_exclusive[index]; index++) {
sprintf(buf, "0x%x", edev->mutually_exclusive[index]);
- name = kzalloc(sizeof(char) * (strlen(buf) + 1),
+ name = kzalloc(strlen(buf) + 1,
GFP_KERNEL);
if (!name) {
for (index--; index >= 0; index--) {
@@ -1220,8 +1223,9 @@ int extcon_dev_register(struct extcon_dev *edev)
if (edev->max_supported) {
edev->extcon_dev_type.groups =
- kzalloc(sizeof(struct attribute_group *) *
- (edev->max_supported + 2), GFP_KERNEL);
+ kcalloc(edev->max_supported + 2,
+ sizeof(struct attribute_group *),
+ GFP_KERNEL);
if (!edev->extcon_dev_type.groups) {
ret = -ENOMEM;
goto err_alloc_groups;
diff --git a/drivers/firewire/core-iso.c b/drivers/firewire/core-iso.c
index 38c0aa6..051327a 100644
--- a/drivers/firewire/core-iso.c
+++ b/drivers/firewire/core-iso.c
@@ -45,8 +45,8 @@ int fw_iso_buffer_alloc(struct fw_iso_buffer *buffer, int page_count)
buffer->page_count = 0;
buffer->page_count_mapped = 0;
- buffer->pages = kmalloc(page_count * sizeof(buffer->pages[0]),
- GFP_KERNEL);
+ buffer->pages = kmalloc_array(page_count, sizeof(buffer->pages[0]),
+ GFP_KERNEL);
if (buffer->pages == NULL)
return -ENOMEM;
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index 60e75e6..82ba110 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -1121,7 +1121,7 @@ static int fwnet_broadcast_start(struct fwnet_device *dev)
max_receive = 1U << (dev->card->max_receive + 1);
num_packets = (FWNET_ISO_PAGE_COUNT * PAGE_SIZE) / max_receive;
- ptrptr = kmalloc(sizeof(void *) * num_packets, GFP_KERNEL);
+ ptrptr = kmalloc_array(num_packets, sizeof(void *), GFP_KERNEL);
if (!ptrptr) {
retval = -ENOMEM;
goto failed;
diff --git a/drivers/firmware/arm_scmi/base.c b/drivers/firmware/arm_scmi/base.c
index 0d3806c..9dff33e 100644
--- a/drivers/firmware/arm_scmi/base.c
+++ b/drivers/firmware/arm_scmi/base.c
@@ -26,7 +26,7 @@ struct scmi_msg_resp_base_attributes {
* scmi_base_attributes_get() - gets the implementation details
* that are associated with the base protocol.
*
- * @handle - SCMI entity handle
+ * @handle: SCMI entity handle
*
* Return: 0 on success, else appropriate SCMI error.
*/
@@ -37,7 +37,7 @@ static int scmi_base_attributes_get(const struct scmi_handle *handle)
struct scmi_msg_resp_base_attributes *attr_info;
struct scmi_revision_info *rev = handle->version;
- ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+ ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
SCMI_PROTOCOL_BASE, 0, sizeof(*attr_info), &t);
if (ret)
return ret;
@@ -49,15 +49,16 @@ static int scmi_base_attributes_get(const struct scmi_handle *handle)
rev->num_agents = attr_info->num_agents;
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
+
return ret;
}
/**
* scmi_base_vendor_id_get() - gets vendor/subvendor identifier ASCII string.
*
- * @handle - SCMI entity handle
- * @sub_vendor - specify true if sub-vendor ID is needed
+ * @handle: SCMI entity handle
+ * @sub_vendor: specify true if sub-vendor ID is needed
*
* Return: 0 on success, else appropriate SCMI error.
*/
@@ -80,7 +81,7 @@ scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
size = ARRAY_SIZE(rev->vendor_id);
}
- ret = scmi_one_xfer_init(handle, cmd, SCMI_PROTOCOL_BASE, 0, size, &t);
+ ret = scmi_xfer_get_init(handle, cmd, SCMI_PROTOCOL_BASE, 0, size, &t);
if (ret)
return ret;
@@ -88,7 +89,8 @@ scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
if (!ret)
memcpy(vendor_id, t->rx.buf, size);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
+
return ret;
}
@@ -97,7 +99,7 @@ scmi_base_vendor_id_get(const struct scmi_handle *handle, bool sub_vendor)
* implementation 32-bit version. The format of the version number is
* vendor-specific
*
- * @handle - SCMI entity handle
+ * @handle: SCMI entity handle
*
* Return: 0 on success, else appropriate SCMI error.
*/
@@ -109,7 +111,7 @@ scmi_base_implementation_version_get(const struct scmi_handle *handle)
struct scmi_xfer *t;
struct scmi_revision_info *rev = handle->version;
- ret = scmi_one_xfer_init(handle, BASE_DISCOVER_IMPLEMENT_VERSION,
+ ret = scmi_xfer_get_init(handle, BASE_DISCOVER_IMPLEMENT_VERSION,
SCMI_PROTOCOL_BASE, 0, sizeof(*impl_ver), &t);
if (ret)
return ret;
@@ -120,7 +122,8 @@ scmi_base_implementation_version_get(const struct scmi_handle *handle)
rev->impl_ver = le32_to_cpu(*impl_ver);
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
+
return ret;
}
@@ -128,8 +131,8 @@ scmi_base_implementation_version_get(const struct scmi_handle *handle)
* scmi_base_implementation_list_get() - gets the list of protocols it is
* OSPM is allowed to access
*
- * @handle - SCMI entity handle
- * @protocols_imp - pointer to hold the list of protocol identifiers
+ * @handle: SCMI entity handle
+ * @protocols_imp: pointer to hold the list of protocol identifiers
*
* Return: 0 on success, else appropriate SCMI error.
*/
@@ -143,7 +146,7 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
u32 tot_num_ret = 0, loop_num_ret;
struct device *dev = handle->dev;
- ret = scmi_one_xfer_init(handle, BASE_DISCOVER_LIST_PROTOCOLS,
+ ret = scmi_xfer_get_init(handle, BASE_DISCOVER_LIST_PROTOCOLS,
SCMI_PROTOCOL_BASE, sizeof(*num_skip), 0, &t);
if (ret)
return ret;
@@ -172,16 +175,17 @@ static int scmi_base_implementation_list_get(const struct scmi_handle *handle,
tot_num_ret += loop_num_ret;
} while (loop_num_ret);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
+
return ret;
}
/**
* scmi_base_discover_agent_get() - discover the name of an agent
*
- * @handle - SCMI entity handle
- * @id - Agent identifier
- * @name - Agent identifier ASCII string
+ * @handle: SCMI entity handle
+ * @id: Agent identifier
+ * @name: Agent identifier ASCII string
*
* An agent id of 0 is reserved to identify the platform itself.
* Generally operating system is represented as "OSPM"
@@ -194,7 +198,7 @@ static int scmi_base_discover_agent_get(const struct scmi_handle *handle,
int ret;
struct scmi_xfer *t;
- ret = scmi_one_xfer_init(handle, BASE_DISCOVER_AGENT,
+ ret = scmi_xfer_get_init(handle, BASE_DISCOVER_AGENT,
SCMI_PROTOCOL_BASE, sizeof(__le32),
SCMI_MAX_STR_SIZE, &t);
if (ret)
@@ -206,7 +210,8 @@ static int scmi_base_discover_agent_get(const struct scmi_handle *handle,
if (!ret)
memcpy(name, t->rx.buf, SCMI_MAX_STR_SIZE);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
+
return ret;
}
diff --git a/drivers/firmware/arm_scmi/bus.c b/drivers/firmware/arm_scmi/bus.c
index f2760a5..472c88a 100644
--- a/drivers/firmware/arm_scmi/bus.c
+++ b/drivers/firmware/arm_scmi/bus.c
@@ -125,13 +125,13 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
int id, retval;
struct scmi_device *scmi_dev;
- id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
- if (id < 0)
- return NULL;
-
scmi_dev = kzalloc(sizeof(*scmi_dev), GFP_KERNEL);
if (!scmi_dev)
- goto no_mem;
+ return NULL;
+
+ id = ida_simple_get(&scmi_bus_id, 1, 0, GFP_KERNEL);
+ if (id < 0)
+ goto free_mem;
scmi_dev->id = id;
scmi_dev->protocol_id = protocol;
@@ -141,13 +141,15 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
retval = device_register(&scmi_dev->dev);
- if (!retval)
- return scmi_dev;
+ if (retval)
+ goto put_dev;
+ return scmi_dev;
+put_dev:
put_device(&scmi_dev->dev);
- kfree(scmi_dev);
-no_mem:
ida_simple_remove(&scmi_bus_id, id);
+free_mem:
+ kfree(scmi_dev);
return NULL;
}
@@ -171,9 +173,9 @@ int scmi_protocol_register(int protocol_id, scmi_prot_init_fn_t fn)
spin_lock(&protocol_lock);
ret = idr_alloc(&scmi_protocols, fn, protocol_id, protocol_id + 1,
GFP_ATOMIC);
+ spin_unlock(&protocol_lock);
if (ret != protocol_id)
pr_err("unable to allocate SCMI idr slot, err %d\n", ret);
- spin_unlock(&protocol_lock);
return ret;
}
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index 2b90606..e4119eb 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -77,7 +77,7 @@ static int scmi_clock_protocol_attributes_get(const struct scmi_handle *handle,
struct scmi_xfer *t;
struct scmi_msg_resp_clock_protocol_attributes *attr;
- ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+ ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
SCMI_PROTOCOL_CLOCK, 0, sizeof(*attr), &t);
if (ret)
return ret;
@@ -90,7 +90,7 @@ static int scmi_clock_protocol_attributes_get(const struct scmi_handle *handle,
ci->max_async_req = attr->max_async_req;
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -101,7 +101,7 @@ static int scmi_clock_attributes_get(const struct scmi_handle *handle,
struct scmi_xfer *t;
struct scmi_msg_resp_clock_attributes *attr;
- ret = scmi_one_xfer_init(handle, CLOCK_ATTRIBUTES, SCMI_PROTOCOL_CLOCK,
+ ret = scmi_xfer_get_init(handle, CLOCK_ATTRIBUTES, SCMI_PROTOCOL_CLOCK,
sizeof(clk_id), sizeof(*attr), &t);
if (ret)
return ret;
@@ -115,7 +115,7 @@ static int scmi_clock_attributes_get(const struct scmi_handle *handle,
else
clk->name[0] = '\0';
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -132,7 +132,7 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id,
struct scmi_msg_clock_describe_rates *clk_desc;
struct scmi_msg_resp_clock_describe_rates *rlist;
- ret = scmi_one_xfer_init(handle, CLOCK_DESCRIBE_RATES,
+ ret = scmi_xfer_get_init(handle, CLOCK_DESCRIBE_RATES,
SCMI_PROTOCOL_CLOCK, sizeof(*clk_desc), 0, &t);
if (ret)
return ret;
@@ -186,7 +186,7 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id,
clk->list.num_rates = tot_rate_cnt;
err:
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -196,7 +196,7 @@ scmi_clock_rate_get(const struct scmi_handle *handle, u32 clk_id, u64 *value)
int ret;
struct scmi_xfer *t;
- ret = scmi_one_xfer_init(handle, CLOCK_RATE_GET, SCMI_PROTOCOL_CLOCK,
+ ret = scmi_xfer_get_init(handle, CLOCK_RATE_GET, SCMI_PROTOCOL_CLOCK,
sizeof(__le32), sizeof(u64), &t);
if (ret)
return ret;
@@ -211,7 +211,7 @@ scmi_clock_rate_get(const struct scmi_handle *handle, u32 clk_id, u64 *value)
*value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -222,7 +222,7 @@ static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id,
struct scmi_xfer *t;
struct scmi_clock_set_rate *cfg;
- ret = scmi_one_xfer_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK,
+ ret = scmi_xfer_get_init(handle, CLOCK_RATE_SET, SCMI_PROTOCOL_CLOCK,
sizeof(*cfg), 0, &t);
if (ret)
return ret;
@@ -235,7 +235,7 @@ static int scmi_clock_rate_set(const struct scmi_handle *handle, u32 clk_id,
ret = scmi_do_xfer(handle, t);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -246,7 +246,7 @@ scmi_clock_config_set(const struct scmi_handle *handle, u32 clk_id, u32 config)
struct scmi_xfer *t;
struct scmi_clock_set_config *cfg;
- ret = scmi_one_xfer_init(handle, CLOCK_CONFIG_SET, SCMI_PROTOCOL_CLOCK,
+ ret = scmi_xfer_get_init(handle, CLOCK_CONFIG_SET, SCMI_PROTOCOL_CLOCK,
sizeof(*cfg), 0, &t);
if (ret)
return ret;
@@ -257,7 +257,7 @@ scmi_clock_config_set(const struct scmi_handle *handle, u32 clk_id, u32 config)
ret = scmi_do_xfer(handle, t);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
diff --git a/drivers/firmware/arm_scmi/common.h b/drivers/firmware/arm_scmi/common.h
index 0c30234..937a930 100644
--- a/drivers/firmware/arm_scmi/common.h
+++ b/drivers/firmware/arm_scmi/common.h
@@ -7,6 +7,7 @@
* Copyright (C) 2018 ARM Ltd.
*/
+#include <linux/bitfield.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/errno.h>
@@ -14,10 +15,10 @@
#include <linux/scmi_protocol.h>
#include <linux/types.h>
-#define PROTOCOL_REV_MINOR_BITS 16
-#define PROTOCOL_REV_MINOR_MASK ((1U << PROTOCOL_REV_MINOR_BITS) - 1)
-#define PROTOCOL_REV_MAJOR(x) ((x) >> PROTOCOL_REV_MINOR_BITS)
-#define PROTOCOL_REV_MINOR(x) ((x) & PROTOCOL_REV_MINOR_MASK)
+#define PROTOCOL_REV_MINOR_MASK GENMASK(15, 0)
+#define PROTOCOL_REV_MAJOR_MASK GENMASK(31, 16)
+#define PROTOCOL_REV_MAJOR(x) (u16)(FIELD_GET(PROTOCOL_REV_MAJOR_MASK, (x)))
+#define PROTOCOL_REV_MINOR(x) (u16)(FIELD_GET(PROTOCOL_REV_MINOR_MASK, (x)))
#define MAX_PROTOCOLS_IMP 16
#define MAX_OPPS 16
@@ -50,8 +51,11 @@ struct scmi_msg_resp_prot_version {
* @id: The identifier of the command being sent
* @protocol_id: The identifier of the protocol used to send @id command
* @seq: The token to identify the message. when a message/command returns,
- * the platform returns the whole message header unmodified including
- * the token.
+ * the platform returns the whole message header unmodified including
+ * the token
+ * @status: Status of the transfer once it's complete
+ * @poll_completion: Indicate if the transfer needs to be polled for
+ * completion or interrupt mode is used
*/
struct scmi_msg_hdr {
u8 id;
@@ -82,18 +86,16 @@ struct scmi_msg {
* buffer for the rx path as we use for the tx path.
* @done: completion event
*/
-
struct scmi_xfer {
- void *con_priv;
struct scmi_msg_hdr hdr;
struct scmi_msg tx;
struct scmi_msg rx;
struct completion done;
};
-void scmi_one_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
+void scmi_xfer_put(const struct scmi_handle *h, struct scmi_xfer *xfer);
int scmi_do_xfer(const struct scmi_handle *h, struct scmi_xfer *xfer);
-int scmi_one_xfer_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
+int scmi_xfer_get_init(const struct scmi_handle *h, u8 msg_id, u8 prot_id,
size_t tx_size, size_t rx_size, struct scmi_xfer **p);
int scmi_handle_put(const struct scmi_handle *handle);
struct scmi_handle *scmi_handle_get(struct device *dev);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 2455be8..8f952f2 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -29,16 +29,12 @@
#include "common.h"
-#define MSG_ID_SHIFT 0
-#define MSG_ID_MASK 0xff
-#define MSG_TYPE_SHIFT 8
-#define MSG_TYPE_MASK 0x3
-#define MSG_PROTOCOL_ID_SHIFT 10
-#define MSG_PROTOCOL_ID_MASK 0xff
-#define MSG_TOKEN_ID_SHIFT 18
-#define MSG_TOKEN_ID_MASK 0x3ff
-#define MSG_XTRACT_TOKEN(header) \
- (((header) >> MSG_TOKEN_ID_SHIFT) & MSG_TOKEN_ID_MASK)
+#define MSG_ID_MASK GENMASK(7, 0)
+#define MSG_TYPE_MASK GENMASK(9, 8)
+#define MSG_PROTOCOL_ID_MASK GENMASK(17, 10)
+#define MSG_TOKEN_ID_MASK GENMASK(27, 18)
+#define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr))
+#define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1)
enum scmi_error_codes {
SCMI_SUCCESS = 0, /* Success */
@@ -55,7 +51,7 @@ enum scmi_error_codes {
SCMI_ERR_MAX
};
-/* List of all SCMI devices active in system */
+/* List of all SCMI devices active in system */
static LIST_HEAD(scmi_list);
/* Protection for the entire list */
static DEFINE_MUTEX(scmi_list_mutex);
@@ -72,7 +68,6 @@ static DEFINE_MUTEX(scmi_list_mutex);
struct scmi_xfers_info {
struct scmi_xfer *xfer_block;
unsigned long *xfer_alloc_table;
- /* protect transfer allocation */
spinlock_t xfer_lock;
};
@@ -98,6 +93,7 @@ struct scmi_desc {
* @payload: Transmit/Receive mailbox channel payload area
* @dev: Reference to device in the SCMI hierarchy corresponding to this
* channel
+ * @handle: Pointer to SCMI entity handle
*/
struct scmi_chan_info {
struct mbox_client cl;
@@ -108,7 +104,7 @@ struct scmi_chan_info {
};
/**
- * struct scmi_info - Structure representing a SCMI instance
+ * struct scmi_info - Structure representing a SCMI instance
*
* @dev: Device pointer
* @desc: SoC description for this instance
@@ -117,9 +113,9 @@ struct scmi_chan_info {
* implementation version and (sub-)vendor identification.
* @minfo: Message info
* @tx_idr: IDR object to map protocol id to channel info pointer
- * @protocols_imp: list of protocols implemented, currently maximum of
+ * @protocols_imp: List of protocols implemented, currently maximum of
* MAX_PROTOCOLS_IMP elements allocated by the base protocol
- * @node: list head
+ * @node: List head
* @users: Number of users of this instance
*/
struct scmi_info {
@@ -225,9 +221,7 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m)
xfer_id = MSG_XTRACT_TOKEN(ioread32(&mem->msg_header));
- /*
- * Are we even expecting this?
- */
+ /* Are we even expecting this? */
if (!test_bit(xfer_id, minfo->xfer_alloc_table)) {
dev_err(dev, "message for %d is not expected!\n", xfer_id);
return;
@@ -252,12 +246,14 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m)
*
* @hdr: pointer to header containing all the information on message id,
* protocol id and sequence id.
+ *
+ * Return: 32-bit packed command header to be sent to the platform.
*/
static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
{
- return ((hdr->id & MSG_ID_MASK) << MSG_ID_SHIFT) |
- ((hdr->seq & MSG_TOKEN_ID_MASK) << MSG_TOKEN_ID_SHIFT) |
- ((hdr->protocol_id & MSG_PROTOCOL_ID_MASK) << MSG_PROTOCOL_ID_SHIFT);
+ return FIELD_PREP(MSG_ID_MASK, hdr->id) |
+ FIELD_PREP(MSG_TOKEN_ID_MASK, hdr->seq) |
+ FIELD_PREP(MSG_PROTOCOL_ID_MASK, hdr->protocol_id);
}
/**
@@ -286,9 +282,9 @@ static void scmi_tx_prepare(struct mbox_client *cl, void *m)
}
/**
- * scmi_one_xfer_get() - Allocate one message
+ * scmi_xfer_get() - Allocate one message
*
- * @handle: SCMI entity handle
+ * @handle: Pointer to SCMI entity handle
*
* Helper function which is used by various command functions that are
* exposed to clients of this driver for allocating a message traffic event.
@@ -299,7 +295,7 @@ static void scmi_tx_prepare(struct mbox_client *cl, void *m)
*
* Return: 0 if all went fine, else corresponding error.
*/
-static struct scmi_xfer *scmi_one_xfer_get(const struct scmi_handle *handle)
+static struct scmi_xfer *scmi_xfer_get(const struct scmi_handle *handle)
{
u16 xfer_id;
struct scmi_xfer *xfer;
@@ -328,14 +324,14 @@ static struct scmi_xfer *scmi_one_xfer_get(const struct scmi_handle *handle)
}
/**
- * scmi_one_xfer_put() - Release a message
+ * scmi_xfer_put() - Release a message
*
- * @minfo: transfer info pointer
- * @xfer: message that was reserved by scmi_one_xfer_get
+ * @handle: Pointer to SCMI entity handle
+ * @xfer: message that was reserved by scmi_xfer_get
*
* This holds a spinlock to maintain integrity of internal data structures.
*/
-void scmi_one_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
+void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer)
{
unsigned long flags;
struct scmi_info *info = handle_to_scmi_info(handle);
@@ -378,12 +374,12 @@ static bool scmi_xfer_done_no_timeout(const struct scmi_chan_info *cinfo,
/**
* scmi_do_xfer() - Do one transfer
*
- * @info: Pointer to SCMI entity information
+ * @handle: Pointer to SCMI entity handle
* @xfer: Transfer to initiate and wait for response
*
* Return: -ETIMEDOUT in case of no response, if transmit error,
- * return corresponding error, else if all goes well,
- * return 0.
+ * return corresponding error, else if all goes well,
+ * return 0.
*/
int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
{
@@ -440,22 +436,22 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer)
}
/**
- * scmi_one_xfer_init() - Allocate and initialise one message
+ * scmi_xfer_get_init() - Allocate and initialise one message
*
- * @handle: SCMI entity handle
+ * @handle: Pointer to SCMI entity handle
* @msg_id: Message identifier
- * @msg_prot_id: Protocol identifier for the message
+ * @prot_id: Protocol identifier for the message
* @tx_size: transmit message size
* @rx_size: receive message size
* @p: pointer to the allocated and initialised message
*
- * This function allocates the message using @scmi_one_xfer_get and
+ * This function allocates the message using @scmi_xfer_get and
* initialise the header.
*
* Return: 0 if all went fine with @p pointing to message, else
* corresponding error.
*/
-int scmi_one_xfer_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
+int scmi_xfer_get_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
size_t tx_size, size_t rx_size, struct scmi_xfer **p)
{
int ret;
@@ -468,7 +464,7 @@ int scmi_one_xfer_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
tx_size > info->desc->max_msg_size)
return -ERANGE;
- xfer = scmi_one_xfer_get(handle);
+ xfer = scmi_xfer_get(handle);
if (IS_ERR(xfer)) {
ret = PTR_ERR(xfer);
dev_err(dev, "failed to get free message slot(%d)\n", ret);
@@ -482,13 +478,16 @@ int scmi_one_xfer_init(const struct scmi_handle *handle, u8 msg_id, u8 prot_id,
xfer->hdr.poll_completion = false;
*p = xfer;
+
return 0;
}
/**
* scmi_version_get() - command to get the revision of the SCMI entity
*
- * @handle: Handle to SCMI entity information
+ * @handle: Pointer to SCMI entity handle
+ * @protocol: Protocol identifier for the message
+ * @version: Holds returned version of protocol.
*
* Updates the SCMI information in the internal data structure.
*
@@ -501,7 +500,7 @@ int scmi_version_get(const struct scmi_handle *handle, u8 protocol,
__le32 *rev_info;
struct scmi_xfer *t;
- ret = scmi_one_xfer_init(handle, PROTOCOL_VERSION, protocol, 0,
+ ret = scmi_xfer_get_init(handle, PROTOCOL_VERSION, protocol, 0,
sizeof(*version), &t);
if (ret)
return ret;
@@ -512,7 +511,7 @@ int scmi_version_get(const struct scmi_handle *handle, u8 protocol,
*version = le32_to_cpu(*rev_info);
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -540,12 +539,12 @@ scmi_is_protocol_implemented(const struct scmi_handle *handle, u8 prot_id)
}
/**
- * scmi_handle_get() - Get the SCMI handle for a device
+ * scmi_handle_get() - Get the SCMI handle for a device
*
* @dev: pointer to device for which we want SCMI handle
*
* NOTE: The function does not track individual clients of the framework
- * and is expected to be maintained by caller of SCMI protocol library.
+ * and is expected to be maintained by caller of SCMI protocol library.
* scmi_handle_put must be balanced with successful scmi_handle_get
*
* Return: pointer to handle if successful, NULL on error
@@ -576,7 +575,7 @@ struct scmi_handle *scmi_handle_get(struct device *dev)
* @handle: handle acquired by scmi_handle_get
*
* NOTE: The function does not track individual clients of the framework
- * and is expected to be maintained by caller of SCMI protocol library.
+ * and is expected to be maintained by caller of SCMI protocol library.
* scmi_handle_put must be balanced with successful scmi_handle_get
*
* Return: 0 is successfully released
@@ -599,7 +598,7 @@ int scmi_handle_put(const struct scmi_handle *handle)
}
static const struct scmi_desc scmi_generic_desc = {
- .max_rx_timeout_ms = 30, /* we may increase this if required */
+ .max_rx_timeout_ms = 30, /* We may increase this if required */
.max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */
.max_msg_size = 128,
};
@@ -621,9 +620,9 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
struct scmi_xfers_info *info = &sinfo->minfo;
/* Pre-allocated messages, no more than what hdr.seq can support */
- if (WARN_ON(desc->max_msg >= (MSG_TOKEN_ID_MASK + 1))) {
- dev_err(dev, "Maximum message of %d exceeds supported %d\n",
- desc->max_msg, MSG_TOKEN_ID_MASK + 1);
+ if (WARN_ON(desc->max_msg >= MSG_TOKEN_MAX)) {
+ dev_err(dev, "Maximum message of %d exceeds supported %ld\n",
+ desc->max_msg, MSG_TOKEN_MAX);
return -EINVAL;
}
@@ -637,8 +636,6 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo)
if (!info->xfer_alloc_table)
return -ENOMEM;
- bitmap_zero(info->xfer_alloc_table, desc->max_msg);
-
/* Pre-initialize the buffer pointer to pre-allocated buffers */
for (i = 0, xfer = info->xfer_block; i < desc->max_msg; i++, xfer++) {
xfer->rx.buf = devm_kcalloc(dev, sizeof(u8), desc->max_msg_size,
@@ -690,11 +687,12 @@ static int scmi_remove(struct platform_device *pdev)
list_del(&info->node);
mutex_unlock(&scmi_list_mutex);
- if (!ret) {
- /* Safe to free channels since no more users */
- ret = idr_for_each(idr, scmi_mbox_free_channel, idr);
- idr_destroy(&info->tx_idr);
- }
+ if (ret)
+ return ret;
+
+ /* Safe to free channels since no more users */
+ ret = idr_for_each(idr, scmi_mbox_free_channel, idr);
+ idr_destroy(&info->tx_idr);
return ret;
}
@@ -841,7 +839,8 @@ static int scmi_probe(struct platform_device *pdev)
if (of_property_read_u32(child, "reg", &prot_id))
continue;
- prot_id &= MSG_PROTOCOL_ID_MASK;
+ if (!FIELD_FIT(MSG_PROTOCOL_ID_MASK, prot_id))
+ dev_err(dev, "Out of range protocol %d\n", prot_id);
if (!scmi_is_protocol_implemented(handle, prot_id)) {
dev_err(dev, "SCMI protocol %d not implemented\n",
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 987c64d..2a219b1 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -115,7 +115,7 @@ static int scmi_perf_attributes_get(const struct scmi_handle *handle,
struct scmi_xfer *t;
struct scmi_msg_resp_perf_attributes *attr;
- ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+ ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
SCMI_PROTOCOL_PERF, 0, sizeof(*attr), &t);
if (ret)
return ret;
@@ -133,7 +133,7 @@ static int scmi_perf_attributes_get(const struct scmi_handle *handle,
pi->stats_size = le32_to_cpu(attr->stats_size);
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -145,7 +145,7 @@ scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
struct scmi_xfer *t;
struct scmi_msg_resp_perf_domain_attributes *attr;
- ret = scmi_one_xfer_init(handle, PERF_DOMAIN_ATTRIBUTES,
+ ret = scmi_xfer_get_init(handle, PERF_DOMAIN_ATTRIBUTES,
SCMI_PROTOCOL_PERF, sizeof(domain),
sizeof(*attr), &t);
if (ret)
@@ -171,7 +171,7 @@ scmi_perf_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
memcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -194,7 +194,7 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain,
struct scmi_msg_perf_describe_levels *dom_info;
struct scmi_msg_resp_perf_describe_levels *level_info;
- ret = scmi_one_xfer_init(handle, PERF_DESCRIBE_LEVELS,
+ ret = scmi_xfer_get_init(handle, PERF_DESCRIBE_LEVELS,
SCMI_PROTOCOL_PERF, sizeof(*dom_info), 0, &t);
if (ret)
return ret;
@@ -237,7 +237,7 @@ scmi_perf_describe_levels_get(const struct scmi_handle *handle, u32 domain,
} while (num_returned && num_remaining);
perf_dom->opp_count = tot_opp_cnt;
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
sort(perf_dom->opp, tot_opp_cnt, sizeof(*opp), opp_cmp_func, NULL);
return ret;
@@ -250,7 +250,7 @@ static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain,
struct scmi_xfer *t;
struct scmi_perf_set_limits *limits;
- ret = scmi_one_xfer_init(handle, PERF_LIMITS_SET, SCMI_PROTOCOL_PERF,
+ ret = scmi_xfer_get_init(handle, PERF_LIMITS_SET, SCMI_PROTOCOL_PERF,
sizeof(*limits), 0, &t);
if (ret)
return ret;
@@ -262,7 +262,7 @@ static int scmi_perf_limits_set(const struct scmi_handle *handle, u32 domain,
ret = scmi_do_xfer(handle, t);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -273,7 +273,7 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
struct scmi_xfer *t;
struct scmi_perf_get_limits *limits;
- ret = scmi_one_xfer_init(handle, PERF_LIMITS_GET, SCMI_PROTOCOL_PERF,
+ ret = scmi_xfer_get_init(handle, PERF_LIMITS_GET, SCMI_PROTOCOL_PERF,
sizeof(__le32), 0, &t);
if (ret)
return ret;
@@ -288,7 +288,7 @@ static int scmi_perf_limits_get(const struct scmi_handle *handle, u32 domain,
*min_perf = le32_to_cpu(limits->min_level);
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -299,7 +299,7 @@ static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain,
struct scmi_xfer *t;
struct scmi_perf_set_level *lvl;
- ret = scmi_one_xfer_init(handle, PERF_LEVEL_SET, SCMI_PROTOCOL_PERF,
+ ret = scmi_xfer_get_init(handle, PERF_LEVEL_SET, SCMI_PROTOCOL_PERF,
sizeof(*lvl), 0, &t);
if (ret)
return ret;
@@ -311,7 +311,7 @@ static int scmi_perf_level_set(const struct scmi_handle *handle, u32 domain,
ret = scmi_do_xfer(handle, t);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -321,7 +321,7 @@ static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain,
int ret;
struct scmi_xfer *t;
- ret = scmi_one_xfer_init(handle, PERF_LEVEL_GET, SCMI_PROTOCOL_PERF,
+ ret = scmi_xfer_get_init(handle, PERF_LEVEL_GET, SCMI_PROTOCOL_PERF,
sizeof(u32), sizeof(u32), &t);
if (ret)
return ret;
@@ -333,7 +333,7 @@ static int scmi_perf_level_get(const struct scmi_handle *handle, u32 domain,
if (!ret)
*level = le32_to_cpu(*(__le32 *)t->rx.buf);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -349,8 +349,8 @@ static int scmi_dev_domain_id(struct device *dev)
return clkspec.args[0];
}
-static int scmi_dvfs_add_opps_to_device(const struct scmi_handle *handle,
- struct device *dev)
+static int scmi_dvfs_device_opps_add(const struct scmi_handle *handle,
+ struct device *dev)
{
int idx, ret, domain;
unsigned long freq;
@@ -383,7 +383,7 @@ static int scmi_dvfs_add_opps_to_device(const struct scmi_handle *handle,
return 0;
}
-static int scmi_dvfs_get_transition_latency(const struct scmi_handle *handle,
+static int scmi_dvfs_transition_latency_get(const struct scmi_handle *handle,
struct device *dev)
{
struct perf_dom_info *dom;
@@ -432,8 +432,8 @@ static struct scmi_perf_ops perf_ops = {
.level_set = scmi_perf_level_set,
.level_get = scmi_perf_level_get,
.device_domain_id = scmi_dev_domain_id,
- .get_transition_latency = scmi_dvfs_get_transition_latency,
- .add_opps_to_device = scmi_dvfs_add_opps_to_device,
+ .transition_latency_get = scmi_dvfs_transition_latency_get,
+ .device_opps_add = scmi_dvfs_device_opps_add,
.freq_set = scmi_dvfs_freq_set,
.freq_get = scmi_dvfs_freq_get,
};
diff --git a/drivers/firmware/arm_scmi/power.c b/drivers/firmware/arm_scmi/power.c
index 087c287..cfa033b 100644
--- a/drivers/firmware/arm_scmi/power.c
+++ b/drivers/firmware/arm_scmi/power.c
@@ -63,7 +63,7 @@ static int scmi_power_attributes_get(const struct scmi_handle *handle,
struct scmi_xfer *t;
struct scmi_msg_resp_power_attributes *attr;
- ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+ ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
SCMI_PROTOCOL_POWER, 0, sizeof(*attr), &t);
if (ret)
return ret;
@@ -78,7 +78,7 @@ static int scmi_power_attributes_get(const struct scmi_handle *handle,
pi->stats_size = le32_to_cpu(attr->stats_size);
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -90,7 +90,7 @@ scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
struct scmi_xfer *t;
struct scmi_msg_resp_power_domain_attributes *attr;
- ret = scmi_one_xfer_init(handle, POWER_DOMAIN_ATTRIBUTES,
+ ret = scmi_xfer_get_init(handle, POWER_DOMAIN_ATTRIBUTES,
SCMI_PROTOCOL_POWER, sizeof(domain),
sizeof(*attr), &t);
if (ret)
@@ -109,7 +109,7 @@ scmi_power_domain_attributes_get(const struct scmi_handle *handle, u32 domain,
memcpy(dom_info->name, attr->name, SCMI_MAX_STR_SIZE);
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -120,7 +120,7 @@ scmi_power_state_set(const struct scmi_handle *handle, u32 domain, u32 state)
struct scmi_xfer *t;
struct scmi_power_set_state *st;
- ret = scmi_one_xfer_init(handle, POWER_STATE_SET, SCMI_PROTOCOL_POWER,
+ ret = scmi_xfer_get_init(handle, POWER_STATE_SET, SCMI_PROTOCOL_POWER,
sizeof(*st), 0, &t);
if (ret)
return ret;
@@ -132,7 +132,7 @@ scmi_power_state_set(const struct scmi_handle *handle, u32 domain, u32 state)
ret = scmi_do_xfer(handle, t);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -142,7 +142,7 @@ scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state)
int ret;
struct scmi_xfer *t;
- ret = scmi_one_xfer_init(handle, POWER_STATE_GET, SCMI_PROTOCOL_POWER,
+ ret = scmi_xfer_get_init(handle, POWER_STATE_GET, SCMI_PROTOCOL_POWER,
sizeof(u32), sizeof(u32), &t);
if (ret)
return ret;
@@ -153,7 +153,7 @@ scmi_power_state_get(const struct scmi_handle *handle, u32 domain, u32 *state)
if (!ret)
*state = le32_to_cpu(*(__le32 *)t->rx.buf);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
diff --git a/drivers/firmware/arm_scmi/sensors.c b/drivers/firmware/arm_scmi/sensors.c
index bbb469f..27f2092 100644
--- a/drivers/firmware/arm_scmi/sensors.c
+++ b/drivers/firmware/arm_scmi/sensors.c
@@ -79,7 +79,7 @@ static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
struct scmi_xfer *t;
struct scmi_msg_resp_sensor_attributes *attr;
- ret = scmi_one_xfer_init(handle, PROTOCOL_ATTRIBUTES,
+ ret = scmi_xfer_get_init(handle, PROTOCOL_ATTRIBUTES,
SCMI_PROTOCOL_SENSOR, 0, sizeof(*attr), &t);
if (ret)
return ret;
@@ -95,7 +95,7 @@ static int scmi_sensor_attributes_get(const struct scmi_handle *handle,
si->reg_size = le32_to_cpu(attr->reg_size);
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -108,7 +108,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
struct scmi_xfer *t;
struct scmi_msg_resp_sensor_description *buf;
- ret = scmi_one_xfer_init(handle, SENSOR_DESCRIPTION_GET,
+ ret = scmi_xfer_get_init(handle, SENSOR_DESCRIPTION_GET,
SCMI_PROTOCOL_SENSOR, sizeof(__le32), 0, &t);
if (ret)
return ret;
@@ -150,7 +150,7 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle,
*/
} while (num_returned && num_remaining);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -162,7 +162,7 @@ scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
struct scmi_xfer *t;
struct scmi_msg_set_sensor_config *cfg;
- ret = scmi_one_xfer_init(handle, SENSOR_CONFIG_SET,
+ ret = scmi_xfer_get_init(handle, SENSOR_CONFIG_SET,
SCMI_PROTOCOL_SENSOR, sizeof(*cfg), 0, &t);
if (ret)
return ret;
@@ -173,7 +173,7 @@ scmi_sensor_configuration_set(const struct scmi_handle *handle, u32 sensor_id)
ret = scmi_do_xfer(handle, t);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -185,7 +185,7 @@ static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
struct scmi_xfer *t;
struct scmi_msg_set_sensor_trip_point *trip;
- ret = scmi_one_xfer_init(handle, SENSOR_TRIP_POINT_SET,
+ ret = scmi_xfer_get_init(handle, SENSOR_TRIP_POINT_SET,
SCMI_PROTOCOL_SENSOR, sizeof(*trip), 0, &t);
if (ret)
return ret;
@@ -198,7 +198,7 @@ static int scmi_sensor_trip_point_set(const struct scmi_handle *handle,
ret = scmi_do_xfer(handle, t);
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
@@ -209,7 +209,7 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle,
struct scmi_xfer *t;
struct scmi_msg_sensor_reading_get *sensor;
- ret = scmi_one_xfer_init(handle, SENSOR_READING_GET,
+ ret = scmi_xfer_get_init(handle, SENSOR_READING_GET,
SCMI_PROTOCOL_SENSOR, sizeof(*sensor),
sizeof(u64), &t);
if (ret)
@@ -227,7 +227,7 @@ static int scmi_sensor_reading_get(const struct scmi_handle *handle,
*value |= (u64)le32_to_cpu(*(pval + 1)) << 32;
}
- scmi_one_xfer_put(handle, t);
+ scmi_xfer_put(handle, t);
return ret;
}
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 6d7a6c0..c7d06a3 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -890,7 +890,7 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
int i;
struct scpi_xfer *xfers;
- xfers = devm_kzalloc(dev, MAX_SCPI_XFERS * sizeof(*xfers), GFP_KERNEL);
+ xfers = devm_kcalloc(dev, MAX_SCPI_XFERS, sizeof(*xfers), GFP_KERNEL);
if (!xfers)
return -ENOMEM;
diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c
index 0b631e5..d25f080 100644
--- a/drivers/firmware/broadcom/bcm47xx_nvram.c
+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c
@@ -36,7 +36,7 @@ struct nvram_header {
static char nvram_buf[NVRAM_SPACE];
static size_t nvram_len;
-static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000};
+static const u32 nvram_sizes[] = {0x6000, 0x8000, 0xF000, 0x10000};
static u32 find_nvram_size(void __iomem *end)
{
diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c
index 2f452f1..fb8af5c 100644
--- a/drivers/firmware/dell_rbu.c
+++ b/drivers/firmware/dell_rbu.c
@@ -146,7 +146,7 @@ static int create_packet(void *data, size_t length)
packet_array_size = max(
(unsigned int)(allocation_floor / rbu_data.packetsize),
(unsigned int)1);
- invalid_addr_packet_array = kzalloc(packet_array_size * sizeof(void*),
+ invalid_addr_packet_array = kcalloc(packet_array_size, sizeof(void *),
GFP_KERNEL);
if (!invalid_addr_packet_array) {
diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c
index 951b6c7..624a11c 100644
--- a/drivers/firmware/dmi-id.c
+++ b/drivers/firmware/dmi-id.c
@@ -47,6 +47,7 @@ DEFINE_DMI_ATTR_WITH_SHOW(product_name, 0444, DMI_PRODUCT_NAME);
DEFINE_DMI_ATTR_WITH_SHOW(product_version, 0444, DMI_PRODUCT_VERSION);
DEFINE_DMI_ATTR_WITH_SHOW(product_serial, 0400, DMI_PRODUCT_SERIAL);
DEFINE_DMI_ATTR_WITH_SHOW(product_uuid, 0400, DMI_PRODUCT_UUID);
+DEFINE_DMI_ATTR_WITH_SHOW(product_sku, 0444, DMI_PRODUCT_SKU);
DEFINE_DMI_ATTR_WITH_SHOW(product_family, 0444, DMI_PRODUCT_FAMILY);
DEFINE_DMI_ATTR_WITH_SHOW(board_vendor, 0444, DMI_BOARD_VENDOR);
DEFINE_DMI_ATTR_WITH_SHOW(board_name, 0444, DMI_BOARD_NAME);
@@ -193,6 +194,7 @@ static void __init dmi_id_init_attr_table(void)
ADD_DMI_ATTR(product_serial, DMI_PRODUCT_SERIAL);
ADD_DMI_ATTR(product_uuid, DMI_PRODUCT_UUID);
ADD_DMI_ATTR(product_family, DMI_PRODUCT_FAMILY);
+ ADD_DMI_ATTR(product_sku, DMI_PRODUCT_SKU);
ADD_DMI_ATTR(board_vendor, DMI_BOARD_VENDOR);
ADD_DMI_ATTR(board_name, DMI_BOARD_NAME);
ADD_DMI_ATTR(board_version, DMI_BOARD_VERSION);
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index 54e66ad..f248354 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -447,6 +447,7 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
dmi_save_ident(dm, DMI_PRODUCT_VERSION, 6);
dmi_save_ident(dm, DMI_PRODUCT_SERIAL, 7);
dmi_save_uuid(dm, DMI_PRODUCT_UUID, 8);
+ dmi_save_ident(dm, DMI_PRODUCT_SKU, 25);
dmi_save_ident(dm, DMI_PRODUCT_FAMILY, 26);
break;
case 2: /* Base Board Information */
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index 80d1a88..b5214c1 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -193,7 +193,7 @@ static __init void reserve_regions(void)
* uses its own memory map instead.
*/
memblock_dump_all();
- memblock_remove(0, (phys_addr_t)ULLONG_MAX);
+ memblock_remove(0, PHYS_ADDR_MAX);
for_each_efi_memory_desc(md) {
paddr = md->phys_addr;
diff --git a/drivers/firmware/efi/capsule.c b/drivers/firmware/efi/capsule.c
index 901b930..4938c29 100644
--- a/drivers/firmware/efi/capsule.c
+++ b/drivers/firmware/efi/capsule.c
@@ -231,7 +231,7 @@ int efi_capsule_update(efi_capsule_header_t *capsule, phys_addr_t *pages)
count = DIV_ROUND_UP(imagesize, PAGE_SIZE);
sg_count = sg_pages_num(count);
- sg_pages = kzalloc(sg_count * sizeof(*sg_pages), GFP_KERNEL);
+ sg_pages = kcalloc(sg_count, sizeof(*sg_pages), GFP_KERNEL);
if (!sg_pages)
return -ENOMEM;
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index 5a0fa93..cfe87b4 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -28,10 +28,9 @@ static int efi_pstore_close(struct pstore_info *psi)
return 0;
}
-static inline u64 generic_id(unsigned long timestamp,
- unsigned int part, int count)
+static inline u64 generic_id(u64 timestamp, unsigned int part, int count)
{
- return ((u64) timestamp * 100 + part) * 1000 + count;
+ return (timestamp * 100 + part) * 1000 + count;
}
static int efi_pstore_read_func(struct efivar_entry *entry,
@@ -42,7 +41,8 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
int i;
int cnt;
unsigned int part;
- unsigned long time, size;
+ unsigned long size;
+ u64 time;
if (efi_guidcmp(entry->var.VendorGuid, vendor))
return 0;
@@ -50,7 +50,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
for (i = 0; i < DUMP_NAME_LEN; i++)
name[i] = entry->var.VariableName[i];
- if (sscanf(name, "dump-type%u-%u-%d-%lu-%c",
+ if (sscanf(name, "dump-type%u-%u-%d-%llu-%c",
&record->type, &part, &cnt, &time, &data_type) == 5) {
record->id = generic_id(time, part, cnt);
record->part = part;
@@ -62,7 +62,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
else
record->compressed = false;
record->ecc_notice_size = 0;
- } else if (sscanf(name, "dump-type%u-%u-%d-%lu",
+ } else if (sscanf(name, "dump-type%u-%u-%d-%llu",
&record->type, &part, &cnt, &time) == 4) {
record->id = generic_id(time, part, cnt);
record->part = part;
@@ -71,7 +71,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry,
record->time.tv_nsec = 0;
record->compressed = false;
record->ecc_notice_size = 0;
- } else if (sscanf(name, "dump-type%u-%u-%lu",
+ } else if (sscanf(name, "dump-type%u-%u-%llu",
&record->type, &part, &time) == 3) {
/*
* Check if an old format,
@@ -250,9 +250,10 @@ static int efi_pstore_write(struct pstore_record *record)
/* Since we copy the entire length of name, make sure it is wiped. */
memset(name, 0, sizeof(name));
- snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu-%c",
+ snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lld-%c",
record->type, record->part, record->count,
- record->time.tv_sec, record->compressed ? 'C' : 'D');
+ (long long)record->time.tv_sec,
+ record->compressed ? 'C' : 'D');
for (i = 0; i < DUMP_NAME_LEN; i++)
efi_name[i] = name[i];
@@ -327,15 +328,15 @@ static int efi_pstore_erase(struct pstore_record *record)
char name[DUMP_NAME_LEN];
int ret;
- snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lu",
+ snprintf(name, sizeof(name), "dump-type%u-%u-%d-%lld",
record->type, record->part, record->count,
- record->time.tv_sec);
+ (long long)record->time.tv_sec);
ret = efi_pstore_erase_name(name);
if (ret != -ENOENT)
return ret;
- snprintf(name, sizeof(name), "dump-type%u-%u-%lu",
- record->type, record->part, record->time.tv_sec);
+ snprintf(name, sizeof(name), "dump-type%u-%u-%lld",
+ record->type, record->part, (long long)record->time.tv_sec);
ret = efi_pstore_erase_name(name);
return ret;
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c
index caa37a6..a90b0b8 100644
--- a/drivers/firmware/efi/libstub/tpm.c
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -64,7 +64,7 @@ static void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
efi_status_t status;
- efi_physical_addr_t log_location, log_last_entry;
+ efi_physical_addr_t log_location = 0, log_last_entry = 0;
struct linux_efi_tpm_eventlog *log_tbl = NULL;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c
index f377609..84a11d0 100644
--- a/drivers/firmware/efi/runtime-map.c
+++ b/drivers/firmware/efi/runtime-map.c
@@ -166,7 +166,7 @@ int __init efi_runtime_map_init(struct kobject *efi_kobj)
if (!efi_enabled(EFI_MEMMAP))
return 0;
- map_entries = kzalloc(efi.memmap.nr_map * sizeof(entry), GFP_KERNEL);
+ map_entries = kcalloc(efi.memmap.nr_map, sizeof(entry), GFP_KERNEL);
if (!map_entries) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 5a7d6930..e778af7 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -603,6 +603,9 @@ static const struct of_device_id qcom_scm_dt_match[] = {
{ .compatible = "qcom,scm-msm8996",
.data = NULL, /* no clocks */
},
+ { .compatible = "qcom,scm-ipq4019",
+ .data = NULL, /* no clocks */
+ },
{ .compatible = "qcom,scm",
.data = (void *)(SCM_HAS_CORE_CLK
| SCM_HAS_IFACE_CLK
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index 5229036..7fa7447 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Texas Instruments System Control Interface Protocol Driver
*
* Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
* Nishanth Menon
- *
- * 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 "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; 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__
@@ -1862,9 +1854,9 @@ static int ti_sci_probe(struct platform_device *pdev)
if (!minfo->xfer_block)
return -ENOMEM;
- minfo->xfer_alloc_table = devm_kzalloc(dev,
- BITS_TO_LONGS(desc->max_msgs)
- * sizeof(unsigned long),
+ minfo->xfer_alloc_table = devm_kcalloc(dev,
+ BITS_TO_LONGS(desc->max_msgs),
+ sizeof(unsigned long),
GFP_KERNEL);
if (!minfo->xfer_alloc_table)
return -ENOMEM;
diff --git a/drivers/firmware/ti_sci.h b/drivers/firmware/ti_sci.h
index 9b611e9..12bf316 100644
--- a/drivers/firmware/ti_sci.h
+++ b/drivers/firmware/ti_sci.h
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: BSD-3-Clause
/*
* Texas Instruments System Control Interface (TISCI) Protocol
*
@@ -6,35 +7,6 @@
* See: http://processors.wiki.ti.com/index.php/TISCI for details
*
* Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the
- * distribution.
- *
- * Neither the name of Texas Instruments Incorporated nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
#ifndef __TI_SCI_H
diff --git a/drivers/fmc/fmc-sdb.c b/drivers/fmc/fmc-sdb.c
index ffdc176..d0e65b8 100644
--- a/drivers/fmc/fmc-sdb.c
+++ b/drivers/fmc/fmc-sdb.c
@@ -48,8 +48,8 @@ static struct sdb_array *__fmc_scan_sdb_tree(struct fmc_device *fmc,
arr = kzalloc(sizeof(*arr), GFP_KERNEL);
if (!arr)
return ERR_PTR(-ENOMEM);
- arr->record = kzalloc(sizeof(arr->record[0]) * n, GFP_KERNEL);
- arr->subtree = kzalloc(sizeof(arr->subtree[0]) * n, GFP_KERNEL);
+ arr->record = kcalloc(n, sizeof(arr->record[0]), GFP_KERNEL);
+ arr->subtree = kcalloc(n, sizeof(arr->subtree[0]), GFP_KERNEL);
if (!arr->record || !arr->subtree) {
kfree(arr->record);
kfree(arr->subtree);
diff --git a/drivers/gpio/gpio-adnp.c b/drivers/gpio/gpio-adnp.c
index 44c0990..91b90c0 100644
--- a/drivers/gpio/gpio-adnp.c
+++ b/drivers/gpio/gpio-adnp.c
@@ -427,7 +427,7 @@ static int adnp_irq_setup(struct adnp *adnp)
* is chosen to match the register layout of the hardware in that
* each segment contains the corresponding bits for all interrupts.
*/
- adnp->irq_enable = devm_kzalloc(chip->parent, num_regs * 6,
+ adnp->irq_enable = devm_kcalloc(chip->parent, num_regs, 6,
GFP_KERNEL);
if (!adnp->irq_enable)
return -ENOMEM;
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 5e89f1c..b31ae16 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -897,8 +897,8 @@ static int __init aspeed_gpio_probe(struct platform_device *pdev)
/* Allocate a cache of the output registers */
banks = gpio->config->nr_gpios >> 5;
- gpio->dcache = devm_kzalloc(&pdev->dev,
- sizeof(u32) * banks, GFP_KERNEL);
+ gpio->dcache = devm_kcalloc(&pdev->dev,
+ banks, sizeof(u32), GFP_KERNEL);
if (!gpio->dcache)
return -ENOMEM;
diff --git a/drivers/gpio/gpio-bcm-kona.c b/drivers/gpio/gpio-bcm-kona.c
index eb8369b..00272fa 100644
--- a/drivers/gpio/gpio-bcm-kona.c
+++ b/drivers/gpio/gpio-bcm-kona.c
@@ -601,9 +601,10 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
GPIO_MAX_BANK_NUM);
return -ENXIO;
}
- kona_gpio->banks = devm_kzalloc(dev,
- kona_gpio->num_bank *
- sizeof(*kona_gpio->banks), GFP_KERNEL);
+ kona_gpio->banks = devm_kcalloc(dev,
+ kona_gpio->num_bank,
+ sizeof(*kona_gpio->banks),
+ GFP_KERNEL);
if (!kona_gpio->banks)
return -ENOMEM;
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
index b574ecf..035a454 100644
--- a/drivers/gpio/gpio-davinci.c
+++ b/drivers/gpio/gpio-davinci.c
@@ -198,8 +198,8 @@ static int davinci_gpio_probe(struct platform_device *pdev)
ngpio = ARCH_NR_GPIOS;
nbank = DIV_ROUND_UP(ngpio, 32);
- chips = devm_kzalloc(dev,
- nbank * sizeof(struct davinci_gpio_controller),
+ chips = devm_kcalloc(dev,
+ nbank, sizeof(struct davinci_gpio_controller),
GFP_KERNEL);
if (!chips)
return -ENOMEM;
diff --git a/drivers/gpio/gpio-htc-egpio.c b/drivers/gpio/gpio-htc-egpio.c
index 5163839..ad6e5b5 100644
--- a/drivers/gpio/gpio-htc-egpio.c
+++ b/drivers/gpio/gpio-htc-egpio.c
@@ -321,8 +321,8 @@ static int __init egpio_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ei);
ei->nchips = pdata->num_chips;
- ei->chip = devm_kzalloc(&pdev->dev,
- sizeof(struct egpio_chip) * ei->nchips,
+ ei->chip = devm_kcalloc(&pdev->dev,
+ ei->nchips, sizeof(struct egpio_chip),
GFP_KERNEL);
if (!ei->chip) {
ret = -ENOMEM;
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index e2bee27..b23d9a3 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -443,7 +443,7 @@ static int ioh_gpio_probe(struct pci_dev *pdev,
goto err_iomap;
}
- chip_save = kzalloc(sizeof(*chip) * 8, GFP_KERNEL);
+ chip_save = kcalloc(8, sizeof(*chip), GFP_KERNEL);
if (chip_save == NULL) {
ret = -ENOMEM;
goto err_kzalloc;
diff --git a/drivers/gpio/gpio-thunderx.c b/drivers/gpio/gpio-thunderx.c
index d16e9d4..1306722 100644
--- a/drivers/gpio/gpio-thunderx.c
+++ b/drivers/gpio/gpio-thunderx.c
@@ -504,16 +504,17 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
txgpio->base_msi = (c >> 8) & 0xff;
}
- txgpio->msix_entries = devm_kzalloc(dev,
- sizeof(struct msix_entry) * ngpio,
+ txgpio->msix_entries = devm_kcalloc(dev,
+ ngpio, sizeof(struct msix_entry),
GFP_KERNEL);
if (!txgpio->msix_entries) {
err = -ENOMEM;
goto out;
}
- txgpio->line_entries = devm_kzalloc(dev,
- sizeof(struct thunderx_line) * ngpio,
+ txgpio->line_entries = devm_kcalloc(dev,
+ ngpio,
+ sizeof(struct thunderx_line),
GFP_KERNEL);
if (!txgpio->line_entries) {
err = -ENOMEM;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
index 428e5eb..f4c474a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c
@@ -310,20 +310,20 @@ static int acp_hw_init(void *handle)
pm_genpd_init(&adev->acp.acp_genpd->gpd, NULL, false);
}
- adev->acp.acp_cell = kzalloc(sizeof(struct mfd_cell) * ACP_DEVS,
+ adev->acp.acp_cell = kcalloc(ACP_DEVS, sizeof(struct mfd_cell),
GFP_KERNEL);
if (adev->acp.acp_cell == NULL)
return -ENOMEM;
- adev->acp.acp_res = kzalloc(sizeof(struct resource) * 4, GFP_KERNEL);
+ adev->acp.acp_res = kcalloc(4, sizeof(struct resource), GFP_KERNEL);
if (adev->acp.acp_res == NULL) {
kfree(adev->acp.acp_cell);
return -ENOMEM;
}
- i2s_pdata = kzalloc(sizeof(struct i2s_platform_data) * 2, GFP_KERNEL);
+ i2s_pdata = kcalloc(2, sizeof(struct i2s_platform_data), GFP_KERNEL);
if (i2s_pdata == NULL) {
kfree(adev->acp.acp_res);
kfree(adev->acp.acp_cell);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 8f6f455..305143f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -342,15 +342,12 @@ void get_local_mem_info(struct kgd_dev *kgd,
mem_info->local_mem_size_public,
mem_info->local_mem_size_private);
- if (amdgpu_emu_mode == 1) {
- mem_info->mem_clk_max = 100;
- return;
- }
-
if (amdgpu_sriov_vf(adev))
mem_info->mem_clk_max = adev->clock.default_mclk / 100;
- else
+ else if (adev->powerplay.pp_funcs)
mem_info->mem_clk_max = amdgpu_dpm_get_mclk(adev, false) / 100;
+ else
+ mem_info->mem_clk_max = 100;
}
uint64_t get_gpu_clock_counter(struct kgd_dev *kgd)
@@ -367,13 +364,12 @@ uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd)
struct amdgpu_device *adev = (struct amdgpu_device *)kgd;
/* the sclk is in quantas of 10kHz */
- if (amdgpu_emu_mode == 1)
- return 100;
-
if (amdgpu_sriov_vf(adev))
return adev->clock.default_sclk / 100;
-
- return amdgpu_dpm_get_sclk(adev, false) / 100;
+ else if (adev->powerplay.pp_funcs)
+ return amdgpu_dpm_get_sclk(adev, false) / 100;
+ else
+ return 100;
}
void get_cu_info(struct kgd_dev *kgd, struct kfd_cu_info *cu_info)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
index 0ff36d4..ea79908 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c
@@ -407,7 +407,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
(*dump)[i++][1] = RREG32(addr); \
} while (0)
- *dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
+ *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL);
if (*dump == NULL)
return -ENOMEM;
@@ -504,7 +504,7 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
#undef HQD_N_REGS
#define HQD_N_REGS (19+4)
- *dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
+ *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL);
if (*dump == NULL)
return -ENOMEM;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
index 6ef9762..19dd665 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c
@@ -395,7 +395,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
(*dump)[i++][1] = RREG32(addr); \
} while (0)
- *dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
+ *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL);
if (*dump == NULL)
return -ENOMEM;
@@ -491,7 +491,7 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
#undef HQD_N_REGS
#define HQD_N_REGS (19+4+2+3+7)
- *dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
+ *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL);
if (*dump == NULL)
return -ENOMEM;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
index f0c0d39..1db60aa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
@@ -504,7 +504,7 @@ static int kgd_hqd_dump(struct kgd_dev *kgd,
(*dump)[i++][1] = RREG32(addr); \
} while (0)
- *dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
+ *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL);
if (*dump == NULL)
return -ENOMEM;
@@ -606,7 +606,7 @@ static int kgd_hqd_sdma_dump(struct kgd_dev *kgd,
#undef HQD_N_REGS
#define HQD_N_REGS (19+6+7+10)
- *dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
+ *dump = kmalloc_array(HQD_N_REGS * 2, sizeof(uint32_t), GFP_KERNEL);
if (*dump == NULL)
return -ENOMEM;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
index 1bcb2b2..daa06e7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
@@ -569,7 +569,6 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
{ 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
- { 0x1002, 0x67DF, 0x1028, 0x0774, AMDGPU_PX_QUIRK_FORCE_ATPX },
{ 0, 0, 0, 0, 0 },
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 9c1d491..82312a7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -522,6 +522,9 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
struct amdgpu_bo_list_entry *e;
struct list_head duplicates;
unsigned i, tries = 10;
+ struct amdgpu_bo *gds;
+ struct amdgpu_bo *gws;
+ struct amdgpu_bo *oa;
int r;
INIT_LIST_HEAD(&p->validated);
@@ -652,31 +655,36 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,
amdgpu_cs_report_moved_bytes(p->adev, p->bytes_moved,
p->bytes_moved_vis);
+
if (p->bo_list) {
- struct amdgpu_bo *gds = p->bo_list->gds_obj;
- struct amdgpu_bo *gws = p->bo_list->gws_obj;
- struct amdgpu_bo *oa = p->bo_list->oa_obj;
struct amdgpu_vm *vm = &fpriv->vm;
unsigned i;
+ gds = p->bo_list->gds_obj;
+ gws = p->bo_list->gws_obj;
+ oa = p->bo_list->oa_obj;
for (i = 0; i < p->bo_list->num_entries; i++) {
struct amdgpu_bo *bo = p->bo_list->array[i].robj;
p->bo_list->array[i].bo_va = amdgpu_vm_bo_find(vm, bo);
}
+ } else {
+ gds = p->adev->gds.gds_gfx_bo;
+ gws = p->adev->gds.gws_gfx_bo;
+ oa = p->adev->gds.oa_gfx_bo;
+ }
- if (gds) {
- p->job->gds_base = amdgpu_bo_gpu_offset(gds);
- p->job->gds_size = amdgpu_bo_size(gds);
- }
- if (gws) {
- p->job->gws_base = amdgpu_bo_gpu_offset(gws);
- p->job->gws_size = amdgpu_bo_size(gws);
- }
- if (oa) {
- p->job->oa_base = amdgpu_bo_gpu_offset(oa);
- p->job->oa_size = amdgpu_bo_size(oa);
- }
+ if (gds) {
+ p->job->gds_base = amdgpu_bo_gpu_offset(gds);
+ p->job->gds_size = amdgpu_bo_size(gds);
+ }
+ if (gws) {
+ p->job->gws_base = amdgpu_bo_gpu_offset(gws);
+ p->job->gws_size = amdgpu_bo_size(gws);
+ }
+ if (oa) {
+ p->job->oa_base = amdgpu_bo_gpu_offset(oa);
+ p->job->oa_size = amdgpu_bo_size(oa);
}
if (!r && p->uf_entry.robj) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 290e279..6e5284e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1730,6 +1730,18 @@ static int amdgpu_device_ip_late_set_cg_state(struct amdgpu_device *adev)
}
}
}
+
+ if (adev->powerplay.pp_feature & PP_GFXOFF_MASK) {
+ /* enable gfx powergating */
+ amdgpu_device_ip_set_powergating_state(adev,
+ AMD_IP_BLOCK_TYPE_GFX,
+ AMD_PG_STATE_GATE);
+ /* enable gfxoff */
+ amdgpu_device_ip_set_powergating_state(adev,
+ AMD_IP_BLOCK_TYPE_SMC,
+ AMD_PG_STATE_GATE);
+ }
+
return 0;
}
@@ -2146,10 +2158,18 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
switch (asic_type) {
#if defined(CONFIG_DRM_AMD_DC)
case CHIP_BONAIRE:
- case CHIP_HAWAII:
case CHIP_KAVERI:
case CHIP_KABINI:
case CHIP_MULLINS:
+ /*
+ * We have systems in the wild with these ASICs that require
+ * LVDS and VGA support which is not supported with DC.
+ *
+ * Fallback to the non-DC driver here by default so as not to
+ * cause regressions.
+ */
+ return amdgpu_dc > 0;
+ case CHIP_HAWAII:
case CHIP_CARRIZO:
case CHIP_STONEY:
case CHIP_POLARIS10:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
index def1010..77ad59a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c
@@ -452,7 +452,7 @@ int amdgpu_parse_extended_power_table(struct amdgpu_device *adev)
ATOM_PPLIB_PhaseSheddingLimits_Record *entry;
adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries =
- kzalloc(psl->ucNumEntries *
+ kcalloc(psl->ucNumEntries,
sizeof(struct amdgpu_phase_shedding_limits_entry),
GFP_KERNEL);
if (!adev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
index 17d6b9f..dd11b73 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
@@ -369,7 +369,8 @@ int amdgpu_gart_init(struct amdgpu_device *adev)
#ifdef CONFIG_DRM_AMDGPU_GART_DEBUGFS
/* Allocate pages table */
- adev->gart.pages = vzalloc(sizeof(void *) * adev->gart.num_cpu_pages);
+ adev->gart.pages = vzalloc(array_size(sizeof(void *),
+ adev->gart.num_cpu_pages));
if (adev->gart.pages == NULL)
return -ENOMEM;
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 2c8e273..5fb156a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -30,6 +30,7 @@
#include <drm/drmP.h>
#include <drm/amdgpu_drm.h>
#include "amdgpu.h"
+#include "amdgpu_display.h"
void amdgpu_gem_object_free(struct drm_gem_object *gobj)
{
@@ -235,6 +236,13 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
/* create a gem object to contain this object in */
if (args->in.domains & (AMDGPU_GEM_DOMAIN_GDS |
AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA)) {
+ if (flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) {
+ /* if gds bo is created from user space, it must be
+ * passed to bo list
+ */
+ DRM_ERROR("GDS bo cannot be per-vm-bo\n");
+ return -EINVAL;
+ }
flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
if (args->in.domains == AMDGPU_GEM_DOMAIN_GDS)
size = size << AMDGPU_GDS_SHIFT;
@@ -749,15 +757,16 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv,
struct amdgpu_device *adev = dev->dev_private;
struct drm_gem_object *gobj;
uint32_t handle;
+ u32 domain;
int r;
args->pitch = amdgpu_align_pitch(adev, args->width,
DIV_ROUND_UP(args->bpp, 8), 0);
args->size = (u64)args->pitch * args->height;
args->size = ALIGN(args->size, PAGE_SIZE);
-
- r = amdgpu_gem_object_create(adev, args->size, 0,
- AMDGPU_GEM_DOMAIN_VRAM,
+ domain = amdgpu_bo_get_preferred_pin_domain(adev,
+ amdgpu_display_supported_domains(adev));
+ r = amdgpu_gem_object_create(adev, args->size, 0, domain,
AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED,
false, NULL, &gobj);
if (r)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 6a9e46a..3526efa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -703,11 +703,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
/* This assumes only APU display buffers are pinned with (VRAM|GTT).
* See function amdgpu_display_supported_domains()
*/
- if (domain == (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT)) {
- domain = AMDGPU_GEM_DOMAIN_VRAM;
- if (adev->gmc.real_vram_size <= AMDGPU_SG_THRESHOLD)
- domain = AMDGPU_GEM_DOMAIN_GTT;
- }
+ domain = amdgpu_bo_get_preferred_pin_domain(adev, domain);
if (bo->pin_count) {
uint32_t mem_type = bo->tbo.mem.mem_type;
@@ -766,8 +762,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
adev->vram_pin_size += amdgpu_bo_size(bo);
- if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
- adev->invisible_pin_size += amdgpu_bo_size(bo);
+ adev->invisible_pin_size += amdgpu_vram_mgr_bo_invisible_size(bo);
} else if (domain == AMDGPU_GEM_DOMAIN_GTT) {
adev->gart_pin_size += amdgpu_bo_size(bo);
}
@@ -794,25 +789,22 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo)
bo->pin_count--;
if (bo->pin_count)
return 0;
- for (i = 0; i < bo->placement.num_placement; i++) {
- bo->placements[i].lpfn = 0;
- bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
- }
- r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
- if (unlikely(r)) {
- dev_err(adev->dev, "%p validate failed for unpin\n", bo);
- goto error;
- }
if (bo->tbo.mem.mem_type == TTM_PL_VRAM) {
adev->vram_pin_size -= amdgpu_bo_size(bo);
- if (bo->flags & AMDGPU_GEM_CREATE_NO_CPU_ACCESS)
- adev->invisible_pin_size -= amdgpu_bo_size(bo);
+ adev->invisible_pin_size -= amdgpu_vram_mgr_bo_invisible_size(bo);
} else if (bo->tbo.mem.mem_type == TTM_PL_TT) {
adev->gart_pin_size -= amdgpu_bo_size(bo);
}
-error:
+ for (i = 0; i < bo->placement.num_placement; i++) {
+ bo->placements[i].lpfn = 0;
+ bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT;
+ }
+ r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
+ if (unlikely(r))
+ dev_err(adev->dev, "%p validate failed for unpin\n", bo);
+
return r;
}
@@ -1066,3 +1058,14 @@ u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo)
return bo->tbo.offset;
}
+
+uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev,
+ uint32_t domain)
+{
+ if (domain == (AMDGPU_GEM_DOMAIN_VRAM | AMDGPU_GEM_DOMAIN_GTT)) {
+ domain = AMDGPU_GEM_DOMAIN_VRAM;
+ if (adev->gmc.real_vram_size <= AMDGPU_SG_THRESHOLD)
+ domain = AMDGPU_GEM_DOMAIN_GTT;
+ }
+ return domain;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
index 540e03f..7317480 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
@@ -289,7 +289,8 @@ int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
struct reservation_object *resv,
struct dma_fence **fence,
bool direct);
-
+uint32_t amdgpu_bo_get_preferred_pin_domain(struct amdgpu_device *adev,
+ uint32_t domain);
/*
* sub allocation
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
index d167e8a..e387825 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_test.c
@@ -53,7 +53,7 @@ static void amdgpu_do_test_moves(struct amdgpu_device *adev)
n -= adev->irq.ih.ring_size;
n /= size;
- gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
+ gtt_obj = kcalloc(n, sizeof(*gtt_obj), GFP_KERNEL);
if (!gtt_obj) {
DRM_ERROR("Failed to allocate %d pointers\n", n);
r = 1;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index e969c87..e5da465 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@ -73,6 +73,7 @@ bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_mem_reg *mem);
uint64_t amdgpu_gtt_mgr_usage(struct ttm_mem_type_manager *man);
int amdgpu_gtt_mgr_recover(struct ttm_mem_type_manager *man);
+u64 amdgpu_vram_mgr_bo_invisible_size(struct amdgpu_bo *bo);
uint64_t amdgpu_vram_mgr_usage(struct ttm_mem_type_manager *man);
uint64_t amdgpu_vram_mgr_vis_usage(struct ttm_mem_type_manager *man);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index bcf68f8..3ff08e3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -130,7 +130,7 @@ int amdgpu_uvd_sw_init(struct amdgpu_device *adev)
unsigned version_major, version_minor, family_id;
int i, j, r;
- INIT_DELAYED_WORK(&adev->uvd.inst->idle_work, amdgpu_uvd_idle_work_handler);
+ INIT_DELAYED_WORK(&adev->uvd.idle_work, amdgpu_uvd_idle_work_handler);
switch (adev->asic_type) {
#ifdef CONFIG_DRM_AMDGPU_CIK
@@ -314,12 +314,12 @@ int amdgpu_uvd_suspend(struct amdgpu_device *adev)
void *ptr;
int i, j;
+ cancel_delayed_work_sync(&adev->uvd.idle_work);
+
for (j = 0; j < adev->uvd.num_uvd_inst; ++j) {
if (adev->uvd.inst[j].vcpu_bo == NULL)
continue;
- cancel_delayed_work_sync(&adev->uvd.inst[j].idle_work);
-
/* only valid for physical mode */
if (adev->asic_type < CHIP_POLARIS10) {
for (i = 0; i < adev->uvd.max_handles; ++i)
@@ -1145,7 +1145,7 @@ int amdgpu_uvd_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
static void amdgpu_uvd_idle_work_handler(struct work_struct *work)
{
struct amdgpu_device *adev =
- container_of(work, struct amdgpu_device, uvd.inst->idle_work.work);
+ container_of(work, struct amdgpu_device, uvd.idle_work.work);
unsigned fences = 0, i, j;
for (i = 0; i < adev->uvd.num_uvd_inst; ++i) {
@@ -1167,7 +1167,7 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work)
AMD_CG_STATE_GATE);
}
} else {
- schedule_delayed_work(&adev->uvd.inst->idle_work, UVD_IDLE_TIMEOUT);
+ schedule_delayed_work(&adev->uvd.idle_work, UVD_IDLE_TIMEOUT);
}
}
@@ -1179,7 +1179,7 @@ void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring)
if (amdgpu_sriov_vf(adev))
return;
- set_clocks = !cancel_delayed_work_sync(&adev->uvd.inst->idle_work);
+ set_clocks = !cancel_delayed_work_sync(&adev->uvd.idle_work);
if (set_clocks) {
if (adev->pm.dpm_enabled) {
amdgpu_dpm_enable_uvd(adev, true);
@@ -1196,7 +1196,7 @@ void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring)
void amdgpu_uvd_ring_end_use(struct amdgpu_ring *ring)
{
if (!amdgpu_sriov_vf(ring->adev))
- schedule_delayed_work(&ring->adev->uvd.inst->idle_work, UVD_IDLE_TIMEOUT);
+ schedule_delayed_work(&ring->adev->uvd.idle_work, UVD_IDLE_TIMEOUT);
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
index b1579fb..8b23a1b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.h
@@ -44,7 +44,6 @@ struct amdgpu_uvd_inst {
void *saved_bo;
atomic_t handles[AMDGPU_MAX_UVD_HANDLES];
struct drm_file *filp[AMDGPU_MAX_UVD_HANDLES];
- struct delayed_work idle_work;
struct amdgpu_ring ring;
struct amdgpu_ring ring_enc[AMDGPU_MAX_UVD_ENC_RINGS];
struct amdgpu_irq_src irq;
@@ -62,6 +61,7 @@ struct amdgpu_uvd {
bool address_64_bit;
bool use_ctx_buf;
struct amdgpu_uvd_inst inst[AMDGPU_MAX_UVD_INSTANCES];
+ struct delayed_work idle_work;
};
int amdgpu_uvd_sw_init(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 8851bcd..127e87b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -49,8 +49,6 @@ static void amdgpu_vcn_idle_work_handler(struct work_struct *work);
int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
{
- struct amdgpu_ring *ring;
- struct drm_sched_rq *rq;
unsigned long bo_size;
const char *fw_name;
const struct common_firmware_header *hdr;
@@ -84,6 +82,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
}
hdr = (const struct common_firmware_header *)adev->vcn.fw->data;
+ adev->vcn.fw_version = le32_to_cpu(hdr->ucode_version);
family_id = le32_to_cpu(hdr->ucode_version) & 0xff;
version_major = (le32_to_cpu(hdr->ucode_version) >> 24) & 0xff;
version_minor = (le32_to_cpu(hdr->ucode_version) >> 8) & 0xff;
@@ -102,24 +101,6 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
return r;
}
- ring = &adev->vcn.ring_dec;
- rq = &ring->sched.sched_rq[DRM_SCHED_PRIORITY_NORMAL];
- r = drm_sched_entity_init(&ring->sched, &adev->vcn.entity_dec,
- rq, NULL);
- if (r != 0) {
- DRM_ERROR("Failed setting up VCN dec run queue.\n");
- return r;
- }
-
- ring = &adev->vcn.ring_enc[0];
- rq = &ring->sched.sched_rq[DRM_SCHED_PRIORITY_NORMAL];
- r = drm_sched_entity_init(&ring->sched, &adev->vcn.entity_enc,
- rq, NULL);
- if (r != 0) {
- DRM_ERROR("Failed setting up VCN enc run queue.\n");
- return r;
- }
-
return 0;
}
@@ -129,10 +110,6 @@ int amdgpu_vcn_sw_fini(struct amdgpu_device *adev)
kfree(adev->vcn.saved_bo);
- drm_sched_entity_fini(&adev->vcn.ring_dec.sched, &adev->vcn.entity_dec);
-
- drm_sched_entity_fini(&adev->vcn.ring_enc[0].sched, &adev->vcn.entity_enc);
-
amdgpu_bo_free_kernel(&adev->vcn.vcpu_bo,
&adev->vcn.gpu_addr,
(void **)&adev->vcn.cpu_addr);
@@ -278,7 +255,7 @@ int amdgpu_vcn_dec_ring_test_ring(struct amdgpu_ring *ring)
}
static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
- struct amdgpu_bo *bo, bool direct,
+ struct amdgpu_bo *bo,
struct dma_fence **fence)
{
struct amdgpu_device *adev = ring->adev;
@@ -306,19 +283,12 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
}
ib->length_dw = 16;
- if (direct) {
- r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f);
- job->fence = dma_fence_get(f);
- if (r)
- goto err_free;
+ r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f);
+ job->fence = dma_fence_get(f);
+ if (r)
+ goto err_free;
- amdgpu_job_free(job);
- } else {
- r = amdgpu_job_submit(job, ring, &adev->vcn.entity_dec,
- AMDGPU_FENCE_OWNER_UNDEFINED, &f);
- if (r)
- goto err_free;
- }
+ amdgpu_job_free(job);
amdgpu_bo_fence(bo, f, false);
amdgpu_bo_unreserve(bo);
@@ -370,11 +340,11 @@ static int amdgpu_vcn_dec_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
for (i = 14; i < 1024; ++i)
msg[i] = cpu_to_le32(0x0);
- return amdgpu_vcn_dec_send_msg(ring, bo, true, fence);
+ return amdgpu_vcn_dec_send_msg(ring, bo, fence);
}
static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
- bool direct, struct dma_fence **fence)
+ struct dma_fence **fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_bo *bo = NULL;
@@ -396,7 +366,7 @@ static int amdgpu_vcn_dec_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
for (i = 6; i < 1024; ++i)
msg[i] = cpu_to_le32(0x0);
- return amdgpu_vcn_dec_send_msg(ring, bo, direct, fence);
+ return amdgpu_vcn_dec_send_msg(ring, bo, fence);
}
int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)
@@ -410,7 +380,7 @@ int amdgpu_vcn_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout)
goto error;
}
- r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, true, &fence);
+ r = amdgpu_vcn_dec_get_destroy_msg(ring, 1, &fence);
if (r) {
DRM_ERROR("amdgpu: failed to get destroy ib (%ld).\n", r);
goto error;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 181e6af..773010b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -67,8 +67,6 @@ struct amdgpu_vcn {
struct amdgpu_ring ring_dec;
struct amdgpu_ring ring_enc[AMDGPU_VCN_MAX_ENC_RINGS];
struct amdgpu_irq_src irq;
- struct drm_sched_entity entity_dec;
- struct drm_sched_entity entity_enc;
unsigned num_enc_rings;
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index ccba88c..b0eb2f5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -2123,7 +2123,8 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
before->last = saddr - 1;
before->offset = tmp->offset;
before->flags = tmp->flags;
- list_add(&before->list, &tmp->list);
+ before->bo_va = tmp->bo_va;
+ list_add(&before->list, &tmp->bo_va->invalids);
}
/* Remember mapping split at the end */
@@ -2133,7 +2134,8 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev,
after->offset = tmp->offset;
after->offset += after->start - tmp->start;
after->flags = tmp->flags;
- list_add(&after->list, &tmp->list);
+ after->bo_va = tmp->bo_va;
+ list_add(&after->list, &tmp->bo_va->invalids);
}
list_del(&tmp->list);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index 9aca653..b6333f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -97,6 +97,38 @@ static u64 amdgpu_vram_mgr_vis_size(struct amdgpu_device *adev,
}
/**
+ * amdgpu_vram_mgr_bo_invisible_size - CPU invisible BO size
+ *
+ * @bo: &amdgpu_bo buffer object (must be in VRAM)
+ *
+ * Returns:
+ * How much of the given &amdgpu_bo buffer object lies in CPU invisible VRAM.
+ */
+u64 amdgpu_vram_mgr_bo_invisible_size(struct amdgpu_bo *bo)
+{
+ struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
+ struct ttm_mem_reg *mem = &bo->tbo.mem;
+ struct drm_mm_node *nodes = mem->mm_node;
+ unsigned pages = mem->num_pages;
+ u64 usage = 0;
+
+ if (adev->gmc.visible_vram_size == adev->gmc.real_vram_size)
+ return 0;
+
+ if (mem->start >= adev->gmc.visible_vram_size >> PAGE_SHIFT)
+ return amdgpu_bo_size(bo);
+
+ while (nodes && pages) {
+ usage += nodes->size << PAGE_SHIFT;
+ usage -= amdgpu_vram_mgr_vis_size(adev, nodes);
+ pages -= nodes->size;
+ ++nodes;
+ }
+
+ return usage;
+}
+
+/**
* amdgpu_vram_mgr_new - allocate new ranges
*
* @man: TTM memory type manager
@@ -135,7 +167,8 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
num_nodes = DIV_ROUND_UP(mem->num_pages, pages_per_node);
}
- nodes = kcalloc(num_nodes, sizeof(*nodes), GFP_KERNEL);
+ nodes = kvmalloc_array(num_nodes, sizeof(*nodes),
+ GFP_KERNEL | __GFP_ZERO);
if (!nodes)
return -ENOMEM;
@@ -190,7 +223,7 @@ error:
drm_mm_remove_node(&nodes[i]);
spin_unlock(&mgr->lock);
- kfree(nodes);
+ kvfree(nodes);
return r == -ENOSPC ? 0 : r;
}
@@ -229,7 +262,7 @@ static void amdgpu_vram_mgr_del(struct ttm_mem_type_manager *man,
atomic64_sub(usage, &mgr->usage);
atomic64_sub(vis_usage, &mgr->vis_usage);
- kfree(mem->mm_node);
+ kvfree(mem->mm_node);
mem->mm_node = NULL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/atom.c b/drivers/gpu/drm/amd/amdgpu/atom.c
index 69500a8..e9934de 100644
--- a/drivers/gpu/drm/amd/amdgpu/atom.c
+++ b/drivers/gpu/drm/amd/amdgpu/atom.c
@@ -1221,7 +1221,7 @@ static int amdgpu_atom_execute_table_locked(struct atom_context *ctx, int index,
ectx.abort = false;
ectx.last_jump = 0;
if (ws)
- ectx.ws = kzalloc(4 * ws, GFP_KERNEL);
+ ectx.ws = kcalloc(4, ws, GFP_KERNEL);
else
ectx.ws = NULL;
diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
index a266dcf..7fbad2f 100644
--- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c
@@ -5679,8 +5679,9 @@ static int ci_parse_power_table(struct amdgpu_device *adev)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
- adev->pm.dpm.ps = kzalloc(sizeof(struct amdgpu_ps) *
- state_array->ucNumEntries, GFP_KERNEL);
+ adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
+ sizeof(struct amdgpu_ps),
+ GFP_KERNEL);
if (!adev->pm.dpm.ps)
return -ENOMEM;
power_state_offset = (u8 *)state_array->states;
@@ -5927,7 +5928,9 @@ static int ci_dpm_init(struct amdgpu_device *adev)
ci_set_private_data_variables_based_on_pptable(adev);
adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
- kzalloc(4 * sizeof(struct amdgpu_clock_voltage_dependency_entry), GFP_KERNEL);
+ kcalloc(4,
+ sizeof(struct amdgpu_clock_voltage_dependency_entry),
+ GFP_KERNEL);
if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
ci_dpm_fini(adev);
return -ENOMEM;
diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
index 60608b3..d5ebe56 100644
--- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
+++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
@@ -64,7 +64,7 @@ static u32 df_v3_6_get_hbm_channel_number(struct amdgpu_device *adev)
int fb_channel_number;
fb_channel_number = adev->df_funcs->get_fb_channel_number(adev);
- if (fb_channel_number > ARRAY_SIZE(df_v3_6_channel_number))
+ if (fb_channel_number >= ARRAY_SIZE(df_v3_6_channel_number))
fb_channel_number = 0;
return df_v3_6_channel_number[fb_channel_number];
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index d7530fd..a691534 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -111,6 +111,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] =
{
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_DCC_CONFIG, 0x0f000080, 0x04000080),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_2, 0x0f000000, 0x0a000000),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmCB_HW_CONTROL_3, 0x30000000, 0x10000000),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmGB_ADDR_CONFIG, 0xf3e777ff, 0x22014042),
@@ -1837,13 +1838,15 @@ static void gfx_v9_1_parse_ind_reg_list(int *register_list_format,
int indirect_offset,
int list_size,
int *unique_indirect_regs,
- int *unique_indirect_reg_count,
+ int unique_indirect_reg_count,
int *indirect_start_offsets,
- int *indirect_start_offsets_count)
+ int *indirect_start_offsets_count,
+ int max_start_offsets_count)
{
int idx;
for (; indirect_offset < list_size; indirect_offset++) {
+ WARN_ON(*indirect_start_offsets_count >= max_start_offsets_count);
indirect_start_offsets[*indirect_start_offsets_count] = indirect_offset;
*indirect_start_offsets_count = *indirect_start_offsets_count + 1;
@@ -1851,14 +1854,14 @@ static void gfx_v9_1_parse_ind_reg_list(int *register_list_format,
indirect_offset += 2;
/* look for the matching indice */
- for (idx = 0; idx < *unique_indirect_reg_count; idx++) {
+ for (idx = 0; idx < unique_indirect_reg_count; idx++) {
if (unique_indirect_regs[idx] ==
register_list_format[indirect_offset] ||
!unique_indirect_regs[idx])
break;
}
- BUG_ON(idx >= *unique_indirect_reg_count);
+ BUG_ON(idx >= unique_indirect_reg_count);
if (!unique_indirect_regs[idx])
unique_indirect_regs[idx] = register_list_format[indirect_offset];
@@ -1893,9 +1896,10 @@ static int gfx_v9_1_init_rlc_save_restore_list(struct amdgpu_device *adev)
adev->gfx.rlc.reg_list_format_direct_reg_list_length,
adev->gfx.rlc.reg_list_format_size_bytes >> 2,
unique_indirect_regs,
- &unique_indirect_reg_count,
+ unique_indirect_reg_count,
indirect_start_offsets,
- &indirect_start_offsets_count);
+ &indirect_start_offsets_count,
+ ARRAY_SIZE(indirect_start_offsets));
/* enable auto inc in case it is disabled */
tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_CNTL));
@@ -3404,11 +3408,6 @@ static int gfx_v9_0_late_init(void *handle)
if (r)
return r;
- r = amdgpu_device_ip_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_GFX,
- AMD_PG_STATE_GATE);
- if (r)
- return r;
-
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
index 17f7f07..7a1e77c9 100644
--- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
@@ -2727,8 +2727,9 @@ static int kv_parse_power_table(struct amdgpu_device *adev)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
- adev->pm.dpm.ps = kzalloc(sizeof(struct amdgpu_ps) *
- state_array->ucNumEntries, GFP_KERNEL);
+ adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
+ sizeof(struct amdgpu_ps),
+ GFP_KERNEL);
if (!adev->pm.dpm.ps)
return -ENOMEM;
power_state_offset = (u8 *)state_array->states;
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
index 0c768e3..727071f 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
@@ -47,6 +47,8 @@ MODULE_FIRMWARE("amdgpu/vega20_asd.bin");
#define smnMP1_FIRMWARE_FLAGS 0x3010028
+static uint32_t sos_old_versions[] = {1517616, 1510592, 1448594, 1446554};
+
static int
psp_v3_1_get_fw_type(struct amdgpu_firmware_info *ucode, enum psp_gfx_fw_type *type)
{
@@ -210,12 +212,31 @@ static int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp)
return ret;
}
+static bool psp_v3_1_match_version(struct amdgpu_device *adev, uint32_t ver)
+{
+ int i;
+
+ if (ver == adev->psp.sos_fw_version)
+ return true;
+
+ /*
+ * Double check if the latest four legacy versions.
+ * If yes, it is still the right version.
+ */
+ for (i = 0; i < sizeof(sos_old_versions) / sizeof(uint32_t); i++) {
+ if (sos_old_versions[i] == adev->psp.sos_fw_version)
+ return true;
+ }
+
+ return false;
+}
+
static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
{
int ret;
unsigned int psp_gfxdrv_command_reg = 0;
struct amdgpu_device *adev = psp->adev;
- uint32_t sol_reg;
+ uint32_t sol_reg, ver;
/* Check sOS sign of life register to confirm sys driver and sOS
* are already been loaded.
@@ -248,6 +269,10 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_81),
0, true);
+ ver = RREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_58);
+ if (!psp_v3_1_match_version(adev, ver))
+ DRM_WARN("SOS version doesn't match\n");
+
return ret;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c
index b12d7c9..5c97a36 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c
@@ -7242,8 +7242,9 @@ static int si_parse_power_table(struct amdgpu_device *adev)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
- adev->pm.dpm.ps = kzalloc(sizeof(struct amdgpu_ps) *
- state_array->ucNumEntries, GFP_KERNEL);
+ adev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
+ sizeof(struct amdgpu_ps),
+ GFP_KERNEL);
if (!adev->pm.dpm.ps)
return -ENOMEM;
power_state_offset = (u8 *)state_array->states;
@@ -7346,7 +7347,9 @@ static int si_dpm_init(struct amdgpu_device *adev)
return ret;
adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
- kzalloc(4 * sizeof(struct amdgpu_clock_voltage_dependency_entry), GFP_KERNEL);
+ kcalloc(4,
+ sizeof(struct amdgpu_clock_voltage_dependency_entry),
+ GFP_KERNEL);
if (!adev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
amdgpu_free_extended_power_table(adev);
return -ENOMEM;
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index 68b4a22..83f2717 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -685,6 +685,7 @@ static int soc15_common_early_init(void *handle)
AMD_CG_SUPPORT_BIF_MGCG |
AMD_CG_SUPPORT_BIF_LS |
AMD_CG_SUPPORT_HDP_MGCG |
+ AMD_CG_SUPPORT_HDP_LS |
AMD_CG_SUPPORT_ROM_MGCG |
AMD_CG_SUPPORT_VCE_MGCG |
AMD_CG_SUPPORT_UVD_MGCG;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index 110b294..29684c3 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -769,14 +769,14 @@ static int vcn_v1_0_stop(struct amdgpu_device *adev)
return 0;
}
-bool vcn_v1_0_is_idle(void *handle)
+static bool vcn_v1_0_is_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
return (RREG32_SOC15(VCN, 0, mmUVD_STATUS) == 0x2);
}
-int vcn_v1_0_wait_for_idle(void *handle)
+static int vcn_v1_0_wait_for_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int ret = 0;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f9b9ab9..f9add85 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -46,6 +46,7 @@
#include <linux/moduleparam.h>
#include <linux/version.h>
#include <linux/types.h>
+#include <linux/pm_runtime.h>
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
@@ -2095,12 +2096,6 @@ convert_color_depth_from_display_info(const struct drm_connector *connector)
{
uint32_t bpc = connector->display_info.bpc;
- /* Limited color depth to 8bit
- * TODO: Still need to handle deep color
- */
- if (bpc > 8)
- bpc = 8;
-
switch (bpc) {
case 0:
/* Temporary Work around, DRM don't parse color depth for
@@ -2316,27 +2311,22 @@ decide_crtc_timing_for_drm_display_mode(struct drm_display_mode *drm_mode,
}
}
-static int create_fake_sink(struct amdgpu_dm_connector *aconnector)
+static struct dc_sink *
+create_fake_sink(struct amdgpu_dm_connector *aconnector)
{
- struct dc_sink *sink = NULL;
struct dc_sink_init_data sink_init_data = { 0 };
-
+ struct dc_sink *sink = NULL;
sink_init_data.link = aconnector->dc_link;
sink_init_data.sink_signal = aconnector->dc_link->connector_signal;
sink = dc_sink_create(&sink_init_data);
if (!sink) {
DRM_ERROR("Failed to create sink!\n");
- return -ENOMEM;
+ return NULL;
}
-
sink->sink_signal = SIGNAL_TYPE_VIRTUAL;
- aconnector->fake_enable = true;
-
- aconnector->dc_sink = sink;
- aconnector->dc_link->local_sink = sink;
- return 0;
+ return sink;
}
static void set_multisync_trigger_params(
@@ -2399,7 +2389,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
struct dc_stream_state *stream = NULL;
struct drm_display_mode mode = *drm_mode;
bool native_mode_found = false;
-
+ struct dc_sink *sink = NULL;
if (aconnector == NULL) {
DRM_ERROR("aconnector is NULL!\n");
return stream;
@@ -2417,15 +2407,18 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
return stream;
}
- if (create_fake_sink(aconnector))
+ sink = create_fake_sink(aconnector);
+ if (!sink)
return stream;
+ } else {
+ sink = aconnector->dc_sink;
}
- stream = dc_create_stream_for_sink(aconnector->dc_sink);
+ stream = dc_create_stream_for_sink(sink);
if (stream == NULL) {
DRM_ERROR("Failed to create stream for sink!\n");
- return stream;
+ goto finish;
}
list_for_each_entry(preferred_mode, &aconnector->base.modes, head) {
@@ -2464,12 +2457,15 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
fill_audio_info(
&stream->audio_info,
drm_connector,
- aconnector->dc_sink);
+ sink);
update_stream_signal(stream);
if (dm_state && dm_state->freesync_capable)
stream->ignore_msa_timing_param = true;
+finish:
+ if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL)
+ dc_sink_release(sink);
return stream;
}
@@ -2714,6 +2710,9 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
struct dm_connector_state *state =
to_dm_connector_state(connector->state);
+ if (connector->state)
+ __drm_atomic_helper_connector_destroy_state(connector->state);
+
kfree(state);
state = kzalloc(sizeof(*state), GFP_KERNEL);
@@ -2724,8 +2723,7 @@ void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector)
state->underscan_hborder = 0;
state->underscan_vborder = 0;
- connector->state = &state->base;
- connector->state->connector = connector;
+ __drm_atomic_helper_connector_reset(connector, &state->base);
}
}
@@ -3083,17 +3081,6 @@ static int dm_plane_helper_prepare_fb(struct drm_plane *plane,
}
}
- /* It's a hack for s3 since in 4.9 kernel filter out cursor buffer
- * prepare and cleanup in drm_atomic_helper_prepare_planes
- * and drm_atomic_helper_cleanup_planes because fb doens't in s3.
- * IN 4.10 kernel this code should be removed and amdgpu_device_suspend
- * code touching fram buffers should be avoided for DC.
- */
- if (plane->type == DRM_PLANE_TYPE_CURSOR) {
- struct amdgpu_crtc *acrtc = to_amdgpu_crtc(new_state->crtc);
-
- acrtc->cursor_bo = obj;
- }
return 0;
}
@@ -4281,6 +4268,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
if (dm_old_crtc_state->stream)
remove_stream(adev, acrtc, dm_old_crtc_state->stream);
+ pm_runtime_get_noresume(dev->dev);
+
acrtc->enabled = true;
acrtc->hw_mode = new_crtc_state->mode;
crtc->hwmode = new_crtc_state->mode;
@@ -4469,6 +4458,16 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_wait_for_flip_done(dev, state);
drm_atomic_helper_cleanup_planes(dev, state);
+
+ /* Finally, drop a runtime PM reference for each newly disabled CRTC,
+ * so we can put the GPU into runtime suspend if we're not driving any
+ * displays anymore
+ */
+ pm_runtime_mark_last_busy(dev->dev);
+ for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+ if (old_crtc_state->active && !new_crtc_state->active)
+ pm_runtime_put_autosuspend(dev->dev);
+ }
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index bd44935..ec304b1 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -435,7 +435,7 @@ bool dm_helpers_submit_i2c(
return false;
}
- msgs = kzalloc(num * sizeof(struct i2c_msg), GFP_KERNEL);
+ msgs = kcalloc(num, sizeof(struct i2c_msg), GFP_KERNEL);
if (!msgs)
return false;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
index 4be21bf..a910f01 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
@@ -555,6 +555,9 @@ static inline int dm_irq_state(struct amdgpu_device *adev,
return 0;
}
+ if (acrtc->otg_inst == -1)
+ return 0;
+
irq_source = dal_irq_type + acrtc->otg_inst;
st = (state == AMDGPU_IRQ_STATE_ENABLE);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c
index 0229c7ed..5a33461 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_services.c
@@ -234,6 +234,33 @@ static void pp_to_dc_clock_levels(
}
}
+static void pp_to_dc_clock_levels_with_latency(
+ const struct pp_clock_levels_with_latency *pp_clks,
+ struct dm_pp_clock_levels_with_latency *clk_level_info,
+ enum dm_pp_clock_type dc_clk_type)
+{
+ uint32_t i;
+
+ if (pp_clks->num_levels > DM_PP_MAX_CLOCK_LEVELS) {
+ DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
+ DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
+ pp_clks->num_levels,
+ DM_PP_MAX_CLOCK_LEVELS);
+
+ clk_level_info->num_levels = DM_PP_MAX_CLOCK_LEVELS;
+ } else
+ clk_level_info->num_levels = pp_clks->num_levels;
+
+ DRM_DEBUG("DM_PPLIB: values for %s clock\n",
+ DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
+
+ for (i = 0; i < clk_level_info->num_levels; i++) {
+ DRM_DEBUG("DM_PPLIB:\t %d\n", pp_clks->data[i].clocks_in_khz);
+ clk_level_info->data[i].clocks_in_khz = pp_clks->data[i].clocks_in_khz;
+ clk_level_info->data[i].latency_in_us = pp_clks->data[i].latency_in_us;
+ }
+}
+
bool dm_pp_get_clock_levels_by_type(
const struct dc_context *ctx,
enum dm_pp_clock_type clk_type,
@@ -311,8 +338,22 @@ bool dm_pp_get_clock_levels_by_type_with_latency(
enum dm_pp_clock_type clk_type,
struct dm_pp_clock_levels_with_latency *clk_level_info)
{
- /* TODO: to be implemented */
- return false;
+ struct amdgpu_device *adev = ctx->driver_context;
+ void *pp_handle = adev->powerplay.pp_handle;
+ struct pp_clock_levels_with_latency pp_clks = { 0 };
+ const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs;
+
+ if (!pp_funcs || !pp_funcs->get_clock_by_type_with_latency)
+ return false;
+
+ if (pp_funcs->get_clock_by_type_with_latency(pp_handle,
+ dc_to_pp_clock_type(clk_type),
+ &pp_clks))
+ return false;
+
+ pp_to_dc_clock_levels_with_latency(&pp_clks, clk_level_info, clk_type);
+
+ return true;
}
bool dm_pp_get_clock_levels_by_type_with_voltage(
diff --git a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
index e61dd97d..f289898 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/fixpt31_32.c
@@ -449,6 +449,11 @@ static inline unsigned int clamp_ux_dy(
return min_clamp;
}
+unsigned int dc_fixpt_u3d19(struct fixed31_32 arg)
+{
+ return ux_dy(arg.value, 3, 19);
+}
+
unsigned int dc_fixpt_u2d19(struct fixed31_32 arg)
{
return ux_dy(arg.value, 2, 19);
diff --git a/drivers/gpu/drm/amd/display/dc/basics/logger.c b/drivers/gpu/drm/amd/display/dc/basics/logger.c
index 738a818..0866874 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/logger.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/logger.c
@@ -364,7 +364,7 @@ void dm_logger_open(
entry->type = log_type;
entry->logger = logger;
- entry->buf = kzalloc(DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char),
+ entry->buf = kzalloc(DAL_LOGGER_BUFFER_MAX_SIZE,
GFP_KERNEL);
entry->buf_offset = 0;
diff --git a/drivers/gpu/drm/amd/display/dc/basics/vector.c b/drivers/gpu/drm/amd/display/dc/basics/vector.c
index 217b8f1..d28e9cf 100644
--- a/drivers/gpu/drm/amd/display/dc/basics/vector.c
+++ b/drivers/gpu/drm/amd/display/dc/basics/vector.c
@@ -40,7 +40,7 @@ bool dal_vector_construct(
return false;
}
- vector->container = kzalloc(struct_size * capacity, GFP_KERNEL);
+ vector->container = kcalloc(capacity, struct_size, GFP_KERNEL);
if (vector->container == NULL)
return false;
vector->capacity = capacity;
@@ -67,7 +67,7 @@ bool dal_vector_presized_costruct(
return false;
}
- vector->container = kzalloc(struct_size * count, GFP_KERNEL);
+ vector->container = kcalloc(count, struct_size, GFP_KERNEL);
if (vector->container == NULL)
return false;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 7d609c7..7857cb4 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -1630,17 +1630,42 @@ static enum dc_status read_hpd_rx_irq_data(
struct dc_link *link,
union hpd_irq_data *irq_data)
{
+ static enum dc_status retval;
+
/* The HW reads 16 bytes from 200h on HPD,
* but if we get an AUX_DEFER, the HW cannot retry
* and this causes the CTS tests 4.3.2.1 - 3.2.4 to
* fail, so we now explicitly read 6 bytes which is
* the req from the above mentioned test cases.
+ *
+ * For DP 1.4 we need to read those from 2002h range.
*/
- return core_link_read_dpcd(
- link,
- DP_SINK_COUNT,
- irq_data->raw,
- sizeof(union hpd_irq_data));
+ if (link->dpcd_caps.dpcd_rev.raw < DPCD_REV_14)
+ retval = core_link_read_dpcd(
+ link,
+ DP_SINK_COUNT,
+ irq_data->raw,
+ sizeof(union hpd_irq_data));
+ else {
+ /* Read 2 bytes at this location,... */
+ retval = core_link_read_dpcd(
+ link,
+ DP_SINK_COUNT_ESI,
+ irq_data->raw,
+ 2);
+
+ if (retval != DC_OK)
+ return retval;
+
+ /* ... then read remaining 4 at the other location */
+ retval = core_link_read_dpcd(
+ link,
+ DP_LANE0_1_STATUS_ESI,
+ &irq_data->raw[2],
+ 4);
+ }
+
+ return retval;
}
static bool allow_hpd_rx_irq(const struct dc_link *link)
@@ -2278,7 +2303,7 @@ static void dp_wa_power_up_0010FA(struct dc_link *link, uint8_t *dpcd_data,
static bool retrieve_link_cap(struct dc_link *link)
{
- uint8_t dpcd_data[DP_TRAINING_AUX_RD_INTERVAL - DP_DPCD_REV + 1];
+ uint8_t dpcd_data[DP_ADAPTER_CAP - DP_DPCD_REV + 1];
union down_stream_port_count down_strm_port_count;
union edp_configuration_cap edp_config_cap;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
index 599c7ab..88b09dd 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clock_source.c
@@ -1079,13 +1079,15 @@ static void get_ss_info_from_atombios(
if (*ss_entries_num == 0)
return;
- ss_info = kzalloc(sizeof(struct spread_spectrum_info) * (*ss_entries_num),
+ ss_info = kcalloc(*ss_entries_num,
+ sizeof(struct spread_spectrum_info),
GFP_KERNEL);
ss_info_cur = ss_info;
if (ss_info == NULL)
return;
- ss_data = kzalloc(sizeof(struct spread_spectrum_data) * (*ss_entries_num),
+ ss_data = kcalloc(*ss_entries_num,
+ sizeof(struct spread_spectrum_data),
GFP_KERNEL);
if (ss_data == NULL)
goto out_free_info;
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
index 0a6d483..c0e813c 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c
@@ -72,7 +72,8 @@ static void dce110_update_generic_info_packet(
uint32_t max_retries = 50;
/*we need turn on clock before programming AFMT block*/
- REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1);
+ if (REG(AFMT_CNTL))
+ REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1);
if (REG(AFMT_VBI_PACKET_CONTROL1)) {
if (packet_index >= 8)
@@ -719,7 +720,8 @@ static void dce110_stream_encoder_update_hdmi_info_packets(
const uint32_t *content =
(const uint32_t *) &info_frame->avi.sb[0];
/*we need turn on clock before programming AFMT block*/
- REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1);
+ if (REG(AFMT_CNTL))
+ REG_UPDATE(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, 1);
REG_WRITE(AFMT_AVI_INFO0, content[0]);
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
index 9150d26..e2994d3 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_compressor.c
@@ -121,10 +121,10 @@ static void reset_lb_on_vblank(struct dc_context *ctx)
frame_count = dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT);
- for (retry = 100; retry > 0; retry--) {
+ for (retry = 10000; retry > 0; retry--) {
if (frame_count != dm_read_reg(ctx, mmCRTC_STATUS_FRAME_COUNT))
break;
- msleep(1);
+ udelay(10);
}
if (!retry)
dm_error("Frame count did not increase for 100ms.\n");
@@ -147,14 +147,14 @@ static void wait_for_fbc_state_changed(
uint32_t addr = mmFBC_STATUS;
uint32_t value;
- while (counter < 10) {
+ while (counter < 1000) {
value = dm_read_reg(cp110->base.ctx, addr);
if (get_reg_field_value(
value,
FBC_STATUS,
FBC_ENABLE_STATUS) == enabled)
break;
- msleep(10);
+ udelay(100);
counter++;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index a92fb0a..c29052b 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -1004,9 +1004,9 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option)
/*don't free audio if it is from retrain or internal disable stream*/
if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) {
/*we have to dynamic arbitrate the audio endpoints*/
- pipe_ctx->stream_res.audio = NULL;
/*we free the resource, need reset is_audio_acquired*/
update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
+ pipe_ctx->stream_res.audio = NULL;
}
/* TODO: notify audio driver for if audio modes list changed
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
index 46a35c7..c69fa4b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.c
@@ -132,8 +132,7 @@ void dpp_set_gamut_remap_bypass(struct dcn10_dpp *dpp)
#define IDENTITY_RATIO(ratio) (dc_fixpt_u2d19(ratio) == (1 << 19))
-
-bool dpp_get_optimal_number_of_taps(
+static bool dpp_get_optimal_number_of_taps(
struct dpp *dpp,
struct scaler_data *scl_data,
const struct scaling_taps *in_taps)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h
index 5944a3b..e862caf 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp.h
@@ -1424,12 +1424,8 @@ void dpp1_set_degamma(
enum ipp_degamma_mode mode);
void dpp1_set_degamma_pwl(struct dpp *dpp_base,
- const struct pwl_params *params);
+ const struct pwl_params *params);
-bool dpp_get_optimal_number_of_taps(
- struct dpp *dpp,
- struct scaler_data *scl_data,
- const struct scaling_taps *in_taps);
void dpp_read_state(struct dpp *dpp_base,
struct dcn_dpp_state *s);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
index 4ddd627..f862fd1 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c
@@ -565,16 +565,16 @@ static void dpp1_dscl_set_manual_ratio_init(
uint32_t init_int = 0;
REG_SET(SCL_HORZ_FILTER_SCALE_RATIO, 0,
- SCL_H_SCALE_RATIO, dc_fixpt_u2d19(data->ratios.horz) << 5);
+ SCL_H_SCALE_RATIO, dc_fixpt_u3d19(data->ratios.horz) << 5);
REG_SET(SCL_VERT_FILTER_SCALE_RATIO, 0,
- SCL_V_SCALE_RATIO, dc_fixpt_u2d19(data->ratios.vert) << 5);
+ SCL_V_SCALE_RATIO, dc_fixpt_u3d19(data->ratios.vert) << 5);
REG_SET(SCL_HORZ_FILTER_SCALE_RATIO_C, 0,
- SCL_H_SCALE_RATIO_C, dc_fixpt_u2d19(data->ratios.horz_c) << 5);
+ SCL_H_SCALE_RATIO_C, dc_fixpt_u3d19(data->ratios.horz_c) << 5);
REG_SET(SCL_VERT_FILTER_SCALE_RATIO_C, 0,
- SCL_V_SCALE_RATIO_C, dc_fixpt_u2d19(data->ratios.vert_c) << 5);
+ SCL_V_SCALE_RATIO_C, dc_fixpt_u3d19(data->ratios.vert_c) << 5);
/*
* 0.24 format for fraction, first five bits zeroed
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
index d2ab78b..c28085b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c
@@ -396,11 +396,15 @@ bool hubp1_program_surface_flip_and_addr(
if (address->grph_stereo.right_addr.quad_part == 0)
break;
- REG_UPDATE_4(DCSURF_SURFACE_CONTROL,
+ REG_UPDATE_8(DCSURF_SURFACE_CONTROL,
PRIMARY_SURFACE_TMZ, address->tmz_surface,
PRIMARY_SURFACE_TMZ_C, address->tmz_surface,
PRIMARY_META_SURFACE_TMZ, address->tmz_surface,
- PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface);
+ PRIMARY_META_SURFACE_TMZ_C, address->tmz_surface,
+ SECONDARY_SURFACE_TMZ, address->tmz_surface,
+ SECONDARY_SURFACE_TMZ_C, address->tmz_surface,
+ SECONDARY_META_SURFACE_TMZ, address->tmz_surface,
+ SECONDARY_META_SURFACE_TMZ_C, address->tmz_surface);
if (address->grph_stereo.right_meta_addr.quad_part != 0) {
@@ -459,9 +463,11 @@ void hubp1_dcc_control(struct hubp *hubp, bool enable,
uint32_t dcc_ind_64b_blk = independent_64b_blks ? 1 : 0;
struct dcn10_hubp *hubp1 = TO_DCN10_HUBP(hubp);
- REG_UPDATE_2(DCSURF_SURFACE_CONTROL,
+ REG_UPDATE_4(DCSURF_SURFACE_CONTROL,
PRIMARY_SURFACE_DCC_EN, dcc_en,
- PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk);
+ PRIMARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk,
+ SECONDARY_SURFACE_DCC_EN, dcc_en,
+ SECONDARY_SURFACE_DCC_IND_64B_BLK, dcc_ind_64b_blk);
}
void hubp1_program_surface_config(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
index af38403..d901d50 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.h
@@ -312,6 +312,12 @@
HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_META_SURFACE_TMZ_C, mask_sh),\
HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_EN, mask_sh),\
HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, PRIMARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\
+ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_TMZ, mask_sh),\
+ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_TMZ_C, mask_sh),\
+ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_META_SURFACE_TMZ, mask_sh),\
+ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_META_SURFACE_TMZ_C, mask_sh),\
+ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_EN, mask_sh),\
+ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_IND_64B_BLK, mask_sh),\
HUBP_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\
HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\
HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\
@@ -489,6 +495,8 @@
type SECONDARY_META_SURFACE_TMZ_C;\
type PRIMARY_SURFACE_DCC_EN;\
type PRIMARY_SURFACE_DCC_IND_64B_BLK;\
+ type SECONDARY_SURFACE_DCC_EN;\
+ type SECONDARY_SURFACE_DCC_IND_64B_BLK;\
type DET_BUF_PLANE1_BASE_ADDRESS;\
type CROSSBAR_SRC_CB_B;\
type CROSSBAR_SRC_CR_R;\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
index 653b7b2..c928ee4 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_stream_encoder.c
@@ -319,6 +319,10 @@ void enc1_stream_encoder_dp_set_stream_attribute(
REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
DP_COMPONENT_PIXEL_DEPTH_12BPC);
break;
+ case COLOR_DEPTH_161616:
+ REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
+ DP_COMPONENT_PIXEL_DEPTH_16BPC);
+ break;
default:
REG_UPDATE(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH,
DP_COMPONENT_PIXEL_DEPTH_6BPC);
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
index 80038e0..ab5483c 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
@@ -98,7 +98,8 @@ struct gpio_service *dal_gpio_service_create(
if (number_of_bits) {
uint32_t index_of_uint = 0;
- slot = kzalloc(number_of_uints * sizeof(uint32_t),
+ slot = kcalloc(number_of_uints,
+ sizeof(uint32_t),
GFP_KERNEL);
if (!slot) {
diff --git a/drivers/gpu/drm/amd/display/include/fixed31_32.h b/drivers/gpu/drm/amd/display/include/fixed31_32.h
index bb0d4eb..a981b3e 100644
--- a/drivers/gpu/drm/amd/display/include/fixed31_32.h
+++ b/drivers/gpu/drm/amd/display/include/fixed31_32.h
@@ -496,6 +496,8 @@ static inline int dc_fixpt_ceil(struct fixed31_32 arg)
* fractional
*/
+unsigned int dc_fixpt_u3d19(struct fixed31_32 arg);
+
unsigned int dc_fixpt_u2d19(struct fixed31_32 arg);
unsigned int dc_fixpt_u0d19(struct fixed31_32 arg);
diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
index 0cd111d..eee0dfa 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -1274,19 +1274,22 @@ bool mod_color_calculate_regamma_params(struct dc_transfer_func *output_tf,
output_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
- rgb_user = kvzalloc(sizeof(*rgb_user) * (ramp->num_entries + _EXTRA_POINTS),
+ rgb_user = kvcalloc(ramp->num_entries + _EXTRA_POINTS,
+ sizeof(*rgb_user),
GFP_KERNEL);
if (!rgb_user)
goto rgb_user_alloc_fail;
- rgb_regamma = kvzalloc(sizeof(*rgb_regamma) * (MAX_HW_POINTS + _EXTRA_POINTS),
+ rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
+ sizeof(*rgb_regamma),
GFP_KERNEL);
if (!rgb_regamma)
goto rgb_regamma_alloc_fail;
- axix_x = kvzalloc(sizeof(*axix_x) * (ramp->num_entries + 3),
+ axix_x = kvcalloc(ramp->num_entries + 3, sizeof(*axix_x),
GFP_KERNEL);
if (!axix_x)
goto axix_x_alloc_fail;
- coeff = kvzalloc(sizeof(*coeff) * (MAX_HW_POINTS + _EXTRA_POINTS), GFP_KERNEL);
+ coeff = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*coeff),
+ GFP_KERNEL);
if (!coeff)
goto coeff_alloc_fail;
@@ -1413,13 +1416,15 @@ bool calculate_user_regamma_ramp(struct dc_transfer_func *output_tf,
output_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
- rgb_user = kzalloc(sizeof(*rgb_user) * (GAMMA_RGB_256_ENTRIES + _EXTRA_POINTS),
- GFP_KERNEL);
+ rgb_user = kcalloc(GAMMA_RGB_256_ENTRIES + _EXTRA_POINTS,
+ sizeof(*rgb_user),
+ GFP_KERNEL);
if (!rgb_user)
goto rgb_user_alloc_fail;
- rgb_regamma = kzalloc(sizeof(*rgb_regamma) * (MAX_HW_POINTS + _EXTRA_POINTS),
- GFP_KERNEL);
+ rgb_regamma = kcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
+ sizeof(*rgb_regamma),
+ GFP_KERNEL);
if (!rgb_regamma)
goto rgb_regamma_alloc_fail;
@@ -1480,19 +1485,21 @@ bool mod_color_calculate_degamma_params(struct dc_transfer_func *input_tf,
input_tf->type = TF_TYPE_DISTRIBUTED_POINTS;
- rgb_user = kvzalloc(sizeof(*rgb_user) * (ramp->num_entries + _EXTRA_POINTS),
+ rgb_user = kvcalloc(ramp->num_entries + _EXTRA_POINTS,
+ sizeof(*rgb_user),
GFP_KERNEL);
if (!rgb_user)
goto rgb_user_alloc_fail;
- curve = kvzalloc(sizeof(*curve) * (MAX_HW_POINTS + _EXTRA_POINTS),
+ curve = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*curve),
GFP_KERNEL);
if (!curve)
goto curve_alloc_fail;
- axix_x = kvzalloc(sizeof(*axix_x) * (ramp->num_entries + _EXTRA_POINTS),
+ axix_x = kvcalloc(ramp->num_entries + _EXTRA_POINTS, sizeof(*axix_x),
GFP_KERNEL);
if (!axix_x)
goto axix_x_alloc_fail;
- coeff = kvzalloc(sizeof(*coeff) * (MAX_HW_POINTS + _EXTRA_POINTS), GFP_KERNEL);
+ coeff = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS, sizeof(*coeff),
+ GFP_KERNEL);
if (!coeff)
goto coeff_alloc_fail;
@@ -1569,8 +1576,8 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
}
ret = true;
} else if (trans == TRANSFER_FUNCTION_PQ) {
- rgb_regamma = kvzalloc(sizeof(*rgb_regamma) *
- (MAX_HW_POINTS + _EXTRA_POINTS),
+ rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
+ sizeof(*rgb_regamma),
GFP_KERNEL);
if (!rgb_regamma)
goto rgb_regamma_alloc_fail;
@@ -1594,8 +1601,8 @@ bool mod_color_calculate_curve(enum dc_transfer_func_predefined trans,
kvfree(rgb_regamma);
} else if (trans == TRANSFER_FUNCTION_SRGB ||
trans == TRANSFER_FUNCTION_BT709) {
- rgb_regamma = kvzalloc(sizeof(*rgb_regamma) *
- (MAX_HW_POINTS + _EXTRA_POINTS),
+ rgb_regamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
+ sizeof(*rgb_regamma),
GFP_KERNEL);
if (!rgb_regamma)
goto rgb_regamma_alloc_fail;
@@ -1638,8 +1645,8 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
}
ret = true;
} else if (trans == TRANSFER_FUNCTION_PQ) {
- rgb_degamma = kvzalloc(sizeof(*rgb_degamma) *
- (MAX_HW_POINTS + _EXTRA_POINTS),
+ rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
+ sizeof(*rgb_degamma),
GFP_KERNEL);
if (!rgb_degamma)
goto rgb_degamma_alloc_fail;
@@ -1658,8 +1665,8 @@ bool mod_color_calculate_degamma_curve(enum dc_transfer_func_predefined trans,
kvfree(rgb_degamma);
} else if (trans == TRANSFER_FUNCTION_SRGB ||
trans == TRANSFER_FUNCTION_BT709) {
- rgb_degamma = kvzalloc(sizeof(*rgb_degamma) *
- (MAX_HW_POINTS + _EXTRA_POINTS),
+ rgb_degamma = kvcalloc(MAX_HW_POINTS + _EXTRA_POINTS,
+ sizeof(*rgb_degamma),
GFP_KERNEL);
if (!rgb_degamma)
goto rgb_degamma_alloc_fail;
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index 27d4003..fa344ce 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -155,7 +155,8 @@ struct mod_freesync *mod_freesync_create(struct dc *dc)
if (core_freesync == NULL)
goto fail_alloc_context;
- core_freesync->map = kzalloc(sizeof(struct freesync_entity) * MOD_FREESYNC_MAX_CONCURRENT_STREAMS,
+ core_freesync->map = kcalloc(MOD_FREESYNC_MAX_CONCURRENT_STREAMS,
+ sizeof(struct freesync_entity),
GFP_KERNEL);
if (core_freesync->map == NULL)
diff --git a/drivers/gpu/drm/amd/display/modules/stats/stats.c b/drivers/gpu/drm/amd/display/modules/stats/stats.c
index 3f7d47f..710852a 100644
--- a/drivers/gpu/drm/amd/display/modules/stats/stats.c
+++ b/drivers/gpu/drm/amd/display/modules/stats/stats.c
@@ -141,19 +141,17 @@ struct mod_stats *mod_stats_create(struct dc *dc)
else
core_stats->entries = reg_data;
}
- core_stats->time = kzalloc(
- sizeof(struct stats_time_cache) *
- core_stats->entries,
+ core_stats->time = kcalloc(core_stats->entries,
+ sizeof(struct stats_time_cache),
GFP_KERNEL);
if (core_stats->time == NULL)
goto fail_construct_time;
core_stats->event_entries = DAL_STATS_EVENT_ENTRIES_DEFAULT;
- core_stats->events = kzalloc(
- sizeof(struct stats_event_cache) *
- core_stats->event_entries,
- GFP_KERNEL);
+ core_stats->events = kcalloc(core_stats->event_entries,
+ sizeof(struct stats_event_cache),
+ GFP_KERNEL);
if (core_stats->events == NULL)
goto fail_construct_events;
diff --git a/drivers/gpu/drm/amd/include/asic_reg/df/df_3_6_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/df/df_3_6_sh_mask.h
index 88f7c69..06fac50 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/df/df_3_6_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/df/df_3_6_sh_mask.h
@@ -36,13 +36,13 @@
/* DF_CS_AON0_DramBaseAddress0 */
#define DF_CS_UMC_AON0_DramBaseAddress0__AddrRngVal__SHIFT 0x0
#define DF_CS_UMC_AON0_DramBaseAddress0__LgcyMmioHoleEn__SHIFT 0x1
-#define DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan__SHIFT 0x4
-#define DF_CS_UMC_AON0_DramBaseAddress0__IntLvAddrSel__SHIFT 0x8
+#define DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan__SHIFT 0x2
+#define DF_CS_UMC_AON0_DramBaseAddress0__IntLvAddrSel__SHIFT 0x9
#define DF_CS_UMC_AON0_DramBaseAddress0__DramBaseAddr__SHIFT 0xc
#define DF_CS_UMC_AON0_DramBaseAddress0__AddrRngVal_MASK 0x00000001L
#define DF_CS_UMC_AON0_DramBaseAddress0__LgcyMmioHoleEn_MASK 0x00000002L
-#define DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK 0x000000F0L
-#define DF_CS_UMC_AON0_DramBaseAddress0__IntLvAddrSel_MASK 0x00000700L
+#define DF_CS_UMC_AON0_DramBaseAddress0__IntLvNumChan_MASK 0x0000003CL
+#define DF_CS_UMC_AON0_DramBaseAddress0__IntLvAddrSel_MASK 0x00000E00L
#define DF_CS_UMC_AON0_DramBaseAddress0__DramBaseAddr_MASK 0xFFFFF000L
#endif
diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h
index c6c1666..092d800 100644
--- a/drivers/gpu/drm/amd/include/atomfirmware.h
+++ b/drivers/gpu/drm/amd/include/atomfirmware.h
@@ -2026,17 +2026,15 @@ enum atom_smu11_syspll_id {
SMU11_SYSPLL3_1_ID = 6,
};
-
enum atom_smu11_syspll0_clock_id {
- SMU11_SYSPLL0_SOCCLK_ID = 0, // SOCCLK
- SMU11_SYSPLL0_MP0CLK_ID = 1, // MP0CLK
- SMU11_SYSPLL0_DCLK_ID = 2, // DCLK
- SMU11_SYSPLL0_VCLK_ID = 3, // VCLK
- SMU11_SYSPLL0_ECLK_ID = 4, // ECLK
+ SMU11_SYSPLL0_ECLK_ID = 0, // ECLK
+ SMU11_SYSPLL0_SOCCLK_ID = 1, // SOCCLK
+ SMU11_SYSPLL0_MP0CLK_ID = 2, // MP0CLK
+ SMU11_SYSPLL0_DCLK_ID = 3, // DCLK
+ SMU11_SYSPLL0_VCLK_ID = 4, // VCLK
SMU11_SYSPLL0_DCEFCLK_ID = 5, // DCEFCLK
};
-
enum atom_smu11_syspll1_0_clock_id {
SMU11_SYSPLL1_0_UCLKA_ID = 0, // UCLK_a
};
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index b493369..d567be4 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -180,7 +180,6 @@ static int pp_late_init(void *handle)
{
struct amdgpu_device *adev = handle;
struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
- int ret;
if (hwmgr && hwmgr->pm_en) {
mutex_lock(&hwmgr->smu_lock);
@@ -191,13 +190,6 @@ static int pp_late_init(void *handle)
if (adev->pm.smu_prv_buffer_size != 0)
pp_reserve_vram_for_smu(adev);
- if (hwmgr->hwmgr_func->gfx_off_control &&
- (hwmgr->feature_mask & PP_GFXOFF_MASK)) {
- ret = hwmgr->hwmgr_func->gfx_off_control(hwmgr, true);
- if (ret)
- pr_err("gfx off enabling failed!\n");
- }
-
return 0;
}
@@ -245,7 +237,7 @@ static int pp_set_powergating_state(void *handle,
}
if (hwmgr->hwmgr_func->enable_per_cu_power_gating == NULL) {
- pr_info("%s was not implemented.\n", __func__);
+ pr_debug("%s was not implemented.\n", __func__);
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c
index 0af13c1..91ffb7b 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c
@@ -50,7 +50,7 @@ int psm_init_power_state_table(struct pp_hwmgr *hwmgr)
return 0;
}
- hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL);
+ hwmgr->ps = kcalloc(table_entries, size, GFP_KERNEL);
if (hwmgr->ps == NULL)
return -ENOMEM;
@@ -265,19 +265,18 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip,
if (skip)
return 0;
- if (!hwmgr->ps)
- /*
- * for vega12/vega20 which does not support power state manager
- * DAL clock limits should also be honoured
- */
- phm_apply_clock_adjust_rules(hwmgr);
-
phm_pre_display_configuration_changed(hwmgr);
phm_display_configuration_changed(hwmgr);
if (hwmgr->ps)
power_state_management(hwmgr, new_ps);
+ else
+ /*
+ * for vega12/vega20 which does not support power state manager
+ * DAL clock limits should also be honoured
+ */
+ phm_apply_clock_adjust_rules(hwmgr);
phm_notify_smc_display_config_after_ps_adjustment(hwmgr);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c
index c97b0e5..5325661 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c
@@ -496,7 +496,9 @@ int pp_atomfwctrl_get_clk_information_by_clkid(struct pp_hwmgr *hwmgr, BIOS_CLKI
uint32_t ix;
parameters.clk_id = id;
+ parameters.syspll_id = 0;
parameters.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ;
+ parameters.dfsdid = 0;
ix = GetIndexIntoMasterCmdTable(getsmuclockinfo);
@@ -505,7 +507,7 @@ int pp_atomfwctrl_get_clk_information_by_clkid(struct pp_hwmgr *hwmgr, BIOS_CLKI
return -EINVAL;
output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)&parameters;
- *frequency = output->atom_smu_outputclkfreq.smu_clock_freq_hz / 10000;
+ *frequency = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000;
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c
index f0d48b1..35bd987 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c
@@ -870,12 +870,6 @@ static int init_over_drive_limits(
hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
hwmgr->platform_descriptor.overdriveVDDCStep = 0;
- if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0 \
- || hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) {
- hwmgr->od_enabled = false;
- pr_debug("OverDrive feature not support by VBIOS\n");
- }
-
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
index ce64dfa..925e171 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c
@@ -1074,12 +1074,6 @@ static int init_overdrive_limits(struct pp_hwmgr *hwmgr,
powerplay_table,
(const ATOM_FIRMWARE_INFO_V2_1 *)fw_info);
- if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0
- && hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) {
- hwmgr->od_enabled = false;
- pr_debug("OverDrive feature not support by VBIOS\n");
- }
-
return result;
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
index 85f84f4..d4bc83e 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
@@ -53,8 +53,37 @@ static const unsigned long SMU10_Magic = (unsigned long) PHM_Rv_Magic;
static int smu10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
- struct pp_display_clock_request *clock_req);
+ struct pp_display_clock_request *clock_req)
+{
+ struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
+ enum amd_pp_clock_type clk_type = clock_req->clock_type;
+ uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
+ PPSMC_Msg msg;
+ switch (clk_type) {
+ case amd_pp_dcf_clock:
+ if (clk_freq == smu10_data->dcf_actual_hard_min_freq)
+ return 0;
+ msg = PPSMC_MSG_SetHardMinDcefclkByFreq;
+ smu10_data->dcf_actual_hard_min_freq = clk_freq;
+ break;
+ case amd_pp_soc_clock:
+ msg = PPSMC_MSG_SetHardMinSocclkByFreq;
+ break;
+ case amd_pp_f_clock:
+ if (clk_freq == smu10_data->f_actual_hard_min_freq)
+ return 0;
+ smu10_data->f_actual_hard_min_freq = clk_freq;
+ msg = PPSMC_MSG_SetHardMinFclkByFreq;
+ break;
+ default:
+ pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
+ return -EINVAL;
+ }
+ smum_send_msg_to_smc_with_parameter(hwmgr, msg, clk_freq);
+
+ return 0;
+}
static struct smu10_power_state *cast_smu10_ps(struct pp_hw_power_state *hw_ps)
{
@@ -284,7 +313,7 @@ static int smu10_disable_gfx_off(struct pp_hwmgr *hwmgr)
static int smu10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
{
- return smu10_disable_gfx_off(hwmgr);
+ return 0;
}
static int smu10_enable_gfx_off(struct pp_hwmgr *hwmgr)
@@ -299,7 +328,7 @@ static int smu10_enable_gfx_off(struct pp_hwmgr *hwmgr)
static int smu10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
{
- return smu10_enable_gfx_off(hwmgr);
+ return 0;
}
static int smu10_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable)
@@ -1000,6 +1029,12 @@ static int smu10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
case amd_pp_soc_clock:
pclk_vol_table = pinfo->vdd_dep_on_socclk;
break;
+ case amd_pp_disp_clock:
+ pclk_vol_table = pinfo->vdd_dep_on_dispclk;
+ break;
+ case amd_pp_phy_clock:
+ pclk_vol_table = pinfo->vdd_dep_on_phyclk;
+ break;
default:
return -EINVAL;
}
@@ -1017,39 +1052,7 @@ static int smu10_get_clock_by_type_with_voltage(struct pp_hwmgr *hwmgr,
return 0;
}
-static int smu10_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
- struct pp_display_clock_request *clock_req)
-{
- struct smu10_hwmgr *smu10_data = (struct smu10_hwmgr *)(hwmgr->backend);
- enum amd_pp_clock_type clk_type = clock_req->clock_type;
- uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
- PPSMC_Msg msg;
- switch (clk_type) {
- case amd_pp_dcf_clock:
- if (clk_freq == smu10_data->dcf_actual_hard_min_freq)
- return 0;
- msg = PPSMC_MSG_SetHardMinDcefclkByFreq;
- smu10_data->dcf_actual_hard_min_freq = clk_freq;
- break;
- case amd_pp_soc_clock:
- msg = PPSMC_MSG_SetHardMinSocclkByFreq;
- break;
- case amd_pp_f_clock:
- if (clk_freq == smu10_data->f_actual_hard_min_freq)
- return 0;
- smu10_data->f_actual_hard_min_freq = clk_freq;
- msg = PPSMC_MSG_SetHardMinFclkByFreq;
- break;
- default:
- pr_info("[DisplayClockVoltageRequest]Invalid Clock Type!");
- return -EINVAL;
- }
-
- smum_send_msg_to_smc_with_parameter(hwmgr, msg, clk_freq);
-
- return 0;
-}
static int smu10_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks)
{
@@ -1182,6 +1185,7 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = {
.set_mmhub_powergating_by_smu = smu10_set_mmhub_powergating_by_smu,
.smus_notify_pwe = smu10_smus_notify_pwe,
.gfx_off_control = smu10_gfx_off_control,
+ .display_clock_voltage_request = smu10_display_clock_voltage_request,
};
int smu10_init_function_pointers(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
index 45e9b8c..f8e866c 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
@@ -791,7 +791,8 @@ static int smu7_setup_dpm_tables_v1(struct pp_hwmgr *hwmgr)
data->dpm_table.sclk_table.count++;
}
}
-
+ if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0)
+ hwmgr->platform_descriptor.overdriveLimit.engineClock = dep_sclk_table->entries[i-1].clk;
/* Initialize Mclk DPM table based on allow Mclk values */
data->dpm_table.mclk_table.count = 0;
for (i = 0; i < dep_mclk_table->count; i++) {
@@ -806,6 +807,8 @@ static int smu7_setup_dpm_tables_v1(struct pp_hwmgr *hwmgr)
}
}
+ if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0)
+ hwmgr->platform_descriptor.overdriveLimit.memoryClock = dep_mclk_table->entries[i-1].clk;
return 0;
}
@@ -3752,14 +3755,17 @@ static int smu7_trim_dpm_states(struct pp_hwmgr *hwmgr,
static int smu7_generate_dpm_level_enable_mask(
struct pp_hwmgr *hwmgr, const void *input)
{
- int result;
+ int result = 0;
const struct phm_set_power_state_input *states =
(const struct phm_set_power_state_input *)input;
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
const struct smu7_power_state *smu7_ps =
cast_const_phw_smu7_power_state(states->pnew_state);
- result = smu7_trim_dpm_states(hwmgr, smu7_ps);
+ /*skip the trim if od is enabled*/
+ if (!hwmgr->od_enabled)
+ result = smu7_trim_dpm_states(hwmgr, smu7_ps);
+
if (result)
return result;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
index d156b7b..05e680d 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
@@ -321,8 +321,12 @@ static int vega10_odn_initial_default_setting(struct pp_hwmgr *hwmgr)
odn_table->min_vddc = dep_table[0]->entries[0].vddc;
i = od_table[2]->count - 1;
- od_table[2]->entries[i].clk = hwmgr->platform_descriptor.overdriveLimit.memoryClock;
- od_table[2]->entries[i].vddc = odn_table->max_vddc;
+ od_table[2]->entries[i].clk = hwmgr->platform_descriptor.overdriveLimit.memoryClock > od_table[2]->entries[i].clk ?
+ hwmgr->platform_descriptor.overdriveLimit.memoryClock :
+ od_table[2]->entries[i].clk;
+ od_table[2]->entries[i].vddc = odn_table->max_vddc > od_table[2]->entries[i].vddc ?
+ odn_table->max_vddc :
+ od_table[2]->entries[i].vddc;
return 0;
}
@@ -1311,6 +1315,9 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
vega10_setup_default_single_dpm_table(hwmgr,
dpm_table,
dep_gfx_table);
+ if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0)
+ hwmgr->platform_descriptor.overdriveLimit.engineClock =
+ dpm_table->dpm_levels[dpm_table->count-1].value;
vega10_init_dpm_state(&(dpm_table->dpm_state));
/* Initialize Mclk DPM table based on allow Mclk values */
@@ -1319,6 +1326,10 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
vega10_setup_default_single_dpm_table(hwmgr,
dpm_table,
dep_mclk_table);
+ if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0)
+ hwmgr->platform_descriptor.overdriveLimit.memoryClock =
+ dpm_table->dpm_levels[dpm_table->count-1].value;
+
vega10_init_dpm_state(&(dpm_table->dpm_state));
data->dpm_table.eclk_table.count = 0;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c
index a9efd855..2236487 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c
@@ -1090,7 +1090,7 @@ static int vega10_disable_se_edc_config(struct pp_hwmgr *hwmgr)
static int vega10_enable_psm_gc_edc_config(struct pp_hwmgr *hwmgr)
{
struct amdgpu_device *adev = hwmgr->adev;
- int result;
+ int result = 0;
uint32_t num_se = 0;
uint32_t count, data;
@@ -1104,7 +1104,7 @@ static int vega10_enable_psm_gc_edc_config(struct pp_hwmgr *hwmgr)
for (count = 0; count < num_se; count++) {
data = GRBM_GFX_INDEX__INSTANCE_BROADCAST_WRITES_MASK | GRBM_GFX_INDEX__SH_BROADCAST_WRITES_MASK | ( count << GRBM_GFX_INDEX__SE_INDEX__SHIFT);
WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data);
- result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT);
+ result = vega10_program_didt_config_registers(hwmgr, PSMSEEDCStallPatternConfig_Vega10, VEGA10_CONFIGREG_DIDT);
result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCStallDelayConfig_Vega10, VEGA10_CONFIGREG_DIDT);
result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCCtrlResetConfig_Vega10, VEGA10_CONFIGREG_DIDT);
result |= vega10_program_didt_config_registers(hwmgr, PSMSEEDCCtrlConfig_Vega10, VEGA10_CONFIGREG_DIDT);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
index 0768d25..16b1a9c 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
@@ -267,12 +267,6 @@ static int init_over_drive_limits(
hwmgr->platform_descriptor.maxOverdriveVDDC = 0;
hwmgr->platform_descriptor.overdriveVDDCStep = 0;
- if (hwmgr->platform_descriptor.overdriveLimit.engineClock == 0 ||
- hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) {
- hwmgr->od_enabled = false;
- pr_debug("OverDrive feature not support by VBIOS\n");
- }
-
return 0;
}
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index 73c875d..47e0992 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -839,7 +839,7 @@ static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane)
return ret;
}
- if (desc->layout.xstride && desc->layout.pstride) {
+ if (desc->layout.xstride[0] && desc->layout.pstride[0]) {
int ret;
ret = drm_plane_create_rotation_property(&plane->base,
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index 7ab3604..250effa 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -36,8 +36,11 @@
#define SII8620_BURST_BUF_LEN 288
#define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3)
-#define MHL1_MAX_LCLK 225000
-#define MHL3_MAX_LCLK 600000
+
+#define MHL1_MAX_PCLK 75000
+#define MHL1_MAX_PCLK_PP_MODE 150000
+#define MHL3_MAX_PCLK 200000
+#define MHL3_MAX_PCLK_PP_MODE 300000
enum sii8620_mode {
CM_DISCONNECTED,
@@ -80,6 +83,9 @@ struct sii8620 {
u8 devcap[MHL_DCAP_SIZE];
u8 xdevcap[MHL_XDC_SIZE];
u8 avif[HDMI_INFOFRAME_SIZE(AVI)];
+ bool feature_complete;
+ bool devcap_read;
+ bool sink_detected;
struct edid *edid;
unsigned int gen2_write_burst:1;
enum sii8620_mt_state mt_state;
@@ -476,7 +482,7 @@ static void sii8620_update_array(u8 *dst, u8 *src, int count)
}
}
-static void sii8620_sink_detected(struct sii8620 *ctx, int ret)
+static void sii8620_identify_sink(struct sii8620 *ctx)
{
static const char * const sink_str[] = {
[SINK_NONE] = "NONE",
@@ -487,7 +493,7 @@ static void sii8620_sink_detected(struct sii8620 *ctx, int ret)
char sink_name[20];
struct device *dev = ctx->dev;
- if (ret < 0)
+ if (!ctx->sink_detected || !ctx->devcap_read)
return;
sii8620_fetch_edid(ctx);
@@ -496,6 +502,7 @@ static void sii8620_sink_detected(struct sii8620 *ctx, int ret)
sii8620_mhl_disconnected(ctx);
return;
}
+ sii8620_set_upstream_edid(ctx);
if (drm_detect_hdmi_monitor(ctx->edid))
ctx->sink_type = SINK_HDMI;
@@ -508,53 +515,6 @@ static void sii8620_sink_detected(struct sii8620 *ctx, int ret)
sink_str[ctx->sink_type], sink_name);
}
-static void sii8620_hsic_init(struct sii8620 *ctx)
-{
- if (!sii8620_is_mhl3(ctx))
- return;
-
- sii8620_write(ctx, REG_FCGC,
- BIT_FCGC_HSIC_HOSTMODE | BIT_FCGC_HSIC_ENABLE);
- sii8620_setbits(ctx, REG_HRXCTRL3,
- BIT_HRXCTRL3_HRX_STAY_RESET | BIT_HRXCTRL3_STATUS_EN, ~0);
- sii8620_setbits(ctx, REG_TTXNUMB, MSK_TTXNUMB_TTX_NUMBPS, 4);
- sii8620_setbits(ctx, REG_TRXCTRL, BIT_TRXCTRL_TRX_FROM_SE_COC, ~0);
- sii8620_setbits(ctx, REG_HTXCTRL, BIT_HTXCTRL_HTX_DRVCONN1, 0);
- sii8620_setbits(ctx, REG_KEEPER, MSK_KEEPER_MODE, VAL_KEEPER_MODE_HOST);
- sii8620_write_seq_static(ctx,
- REG_TDMLLCTL, 0,
- REG_UTSRST, BIT_UTSRST_HRX_SRST | BIT_UTSRST_HTX_SRST |
- BIT_UTSRST_KEEPER_SRST | BIT_UTSRST_FC_SRST,
- REG_UTSRST, BIT_UTSRST_HRX_SRST | BIT_UTSRST_HTX_SRST,
- REG_HRXINTL, 0xff,
- REG_HRXINTH, 0xff,
- REG_TTXINTL, 0xff,
- REG_TTXINTH, 0xff,
- REG_TRXINTL, 0xff,
- REG_TRXINTH, 0xff,
- REG_HTXINTL, 0xff,
- REG_HTXINTH, 0xff,
- REG_FCINTR0, 0xff,
- REG_FCINTR1, 0xff,
- REG_FCINTR2, 0xff,
- REG_FCINTR3, 0xff,
- REG_FCINTR4, 0xff,
- REG_FCINTR5, 0xff,
- REG_FCINTR6, 0xff,
- REG_FCINTR7, 0xff
- );
-}
-
-static void sii8620_edid_read(struct sii8620 *ctx, int ret)
-{
- if (ret < 0)
- return;
-
- sii8620_set_upstream_edid(ctx);
- sii8620_hsic_init(ctx);
- sii8620_enable_hpd(ctx);
-}
-
static void sii8620_mr_devcap(struct sii8620 *ctx)
{
u8 dcap[MHL_DCAP_SIZE];
@@ -570,6 +530,8 @@ static void sii8620_mr_devcap(struct sii8620 *ctx)
dcap[MHL_DCAP_ADOPTER_ID_H], dcap[MHL_DCAP_ADOPTER_ID_L],
dcap[MHL_DCAP_DEVICE_ID_H], dcap[MHL_DCAP_DEVICE_ID_L]);
sii8620_update_array(ctx->devcap, dcap, MHL_DCAP_SIZE);
+ ctx->devcap_read = true;
+ sii8620_identify_sink(ctx);
}
static void sii8620_mr_xdevcap(struct sii8620 *ctx)
@@ -807,6 +769,7 @@ static void sii8620_burst_rx_all(struct sii8620 *ctx)
static void sii8620_fetch_edid(struct sii8620 *ctx)
{
u8 lm_ddc, ddc_cmd, int3, cbus;
+ unsigned long timeout;
int fetched, i;
int edid_len = EDID_LENGTH;
u8 *edid;
@@ -856,23 +819,31 @@ static void sii8620_fetch_edid(struct sii8620 *ctx)
REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_ENH_DDC_READ_NO_ACK
);
- do {
- int3 = sii8620_readb(ctx, REG_INTR3);
+ int3 = 0;
+ timeout = jiffies + msecs_to_jiffies(200);
+ for (;;) {
cbus = sii8620_readb(ctx, REG_CBUS_STATUS);
-
- if (int3 & BIT_DDC_CMD_DONE)
- break;
-
- if (!(cbus & BIT_CBUS_STATUS_CBUS_CONNECTED)) {
+ if (~cbus & BIT_CBUS_STATUS_CBUS_CONNECTED) {
+ kfree(edid);
+ edid = NULL;
+ goto end;
+ }
+ if (int3 & BIT_DDC_CMD_DONE) {
+ if (sii8620_readb(ctx, REG_DDC_DOUT_CNT)
+ >= FETCH_SIZE)
+ break;
+ } else {
+ int3 = sii8620_readb(ctx, REG_INTR3);
+ }
+ if (time_is_before_jiffies(timeout)) {
+ ctx->error = -ETIMEDOUT;
+ dev_err(ctx->dev, "timeout during EDID read\n");
kfree(edid);
edid = NULL;
goto end;
}
- } while (1);
-
- sii8620_readb(ctx, REG_DDC_STATUS);
- while (sii8620_readb(ctx, REG_DDC_DOUT_CNT) < FETCH_SIZE)
usleep_range(10, 20);
+ }
sii8620_read_buf(ctx, REG_DDC_DATA, edid + fetched, FETCH_SIZE);
if (fetched + FETCH_SIZE == EDID_LENGTH) {
@@ -971,8 +942,17 @@ static int sii8620_hw_on(struct sii8620 *ctx)
ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
if (ret)
return ret;
+
usleep_range(10000, 20000);
- return clk_prepare_enable(ctx->clk_xtal);
+ ret = clk_prepare_enable(ctx->clk_xtal);
+ if (ret)
+ return ret;
+
+ msleep(100);
+ gpiod_set_value(ctx->gpio_reset, 0);
+ msleep(100);
+
+ return 0;
}
static int sii8620_hw_off(struct sii8620 *ctx)
@@ -982,17 +962,6 @@ static int sii8620_hw_off(struct sii8620 *ctx)
return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
}
-static void sii8620_hw_reset(struct sii8620 *ctx)
-{
- usleep_range(10000, 20000);
- gpiod_set_value(ctx->gpio_reset, 0);
- usleep_range(5000, 20000);
- gpiod_set_value(ctx->gpio_reset, 1);
- usleep_range(10000, 20000);
- gpiod_set_value(ctx->gpio_reset, 0);
- msleep(300);
-}
-
static void sii8620_cbus_reset(struct sii8620 *ctx)
{
sii8620_write(ctx, REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST
@@ -1048,20 +1017,11 @@ static void sii8620_stop_video(struct sii8620 *ctx)
static void sii8620_set_format(struct sii8620 *ctx)
{
- u8 out_fmt;
-
if (sii8620_is_mhl3(ctx)) {
sii8620_setbits(ctx, REG_M3_P0CTRL,
BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED,
ctx->use_packed_pixel ? ~0 : 0);
} else {
- if (ctx->use_packed_pixel)
- sii8620_write_seq_static(ctx,
- REG_VID_MODE, BIT_VID_MODE_M1080P,
- REG_MHL_TOP_CTL, BIT_MHL_TOP_CTL_MHL_PP_SEL | 1,
- REG_MHLTX_CTL6, 0x60
- );
- else
sii8620_write_seq_static(ctx,
REG_VID_MODE, 0,
REG_MHL_TOP_CTL, 1,
@@ -1069,15 +1029,9 @@ static void sii8620_set_format(struct sii8620 *ctx)
);
}
- if (ctx->use_packed_pixel)
- out_fmt = VAL_TPI_FORMAT(YCBCR422, FULL) |
- BIT_TPI_OUTPUT_CSCMODE709;
- else
- out_fmt = VAL_TPI_FORMAT(RGB, FULL);
-
sii8620_write_seq(ctx,
REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
- REG_TPI_OUTPUT, out_fmt,
+ REG_TPI_OUTPUT, VAL_TPI_FORMAT(RGB, FULL),
);
}
@@ -1216,7 +1170,7 @@ static void sii8620_start_video(struct sii8620 *ctx)
int clk = ctx->pixel_clock * (ctx->use_packed_pixel ? 2 : 3);
int i;
- for (i = 0; i < ARRAY_SIZE(clk_spec); ++i)
+ for (i = 0; i < ARRAY_SIZE(clk_spec) - 1; ++i)
if (clk < clk_spec[i].max_clk)
break;
@@ -1534,6 +1488,16 @@ static void sii8620_set_mode(struct sii8620 *ctx, enum sii8620_mode mode)
);
}
+static void sii8620_hpd_unplugged(struct sii8620 *ctx)
+{
+ sii8620_disable_hpd(ctx);
+ ctx->sink_type = SINK_NONE;
+ ctx->sink_detected = false;
+ ctx->feature_complete = false;
+ kfree(ctx->edid);
+ ctx->edid = NULL;
+}
+
static void sii8620_disconnect(struct sii8620 *ctx)
{
sii8620_disable_gen2_write_burst(ctx);
@@ -1561,7 +1525,7 @@ static void sii8620_disconnect(struct sii8620 *ctx)
REG_MHL_DP_CTL6, 0x2A,
REG_MHL_DP_CTL7, 0x03
);
- sii8620_disable_hpd(ctx);
+ sii8620_hpd_unplugged(ctx);
sii8620_write_seq_static(ctx,
REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE,
REG_MHL_COC_CTL1, 0x07,
@@ -1609,10 +1573,8 @@ static void sii8620_disconnect(struct sii8620 *ctx)
memset(ctx->xstat, 0, sizeof(ctx->xstat));
memset(ctx->devcap, 0, sizeof(ctx->devcap));
memset(ctx->xdevcap, 0, sizeof(ctx->xdevcap));
+ ctx->devcap_read = false;
ctx->cbus_status = 0;
- ctx->sink_type = SINK_NONE;
- kfree(ctx->edid);
- ctx->edid = NULL;
sii8620_mt_cleanup(ctx);
}
@@ -1703,9 +1665,6 @@ static void sii8620_status_changed_path(struct sii8620 *ctx)
sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
MHL_DST_LM_CLK_MODE_NORMAL
| MHL_DST_LM_PATH_ENABLED);
- if (!sii8620_is_mhl3(ctx))
- sii8620_mt_read_devcap(ctx, false);
- sii8620_mt_set_cont(ctx, sii8620_sink_detected);
} else {
sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
MHL_DST_LM_CLK_MODE_NORMAL);
@@ -1722,9 +1681,14 @@ static void sii8620_msc_mr_write_stat(struct sii8620 *ctx)
sii8620_update_array(ctx->stat, st, MHL_DST_SIZE);
sii8620_update_array(ctx->xstat, xst, MHL_XDS_SIZE);
- if (ctx->stat[MHL_DST_CONNECTED_RDY] & MHL_DST_CONN_DCAP_RDY)
+ if (ctx->stat[MHL_DST_CONNECTED_RDY] & st[MHL_DST_CONNECTED_RDY] &
+ MHL_DST_CONN_DCAP_RDY) {
sii8620_status_dcap_ready(ctx);
+ if (!sii8620_is_mhl3(ctx))
+ sii8620_mt_read_devcap(ctx, false);
+ }
+
if (st[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED)
sii8620_status_changed_path(ctx);
}
@@ -1808,8 +1772,11 @@ static void sii8620_msc_mr_set_int(struct sii8620 *ctx)
}
if (ints[MHL_INT_RCHANGE] & MHL_INT_RC_FEAT_REQ)
sii8620_send_features(ctx);
- if (ints[MHL_INT_RCHANGE] & MHL_INT_RC_FEAT_COMPLETE)
- sii8620_edid_read(ctx, 0);
+ if (ints[MHL_INT_RCHANGE] & MHL_INT_RC_FEAT_COMPLETE) {
+ ctx->feature_complete = true;
+ if (ctx->edid)
+ sii8620_enable_hpd(ctx);
+ }
}
static struct sii8620_mt_msg *sii8620_msc_msg_first(struct sii8620 *ctx)
@@ -1884,6 +1851,15 @@ static void sii8620_irq_msc(struct sii8620 *ctx)
if (stat & BIT_CBUS_MSC_MR_WRITE_STAT)
sii8620_msc_mr_write_stat(ctx);
+ if (stat & BIT_CBUS_HPD_CHG) {
+ if (ctx->cbus_status & BIT_CBUS_STATUS_CBUS_HPD) {
+ ctx->sink_detected = true;
+ sii8620_identify_sink(ctx);
+ } else {
+ sii8620_hpd_unplugged(ctx);
+ }
+ }
+
if (stat & BIT_CBUS_MSC_MR_SET_INT)
sii8620_msc_mr_set_int(ctx);
@@ -1931,14 +1907,6 @@ static void sii8620_irq_edid(struct sii8620 *ctx)
ctx->mt_state = MT_STATE_DONE;
}
-static void sii8620_scdt_high(struct sii8620 *ctx)
-{
- sii8620_write_seq_static(ctx,
- REG_INTR8_MASK, BIT_CEA_NEW_AVI | BIT_CEA_NEW_VSI,
- REG_TPI_SC, BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI,
- );
-}
-
static void sii8620_irq_scdt(struct sii8620 *ctx)
{
u8 stat = sii8620_readb(ctx, REG_INTR5);
@@ -1946,53 +1914,13 @@ static void sii8620_irq_scdt(struct sii8620 *ctx)
if (stat & BIT_INTR_SCDT_CHANGE) {
u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3);
- if (cstat & BIT_TMDS_CSTAT_P3_SCDT) {
- if (ctx->sink_type == SINK_HDMI)
- /* enable infoframe interrupt */
- sii8620_scdt_high(ctx);
- else
- sii8620_start_video(ctx);
- }
+ if (cstat & BIT_TMDS_CSTAT_P3_SCDT)
+ sii8620_start_video(ctx);
}
sii8620_write(ctx, REG_INTR5, stat);
}
-static void sii8620_new_vsi(struct sii8620 *ctx)
-{
- u8 vsif[11];
-
- sii8620_write(ctx, REG_RX_HDMI_CTRL2,
- VAL_RX_HDMI_CTRL2_DEFVAL |
- BIT_RX_HDMI_CTRL2_VSI_MON_SEL_VSI);
- sii8620_read_buf(ctx, REG_RX_HDMI_MON_PKT_HEADER1, vsif,
- ARRAY_SIZE(vsif));
-}
-
-static void sii8620_new_avi(struct sii8620 *ctx)
-{
- sii8620_write(ctx, REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL);
- sii8620_read_buf(ctx, REG_RX_HDMI_MON_PKT_HEADER1, ctx->avif,
- ARRAY_SIZE(ctx->avif));
-}
-
-static void sii8620_irq_infr(struct sii8620 *ctx)
-{
- u8 stat = sii8620_readb(ctx, REG_INTR8)
- & (BIT_CEA_NEW_VSI | BIT_CEA_NEW_AVI);
-
- sii8620_write(ctx, REG_INTR8, stat);
-
- if (stat & BIT_CEA_NEW_VSI)
- sii8620_new_vsi(ctx);
-
- if (stat & BIT_CEA_NEW_AVI)
- sii8620_new_avi(ctx);
-
- if (stat & (BIT_CEA_NEW_VSI | BIT_CEA_NEW_AVI))
- sii8620_start_video(ctx);
-}
-
static void sii8620_got_xdevcap(struct sii8620 *ctx, int ret)
{
if (ret < 0)
@@ -2043,11 +1971,11 @@ static void sii8620_irq_ddc(struct sii8620 *ctx)
if (stat & BIT_DDC_CMD_DONE) {
sii8620_write(ctx, REG_INTR3_MASK, 0);
- if (sii8620_is_mhl3(ctx))
+ if (sii8620_is_mhl3(ctx) && !ctx->feature_complete)
sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE),
MHL_INT_RC_FEAT_REQ);
else
- sii8620_edid_read(ctx, 0);
+ sii8620_enable_hpd(ctx);
}
sii8620_write(ctx, REG_INTR3, stat);
}
@@ -2074,7 +2002,6 @@ static irqreturn_t sii8620_irq_thread(int irq, void *data)
{ BIT_FAST_INTR_STAT_EDID, sii8620_irq_edid },
{ BIT_FAST_INTR_STAT_DDC, sii8620_irq_ddc },
{ BIT_FAST_INTR_STAT_SCDT, sii8620_irq_scdt },
- { BIT_FAST_INTR_STAT_INFR, sii8620_irq_infr },
};
struct sii8620 *ctx = data;
u8 stats[LEN_FAST_INTR_STAT];
@@ -2112,7 +2039,6 @@ static void sii8620_cable_in(struct sii8620 *ctx)
dev_err(dev, "Error powering on, %d.\n", ret);
return;
}
- sii8620_hw_reset(ctx);
sii8620_read_buf(ctx, REG_VND_IDL, ver, ARRAY_SIZE(ver));
ret = sii8620_clear_error(ctx);
@@ -2268,17 +2194,43 @@ static void sii8620_detach(struct drm_bridge *bridge)
rc_unregister_device(ctx->rc_dev);
}
+static int sii8620_is_packing_required(struct sii8620 *ctx,
+ const struct drm_display_mode *mode)
+{
+ int max_pclk, max_pclk_pp_mode;
+
+ if (sii8620_is_mhl3(ctx)) {
+ max_pclk = MHL3_MAX_PCLK;
+ max_pclk_pp_mode = MHL3_MAX_PCLK_PP_MODE;
+ } else {
+ max_pclk = MHL1_MAX_PCLK;
+ max_pclk_pp_mode = MHL1_MAX_PCLK_PP_MODE;
+ }
+
+ if (mode->clock < max_pclk)
+ return 0;
+ else if (mode->clock < max_pclk_pp_mode)
+ return 1;
+ else
+ return -1;
+}
+
static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge,
const struct drm_display_mode *mode)
{
struct sii8620 *ctx = bridge_to_sii8620(bridge);
+ int pack_required = sii8620_is_packing_required(ctx, mode);
bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] &
MHL_DCAP_VID_LINK_PPIXEL;
- unsigned int max_pclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK :
- MHL1_MAX_LCLK;
- max_pclk /= can_pack ? 2 : 3;
- return (mode->clock > max_pclk) ? MODE_CLOCK_HIGH : MODE_OK;
+ switch (pack_required) {
+ case 0:
+ return MODE_OK;
+ case 1:
+ return (can_pack) ? MODE_OK : MODE_CLOCK_HIGH;
+ default:
+ return MODE_CLOCK_HIGH;
+ }
}
static bool sii8620_mode_fixup(struct drm_bridge *bridge,
@@ -2286,43 +2238,16 @@ static bool sii8620_mode_fixup(struct drm_bridge *bridge,
struct drm_display_mode *adjusted_mode)
{
struct sii8620 *ctx = bridge_to_sii8620(bridge);
- int max_lclk;
- bool ret = true;
mutex_lock(&ctx->lock);
- max_lclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK : MHL1_MAX_LCLK;
- if (max_lclk > 3 * adjusted_mode->clock) {
- ctx->use_packed_pixel = 0;
- goto end;
- }
- if ((ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL) &&
- max_lclk > 2 * adjusted_mode->clock) {
- ctx->use_packed_pixel = 1;
- goto end;
- }
- ret = false;
-end:
- if (ret) {
- u8 vic = drm_match_cea_mode(adjusted_mode);
-
- if (!vic) {
- union hdmi_infoframe frm;
- u8 mhl_vic[] = { 0, 95, 94, 93, 98 };
-
- /* FIXME: We need the connector here */
- drm_hdmi_vendor_infoframe_from_display_mode(
- &frm.vendor.hdmi, NULL, adjusted_mode);
- vic = frm.vendor.hdmi.vic;
- if (vic >= ARRAY_SIZE(mhl_vic))
- vic = 0;
- vic = mhl_vic[vic];
- }
- ctx->video_code = vic;
- ctx->pixel_clock = adjusted_mode->clock;
- }
+ ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode);
+ ctx->video_code = drm_match_cea_mode(adjusted_mode);
+ ctx->pixel_clock = adjusted_mode->clock;
+
mutex_unlock(&ctx->lock);
- return ret;
+
+ return true;
}
static const struct drm_bridge_funcs sii8620_bridge_funcs = {
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b553a6f..7af748e 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -369,13 +369,6 @@ EXPORT_SYMBOL(drm_dev_exit);
*/
void drm_dev_unplug(struct drm_device *dev)
{
- drm_dev_unregister(dev);
-
- mutex_lock(&drm_global_mutex);
- if (dev->open_count == 0)
- drm_dev_put(dev);
- mutex_unlock(&drm_global_mutex);
-
/*
* After synchronizing any critical read section is guaranteed to see
* the new value of ->unplugged, and any critical section which might
@@ -384,6 +377,13 @@ void drm_dev_unplug(struct drm_device *dev)
*/
dev->unplugged = true;
synchronize_srcu(&drm_unplug_srcu);
+
+ drm_dev_unregister(dev);
+
+ mutex_lock(&drm_global_mutex);
+ if (dev->open_count == 0)
+ drm_dev_put(dev);
+ mutex_unlock(&drm_global_mutex);
}
EXPORT_SYMBOL(drm_dev_unplug);
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 40e1e24..a580838 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1633,7 +1633,8 @@ struct edid *drm_do_get_edid(struct drm_connector *connector,
edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
edid[0x7e] = valid_extensions;
- new = kmalloc((valid_extensions + 1) * EDID_LENGTH, GFP_KERNEL);
+ new = kmalloc_array(valid_extensions + 1, EDID_LENGTH,
+ GFP_KERNEL);
if (!new)
goto out;
diff --git a/drivers/gpu/drm/drm_hashtab.c b/drivers/gpu/drm/drm_hashtab.c
index dae18e5..c92b00d 100644
--- a/drivers/gpu/drm/drm_hashtab.c
+++ b/drivers/gpu/drm/drm_hashtab.c
@@ -47,7 +47,7 @@ int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
if (size <= PAGE_SIZE / sizeof(*ht->table))
ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL);
else
- ht->table = vzalloc(size*sizeof(*ht->table));
+ ht->table = vzalloc(array_size(size, sizeof(*ht->table)));
if (!ht->table) {
DRM_ERROR("Out of memory for hash table\n");
return -ENOMEM;
diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c
index 3c54044..d69e4fc 100644
--- a/drivers/gpu/drm/drm_memory.c
+++ b/drivers/gpu/drm/drm_memory.c
@@ -80,7 +80,7 @@ static void *agp_remap(unsigned long offset, unsigned long size,
* page-table instead (that's probably faster anyhow...).
*/
/* note: use vmalloc() because num_pages could be large... */
- page_map = vmalloc(num_pages * sizeof(struct page *));
+ page_map = vmalloc(array_size(num_pages, sizeof(struct page *)));
if (!page_map)
return NULL;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 7c3030b..6d29777 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -1723,8 +1723,8 @@ static int exynos_dsi_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
- dsi->clks = devm_kzalloc(dev,
- sizeof(*dsi->clks) * dsi->driver_data->num_clks,
+ dsi->clks = devm_kcalloc(dev,
+ dsi->driver_data->num_clks, sizeof(*dsi->clks),
GFP_KERNEL);
if (!dsi->clks)
return -ENOMEM;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 5ce8402..6127ef2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -1271,7 +1271,8 @@ static int fimc_probe(struct platform_device *pdev)
/* construct formats/limits array */
num_formats = ARRAY_SIZE(fimc_formats) + ARRAY_SIZE(fimc_tiled_formats);
- formats = devm_kzalloc(dev, sizeof(*formats) * num_formats, GFP_KERNEL);
+ formats = devm_kcalloc(dev, num_formats, sizeof(*formats),
+ GFP_KERNEL);
if (!formats)
return -ENOMEM;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index e99dd1e..35ac667 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -1202,8 +1202,9 @@ static int gsc_probe(struct platform_device *pdev)
if (!ctx)
return -ENOMEM;
- formats = devm_kzalloc(dev, sizeof(*formats) *
- (ARRAY_SIZE(gsc_formats)), GFP_KERNEL);
+ formats = devm_kcalloc(dev,
+ ARRAY_SIZE(gsc_formats), sizeof(*formats),
+ GFP_KERNEL);
if (!formats)
return -ENOMEM;
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 09c4bc0..db91932 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1692,7 +1692,7 @@ static int hdmi_clk_init(struct hdmi_context *hdata)
if (!count)
return 0;
- clks = devm_kzalloc(dev, sizeof(*clks) * count, GFP_KERNEL);
+ clks = devm_kcalloc(dev, count, sizeof(*clks), GFP_KERNEL);
if (!clks)
return -ENOMEM;
diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c
index 7171b74..237041a 100644
--- a/drivers/gpu/drm/gma500/mid_bios.c
+++ b/drivers/gpu/drm/gma500/mid_bios.c
@@ -239,7 +239,7 @@ static int mid_get_vbt_data_r10(struct drm_psb_private *dev_priv, u32 addr)
if (read_vbt_r10(addr, &vbt))
return -1;
- gct = kmalloc(sizeof(*gct) * vbt.panel_count, GFP_KERNEL);
+ gct = kmalloc_array(vbt.panel_count, sizeof(*gct), GFP_KERNEL);
if (!gct)
return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c
index 718ca08..b51c05d 100644
--- a/drivers/gpu/drm/i915/gvt/cmd_parser.c
+++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c
@@ -2909,6 +2909,7 @@ static int init_cmd_table(struct intel_gvt *gvt)
if (info) {
gvt_err("%s %s duplicated\n", e->info->name,
info->name);
+ kfree(e);
return -EEXIST;
}
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h
index b46b868..ea7c1c5 100644
--- a/drivers/gpu/drm/i915/gvt/display.h
+++ b/drivers/gpu/drm/i915/gvt/display.h
@@ -67,7 +67,7 @@
#define AUX_NATIVE_REPLY_NAK (0x1 << 4)
#define AUX_NATIVE_REPLY_DEFER (0x2 << 4)
-#define AUX_BURST_SIZE 16
+#define AUX_BURST_SIZE 20
/* DPCD addresses */
#define DPCD_REV 0x000
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index 78e55aa..2329654 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -1585,8 +1585,9 @@ static struct intel_vgpu_mm *intel_vgpu_create_ggtt_mm(struct intel_vgpu *vgpu)
mm->type = INTEL_GVT_MM_GGTT;
nr_entries = gvt_ggtt_gm_sz(vgpu->gvt) >> I915_GTT_PAGE_SHIFT;
- mm->ggtt_mm.virtual_ggtt = vzalloc(nr_entries *
- vgpu->gvt->device_info.gtt_entry_size);
+ mm->ggtt_mm.virtual_ggtt =
+ vzalloc(array_size(nr_entries,
+ vgpu->gvt->device_info.gtt_entry_size));
if (!mm->ggtt_mm.virtual_ggtt) {
vgpu_free_mm(mm);
return ERR_PTR(-ENOMEM);
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index 4b6532f..bcbc47a 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -903,11 +903,14 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,
}
/*
- * Write request format: (command + address) occupies
- * 3 bytes, followed by (len + 1) bytes of data.
+ * Write request format: Headr (command + address + size) occupies
+ * 4 bytes, followed by (len + 1) bytes of data. See details at
+ * intel_dp_aux_transfer().
*/
- if (WARN_ON((len + 4) > AUX_BURST_SIZE))
+ if ((len + 1 + 4) > AUX_BURST_SIZE) {
+ gvt_vgpu_err("dp_aux_header: len %d is too large\n", len);
return -EINVAL;
+ }
/* unpack data from vreg to buf */
for (t = 0; t < 4; t++) {
@@ -971,8 +974,10 @@ static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu,
/*
* Read reply format: ACK (1 byte) plus (len + 1) bytes of data.
*/
- if (WARN_ON((len + 2) > AUX_BURST_SIZE))
+ if ((len + 2) > AUX_BURST_SIZE) {
+ gvt_vgpu_err("dp_aux_header: len %d is too large\n", len);
return -EINVAL;
+ }
/* read from virtual DPCD to vreg */
/* first 4 bytes: [ACK][addr][addr+1][addr+2] */
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 1466d87..df4e4a0 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -123,6 +123,12 @@ static int gvt_dma_map_page(struct intel_vgpu *vgpu, unsigned long gfn,
return -EINVAL;
}
+ if (!pfn_valid(pfn)) {
+ gvt_vgpu_err("pfn 0x%lx is not mem backed\n", pfn);
+ vfio_unpin_pages(mdev_dev(vgpu->vdev.mdev), &gfn, 1);
+ return -EINVAL;
+ }
+
/* Setup DMA mapping. */
page = pfn_to_page(pfn);
*dma_addr = dma_map_page(dev, page, 0, PAGE_SIZE,
@@ -583,6 +589,17 @@ out:
return ret;
}
+static void intel_vgpu_release_msi_eventfd_ctx(struct intel_vgpu *vgpu)
+{
+ struct eventfd_ctx *trigger;
+
+ trigger = vgpu->vdev.msi_trigger;
+ if (trigger) {
+ eventfd_ctx_put(trigger);
+ vgpu->vdev.msi_trigger = NULL;
+ }
+}
+
static void __intel_vgpu_release(struct intel_vgpu *vgpu)
{
struct kvmgt_guest_info *info;
@@ -607,6 +624,8 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu)
info = (struct kvmgt_guest_info *)vgpu->handle;
kvmgt_guest_exit(info);
+ intel_vgpu_release_msi_eventfd_ctx(vgpu);
+
vgpu->vdev.kvm = NULL;
vgpu->handle = 0;
}
@@ -987,7 +1006,8 @@ static int intel_vgpu_set_msi_trigger(struct intel_vgpu *vgpu,
return PTR_ERR(trigger);
}
vgpu->vdev.msi_trigger = trigger;
- }
+ } else if ((flags & VFIO_IRQ_SET_DATA_NONE) && !count)
+ intel_vgpu_release_msi_eventfd_ctx(vgpu);
return 0;
}
@@ -1592,6 +1612,18 @@ static int kvmgt_inject_msi(unsigned long handle, u32 addr, u16 data)
info = (struct kvmgt_guest_info *)handle;
vgpu = info->vgpu;
+ /*
+ * When guest is poweroff, msi_trigger is set to NULL, but vgpu's
+ * config and mmio register isn't restored to default during guest
+ * poweroff. If this vgpu is still used in next vm, this vgpu's pipe
+ * may be enabled, then once this vgpu is active, it will get inject
+ * vblank interrupt request. But msi_trigger is null until msi is
+ * enabled by guest. so if msi_trigger is null, success is still
+ * returned and don't inject interrupt into guest.
+ */
+ if (vgpu->vdev.msi_trigger == NULL)
+ return 0;
+
if (eventfd_signal(vgpu->vdev.msi_trigger, 1) == 1)
return 0;
diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c
index e4960af..b31eb36 100644
--- a/drivers/gpu/drm/i915/gvt/mmio.c
+++ b/drivers/gpu/drm/i915/gvt/mmio.c
@@ -267,7 +267,7 @@ int intel_vgpu_init_mmio(struct intel_vgpu *vgpu)
{
const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
- vgpu->mmio.vreg = vzalloc(info->mmio_size * 2);
+ vgpu->mmio.vreg = vzalloc(array_size(info->mmio_size, 2));
if (!vgpu->mmio.vreg)
return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 2e0a02a..572a18c 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -121,7 +121,7 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
high_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE;
num_types = sizeof(vgpu_types) / sizeof(vgpu_types[0]);
- gvt->types = kzalloc(num_types * sizeof(struct intel_vgpu_type),
+ gvt->types = kcalloc(num_types, sizeof(struct intel_vgpu_type),
GFP_KERNEL);
if (!gvt->types)
return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 34c125e..7014a96 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -340,14 +340,21 @@ struct drm_i915_file_private {
unsigned int bsd_engine;
-/* Client can have a maximum of 3 contexts banned before
- * it is denied of creating new contexts. As one context
- * ban needs 4 consecutive hangs, and more if there is
- * progress in between, this is a last resort stop gap measure
- * to limit the badly behaving clients access to gpu.
+/*
+ * Every context ban increments per client ban score. Also
+ * hangs in short succession increments ban score. If ban threshold
+ * is reached, client is considered banned and submitting more work
+ * will fail. This is a stop gap measure to limit the badly behaving
+ * clients access to gpu. Note that unbannable contexts never increment
+ * the client ban score.
*/
-#define I915_MAX_CLIENT_CONTEXT_BANS 3
- atomic_t context_bans;
+#define I915_CLIENT_SCORE_HANG_FAST 1
+#define I915_CLIENT_FAST_HANG_JIFFIES (60 * HZ)
+#define I915_CLIENT_SCORE_CONTEXT_BAN 3
+#define I915_CLIENT_SCORE_BANNED 9
+ /** ban_score: Accumulated score of all ctx bans and fast hangs. */
+ atomic_t ban_score;
+ unsigned long hang_timestamp;
};
/* Interface history:
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0a20701..d44ad7b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2933,32 +2933,54 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj,
return 0;
}
+static void i915_gem_client_mark_guilty(struct drm_i915_file_private *file_priv,
+ const struct i915_gem_context *ctx)
+{
+ unsigned int score;
+ unsigned long prev_hang;
+
+ if (i915_gem_context_is_banned(ctx))
+ score = I915_CLIENT_SCORE_CONTEXT_BAN;
+ else
+ score = 0;
+
+ prev_hang = xchg(&file_priv->hang_timestamp, jiffies);
+ if (time_before(jiffies, prev_hang + I915_CLIENT_FAST_HANG_JIFFIES))
+ score += I915_CLIENT_SCORE_HANG_FAST;
+
+ if (score) {
+ atomic_add(score, &file_priv->ban_score);
+
+ DRM_DEBUG_DRIVER("client %s: gained %u ban score, now %u\n",
+ ctx->name, score,
+ atomic_read(&file_priv->ban_score));
+ }
+}
+
static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx)
{
- bool banned;
+ unsigned int score;
+ bool banned, bannable;
atomic_inc(&ctx->guilty_count);
- banned = false;
- if (i915_gem_context_is_bannable(ctx)) {
- unsigned int score;
+ bannable = i915_gem_context_is_bannable(ctx);
+ score = atomic_add_return(CONTEXT_SCORE_GUILTY, &ctx->ban_score);
+ banned = score >= CONTEXT_SCORE_BAN_THRESHOLD;
- score = atomic_add_return(CONTEXT_SCORE_GUILTY,
- &ctx->ban_score);
- banned = score >= CONTEXT_SCORE_BAN_THRESHOLD;
+ DRM_DEBUG_DRIVER("context %s: guilty %d, score %u, ban %s\n",
+ ctx->name, atomic_read(&ctx->guilty_count),
+ score, yesno(banned && bannable));
- DRM_DEBUG_DRIVER("context %s marked guilty (score %d) banned? %s\n",
- ctx->name, score, yesno(banned));
- }
- if (!banned)
+ /* Cool contexts don't accumulate client ban score */
+ if (!bannable)
return;
- i915_gem_context_set_banned(ctx);
- if (!IS_ERR_OR_NULL(ctx->file_priv)) {
- atomic_inc(&ctx->file_priv->context_bans);
- DRM_DEBUG_DRIVER("client %s has had %d context banned\n",
- ctx->name, atomic_read(&ctx->file_priv->context_bans));
- }
+ if (banned)
+ i915_gem_context_set_banned(ctx);
+
+ if (!IS_ERR_OR_NULL(ctx->file_priv))
+ i915_gem_client_mark_guilty(ctx->file_priv, ctx);
}
static void i915_gem_context_mark_innocent(struct i915_gem_context *ctx)
@@ -2972,23 +2994,22 @@ i915_gem_find_active_request(struct intel_engine_cs *engine)
struct i915_request *request, *active = NULL;
unsigned long flags;
- /* We are called by the error capture and reset at a random
- * point in time. In particular, note that neither is crucially
- * ordered with an interrupt. After a hang, the GPU is dead and we
- * assume that no more writes can happen (we waited long enough for
- * all writes that were in transaction to be flushed) - adding an
+ /*
+ * We are called by the error capture, reset and to dump engine
+ * state at random points in time. In particular, note that neither is
+ * crucially ordered with an interrupt. After a hang, the GPU is dead
+ * and we assume that no more writes can happen (we waited long enough
+ * for all writes that were in transaction to be flushed) - adding an
* extra delay for a recent interrupt is pointless. Hence, we do
* not need an engine->irq_seqno_barrier() before the seqno reads.
+ * At all other times, we must assume the GPU is still running, but
+ * we only care about the snapshot of this moment.
*/
spin_lock_irqsave(&engine->timeline.lock, flags);
list_for_each_entry(request, &engine->timeline.requests, link) {
if (__i915_request_completed(request, request->global_seqno))
continue;
- GEM_BUG_ON(request->engine != engine);
- GEM_BUG_ON(test_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
- &request->fence.flags));
-
active = request;
break;
}
@@ -5737,6 +5758,7 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file)
INIT_LIST_HEAD(&file_priv->mm.request_list);
file_priv->bsd_engine = -1;
+ file_priv->hang_timestamp = jiffies;
ret = i915_gem_context_open(i915, file);
if (ret)
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
index 33f8a4b..060335d 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -652,7 +652,7 @@ int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv)
static bool client_is_banned(struct drm_i915_file_private *file_priv)
{
- return atomic_read(&file_priv->context_bans) > I915_MAX_CLIENT_CONTEXT_BANS;
+ return atomic_read(&file_priv->ban_score) >= I915_CLIENT_SCORE_BANNED;
}
int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index f627a8c..22df17c 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -489,7 +489,9 @@ eb_validate_vma(struct i915_execbuffer *eb,
}
static int
-eb_add_vma(struct i915_execbuffer *eb, unsigned int i, struct i915_vma *vma)
+eb_add_vma(struct i915_execbuffer *eb,
+ unsigned int i, unsigned batch_idx,
+ struct i915_vma *vma)
{
struct drm_i915_gem_exec_object2 *entry = &eb->exec[i];
int err;
@@ -522,6 +524,24 @@ eb_add_vma(struct i915_execbuffer *eb, unsigned int i, struct i915_vma *vma)
eb->flags[i] = entry->flags;
vma->exec_flags = &eb->flags[i];
+ /*
+ * SNA is doing fancy tricks with compressing batch buffers, which leads
+ * to negative relocation deltas. Usually that works out ok since the
+ * relocate address is still positive, except when the batch is placed
+ * very low in the GTT. Ensure this doesn't happen.
+ *
+ * Note that actual hangs have only been observed on gen7, but for
+ * paranoia do it everywhere.
+ */
+ if (i == batch_idx) {
+ if (!(eb->flags[i] & EXEC_OBJECT_PINNED))
+ eb->flags[i] |= __EXEC_OBJECT_NEEDS_BIAS;
+ if (eb->reloc_cache.has_fence)
+ eb->flags[i] |= EXEC_OBJECT_NEEDS_FENCE;
+
+ eb->batch = vma;
+ }
+
err = 0;
if (eb_pin_vma(eb, entry, vma)) {
if (entry->offset != vma->node.start) {
@@ -716,7 +736,7 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
{
struct radix_tree_root *handles_vma = &eb->ctx->handles_vma;
struct drm_i915_gem_object *obj;
- unsigned int i;
+ unsigned int i, batch;
int err;
if (unlikely(i915_gem_context_is_closed(eb->ctx)))
@@ -728,6 +748,8 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
INIT_LIST_HEAD(&eb->relocs);
INIT_LIST_HEAD(&eb->unbound);
+ batch = eb_batch_index(eb);
+
for (i = 0; i < eb->buffer_count; i++) {
u32 handle = eb->exec[i].handle;
struct i915_lut_handle *lut;
@@ -770,33 +792,16 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb)
lut->handle = handle;
add_vma:
- err = eb_add_vma(eb, i, vma);
+ err = eb_add_vma(eb, i, batch, vma);
if (unlikely(err))
goto err_vma;
GEM_BUG_ON(vma != eb->vma[i]);
GEM_BUG_ON(vma->exec_flags != &eb->flags[i]);
+ GEM_BUG_ON(drm_mm_node_allocated(&vma->node) &&
+ eb_vma_misplaced(&eb->exec[i], vma, eb->flags[i]));
}
- /* take note of the batch buffer before we might reorder the lists */
- i = eb_batch_index(eb);
- eb->batch = eb->vma[i];
- GEM_BUG_ON(eb->batch->exec_flags != &eb->flags[i]);
-
- /*
- * SNA is doing fancy tricks with compressing batch buffers, which leads
- * to negative relocation deltas. Usually that works out ok since the
- * relocate address is still positive, except when the batch is placed
- * very low in the GTT. Ensure this doesn't happen.
- *
- * Note that actual hangs have only been observed on gen7, but for
- * paranoia do it everywhere.
- */
- if (!(eb->flags[i] & EXEC_OBJECT_PINNED))
- eb->flags[i] |= __EXEC_OBJECT_NEEDS_BIAS;
- if (eb->reloc_cache.has_fence)
- eb->flags[i] |= EXEC_OBJECT_NEEDS_FENCE;
-
eb->args->flags |= __EXEC_VALIDATED;
return eb_reserve(eb);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index f9bc3aa..4a02747 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1893,9 +1893,17 @@ static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv,
/*
* Clear the PIPE*STAT regs before the IIR
+ *
+ * Toggle the enable bits to make sure we get an
+ * edge in the ISR pipe event bit if we don't clear
+ * all the enabled status bits. Otherwise the edge
+ * triggered IIR on i965/g4x wouldn't notice that
+ * an interrupt is still pending.
*/
- if (pipe_stats[pipe])
- I915_WRITE(reg, enable_mask | pipe_stats[pipe]);
+ if (pipe_stats[pipe]) {
+ I915_WRITE(reg, pipe_stats[pipe]);
+ I915_WRITE(reg, enable_mask);
+ }
}
spin_unlock(&dev_priv->irq_lock);
}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f11bb21..7720569 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2425,12 +2425,17 @@ enum i915_power_well_id {
#define _3D_CHICKEN _MMIO(0x2084)
#define _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB (1 << 10)
#define _3D_CHICKEN2 _MMIO(0x208c)
+
+#define FF_SLICE_CHICKEN _MMIO(0x2088)
+#define FF_SLICE_CHICKEN_CL_PROVOKING_VERTEX_FIX (1 << 1)
+
/* Disables pipelining of read flushes past the SF-WIZ interface.
* Required on all Ironlake steppings according to the B-Spec, but the
* particular danger of not doing so is not specified.
*/
# define _3D_CHICKEN2_WM_READ_PIPELINED (1 << 14)
#define _3D_CHICKEN3 _MMIO(0x2090)
+#define _3D_CHICKEN_SF_PROVOKING_VERTEX_FIX (1 << 12)
#define _3D_CHICKEN_SF_DISABLE_OBJEND_CULL (1 << 10)
#define _3D_CHICKEN3_AA_LINE_QUALITY_FIX_ENABLE (1 << 5)
#define _3D_CHICKEN3_SF_DISABLE_FASTCLIP_CULL (1 << 5)
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index de0e223..072b326 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -304,6 +304,9 @@ intel_crt_mode_valid(struct drm_connector *connector,
int max_dotclk = dev_priv->max_dotclk_freq;
int max_clock;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
if (mode->clock < 25000)
return MODE_CLOCK_LOW;
@@ -337,6 +340,12 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
+ struct drm_display_mode *adjusted_mode =
+ &pipe_config->base.adjusted_mode;
+
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
+
return true;
}
@@ -344,6 +353,12 @@ static bool pch_crt_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
+ struct drm_display_mode *adjusted_mode =
+ &pipe_config->base.adjusted_mode;
+
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
+
pipe_config->has_pch_encoder = true;
return true;
@@ -354,6 +369,11 @@ static bool hsw_crt_compute_config(struct intel_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct drm_display_mode *adjusted_mode =
+ &pipe_config->base.adjusted_mode;
+
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
pipe_config->has_pch_encoder = true;
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index b98ac054..f4a8598 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -2453,12 +2453,13 @@ void icl_map_plls_to_ports(struct drm_crtc *crtc,
for_each_new_connector_in_state(old_state, conn, conn_state, i) {
struct intel_encoder *encoder =
to_intel_encoder(conn_state->best_encoder);
- enum port port = encoder->port;
+ enum port port;
uint32_t val;
if (conn_state->crtc != crtc)
continue;
+ port = encoder->port;
mutex_lock(&dev_priv->dpll_lock);
val = I915_READ(DPCLKA_CFGCR0_ICL);
@@ -2490,11 +2491,12 @@ void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
for_each_old_connector_in_state(old_state, conn, old_conn_state, i) {
struct intel_encoder *encoder =
to_intel_encoder(old_conn_state->best_encoder);
- enum port port = encoder->port;
+ enum port port;
if (old_conn_state->crtc != crtc)
continue;
+ port = encoder->port;
mutex_lock(&dev_priv->dpll_lock);
I915_WRITE(DPCLKA_CFGCR0_ICL,
I915_READ(DPCLKA_CFGCR0_ICL) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ad588d5..2cc6faa 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3690,11 +3690,6 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
plane_color_ctl |= glk_plane_color_ctl_alpha(fb->format->format);
if (intel_format_is_yuv(fb->format->format)) {
- if (fb->format->format == DRM_FORMAT_NV12) {
- plane_color_ctl |=
- PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
- goto out;
- }
if (plane_state->base.color_encoding == DRM_COLOR_YCBCR_BT709)
plane_color_ctl |= PLANE_COLOR_CSC_MODE_YUV709_TO_RGB709;
else
@@ -3703,7 +3698,7 @@ u32 glk_plane_color_ctl(const struct intel_crtc_state *crtc_state,
if (plane_state->base.color_range == DRM_COLOR_YCBCR_FULL_RANGE)
plane_color_ctl |= PLANE_COLOR_YUV_RANGE_CORRECTION_DISABLE;
}
-out:
+
return plane_color_ctl;
}
@@ -14474,12 +14469,22 @@ static enum drm_mode_status
intel_mode_valid(struct drm_device *dev,
const struct drm_display_mode *mode)
{
+ /*
+ * Can't reject DBLSCAN here because Xorg ddxen can add piles
+ * of DBLSCAN modes to the output's mode list when they detect
+ * the scaling mode property on the connector. And they don't
+ * ask the kernel to validate those modes in any way until
+ * modeset time at which point the client gets a protocol error.
+ * So in order to not upset those clients we silently ignore the
+ * DBLSCAN flag on such connectors. For other connectors we will
+ * reject modes with the DBLSCAN flag in encoder->compute_config().
+ * And we always reject DBLSCAN modes in connector->mode_valid()
+ * as we never want such modes on the connector's mode list.
+ */
+
if (mode->vscan > 1)
return MODE_NO_VSCAN;
- if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
- return MODE_NO_DBLESCAN;
-
if (mode->flags & DRM_MODE_FLAG_HSKEW)
return MODE_H_ILLEGAL;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index dde92e4..16faea3 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -420,6 +420,9 @@ intel_dp_mode_valid(struct drm_connector *connector,
int max_rate, mode_rate, max_lanes, max_link_clock;
int max_dotclk;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
max_dotclk = intel_dp_downstream_max_dotclock(intel_dp);
if (intel_dp_is_edp(intel_dp) && fixed_mode) {
@@ -1679,23 +1682,6 @@ static int intel_dp_compute_bpp(struct intel_dp *intel_dp,
return bpp;
}
-static bool intel_edp_compare_alt_mode(struct drm_display_mode *m1,
- struct drm_display_mode *m2)
-{
- bool bres = false;
-
- if (m1 && m2)
- bres = (m1->hdisplay == m2->hdisplay &&
- m1->hsync_start == m2->hsync_start &&
- m1->hsync_end == m2->hsync_end &&
- m1->htotal == m2->htotal &&
- m1->vdisplay == m2->vdisplay &&
- m1->vsync_start == m2->vsync_start &&
- m1->vsync_end == m2->vsync_end &&
- m1->vtotal == m2->vtotal);
- return bres;
-}
-
/* Adjust link config limits based on compliance test requests. */
static void
intel_dp_adjust_compliance_config(struct intel_dp *intel_dp,
@@ -1860,16 +1846,8 @@ intel_dp_compute_config(struct intel_encoder *encoder,
pipe_config->has_audio = intel_conn_state->force_audio == HDMI_AUDIO_ON;
if (intel_dp_is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
- struct drm_display_mode *panel_mode =
- intel_connector->panel.alt_fixed_mode;
- struct drm_display_mode *req_mode = &pipe_config->base.mode;
-
- if (!intel_edp_compare_alt_mode(req_mode, panel_mode))
- panel_mode = intel_connector->panel.fixed_mode;
-
- drm_mode_debug_printmodeline(panel_mode);
-
- intel_fixed_panel_mode(panel_mode, adjusted_mode);
+ intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
+ adjusted_mode);
if (INTEL_GEN(dev_priv) >= 9) {
int ret;
@@ -1887,7 +1865,10 @@ intel_dp_compute_config(struct intel_encoder *encoder,
conn_state->scaling_mode);
}
- if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
+
+ if (HAS_GMCH_DISPLAY(dev_priv) &&
adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE)
return false;
@@ -2809,16 +2790,6 @@ static void g4x_disable_dp(struct intel_encoder *encoder,
const struct drm_connector_state *old_conn_state)
{
intel_disable_dp(encoder, old_crtc_state, old_conn_state);
-
- /* disable the port before the pipe on g4x */
- intel_dp_link_down(encoder, old_crtc_state);
-}
-
-static void ilk_disable_dp(struct intel_encoder *encoder,
- const struct intel_crtc_state *old_crtc_state,
- const struct drm_connector_state *old_conn_state)
-{
- intel_disable_dp(encoder, old_crtc_state, old_conn_state);
}
static void vlv_disable_dp(struct intel_encoder *encoder,
@@ -2832,13 +2803,19 @@ static void vlv_disable_dp(struct intel_encoder *encoder,
intel_disable_dp(encoder, old_crtc_state, old_conn_state);
}
-static void ilk_post_disable_dp(struct intel_encoder *encoder,
+static void g4x_post_disable_dp(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
enum port port = encoder->port;
+ /*
+ * Bspec does not list a specific disable sequence for g4x DP.
+ * Follow the ilk+ sequence (disable pipe before the port) for
+ * g4x DP as it does not suffer from underruns like the normal
+ * g4x modeset sequence (disable pipe after the port).
+ */
intel_dp_link_down(encoder, old_crtc_state);
/* Only ilk+ has port A */
@@ -6159,7 +6136,6 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_connector *connector = &intel_connector->base;
struct drm_display_mode *fixed_mode = NULL;
- struct drm_display_mode *alt_fixed_mode = NULL;
struct drm_display_mode *downclock_mode = NULL;
bool has_dpcd;
struct drm_display_mode *scan;
@@ -6214,14 +6190,13 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
}
intel_connector->edid = edid;
- /* prefer fixed mode from EDID if available, save an alt mode also */
+ /* prefer fixed mode from EDID if available */
list_for_each_entry(scan, &connector->probed_modes, head) {
if ((scan->type & DRM_MODE_TYPE_PREFERRED)) {
fixed_mode = drm_mode_duplicate(dev, scan);
downclock_mode = intel_dp_drrs_init(
intel_connector, fixed_mode);
- } else if (!alt_fixed_mode) {
- alt_fixed_mode = drm_mode_duplicate(dev, scan);
+ break;
}
}
@@ -6258,8 +6233,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
pipe_name(pipe));
}
- intel_panel_init(&intel_connector->panel, fixed_mode, alt_fixed_mode,
- downclock_mode);
+ intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
intel_connector->panel.backlight.power = intel_edp_backlight_power;
intel_panel_setup_backlight(connector, pipe);
@@ -6365,7 +6339,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
- if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
+ if (!HAS_GMCH_DISPLAY(dev_priv))
connector->interlace_allowed = true;
connector->doublescan_allowed = 0;
@@ -6464,15 +6438,11 @@ bool intel_dp_init(struct drm_i915_private *dev_priv,
intel_encoder->enable = vlv_enable_dp;
intel_encoder->disable = vlv_disable_dp;
intel_encoder->post_disable = vlv_post_disable_dp;
- } else if (INTEL_GEN(dev_priv) >= 5) {
- intel_encoder->pre_enable = g4x_pre_enable_dp;
- intel_encoder->enable = g4x_enable_dp;
- intel_encoder->disable = ilk_disable_dp;
- intel_encoder->post_disable = ilk_post_disable_dp;
} else {
intel_encoder->pre_enable = g4x_pre_enable_dp;
intel_encoder->enable = g4x_enable_dp;
intel_encoder->disable = g4x_disable_dp;
+ intel_encoder->post_disable = g4x_post_disable_dp;
}
intel_dig_port->dp.output_reg = output_reg;
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 9e6956c..5890500 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -48,6 +48,9 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
bool reduce_m_n = drm_dp_has_quirk(&intel_dp->desc,
DP_DPCD_QUIRK_LIMITED_M_N);
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
+
pipe_config->has_pch_encoder = false;
bpp = 24;
if (intel_dp->compliance.test_data.bpc) {
@@ -366,6 +369,9 @@ intel_dp_mst_mode_valid(struct drm_connector *connector,
if (!intel_dp)
return MODE_ERROR;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
max_link_clock = intel_dp_max_link_rate(intel_dp);
max_lanes = intel_dp_max_lane_count(intel_dp);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d7dbca1..0361130 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -277,7 +277,6 @@ struct intel_encoder {
struct intel_panel {
struct drm_display_mode *fixed_mode;
- struct drm_display_mode *alt_fixed_mode;
struct drm_display_mode *downclock_mode;
/* backlight */
@@ -1850,7 +1849,6 @@ void intel_overlay_reset(struct drm_i915_private *dev_priv);
/* intel_panel.c */
int intel_panel_init(struct intel_panel *panel,
struct drm_display_mode *fixed_mode,
- struct drm_display_mode *alt_fixed_mode,
struct drm_display_mode *downclock_mode);
void intel_panel_fini(struct intel_panel *panel);
void intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c
index 51a1d68..f349b39 100644
--- a/drivers/gpu/drm/i915/intel_dsi.c
+++ b/drivers/gpu/drm/i915/intel_dsi.c
@@ -326,6 +326,9 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder,
conn_state->scaling_mode);
}
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
+
/* DSI uses short packets for sync events, so clear mode flags for DSI */
adjusted_mode->flags = 0;
@@ -1266,6 +1269,9 @@ intel_dsi_mode_valid(struct drm_connector *connector,
DRM_DEBUG_KMS("\n");
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
if (fixed_mode) {
if (mode->hdisplay > fixed_mode->hdisplay)
return MODE_PANEL;
@@ -1846,7 +1852,7 @@ void intel_dsi_init(struct drm_i915_private *dev_priv)
connector->display_info.width_mm = fixed_mode->width_mm;
connector->display_info.height_mm = fixed_mode->height_mm;
- intel_panel_init(&intel_connector->panel, fixed_mode, NULL, NULL);
+ intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
intel_panel_setup_backlight(connector, INVALID_PIPE);
intel_dsi_add_properties(intel_connector);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index eb0c559b2..61d908e 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -219,6 +219,9 @@ intel_dvo_mode_valid(struct drm_connector *connector,
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
int target_clock = mode->clock;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
/* XXX: Validate clock range */
if (fixed_mode) {
@@ -254,6 +257,9 @@ static bool intel_dvo_compute_config(struct intel_encoder *encoder,
if (fixed_mode)
intel_fixed_panel_mode(fixed_mode, adjusted_mode);
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
+
return true;
}
@@ -536,7 +542,7 @@ void intel_dvo_init(struct drm_i915_private *dev_priv)
*/
intel_panel_init(&intel_connector->panel,
intel_dvo_get_current_mode(intel_encoder),
- NULL, NULL);
+ NULL);
intel_dvo->panel_wants_dither = true;
}
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index 6bfd7e3..1590375 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -1114,7 +1114,7 @@ static void print_request(struct drm_printer *m,
const char *prefix)
{
const char *name = rq->fence.ops->get_timeline_name(&rq->fence);
- char buf[80];
+ char buf[80] = "";
int x = 0;
x = print_sched_attr(rq->i915, &rq->sched.attr, buf, x, sizeof(buf));
diff --git a/drivers/gpu/drm/i915/intel_hdcp.c b/drivers/gpu/drm/i915/intel_hdcp.c
index 2db5da5..0cc6a86 100644
--- a/drivers/gpu/drm/i915/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/intel_hdcp.c
@@ -429,7 +429,7 @@ int intel_hdcp_auth_downstream(struct intel_digital_port *intel_dig_port,
if (num_downstream == 0)
return -EINVAL;
- ksv_fifo = kzalloc(num_downstream * DRM_HDCP_KSV_LEN, GFP_KERNEL);
+ ksv_fifo = kcalloc(DRM_HDCP_KSV_LEN, num_downstream, GFP_KERNEL);
if (!ksv_fifo)
return -ENOMEM;
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index ee929f3..d8cb53e 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -1557,6 +1557,9 @@ intel_hdmi_mode_valid(struct drm_connector *connector,
bool force_dvi =
READ_ONCE(to_intel_digital_connector_state(connector->state)->force_audio) == HDMI_AUDIO_OFF_DVI;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
clock = mode->clock;
if ((mode->flags & DRM_MODE_FLAG_3D_MASK) == DRM_MODE_FLAG_3D_FRAME_PACKING)
@@ -1677,6 +1680,9 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder,
int desired_bpp;
bool force_dvi = intel_conn_state->force_audio == HDMI_AUDIO_OFF_DVI;
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
+
pipe_config->has_hdmi_sink = !force_dvi && intel_hdmi->has_hdmi_sink;
if (pipe_config->has_hdmi_sink)
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 15434ca..7c4c8fb 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1545,11 +1545,21 @@ static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch)
/* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt,glk */
batch = gen8_emit_flush_coherentl3_wa(engine, batch);
+ *batch++ = MI_LOAD_REGISTER_IMM(3);
+
/* WaDisableGatherAtSetShaderCommonSlice:skl,bxt,kbl,glk */
- *batch++ = MI_LOAD_REGISTER_IMM(1);
*batch++ = i915_mmio_reg_offset(COMMON_SLICE_CHICKEN2);
*batch++ = _MASKED_BIT_DISABLE(
GEN9_DISABLE_GATHER_AT_SET_SHADER_COMMON_SLICE);
+
+ /* BSpec: 11391 */
+ *batch++ = i915_mmio_reg_offset(FF_SLICE_CHICKEN);
+ *batch++ = _MASKED_BIT_ENABLE(FF_SLICE_CHICKEN_CL_PROVOKING_VERTEX_FIX);
+
+ /* BSpec: 11299 */
+ *batch++ = i915_mmio_reg_offset(_3D_CHICKEN3);
+ *batch++ = _MASKED_BIT_ENABLE(_3D_CHICKEN_SF_PROVOKING_VERTEX_FIX);
+
*batch++ = MI_NOOP;
/* WaClearSlmSpaceAtContextSwitch:kbl */
@@ -2641,10 +2651,8 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
context_size += LRC_HEADER_PAGES * PAGE_SIZE;
ctx_obj = i915_gem_object_create(ctx->i915, context_size);
- if (IS_ERR(ctx_obj)) {
- ret = PTR_ERR(ctx_obj);
- goto error_deref_obj;
- }
+ if (IS_ERR(ctx_obj))
+ return PTR_ERR(ctx_obj);
vma = i915_vma_instance(ctx_obj, &ctx->i915->ggtt.base, NULL);
if (IS_ERR(vma)) {
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index e125d16..48f618d 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -380,6 +380,8 @@ intel_lvds_mode_valid(struct drm_connector *connector,
struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
int max_pixclk = to_i915(connector->dev)->max_dotclk_freq;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
if (mode->hdisplay > fixed_mode->hdisplay)
return MODE_PANEL;
if (mode->vdisplay > fixed_mode->vdisplay)
@@ -429,6 +431,9 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
adjusted_mode);
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
+
if (HAS_PCH_SPLIT(dev_priv)) {
pipe_config->has_pch_encoder = true;
@@ -1175,8 +1180,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
out:
mutex_unlock(&dev->mode_config.mutex);
- intel_panel_init(&intel_connector->panel, fixed_mode, NULL,
- downclock_mode);
+ intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
intel_panel_setup_backlight(connector, INVALID_PIPE);
lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 41d00b1..b443278 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1928,13 +1928,11 @@ intel_panel_init_backlight_funcs(struct intel_panel *panel)
int intel_panel_init(struct intel_panel *panel,
struct drm_display_mode *fixed_mode,
- struct drm_display_mode *alt_fixed_mode,
struct drm_display_mode *downclock_mode)
{
intel_panel_init_backlight_funcs(panel);
panel->fixed_mode = fixed_mode;
- panel->alt_fixed_mode = alt_fixed_mode;
panel->downclock_mode = downclock_mode;
return 0;
@@ -1948,10 +1946,6 @@ void intel_panel_fini(struct intel_panel *panel)
if (panel->fixed_mode)
drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
- if (panel->alt_fixed_mode)
- drm_mode_destroy(intel_connector->base.dev,
- panel->alt_fixed_mode);
-
if (panel->downclock_mode)
drm_mode_destroy(intel_connector->base.dev,
panel->downclock_mode);
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index b85229e..53aaaa3 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5150,7 +5150,6 @@ skl_copy_ddb_for_pipe(struct skl_ddb_values *dst,
sizeof(dst->ddb.uv_plane[pipe]));
memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe],
sizeof(dst->ddb.plane[pipe]));
- dst->ddb.enabled_slices = src->ddb.enabled_slices;
}
static void
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index 2500502..26975df4 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1160,6 +1160,9 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
adjusted_mode);
}
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
+
/*
* Make the CRTC code factor in the SDVO pixel multiplier. The
* SDVO device will factor out the multiplier during mode_set.
@@ -1621,6 +1624,9 @@ intel_sdvo_mode_valid(struct drm_connector *connector,
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
if (intel_sdvo->pixel_clock_min > mode->clock)
return MODE_CLOCK_LOW;
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index 885fc38..b55b5c1 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -850,6 +850,9 @@ intel_tv_mode_valid(struct drm_connector *connector,
const struct tv_mode *tv_mode = intel_tv_mode_find(connector->state);
int max_dotclk = to_i915(connector->dev)->max_dotclk_freq;
+ if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return MODE_NO_DBLESCAN;
+
if (mode->clock > max_dotclk)
return MODE_CLOCK_HIGH;
@@ -877,16 +880,21 @@ intel_tv_compute_config(struct intel_encoder *encoder,
struct drm_connector_state *conn_state)
{
const struct tv_mode *tv_mode = intel_tv_mode_find(conn_state);
+ struct drm_display_mode *adjusted_mode =
+ &pipe_config->base.adjusted_mode;
if (!tv_mode)
return false;
- pipe_config->base.adjusted_mode.crtc_clock = tv_mode->clock;
+ if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
+ return false;
+
+ adjusted_mode->crtc_clock = tv_mode->clock;
DRM_DEBUG_KMS("forcing bpc to 8 for TV\n");
pipe_config->pipe_bpp = 8*3;
/* TV has it's own notion of sync and other mode flags, so clear them. */
- pipe_config->base.adjusted_mode.flags = 0;
+ adjusted_mode->flags = 0;
/*
* FIXME: We don't check whether the input mode is actually what we want
diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c
index f76f259..47bc5b2 100644
--- a/drivers/gpu/drm/i915/selftests/intel_uncore.c
+++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c
@@ -137,7 +137,7 @@ static int intel_uncore_check_forcewake_domains(struct drm_i915_private *dev_pri
if (!IS_ENABLED(CONFIG_DRM_I915_SELFTEST_BROKEN))
return 0;
- valid = kzalloc(BITS_TO_LONGS(FW_RANGE) * sizeof(*valid),
+ valid = kcalloc(BITS_TO_LONGS(FW_RANGE), sizeof(*valid),
GFP_KERNEL);
if (!valid)
return -ENOMEM;
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
index 7a1ad3a..20e956e 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
@@ -98,21 +98,6 @@ static const struct drm_plane_funcs mdp4_plane_funcs = {
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
};
-static int mdp4_plane_prepare_fb(struct drm_plane *plane,
- struct drm_plane_state *new_state)
-{
- struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
- struct mdp4_kms *mdp4_kms = get_kms(plane);
- struct msm_kms *kms = &mdp4_kms->base.base;
- struct drm_framebuffer *fb = new_state->fb;
-
- if (!fb)
- return 0;
-
- DBG("%s: prepare: FB[%u]", mdp4_plane->name, fb->base.id);
- return msm_framebuffer_prepare(fb, kms->aspace);
-}
-
static void mdp4_plane_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
@@ -152,7 +137,7 @@ static void mdp4_plane_atomic_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs mdp4_plane_helper_funcs = {
- .prepare_fb = mdp4_plane_prepare_fb,
+ .prepare_fb = msm_atomic_prepare_fb,
.cleanup_fb = mdp4_plane_cleanup_fb,
.atomic_check = mdp4_plane_atomic_check,
.atomic_update = mdp4_plane_atomic_update,
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
index 76b9608..1027135 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
@@ -430,6 +430,7 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc,
struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state);
struct mdp5_kms *mdp5_kms = get_kms(crtc);
struct device *dev = &mdp5_kms->pdev->dev;
+ unsigned long flags;
DBG("%s", crtc->name);
@@ -445,6 +446,14 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc,
mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);
pm_runtime_put_sync(dev);
+ if (crtc->state->event && !crtc->state->active) {
+ WARN_ON(mdp5_crtc->event);
+ spin_lock_irqsave(&mdp5_kms->dev->event_lock, flags);
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+ crtc->state->event = NULL;
+ spin_unlock_irqrestore(&mdp5_kms->dev->event_lock, flags);
+ }
+
mdp5_crtc->enabled = false;
}
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 6d8e3a9..6e12e27 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -70,60 +70,110 @@ static int mdp5_hw_init(struct msm_kms *kms)
return 0;
}
-struct mdp5_state *mdp5_get_state(struct drm_atomic_state *s)
+/* Global/shared object state funcs */
+
+/*
+ * This is a helper that returns the private state currently in operation.
+ * Note that this would return the "old_state" if called in the atomic check
+ * path, and the "new_state" after the atomic swap has been done.
+ */
+struct mdp5_global_state *
+mdp5_get_existing_global_state(struct mdp5_kms *mdp5_kms)
+{
+ return to_mdp5_global_state(mdp5_kms->glob_state.state);
+}
+
+/*
+ * This acquires the modeset lock set aside for global state, creates
+ * a new duplicated private object state.
+ */
+struct mdp5_global_state *mdp5_get_global_state(struct drm_atomic_state *s)
{
struct msm_drm_private *priv = s->dev->dev_private;
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
- struct msm_kms_state *state = to_kms_state(s);
- struct mdp5_state *new_state;
+ struct drm_private_state *priv_state;
int ret;
- if (state->state)
- return state->state;
-
- ret = drm_modeset_lock(&mdp5_kms->state_lock, s->acquire_ctx);
+ ret = drm_modeset_lock(&mdp5_kms->glob_state_lock, s->acquire_ctx);
if (ret)
return ERR_PTR(ret);
- new_state = kmalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
- if (!new_state)
- return ERR_PTR(-ENOMEM);
+ priv_state = drm_atomic_get_private_obj_state(s, &mdp5_kms->glob_state);
+ if (IS_ERR(priv_state))
+ return ERR_CAST(priv_state);
- /* Copy state: */
- new_state->hwpipe = mdp5_kms->state->hwpipe;
- new_state->hwmixer = mdp5_kms->state->hwmixer;
- if (mdp5_kms->smp)
- new_state->smp = mdp5_kms->state->smp;
+ return to_mdp5_global_state(priv_state);
+}
+
+static struct drm_private_state *
+mdp5_global_duplicate_state(struct drm_private_obj *obj)
+{
+ struct mdp5_global_state *state;
+
+ state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return NULL;
- state->state = new_state;
+ __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base);
- return new_state;
+ return &state->base;
}
-static void mdp5_swap_state(struct msm_kms *kms, struct drm_atomic_state *state)
+static void mdp5_global_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
{
- struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
- swap(to_kms_state(state)->state, mdp5_kms->state);
+ struct mdp5_global_state *mdp5_state = to_mdp5_global_state(state);
+
+ kfree(mdp5_state);
+}
+
+static const struct drm_private_state_funcs mdp5_global_state_funcs = {
+ .atomic_duplicate_state = mdp5_global_duplicate_state,
+ .atomic_destroy_state = mdp5_global_destroy_state,
+};
+
+static int mdp5_global_obj_init(struct mdp5_kms *mdp5_kms)
+{
+ struct mdp5_global_state *state;
+
+ drm_modeset_lock_init(&mdp5_kms->glob_state_lock);
+
+ state = kzalloc(sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ state->mdp5_kms = mdp5_kms;
+
+ drm_atomic_private_obj_init(&mdp5_kms->glob_state,
+ &state->base,
+ &mdp5_global_state_funcs);
+ return 0;
}
static void mdp5_prepare_commit(struct msm_kms *kms, struct drm_atomic_state *state)
{
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
struct device *dev = &mdp5_kms->pdev->dev;
+ struct mdp5_global_state *global_state;
+
+ global_state = mdp5_get_existing_global_state(mdp5_kms);
pm_runtime_get_sync(dev);
if (mdp5_kms->smp)
- mdp5_smp_prepare_commit(mdp5_kms->smp, &mdp5_kms->state->smp);
+ mdp5_smp_prepare_commit(mdp5_kms->smp, &global_state->smp);
}
static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state)
{
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
struct device *dev = &mdp5_kms->pdev->dev;
+ struct mdp5_global_state *global_state;
+
+ global_state = mdp5_get_existing_global_state(mdp5_kms);
if (mdp5_kms->smp)
- mdp5_smp_complete_commit(mdp5_kms->smp, &mdp5_kms->state->smp);
+ mdp5_smp_complete_commit(mdp5_kms->smp, &global_state->smp);
pm_runtime_put_sync(dev);
}
@@ -229,7 +279,6 @@ static const struct mdp_kms_funcs kms_funcs = {
.irq = mdp5_irq,
.enable_vblank = mdp5_enable_vblank,
.disable_vblank = mdp5_disable_vblank,
- .swap_state = mdp5_swap_state,
.prepare_commit = mdp5_prepare_commit,
.complete_commit = mdp5_complete_commit,
.wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
@@ -727,7 +776,8 @@ static void mdp5_destroy(struct platform_device *pdev)
if (mdp5_kms->rpm_enabled)
pm_runtime_disable(&pdev->dev);
- kfree(mdp5_kms->state);
+ drm_atomic_private_obj_fini(&mdp5_kms->glob_state);
+ drm_modeset_lock_fini(&mdp5_kms->glob_state_lock);
}
static int construct_pipes(struct mdp5_kms *mdp5_kms, int cnt,
@@ -880,12 +930,9 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
mdp5_kms->dev = dev;
mdp5_kms->pdev = pdev;
- drm_modeset_lock_init(&mdp5_kms->state_lock);
- mdp5_kms->state = kzalloc(sizeof(*mdp5_kms->state), GFP_KERNEL);
- if (!mdp5_kms->state) {
- ret = -ENOMEM;
+ ret = mdp5_global_obj_init(mdp5_kms);
+ if (ret)
goto fail;
- }
mdp5_kms->mmio = msm_ioremap(pdev, "mdp_phys", "MDP5");
if (IS_ERR(mdp5_kms->mmio)) {
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h
index 425a03d..854dfd3 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.h
@@ -28,8 +28,6 @@
#include "mdp5_ctl.h"
#include "mdp5_smp.h"
-struct mdp5_state;
-
struct mdp5_kms {
struct mdp_kms base;
@@ -49,11 +47,12 @@ struct mdp5_kms {
struct mdp5_cfg_handler *cfg;
uint32_t caps; /* MDP capabilities (MDP_CAP_XXX bits) */
- /**
- * Global atomic state. Do not access directly, use mdp5_get_state()
+ /*
+ * Global private object state, Do not access directly, use
+ * mdp5_global_get_state()
*/
- struct mdp5_state *state;
- struct drm_modeset_lock state_lock;
+ struct drm_modeset_lock glob_state_lock;
+ struct drm_private_obj glob_state;
struct mdp5_smp *smp;
struct mdp5_ctl_manager *ctlm;
@@ -81,19 +80,23 @@ struct mdp5_kms {
};
#define to_mdp5_kms(x) container_of(x, struct mdp5_kms, base)
-/* Global atomic state for tracking resources that are shared across
+/* Global private object state for tracking resources that are shared across
* multiple kms objects (planes/crtcs/etc).
- *
- * For atomic updates which require modifying global state,
*/
-struct mdp5_state {
+#define to_mdp5_global_state(x) container_of(x, struct mdp5_global_state, base)
+struct mdp5_global_state {
+ struct drm_private_state base;
+
+ struct drm_atomic_state *state;
+ struct mdp5_kms *mdp5_kms;
+
struct mdp5_hw_pipe_state hwpipe;
struct mdp5_hw_mixer_state hwmixer;
struct mdp5_smp_state smp;
};
-struct mdp5_state *__must_check
-mdp5_get_state(struct drm_atomic_state *s);
+struct mdp5_global_state * mdp5_get_existing_global_state(struct mdp5_kms *mdp5_kms);
+struct mdp5_global_state *__must_check mdp5_get_global_state(struct drm_atomic_state *s);
/* Atomic plane state. Subclasses the base drm_plane_state in order to
* track assigned hwpipe and hw specific state.
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c
index 8a00991..113e6b5 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c
@@ -52,14 +52,14 @@ int mdp5_mixer_assign(struct drm_atomic_state *s, struct drm_crtc *crtc,
{
struct msm_drm_private *priv = s->dev->dev_private;
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
- struct mdp5_state *state = mdp5_get_state(s);
+ struct mdp5_global_state *global_state = mdp5_get_global_state(s);
struct mdp5_hw_mixer_state *new_state;
int i;
- if (IS_ERR(state))
- return PTR_ERR(state);
+ if (IS_ERR(global_state))
+ return PTR_ERR(global_state);
- new_state = &state->hwmixer;
+ new_state = &global_state->hwmixer;
for (i = 0; i < mdp5_kms->num_hwmixers; i++) {
struct mdp5_hw_mixer *cur = mdp5_kms->hwmixers[i];
@@ -129,8 +129,8 @@ int mdp5_mixer_assign(struct drm_atomic_state *s, struct drm_crtc *crtc,
void mdp5_mixer_release(struct drm_atomic_state *s, struct mdp5_hw_mixer *mixer)
{
- struct mdp5_state *state = mdp5_get_state(s);
- struct mdp5_hw_mixer_state *new_state = &state->hwmixer;
+ struct mdp5_global_state *global_state = mdp5_get_global_state(s);
+ struct mdp5_hw_mixer_state *new_state = &global_state->hwmixer;
if (!mixer)
return;
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c
index ff52c49..1ef26bc6 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c
@@ -24,17 +24,19 @@ int mdp5_pipe_assign(struct drm_atomic_state *s, struct drm_plane *plane,
{
struct msm_drm_private *priv = s->dev->dev_private;
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
- struct mdp5_state *state;
+ struct mdp5_global_state *new_global_state, *old_global_state;
struct mdp5_hw_pipe_state *old_state, *new_state;
int i, j;
- state = mdp5_get_state(s);
- if (IS_ERR(state))
- return PTR_ERR(state);
+ new_global_state = mdp5_get_global_state(s);
+ if (IS_ERR(new_global_state))
+ return PTR_ERR(new_global_state);
- /* grab old_state after mdp5_get_state(), since now we hold lock: */
- old_state = &mdp5_kms->state->hwpipe;
- new_state = &state->hwpipe;
+ /* grab old_state after mdp5_get_global_state(), since now we hold lock: */
+ old_global_state = mdp5_get_existing_global_state(mdp5_kms);
+
+ old_state = &old_global_state->hwpipe;
+ new_state = &new_global_state->hwpipe;
for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
struct mdp5_hw_pipe *cur = mdp5_kms->hwpipes[i];
@@ -107,7 +109,7 @@ int mdp5_pipe_assign(struct drm_atomic_state *s, struct drm_plane *plane,
WARN_ON(r_hwpipe);
DBG("%s: alloc SMP blocks", (*hwpipe)->name);
- ret = mdp5_smp_assign(mdp5_kms->smp, &state->smp,
+ ret = mdp5_smp_assign(mdp5_kms->smp, &new_global_state->smp,
(*hwpipe)->pipe, blkcfg);
if (ret)
return -ENOMEM;
@@ -132,7 +134,7 @@ void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe)
{
struct msm_drm_private *priv = s->dev->dev_private;
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
- struct mdp5_state *state = mdp5_get_state(s);
+ struct mdp5_global_state *state = mdp5_get_global_state(s);
struct mdp5_hw_pipe_state *new_state = &state->hwpipe;
if (!hwpipe)
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
index a9f31da..e09bc53 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
@@ -245,20 +245,6 @@ static const struct drm_plane_funcs mdp5_plane_funcs = {
.atomic_print_state = mdp5_plane_atomic_print_state,
};
-static int mdp5_plane_prepare_fb(struct drm_plane *plane,
- struct drm_plane_state *new_state)
-{
- struct mdp5_kms *mdp5_kms = get_kms(plane);
- struct msm_kms *kms = &mdp5_kms->base.base;
- struct drm_framebuffer *fb = new_state->fb;
-
- if (!new_state->fb)
- return 0;
-
- DBG("%s: prepare: FB[%u]", plane->name, fb->base.id);
- return msm_framebuffer_prepare(fb, kms->aspace);
-}
-
static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
@@ -543,7 +529,7 @@ static void mdp5_plane_atomic_async_update(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = {
- .prepare_fb = mdp5_plane_prepare_fb,
+ .prepare_fb = msm_atomic_prepare_fb,
.cleanup_fb = mdp5_plane_cleanup_fb,
.atomic_check = mdp5_plane_atomic_check,
.atomic_update = mdp5_plane_atomic_update,
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
index ae4983d..96c2b82 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
@@ -340,17 +340,20 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p)
struct mdp5_kms *mdp5_kms = get_kms(smp);
struct mdp5_hw_pipe_state *hwpstate;
struct mdp5_smp_state *state;
+ struct mdp5_global_state *global_state;
int total = 0, i, j;
drm_printf(p, "name\tinuse\tplane\n");
drm_printf(p, "----\t-----\t-----\n");
if (drm_can_sleep())
- drm_modeset_lock(&mdp5_kms->state_lock, NULL);
+ drm_modeset_lock(&mdp5_kms->glob_state_lock, NULL);
+
+ global_state = mdp5_get_existing_global_state(mdp5_kms);
/* grab these *after* we hold the state_lock */
- hwpstate = &mdp5_kms->state->hwpipe;
- state = &mdp5_kms->state->smp;
+ hwpstate = &global_state->hwpipe;
+ state = &global_state->smp;
for (i = 0; i < mdp5_kms->num_hwpipes; i++) {
struct mdp5_hw_pipe *hwpipe = mdp5_kms->hwpipes[i];
@@ -374,7 +377,7 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p)
bitmap_weight(state->state, smp->blk_cnt));
if (drm_can_sleep())
- drm_modeset_unlock(&mdp5_kms->state_lock);
+ drm_modeset_unlock(&mdp5_kms->glob_state_lock);
}
void mdp5_smp_destroy(struct mdp5_smp *smp)
@@ -384,7 +387,8 @@ void mdp5_smp_destroy(struct mdp5_smp *smp)
struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_block *cfg)
{
- struct mdp5_smp_state *state = &mdp5_kms->state->smp;
+ struct mdp5_smp_state *state;
+ struct mdp5_global_state *global_state;
struct mdp5_smp *smp = NULL;
int ret;
@@ -398,6 +402,9 @@ struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct mdp5_smp_
smp->blk_cnt = cfg->mmb_count;
smp->blk_size = cfg->mmb_size;
+ global_state = mdp5_get_existing_global_state(mdp5_kms);
+ state = &global_state->smp;
+
/* statically tied MMBs cannot be re-allocated: */
bitmap_copy(state->state, cfg->reserved_state, smp->blk_cnt);
memcpy(smp->reserved, cfg->reserved, sizeof(smp->reserved));
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 8baba30..2f1a278 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1036,7 +1036,6 @@ static int dsi_tx_buf_alloc(struct msm_dsi_host *msm_host, int size)
ret = msm_gem_get_iova(msm_host->tx_gem_obj,
priv->kms->aspace, &iova);
- mutex_unlock(&dev->struct_mutex);
if (ret) {
pr_err("%s: failed to get iova, %d\n", __func__, ret);
return ret;
@@ -1067,9 +1066,20 @@ static int dsi_tx_buf_alloc(struct msm_dsi_host *msm_host, int size)
static void dsi_tx_buf_free(struct msm_dsi_host *msm_host)
{
struct drm_device *dev = msm_host->dev;
+ struct msm_drm_private *priv;
+ /*
+ * This is possible if we're tearing down before we've had a chance to
+ * fully initialize. A very real possibility if our probe is deferred,
+ * in which case we'll hit msm_dsi_host_destroy() without having run
+ * through the dsi_tx_buf_alloc().
+ */
+ if (!dev)
+ return;
+
+ priv = dev->dev_private;
if (msm_host->tx_gem_obj) {
- msm_gem_put_iova(msm_host->tx_gem_obj, 0);
+ msm_gem_put_iova(msm_host->tx_gem_obj, priv->kms->aspace);
drm_gem_object_put_unlocked(msm_host->tx_gem_obj);
msm_host->tx_gem_obj = NULL;
}
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index e63dc0f..c79659c 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -157,8 +157,10 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
hdmi->qfprom_mmio = NULL;
}
- hdmi->hpd_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_regs[0]) *
- config->hpd_reg_cnt, GFP_KERNEL);
+ hdmi->hpd_regs = devm_kcalloc(&pdev->dev,
+ config->hpd_reg_cnt,
+ sizeof(hdmi->hpd_regs[0]),
+ GFP_KERNEL);
if (!hdmi->hpd_regs) {
ret = -ENOMEM;
goto fail;
@@ -178,8 +180,10 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
hdmi->hpd_regs[i] = reg;
}
- hdmi->pwr_regs = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_regs[0]) *
- config->pwr_reg_cnt, GFP_KERNEL);
+ hdmi->pwr_regs = devm_kcalloc(&pdev->dev,
+ config->pwr_reg_cnt,
+ sizeof(hdmi->pwr_regs[0]),
+ GFP_KERNEL);
if (!hdmi->pwr_regs) {
ret = -ENOMEM;
goto fail;
@@ -199,8 +203,10 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
hdmi->pwr_regs[i] = reg;
}
- hdmi->hpd_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->hpd_clks[0]) *
- config->hpd_clk_cnt, GFP_KERNEL);
+ hdmi->hpd_clks = devm_kcalloc(&pdev->dev,
+ config->hpd_clk_cnt,
+ sizeof(hdmi->hpd_clks[0]),
+ GFP_KERNEL);
if (!hdmi->hpd_clks) {
ret = -ENOMEM;
goto fail;
@@ -219,8 +225,10 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
hdmi->hpd_clks[i] = clk;
}
- hdmi->pwr_clks = devm_kzalloc(&pdev->dev, sizeof(hdmi->pwr_clks[0]) *
- config->pwr_clk_cnt, GFP_KERNEL);
+ hdmi->pwr_clks = devm_kcalloc(&pdev->dev,
+ config->pwr_clk_cnt,
+ sizeof(hdmi->pwr_clks[0]),
+ GFP_KERNEL);
if (!hdmi->pwr_clks) {
ret = -ENOMEM;
goto fail;
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
index 5e63139..4157722 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
@@ -21,12 +21,12 @@ static int msm_hdmi_phy_resource_init(struct hdmi_phy *phy)
struct device *dev = &phy->pdev->dev;
int i, ret;
- phy->regs = devm_kzalloc(dev, sizeof(phy->regs[0]) * cfg->num_regs,
+ phy->regs = devm_kcalloc(dev, cfg->num_regs, sizeof(phy->regs[0]),
GFP_KERNEL);
if (!phy->regs)
return -ENOMEM;
- phy->clks = devm_kzalloc(dev, sizeof(phy->clks[0]) * cfg->num_clks,
+ phy->clks = devm_kcalloc(dev, cfg->num_clks, sizeof(phy->clks[0]),
GFP_KERNEL);
if (!phy->clks)
return -ENOMEM;
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index bf5f8c3..f0635c3 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -16,69 +16,8 @@
*/
#include "msm_drv.h"
-#include "msm_kms.h"
#include "msm_gem.h"
-#include "msm_fence.h"
-
-struct msm_commit {
- struct drm_device *dev;
- struct drm_atomic_state *state;
- struct work_struct work;
- uint32_t crtc_mask;
-};
-
-static void commit_worker(struct work_struct *work);
-
-/* block until specified crtcs are no longer pending update, and
- * atomically mark them as pending update
- */
-static int start_atomic(struct msm_drm_private *priv, uint32_t crtc_mask)
-{
- int ret;
-
- spin_lock(&priv->pending_crtcs_event.lock);
- ret = wait_event_interruptible_locked(priv->pending_crtcs_event,
- !(priv->pending_crtcs & crtc_mask));
- if (ret == 0) {
- DBG("start: %08x", crtc_mask);
- priv->pending_crtcs |= crtc_mask;
- }
- spin_unlock(&priv->pending_crtcs_event.lock);
-
- return ret;
-}
-
-/* clear specified crtcs (no longer pending update)
- */
-static void end_atomic(struct msm_drm_private *priv, uint32_t crtc_mask)
-{
- spin_lock(&priv->pending_crtcs_event.lock);
- DBG("end: %08x", crtc_mask);
- priv->pending_crtcs &= ~crtc_mask;
- wake_up_all_locked(&priv->pending_crtcs_event);
- spin_unlock(&priv->pending_crtcs_event.lock);
-}
-
-static struct msm_commit *commit_init(struct drm_atomic_state *state)
-{
- struct msm_commit *c = kzalloc(sizeof(*c), GFP_KERNEL);
-
- if (!c)
- return NULL;
-
- c->dev = state->dev;
- c->state = state;
-
- INIT_WORK(&c->work, commit_worker);
-
- return c;
-}
-
-static void commit_destroy(struct msm_commit *c)
-{
- end_atomic(c->dev->dev_private, c->crtc_mask);
- kfree(c);
-}
+#include "msm_kms.h"
static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
struct drm_atomic_state *old_state)
@@ -97,195 +36,48 @@ static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
}
}
-/* The (potentially) asynchronous part of the commit. At this point
- * nothing can fail short of armageddon.
- */
-static void complete_commit(struct msm_commit *c, bool async)
+int msm_atomic_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state)
{
- struct drm_atomic_state *state = c->state;
- struct drm_device *dev = state->dev;
- struct msm_drm_private *priv = dev->dev_private;
+ struct msm_drm_private *priv = plane->dev->dev_private;
struct msm_kms *kms = priv->kms;
+ struct drm_gem_object *obj;
+ struct msm_gem_object *msm_obj;
+ struct dma_fence *fence;
- drm_atomic_helper_wait_for_fences(dev, state, false);
-
- kms->funcs->prepare_commit(kms, state);
-
- drm_atomic_helper_commit_modeset_disables(dev, state);
-
- drm_atomic_helper_commit_planes(dev, state, 0);
-
- drm_atomic_helper_commit_modeset_enables(dev, state);
-
- /* NOTE: _wait_for_vblanks() only waits for vblank on
- * enabled CRTCs. So we end up faulting when disabling
- * due to (potentially) unref'ing the outgoing fb's
- * before the vblank when the disable has latched.
- *
- * But if it did wait on disabled (or newly disabled)
- * CRTCs, that would be racy (ie. we could have missed
- * the irq. We need some way to poll for pipe shut
- * down. Or just live with occasionally hitting the
- * timeout in the CRTC disable path (which really should
- * not be critical path)
- */
-
- msm_atomic_wait_for_commit_done(dev, state);
-
- drm_atomic_helper_cleanup_planes(dev, state);
+ if (!new_state->fb)
+ return 0;
- kms->funcs->complete_commit(kms, state);
+ obj = msm_framebuffer_bo(new_state->fb, 0);
+ msm_obj = to_msm_bo(obj);
+ fence = reservation_object_get_excl_rcu(msm_obj->resv);
- drm_atomic_state_put(state);
+ drm_atomic_set_fence_for_plane(new_state, fence);
- commit_destroy(c);
-}
-
-static void commit_worker(struct work_struct *work)
-{
- complete_commit(container_of(work, struct msm_commit, work), true);
+ return msm_framebuffer_prepare(new_state->fb, kms->aspace);
}
-/**
- * drm_atomic_helper_commit - commit validated state object
- * @dev: DRM device
- * @state: the driver state object
- * @nonblock: nonblocking commit
- *
- * This function commits a with drm_atomic_helper_check() pre-validated state
- * object. This can still fail when e.g. the framebuffer reservation fails.
- *
- * RETURNS
- * Zero for success or -errno.
- */
-int msm_atomic_commit(struct drm_device *dev,
- struct drm_atomic_state *state, bool nonblock)
+void msm_atomic_commit_tail(struct drm_atomic_state *state)
{
+ struct drm_device *dev = state->dev;
struct msm_drm_private *priv = dev->dev_private;
- struct msm_commit *c;
- struct drm_crtc *crtc;
- struct drm_crtc_state *crtc_state;
- struct drm_plane *plane;
- struct drm_plane_state *old_plane_state, *new_plane_state;
- int i, ret;
-
- ret = drm_atomic_helper_prepare_planes(dev, state);
- if (ret)
- return ret;
-
- /*
- * Note that plane->atomic_async_check() should fail if we need
- * to re-assign hwpipe or anything that touches global atomic
- * state, so we'll never go down the async update path in those
- * cases.
- */
- if (state->async_update) {
- drm_atomic_helper_async_commit(dev, state);
- drm_atomic_helper_cleanup_planes(dev, state);
- return 0;
- }
-
- c = commit_init(state);
- if (!c) {
- ret = -ENOMEM;
- goto error;
- }
-
- /*
- * Figure out what crtcs we have:
- */
- for_each_new_crtc_in_state(state, crtc, crtc_state, i)
- c->crtc_mask |= drm_crtc_mask(crtc);
-
- /*
- * Figure out what fence to wait for:
- */
- for_each_oldnew_plane_in_state(state, plane, old_plane_state, new_plane_state, i) {
- if ((new_plane_state->fb != old_plane_state->fb) && new_plane_state->fb) {
- struct drm_gem_object *obj = msm_framebuffer_bo(new_plane_state->fb, 0);
- struct msm_gem_object *msm_obj = to_msm_bo(obj);
- struct dma_fence *fence = reservation_object_get_excl_rcu(msm_obj->resv);
+ struct msm_kms *kms = priv->kms;
- drm_atomic_set_fence_for_plane(new_plane_state, fence);
- }
- }
+ kms->funcs->prepare_commit(kms, state);
- /*
- * Wait for pending updates on any of the same crtc's and then
- * mark our set of crtc's as busy:
- */
- ret = start_atomic(dev->dev_private, c->crtc_mask);
- if (ret)
- goto err_free;
+ drm_atomic_helper_commit_modeset_disables(dev, state);
- BUG_ON(drm_atomic_helper_swap_state(state, false) < 0);
+ drm_atomic_helper_commit_planes(dev, state, 0);
- /*
- * This is the point of no return - everything below never fails except
- * when the hw goes bonghits. Which means we can commit the new state on
- * the software side now.
- *
- * swap driver private state while still holding state_lock
- */
- if (to_kms_state(state)->state)
- priv->kms->funcs->swap_state(priv->kms, state);
+ drm_atomic_helper_commit_modeset_enables(dev, state);
- /*
- * Everything below can be run asynchronously without the need to grab
- * any modeset locks at all under one conditions: It must be guaranteed
- * that the asynchronous work has either been cancelled (if the driver
- * supports it, which at least requires that the framebuffers get
- * cleaned up with drm_atomic_helper_cleanup_planes()) or completed
- * before the new state gets committed on the software side with
- * drm_atomic_helper_swap_state().
- *
- * This scheme allows new atomic state updates to be prepared and
- * checked in parallel to the asynchronous completion of the previous
- * update. Which is important since compositors need to figure out the
- * composition of the next frame right after having submitted the
- * current layout.
- */
+ msm_atomic_wait_for_commit_done(dev, state);
- drm_atomic_state_get(state);
- if (nonblock) {
- queue_work(priv->atomic_wq, &c->work);
- return 0;
- }
+ kms->funcs->complete_commit(kms, state);
- complete_commit(c, false);
+ drm_atomic_helper_wait_for_vblanks(dev, state);
- return 0;
+ drm_atomic_helper_commit_hw_done(state);
-err_free:
- kfree(c);
-error:
drm_atomic_helper_cleanup_planes(dev, state);
- return ret;
-}
-
-struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev)
-{
- struct msm_kms_state *state = kzalloc(sizeof(*state), GFP_KERNEL);
-
- if (!state || drm_atomic_state_init(dev, &state->base) < 0) {
- kfree(state);
- return NULL;
- }
-
- return &state->base;
-}
-
-void msm_atomic_state_clear(struct drm_atomic_state *s)
-{
- struct msm_kms_state *state = to_kms_state(s);
- drm_atomic_state_default_clear(&state->base);
- kfree(state->state);
- state->state = NULL;
-}
-
-void msm_atomic_state_free(struct drm_atomic_state *state)
-{
- kfree(to_kms_state(state)->state);
- drm_atomic_state_default_release(state);
- kfree(state);
}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 30cd514..021a0b6 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -41,10 +41,11 @@ static const struct drm_mode_config_funcs mode_config_funcs = {
.fb_create = msm_framebuffer_create,
.output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
- .atomic_commit = msm_atomic_commit,
- .atomic_state_alloc = msm_atomic_state_alloc,
- .atomic_state_clear = msm_atomic_state_clear,
- .atomic_state_free = msm_atomic_state_free,
+ .atomic_commit = drm_atomic_helper_commit,
+};
+
+static const struct drm_mode_config_helper_funcs mode_config_helper_funcs = {
+ .atomic_commit_tail = msm_atomic_commit_tail,
};
#ifdef CONFIG_DRM_MSM_REGISTER_LOGGING
@@ -384,7 +385,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
priv->wq = alloc_ordered_workqueue("msm", 0);
priv->atomic_wq = alloc_ordered_workqueue("msm:atomic", 0);
- init_waitqueue_head(&priv->pending_crtcs_event);
INIT_LIST_HEAD(&priv->inactive_list);
INIT_LIST_HEAD(&priv->vblank_ctrl.event_list);
@@ -442,6 +442,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
}
ddev->mode_config.funcs = &mode_config_funcs;
+ ddev->mode_config.helper_private = &mode_config_helper_funcs;
ret = drm_vblank_init(ddev, priv->num_crtcs);
if (ret < 0) {
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 48ed5b9..b2da1fb 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -117,10 +117,6 @@ struct msm_drm_private {
struct workqueue_struct *wq;
struct workqueue_struct *atomic_wq;
- /* crtcs pending async atomic updates: */
- uint32_t pending_crtcs;
- wait_queue_head_t pending_crtcs_event;
-
unsigned int num_planes;
struct drm_plane *planes[16];
@@ -160,8 +156,9 @@ struct msm_format {
uint32_t pixel_format;
};
-int msm_atomic_commit(struct drm_device *dev,
- struct drm_atomic_state *state, bool nonblock);
+int msm_atomic_prepare_fb(struct drm_plane *plane,
+ struct drm_plane_state *new_state);
+void msm_atomic_commit_tail(struct drm_atomic_state *state);
struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev);
void msm_atomic_state_clear(struct drm_atomic_state *state);
void msm_atomic_state_free(struct drm_atomic_state *state);
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index aaa329d..dfd9294 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -40,8 +40,6 @@ struct msm_kms_funcs {
irqreturn_t (*irq)(struct msm_kms *kms);
int (*enable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
void (*disable_vblank)(struct msm_kms *kms, struct drm_crtc *crtc);
- /* swap global atomic state: */
- void (*swap_state)(struct msm_kms *kms, struct drm_atomic_state *state);
/* modeset, bracketing atomic_commit(): */
void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
@@ -80,18 +78,6 @@ struct msm_kms {
struct msm_gem_address_space *aspace;
};
-/**
- * Subclass of drm_atomic_state, to allow kms backend to have driver
- * private global state. The kms backend can do whatever it wants
- * with the ->state ptr. On ->atomic_state_clear() the ->state ptr
- * is kfree'd and set back to NULL.
- */
-struct msm_kms_state {
- struct drm_atomic_state base;
- void *state;
-};
-#define to_kms_state(x) container_of(x, struct msm_kms_state, base)
-
static inline void msm_kms_init(struct msm_kms *kms,
const struct msm_kms_funcs *funcs)
{
diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c
index 291c081..397143b 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c
@@ -132,7 +132,7 @@ curs507a_new_(const struct nv50_wimm_func *func, struct nouveau_drm *drm,
nvif_object_map(&wndw->wimm.base.user, NULL, 0);
wndw->immd = func;
- wndw->ctxdma.parent = &disp->core->chan.base.user;
+ wndw->ctxdma.parent = NULL;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
index 224963b5..c5a9bc1 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c
@@ -444,14 +444,17 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state)
if (ret)
return ret;
- ctxdma = nv50_wndw_ctxdma_new(wndw, fb);
- if (IS_ERR(ctxdma)) {
- nouveau_bo_unpin(fb->nvbo);
- return PTR_ERR(ctxdma);
+ if (wndw->ctxdma.parent) {
+ ctxdma = nv50_wndw_ctxdma_new(wndw, fb);
+ if (IS_ERR(ctxdma)) {
+ nouveau_bo_unpin(fb->nvbo);
+ return PTR_ERR(ctxdma);
+ }
+
+ asyw->image.handle[0] = ctxdma->object.handle;
}
asyw->state.fence = reservation_object_get_excl_rcu(fb->nvbo->bo.resv);
- asyw->image.handle[0] = ctxdma->object.handle;
asyw->image.offset[0] = fb->nvbo->bo.offset;
if (wndw->func->prepare) {
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index 0906648..e721bb2 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -141,7 +141,7 @@ nv84_fence_suspend(struct nouveau_drm *drm)
struct nv84_fence_priv *priv = drm->fence;
int i;
- priv->suspend = vmalloc(drm->chan.nr * sizeof(u32));
+ priv->suspend = vmalloc(array_size(sizeof(u32), drm->chan.nr));
if (priv->suspend) {
for (i = 0; i < drm->chan.nr; i++)
priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4);
diff --git a/drivers/gpu/drm/nouveau/nvif/fifo.c b/drivers/gpu/drm/nouveau/nvif/fifo.c
index 99d4fd1..e84a2e2 100644
--- a/drivers/gpu/drm/nouveau/nvif/fifo.c
+++ b/drivers/gpu/drm/nouveau/nvif/fifo.c
@@ -50,8 +50,8 @@ nvif_fifo_runlists(struct nvif_device *device)
goto done;
device->runlists = fls64(a->v.runlists.data);
- device->runlist = kzalloc(sizeof(*device->runlist) *
- device->runlists, GFP_KERNEL);
+ device->runlist = kcalloc(device->runlists, sizeof(*device->runlist),
+ GFP_KERNEL);
if (!device->runlist) {
ret = -ENOMEM;
goto done;
diff --git a/drivers/gpu/drm/nouveau/nvif/mmu.c b/drivers/gpu/drm/nouveau/nvif/mmu.c
index 358ac4f..ae08a1c 100644
--- a/drivers/gpu/drm/nouveau/nvif/mmu.c
+++ b/drivers/gpu/drm/nouveau/nvif/mmu.c
@@ -65,12 +65,15 @@ nvif_mmu_init(struct nvif_object *parent, s32 oclass, struct nvif_mmu *mmu)
goto done;
mmu->mem = mems[ret].oclass;
- mmu->heap = kmalloc(sizeof(*mmu->heap) * mmu->heap_nr, GFP_KERNEL);
- mmu->type = kmalloc(sizeof(*mmu->type) * mmu->type_nr, GFP_KERNEL);
+ mmu->heap = kmalloc_array(mmu->heap_nr, sizeof(*mmu->heap),
+ GFP_KERNEL);
+ mmu->type = kmalloc_array(mmu->type_nr, sizeof(*mmu->type),
+ GFP_KERNEL);
if (ret = -ENOMEM, !mmu->heap || !mmu->type)
goto done;
- mmu->kind = kmalloc(sizeof(*mmu->kind) * mmu->kind_nr, GFP_KERNEL);
+ mmu->kind = kmalloc_array(mmu->kind_nr, sizeof(*mmu->kind),
+ GFP_KERNEL);
if (!mmu->kind && mmu->kind_nr)
goto done;
diff --git a/drivers/gpu/drm/nouveau/nvif/object.c b/drivers/gpu/drm/nouveau/nvif/object.c
index 40adfe9..ef3f6284 100644
--- a/drivers/gpu/drm/nouveau/nvif/object.c
+++ b/drivers/gpu/drm/nouveau/nvif/object.c
@@ -83,7 +83,7 @@ nvif_object_sclass_get(struct nvif_object *object, struct nvif_sclass **psclass)
return ret;
}
- *psclass = kzalloc(sizeof(**psclass) * args->sclass.count, GFP_KERNEL);
+ *psclass = kcalloc(args->sclass.count, sizeof(**psclass), GFP_KERNEL);
if (*psclass) {
for (i = 0; i < args->sclass.count; i++) {
(*psclass)[i].oclass = args->sclass.oclass[i].oclass;
diff --git a/drivers/gpu/drm/nouveau/nvif/vmm.c b/drivers/gpu/drm/nouveau/nvif/vmm.c
index 191832b..6b9c577 100644
--- a/drivers/gpu/drm/nouveau/nvif/vmm.c
+++ b/drivers/gpu/drm/nouveau/nvif/vmm.c
@@ -138,7 +138,8 @@ nvif_vmm_init(struct nvif_mmu *mmu, s32 oclass, u64 addr, u64 size,
vmm->limit = args->size;
vmm->page_nr = args->page_nr;
- vmm->page = kmalloc(sizeof(*vmm->page) * vmm->page_nr, GFP_KERNEL);
+ vmm->page = kmalloc_array(vmm->page_nr, sizeof(*vmm->page),
+ GFP_KERNEL);
if (!vmm->page) {
ret = -ENOMEM;
goto done;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/event.c b/drivers/gpu/drm/nouveau/nvkm/core/event.c
index 4e8d3fa..006618d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/event.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/event.c
@@ -84,7 +84,8 @@ int
nvkm_event_init(const struct nvkm_event_func *func, int types_nr, int index_nr,
struct nvkm_event *event)
{
- event->refs = kzalloc(sizeof(*event->refs) * index_nr * types_nr,
+ event->refs = kzalloc(array3_size(index_nr, types_nr,
+ sizeof(*event->refs)),
GFP_KERNEL);
if (!event->refs)
return -ENOMEM;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index a990464..afccf97 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -910,7 +910,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base)
nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr);
/* Read PBDMA->runlist(s) mapping from HW. */
- if (!(map = kzalloc(sizeof(*map) * fifo->pbdma_nr, GFP_KERNEL)))
+ if (!(map = kcalloc(fifo->pbdma_nr, sizeof(*map), GFP_KERNEL)))
return -ENOMEM;
for (i = 0; i < fifo->pbdma_nr; i++)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c
index 73e463e..dea444d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c
@@ -73,7 +73,8 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense)
}
iccsense->nr_entry = cnt;
- iccsense->rail = kmalloc(sizeof(struct pwr_rail_t) * cnt, GFP_KERNEL);
+ iccsense->rail = kmalloc_array(cnt, sizeof(struct pwr_rail_t),
+ GFP_KERNEL);
if (!iccsense->rail)
return -ENOMEM;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
index 920b3d3..bbfde1c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c
@@ -171,7 +171,7 @@ gt215_link_train(struct gt215_ram *ram)
return -ENOSYS;
/* XXX: Multiple partitions? */
- result = kmalloc(64 * sizeof(u32), GFP_KERNEL);
+ result = kmalloc_array(64, sizeof(u32), GFP_KERNEL);
if (!result)
return -ENOMEM;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c
index 3980848..92e363d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c
@@ -191,9 +191,9 @@ nvkm_mem_new_host(struct nvkm_mmu *mmu, int type, u8 page, u64 size,
nvkm_memory_ctor(&nvkm_mem_dma, &mem->memory);
size = ALIGN(size, PAGE_SIZE) >> PAGE_SHIFT;
- if (!(mem->mem = kvmalloc(sizeof(*mem->mem) * size, GFP_KERNEL)))
+ if (!(mem->mem = kvmalloc_array(size, sizeof(*mem->mem), GFP_KERNEL)))
return -ENOMEM;
- if (!(mem->dma = kvmalloc(sizeof(*mem->dma) * size, GFP_KERNEL)))
+ if (!(mem->dma = kvmalloc_array(size, sizeof(*mem->dma), GFP_KERNEL)))
return -ENOMEM;
if (mmu->dma_bits > 32)
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
index 1c12e58..de269eb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
@@ -59,7 +59,7 @@ nvkm_vmm_pt_new(const struct nvkm_vmm_desc *desc, bool sparse,
pgt->sparse = sparse;
if (desc->type == PGD) {
- pgt->pde = kvzalloc(sizeof(*pgt->pde) * pten, GFP_KERNEL);
+ pgt->pde = kvcalloc(pten, sizeof(*pgt->pde), GFP_KERNEL);
if (!pgt->pde) {
kfree(pgt);
return NULL;
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
index 401c02e..f92fe20 100644
--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
+++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
@@ -940,8 +940,8 @@ int tiler_map_show(struct seq_file *s, void *arg)
h_adj = omap_dmm->container_height / ydiv;
w_adj = omap_dmm->container_width / xdiv;
- map = kmalloc(h_adj * sizeof(*map), GFP_KERNEL);
- global_map = kmalloc((w_adj + 1) * h_adj, GFP_KERNEL);
+ map = kmalloc_array(h_adj, sizeof(*map), GFP_KERNEL);
+ global_map = kmalloc_array(w_adj + 1, h_adj, GFP_KERNEL);
if (!map || !global_map)
goto error;
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index 0faf042..17a53d2 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -244,7 +244,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
* DSS, GPU, etc. are not cache coherent:
*/
if (omap_obj->flags & (OMAP_BO_WC|OMAP_BO_UNCACHED)) {
- addrs = kmalloc(npages * sizeof(*addrs), GFP_KERNEL);
+ addrs = kmalloc_array(npages, sizeof(*addrs), GFP_KERNEL);
if (!addrs) {
ret = -ENOMEM;
goto free_pages;
@@ -268,7 +268,7 @@ static int omap_gem_attach_pages(struct drm_gem_object *obj)
}
}
} else {
- addrs = kzalloc(npages * sizeof(*addrs), GFP_KERNEL);
+ addrs = kcalloc(npages, sizeof(*addrs), GFP_KERNEL);
if (!addrs) {
ret = -ENOMEM;
goto free_pages;
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index b8cda94..768207f 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -623,7 +623,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
struct qxl_cursor_cmd *cmd;
struct qxl_cursor *cursor;
struct drm_gem_object *obj;
- struct qxl_bo *cursor_bo = NULL, *user_bo = NULL;
+ struct qxl_bo *cursor_bo = NULL, *user_bo = NULL, *old_cursor_bo = NULL;
int ret;
void *user_ptr;
int size = 64*64*4;
@@ -677,7 +677,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
cursor_bo, 0);
cmd->type = QXL_CURSOR_SET;
- qxl_bo_unref(&qcrtc->cursor_bo);
+ old_cursor_bo = qcrtc->cursor_bo;
qcrtc->cursor_bo = cursor_bo;
cursor_bo = NULL;
} else {
@@ -697,6 +697,9 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false);
qxl_release_fence_buffer_objects(release);
+ if (old_cursor_bo)
+ qxl_bo_unref(&old_cursor_bo);
+
qxl_bo_unref(&cursor_bo);
return;
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c
index 9a67526..ca465c0 100644
--- a/drivers/gpu/drm/qxl/qxl_fb.c
+++ b/drivers/gpu/drm/qxl/qxl_fb.c
@@ -241,7 +241,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
DRM_DEBUG_DRIVER("%dx%d %d\n", mode_cmd.width,
mode_cmd.height, mode_cmd.pitches[0]);
- shadow = vmalloc(mode_cmd.pitches[0] * mode_cmd.height);
+ shadow = vmalloc(array_size(mode_cmd.pitches[0], mode_cmd.height));
/* TODO: what's the usual response to memory allocation errors? */
BUG_ON(!shadow);
DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n",
diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c
index c5716a0..771250a 100644
--- a/drivers/gpu/drm/qxl/qxl_kms.c
+++ b/drivers/gpu/drm/qxl/qxl_kms.c
@@ -200,8 +200,8 @@ int qxl_device_init(struct qxl_device *qdev,
(~(uint64_t)0) >> (qdev->slot_id_bits + qdev->slot_gen_bits);
qdev->mem_slots =
- kmalloc(qdev->n_mem_slots * sizeof(struct qxl_memslot),
- GFP_KERNEL);
+ kmalloc_array(qdev->n_mem_slots, sizeof(struct qxl_memslot),
+ GFP_KERNEL);
idr_init(&qdev->release_idr);
spin_lock_init(&qdev->release_idr_lock);
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c
index 6a2e091..e55cbee 100644
--- a/drivers/gpu/drm/radeon/atom.c
+++ b/drivers/gpu/drm/radeon/atom.c
@@ -1176,7 +1176,7 @@ static int atom_execute_table_locked(struct atom_context *ctx, int index, uint32
ectx.abort = false;
ectx.last_jump = 0;
if (ws)
- ectx.ws = kzalloc(4 * ws, GFP_KERNEL);
+ ectx.ws = kcalloc(4, ws, GFP_KERNEL);
else
ectx.ws = NULL;
diff --git a/drivers/gpu/drm/radeon/btc_dpm.c b/drivers/gpu/drm/radeon/btc_dpm.c
index 95652e6..0aef493 100644
--- a/drivers/gpu/drm/radeon/btc_dpm.c
+++ b/drivers/gpu/drm/radeon/btc_dpm.c
@@ -2581,7 +2581,9 @@ int btc_dpm_init(struct radeon_device *rdev)
return ret;
rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
- kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL);
+ kcalloc(4,
+ sizeof(struct radeon_clock_voltage_dependency_entry),
+ GFP_KERNEL);
if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
r600_free_extended_power_table(rdev);
return -ENOMEM;
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index 7e1b04d..b9302c9 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -5568,8 +5568,9 @@ static int ci_parse_power_table(struct radeon_device *rdev)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
- rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
- state_array->ucNumEntries, GFP_KERNEL);
+ rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
+ sizeof(struct radeon_ps),
+ GFP_KERNEL);
if (!rdev->pm.dpm.ps)
return -ENOMEM;
power_state_offset = (u8 *)state_array->states;
@@ -5770,7 +5771,9 @@ int ci_dpm_init(struct radeon_device *rdev)
ci_set_private_data_variables_based_on_pptable(rdev);
rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
- kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL);
+ kcalloc(4,
+ sizeof(struct radeon_clock_voltage_dependency_entry),
+ GFP_KERNEL);
if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
ci_dpm_fini(rdev);
return -ENOMEM;
diff --git a/drivers/gpu/drm/radeon/kv_dpm.c b/drivers/gpu/drm/radeon/kv_dpm.c
index ae1529b..f055d6e 100644
--- a/drivers/gpu/drm/radeon/kv_dpm.c
+++ b/drivers/gpu/drm/radeon/kv_dpm.c
@@ -2660,8 +2660,9 @@ static int kv_parse_power_table(struct radeon_device *rdev)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
- rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
- state_array->ucNumEntries, GFP_KERNEL);
+ rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
+ sizeof(struct radeon_ps),
+ GFP_KERNEL);
if (!rdev->pm.dpm.ps)
return -ENOMEM;
power_state_offset = (u8 *)state_array->states;
diff --git a/drivers/gpu/drm/radeon/ni_dpm.c b/drivers/gpu/drm/radeon/ni_dpm.c
index 9416e72..0fd8d6b 100644
--- a/drivers/gpu/drm/radeon/ni_dpm.c
+++ b/drivers/gpu/drm/radeon/ni_dpm.c
@@ -3998,8 +3998,9 @@ static int ni_parse_power_table(struct radeon_device *rdev)
return -EINVAL;
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
- rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
- power_info->pplib.ucNumStates, GFP_KERNEL);
+ rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates,
+ sizeof(struct radeon_ps),
+ GFP_KERNEL);
if (!rdev->pm.dpm.ps)
return -ENOMEM;
@@ -4075,7 +4076,9 @@ int ni_dpm_init(struct radeon_device *rdev)
return ret;
rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
- kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL);
+ kcalloc(4,
+ sizeof(struct radeon_clock_voltage_dependency_entry),
+ GFP_KERNEL);
if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
r600_free_extended_power_table(rdev);
return -ENOMEM;
diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c
index 31d1b47..73d4c53 100644
--- a/drivers/gpu/drm/radeon/r600_dpm.c
+++ b/drivers/gpu/drm/radeon/r600_dpm.c
@@ -991,7 +991,7 @@ int r600_parse_extended_power_table(struct radeon_device *rdev)
ATOM_PPLIB_PhaseSheddingLimits_Record *entry;
rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries =
- kzalloc(psl->ucNumEntries *
+ kcalloc(psl->ucNumEntries,
sizeof(struct radeon_phase_shedding_limits_entry),
GFP_KERNEL);
if (!rdev->pm.dpm.dyn_state.phase_shedding_limits_table.entries) {
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 4134759..f422a8d 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -2126,13 +2126,16 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK;
if (num_modes == 0)
return state_index;
- rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL);
+ rdev->pm.power_state = kcalloc(num_modes,
+ sizeof(struct radeon_power_state),
+ GFP_KERNEL);
if (!rdev->pm.power_state)
return state_index;
/* last mode is usually default, array is low to high */
for (i = 0; i < num_modes; i++) {
rdev->pm.power_state[state_index].clock_info =
- kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+ kcalloc(1, sizeof(struct radeon_pm_clock_info),
+ GFP_KERNEL);
if (!rdev->pm.power_state[state_index].clock_info)
return state_index;
rdev->pm.power_state[state_index].num_clock_modes = 1;
@@ -2587,8 +2590,9 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController);
if (power_info->pplib.ucNumStates == 0)
return state_index;
- rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
- power_info->pplib.ucNumStates, GFP_KERNEL);
+ rdev->pm.power_state = kcalloc(power_info->pplib.ucNumStates,
+ sizeof(struct radeon_power_state),
+ GFP_KERNEL);
if (!rdev->pm.power_state)
return state_index;
/* first mode is usually default, followed by low to high */
@@ -2603,10 +2607,11 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
(power_state->v1.ucNonClockStateIndex *
power_info->pplib.ucNonClockSize));
- rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
- ((power_info->pplib.ucStateEntrySize - 1) ?
- (power_info->pplib.ucStateEntrySize - 1) : 1),
- GFP_KERNEL);
+ rdev->pm.power_state[i].clock_info =
+ kcalloc((power_info->pplib.ucStateEntrySize - 1) ?
+ (power_info->pplib.ucStateEntrySize - 1) : 1,
+ sizeof(struct radeon_pm_clock_info),
+ GFP_KERNEL);
if (!rdev->pm.power_state[i].clock_info)
return state_index;
if (power_info->pplib.ucStateEntrySize - 1) {
@@ -2688,8 +2693,9 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
if (state_array->ucNumEntries == 0)
return state_index;
- rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) *
- state_array->ucNumEntries, GFP_KERNEL);
+ rdev->pm.power_state = kcalloc(state_array->ucNumEntries,
+ sizeof(struct radeon_power_state),
+ GFP_KERNEL);
if (!rdev->pm.power_state)
return state_index;
power_state_offset = (u8 *)state_array->states;
@@ -2699,10 +2705,11 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
non_clock_array_index = power_state->v2.nonClockInfoIndex;
non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
&non_clock_info_array->nonClockInfo[non_clock_array_index];
- rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
- (power_state->v2.ucNumDPMLevels ?
- power_state->v2.ucNumDPMLevels : 1),
- GFP_KERNEL);
+ rdev->pm.power_state[i].clock_info =
+ kcalloc(power_state->v2.ucNumDPMLevels ?
+ power_state->v2.ucNumDPMLevels : 1,
+ sizeof(struct radeon_pm_clock_info),
+ GFP_KERNEL);
if (!rdev->pm.power_state[i].clock_info)
return state_index;
if (power_state->v2.ucNumDPMLevels) {
@@ -2782,7 +2789,9 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL);
if (rdev->pm.power_state) {
rdev->pm.power_state[0].clock_info =
- kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+ kcalloc(1,
+ sizeof(struct radeon_pm_clock_info),
+ GFP_KERNEL);
if (rdev->pm.power_state[0].clock_info) {
/* add the default mode */
rdev->pm.power_state[state_index].type =
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 3178ba0..60a61d3 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -2642,13 +2642,16 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
rdev->pm.default_power_state_index = -1;
/* allocate 2 power states */
- rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * 2, GFP_KERNEL);
+ rdev->pm.power_state = kcalloc(2, sizeof(struct radeon_power_state),
+ GFP_KERNEL);
if (rdev->pm.power_state) {
/* allocate 1 clock mode per state */
rdev->pm.power_state[0].clock_info =
- kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+ kcalloc(1, sizeof(struct radeon_pm_clock_info),
+ GFP_KERNEL);
rdev->pm.power_state[1].clock_info =
- kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+ kcalloc(1, sizeof(struct radeon_pm_clock_info),
+ GFP_KERNEL);
if (!rdev->pm.power_state[0].clock_info ||
!rdev->pm.power_state[1].clock_info)
goto pm_failed;
diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c
index 0b3ec35..1cef155 100644
--- a/drivers/gpu/drm/radeon/radeon_gart.c
+++ b/drivers/gpu/drm/radeon/radeon_gart.c
@@ -347,13 +347,14 @@ int radeon_gart_init(struct radeon_device *rdev)
DRM_INFO("GART: num cpu pages %u, num gpu pages %u\n",
rdev->gart.num_cpu_pages, rdev->gart.num_gpu_pages);
/* Allocate pages table */
- rdev->gart.pages = vzalloc(sizeof(void *) * rdev->gart.num_cpu_pages);
+ rdev->gart.pages = vzalloc(array_size(sizeof(void *),
+ rdev->gart.num_cpu_pages));
if (rdev->gart.pages == NULL) {
radeon_gart_fini(rdev);
return -ENOMEM;
}
- rdev->gart.pages_entry = vmalloc(sizeof(uint64_t) *
- rdev->gart.num_gpu_pages);
+ rdev->gart.pages_entry = vmalloc(array_size(sizeof(uint64_t),
+ rdev->gart.num_gpu_pages));
if (rdev->gart.pages_entry == NULL) {
radeon_gart_fini(rdev);
return -ENOMEM;
diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c
index f5e9abf..48f4b27 100644
--- a/drivers/gpu/drm/radeon/radeon_test.c
+++ b/drivers/gpu/drm/radeon/radeon_test.c
@@ -59,7 +59,7 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag)
n = rdev->mc.gtt_size - rdev->gart_pin_size;
n /= size;
- gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
+ gtt_obj = kcalloc(n, sizeof(*gtt_obj), GFP_KERNEL);
if (!gtt_obj) {
DRM_ERROR("Failed to allocate %d pointers\n", n);
r = 1;
diff --git a/drivers/gpu/drm/radeon/rs780_dpm.c b/drivers/gpu/drm/radeon/rs780_dpm.c
index b5e4e09..694b7b3 100644
--- a/drivers/gpu/drm/radeon/rs780_dpm.c
+++ b/drivers/gpu/drm/radeon/rs780_dpm.c
@@ -804,8 +804,9 @@ static int rs780_parse_power_table(struct radeon_device *rdev)
return -EINVAL;
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
- rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
- power_info->pplib.ucNumStates, GFP_KERNEL);
+ rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates,
+ sizeof(struct radeon_ps),
+ GFP_KERNEL);
if (!rdev->pm.dpm.ps)
return -ENOMEM;
diff --git a/drivers/gpu/drm/radeon/rv6xx_dpm.c b/drivers/gpu/drm/radeon/rv6xx_dpm.c
index d91aa39..6986051 100644
--- a/drivers/gpu/drm/radeon/rv6xx_dpm.c
+++ b/drivers/gpu/drm/radeon/rv6xx_dpm.c
@@ -1888,8 +1888,9 @@ static int rv6xx_parse_power_table(struct radeon_device *rdev)
return -EINVAL;
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
- rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
- power_info->pplib.ucNumStates, GFP_KERNEL);
+ rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates,
+ sizeof(struct radeon_ps),
+ GFP_KERNEL);
if (!rdev->pm.dpm.ps)
return -ENOMEM;
diff --git a/drivers/gpu/drm/radeon/rv770_dpm.c b/drivers/gpu/drm/radeon/rv770_dpm.c
index cb2a7ec..c765ae7 100644
--- a/drivers/gpu/drm/radeon/rv770_dpm.c
+++ b/drivers/gpu/drm/radeon/rv770_dpm.c
@@ -2282,8 +2282,9 @@ int rv7xx_parse_power_table(struct radeon_device *rdev)
return -EINVAL;
power_info = (union power_info *)(mode_info->atom_context->bios + data_offset);
- rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
- power_info->pplib.ucNumStates, GFP_KERNEL);
+ rdev->pm.dpm.ps = kcalloc(power_info->pplib.ucNumStates,
+ sizeof(struct radeon_ps),
+ GFP_KERNEL);
if (!rdev->pm.dpm.ps)
return -ENOMEM;
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c
index 90d5b41..fea8807 100644
--- a/drivers/gpu/drm/radeon/si_dpm.c
+++ b/drivers/gpu/drm/radeon/si_dpm.c
@@ -6832,8 +6832,9 @@ static int si_parse_power_table(struct radeon_device *rdev)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
- rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
- state_array->ucNumEntries, GFP_KERNEL);
+ rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
+ sizeof(struct radeon_ps),
+ GFP_KERNEL);
if (!rdev->pm.dpm.ps)
return -ENOMEM;
power_state_offset = (u8 *)state_array->states;
@@ -6941,7 +6942,9 @@ int si_dpm_init(struct radeon_device *rdev)
return ret;
rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries =
- kzalloc(4 * sizeof(struct radeon_clock_voltage_dependency_entry), GFP_KERNEL);
+ kcalloc(4,
+ sizeof(struct radeon_clock_voltage_dependency_entry),
+ GFP_KERNEL);
if (!rdev->pm.dpm.dyn_state.vddc_dependency_on_dispclk.entries) {
r600_free_extended_power_table(rdev);
return -ENOMEM;
diff --git a/drivers/gpu/drm/radeon/sumo_dpm.c b/drivers/gpu/drm/radeon/sumo_dpm.c
index fd48048..1e4975f 100644
--- a/drivers/gpu/drm/radeon/sumo_dpm.c
+++ b/drivers/gpu/drm/radeon/sumo_dpm.c
@@ -1482,8 +1482,9 @@ static int sumo_parse_power_table(struct radeon_device *rdev)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
- rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
- state_array->ucNumEntries, GFP_KERNEL);
+ rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
+ sizeof(struct radeon_ps),
+ GFP_KERNEL);
if (!rdev->pm.dpm.ps)
return -ENOMEM;
power_state_offset = (u8 *)state_array->states;
diff --git a/drivers/gpu/drm/radeon/trinity_dpm.c b/drivers/gpu/drm/radeon/trinity_dpm.c
index 2ef7c4e..5d317f7 100644
--- a/drivers/gpu/drm/radeon/trinity_dpm.c
+++ b/drivers/gpu/drm/radeon/trinity_dpm.c
@@ -1757,8 +1757,9 @@ static int trinity_parse_power_table(struct radeon_device *rdev)
(mode_info->atom_context->bios + data_offset +
le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset));
- rdev->pm.dpm.ps = kzalloc(sizeof(struct radeon_ps) *
- state_array->ucNumEntries, GFP_KERNEL);
+ rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries,
+ sizeof(struct radeon_ps),
+ GFP_KERNEL);
if (!rdev->pm.dpm.ps)
return -ENOMEM;
power_state_offset = (u8 *)state_array->states;
diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c
index 2a5b846..35dc748 100644
--- a/drivers/gpu/drm/savage/savage_bci.c
+++ b/drivers/gpu/drm/savage/savage_bci.c
@@ -298,8 +298,9 @@ static int savage_dma_init(drm_savage_private_t * dev_priv)
dev_priv->nr_dma_pages = dev_priv->cmd_dma->size /
(SAVAGE_DMA_PAGE_SIZE * 4);
- dev_priv->dma_pages = kmalloc(sizeof(drm_savage_dma_page_t) *
- dev_priv->nr_dma_pages, GFP_KERNEL);
+ dev_priv->dma_pages = kmalloc_array(dev_priv->nr_dma_pages,
+ sizeof(drm_savage_dma_page_t),
+ GFP_KERNEL);
if (dev_priv->dma_pages == NULL)
return -ENOMEM;
diff --git a/drivers/gpu/drm/scheduler/gpu_scheduler.c b/drivers/gpu/drm/scheduler/gpu_scheduler.c
index df1578d..44d4807 100644
--- a/drivers/gpu/drm/scheduler/gpu_scheduler.c
+++ b/drivers/gpu/drm/scheduler/gpu_scheduler.c
@@ -349,8 +349,13 @@ static bool drm_sched_entity_add_dependency_cb(struct drm_sched_entity *entity)
struct dma_fence * fence = entity->dependency;
struct drm_sched_fence *s_fence;
- if (fence->context == entity->fence_context) {
- /* We can ignore fences from ourself */
+ if (fence->context == entity->fence_context ||
+ fence->context == entity->fence_context + 1) {
+ /*
+ * Fence is a scheduled/finished fence from a job
+ * which belongs to the same entity, we can ignore
+ * fences from ourself
+ */
dma_fence_put(entity->dependency);
return false;
}
diff --git a/drivers/gpu/drm/selftests/test-drm_mm.c b/drivers/gpu/drm/selftests/test-drm_mm.c
index 7cc935d..933af1c 100644
--- a/drivers/gpu/drm/selftests/test-drm_mm.c
+++ b/drivers/gpu/drm/selftests/test-drm_mm.c
@@ -389,7 +389,7 @@ static int __igt_reserve(unsigned int count, u64 size)
if (!order)
goto err;
- nodes = vzalloc(sizeof(*nodes) * count);
+ nodes = vzalloc(array_size(count, sizeof(*nodes)));
if (!nodes)
goto err_order;
@@ -579,7 +579,7 @@ static int __igt_insert(unsigned int count, u64 size, bool replace)
DRM_MM_BUG_ON(!size);
ret = -ENOMEM;
- nodes = vmalloc(count * sizeof(*nodes));
+ nodes = vmalloc(array_size(count, sizeof(*nodes)));
if (!nodes)
goto err;
@@ -889,7 +889,7 @@ static int __igt_insert_range(unsigned int count, u64 size, u64 start, u64 end)
*/
ret = -ENOMEM;
- nodes = vzalloc(count * sizeof(*nodes));
+ nodes = vzalloc(array_size(count, sizeof(*nodes)));
if (!nodes)
goto err;
@@ -1046,7 +1046,7 @@ static int igt_align(void *ignored)
* meets our requirements.
*/
- nodes = vzalloc(max_count * sizeof(*nodes));
+ nodes = vzalloc(array_size(max_count, sizeof(*nodes)));
if (!nodes)
goto err;
@@ -1416,7 +1416,7 @@ static int igt_evict(void *ignored)
*/
ret = -ENOMEM;
- nodes = vzalloc(size * sizeof(*nodes));
+ nodes = vzalloc(array_size(size, sizeof(*nodes)));
if (!nodes)
goto err;
@@ -1526,7 +1526,7 @@ static int igt_evict_range(void *ignored)
*/
ret = -ENOMEM;
- nodes = vzalloc(size * sizeof(*nodes));
+ nodes = vzalloc(array_size(size, sizeof(*nodes)));
if (!nodes)
goto err;
@@ -1627,11 +1627,11 @@ static int igt_topdown(void *ignored)
*/
ret = -ENOMEM;
- nodes = vzalloc(count * sizeof(*nodes));
+ nodes = vzalloc(array_size(count, sizeof(*nodes)));
if (!nodes)
goto err;
- bitmap = kzalloc(count / BITS_PER_LONG * sizeof(unsigned long),
+ bitmap = kcalloc(count / BITS_PER_LONG, sizeof(unsigned long),
GFP_KERNEL);
if (!bitmap)
goto err_nodes;
@@ -1741,11 +1741,11 @@ static int igt_bottomup(void *ignored)
*/
ret = -ENOMEM;
- nodes = vzalloc(count * sizeof(*nodes));
+ nodes = vzalloc(array_size(count, sizeof(*nodes)));
if (!nodes)
goto err;
- bitmap = kzalloc(count / BITS_PER_LONG * sizeof(unsigned long),
+ bitmap = kcalloc(count / BITS_PER_LONG, sizeof(unsigned long),
GFP_KERNEL);
if (!bitmap)
goto err_nodes;
@@ -2098,7 +2098,7 @@ static int igt_color_evict(void *ignored)
*/
ret = -ENOMEM;
- nodes = vzalloc(total_size * sizeof(*nodes));
+ nodes = vzalloc(array_size(total_size, sizeof(*nodes)));
if (!nodes)
goto err;
@@ -2199,7 +2199,7 @@ static int igt_color_evict_range(void *ignored)
*/
ret = -ENOMEM;
- nodes = vzalloc(total_size * sizeof(*nodes));
+ nodes = vzalloc(array_size(total_size, sizeof(*nodes)));
if (!nodes)
goto err;
diff --git a/drivers/gpu/drm/shmobile/Kconfig b/drivers/gpu/drm/shmobile/Kconfig
index c987c82..0426d66 100644
--- a/drivers/gpu/drm/shmobile/Kconfig
+++ b/drivers/gpu/drm/shmobile/Kconfig
@@ -2,7 +2,6 @@ config DRM_SHMOBILE
tristate "DRM Support for SH Mobile"
depends on DRM && ARM
depends on ARCH_SHMOBILE || COMPILE_TEST
- depends on FB_SH_MOBILE_MERAM || !FB_SH_MOBILE_MERAM
select BACKLIGHT_CLASS_DEVICE
select BACKLIGHT_LCD_SUPPORT
select DRM_KMS_HELPER
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index e773893..40df888 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -21,8 +21,6 @@
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_plane_helper.h>
-#include <video/sh_mobile_meram.h>
-
#include "shmob_drm_backlight.h"
#include "shmob_drm_crtc.h"
#include "shmob_drm_drv.h"
@@ -47,20 +45,12 @@ static int shmob_drm_clk_on(struct shmob_drm_device *sdev)
if (ret < 0)
return ret;
}
-#if 0
- if (sdev->meram_dev && sdev->meram_dev->pdev)
- pm_runtime_get_sync(&sdev->meram_dev->pdev->dev);
-#endif
return 0;
}
static void shmob_drm_clk_off(struct shmob_drm_device *sdev)
{
-#if 0
- if (sdev->meram_dev && sdev->meram_dev->pdev)
- pm_runtime_put_sync(&sdev->meram_dev->pdev->dev);
-#endif
if (sdev->clock)
clk_disable_unprepare(sdev->clock);
}
@@ -269,12 +259,6 @@ static void shmob_drm_crtc_stop(struct shmob_drm_crtc *scrtc)
if (!scrtc->started)
return;
- /* Disable the MERAM cache. */
- if (scrtc->cache) {
- sh_mobile_meram_cache_free(sdev->meram, scrtc->cache);
- scrtc->cache = NULL;
- }
-
/* Stop the LCDC. */
shmob_drm_crtc_start_stop(scrtc, false);
@@ -305,7 +289,6 @@ static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc,
{
struct drm_crtc *crtc = &scrtc->crtc;
struct drm_framebuffer *fb = crtc->primary->fb;
- struct shmob_drm_device *sdev = crtc->dev->dev_private;
struct drm_gem_cma_object *gem;
unsigned int bpp;
@@ -321,11 +304,6 @@ static void shmob_drm_crtc_compute_base(struct shmob_drm_crtc *scrtc,
+ y / (bpp == 4 ? 2 : 1) * fb->pitches[1]
+ x * (bpp == 16 ? 2 : 1);
}
-
- if (scrtc->cache)
- sh_mobile_meram_cache_update(sdev->meram, scrtc->cache,
- scrtc->dma[0], scrtc->dma[1],
- &scrtc->dma[0], &scrtc->dma[1]);
}
static void shmob_drm_crtc_update_base(struct shmob_drm_crtc *scrtc)
@@ -372,9 +350,7 @@ static int shmob_drm_crtc_mode_set(struct drm_crtc *crtc,
{
struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
struct shmob_drm_device *sdev = crtc->dev->dev_private;
- const struct sh_mobile_meram_cfg *mdata = sdev->pdata->meram;
const struct shmob_drm_format_info *format;
- void *cache;
format = shmob_drm_format_info(crtc->primary->fb->format->format);
if (format == NULL) {
@@ -386,24 +362,6 @@ static int shmob_drm_crtc_mode_set(struct drm_crtc *crtc,
scrtc->format = format;
scrtc->line_size = crtc->primary->fb->pitches[0];
- if (sdev->meram) {
- /* Enable MERAM cache if configured. We need to de-init
- * configured ICBs before we can re-initialize them.
- */
- if (scrtc->cache) {
- sh_mobile_meram_cache_free(sdev->meram, scrtc->cache);
- scrtc->cache = NULL;
- }
-
- cache = sh_mobile_meram_cache_alloc(sdev->meram, mdata,
- crtc->primary->fb->pitches[0],
- adjusted_mode->vdisplay,
- format->meram,
- &scrtc->line_size);
- if (!IS_ERR(cache))
- scrtc->cache = cache;
- }
-
shmob_drm_crtc_compute_base(scrtc, x, y);
return 0;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
index f152973..c11f421 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h
@@ -28,7 +28,6 @@ struct shmob_drm_crtc {
int dpms;
const struct shmob_drm_format_info *format;
- void *cache;
unsigned long dma[2];
unsigned int line_size;
bool started;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.h b/drivers/gpu/drm/shmobile/shmob_drm_drv.h
index 02ea315..088a6e55 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_drv.h
+++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.h
@@ -23,7 +23,6 @@
struct clk;
struct device;
struct drm_device;
-struct sh_mobile_meram_info;
struct shmob_drm_device {
struct device *dev;
@@ -31,7 +30,6 @@ struct shmob_drm_device {
void __iomem *mmio;
struct clk *clock;
- struct sh_mobile_meram_info *meram;
u32 lddckr;
u32 ldmt1r;
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.c b/drivers/gpu/drm/shmobile/shmob_drm_kms.c
index d36919b..4476385 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_kms.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_kms.c
@@ -18,8 +18,6 @@
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <video/sh_mobile_meram.h>
-
#include "shmob_drm_crtc.h"
#include "shmob_drm_drv.h"
#include "shmob_drm_kms.h"
@@ -35,55 +33,46 @@ static const struct shmob_drm_format_info shmob_drm_format_infos[] = {
.bpp = 16,
.yuv = false,
.lddfr = LDDFR_PKF_RGB16,
- .meram = SH_MOBILE_MERAM_PF_RGB,
}, {
.fourcc = DRM_FORMAT_RGB888,
.bpp = 24,
.yuv = false,
.lddfr = LDDFR_PKF_RGB24,
- .meram = SH_MOBILE_MERAM_PF_RGB,
}, {
.fourcc = DRM_FORMAT_ARGB8888,
.bpp = 32,
.yuv = false,
.lddfr = LDDFR_PKF_ARGB32,
- .meram = SH_MOBILE_MERAM_PF_RGB,
}, {
.fourcc = DRM_FORMAT_NV12,
.bpp = 12,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_420,
- .meram = SH_MOBILE_MERAM_PF_NV,
}, {
.fourcc = DRM_FORMAT_NV21,
.bpp = 12,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_420,
- .meram = SH_MOBILE_MERAM_PF_NV,
}, {
.fourcc = DRM_FORMAT_NV16,
.bpp = 16,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_422,
- .meram = SH_MOBILE_MERAM_PF_NV,
}, {
.fourcc = DRM_FORMAT_NV61,
.bpp = 16,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_422,
- .meram = SH_MOBILE_MERAM_PF_NV,
}, {
.fourcc = DRM_FORMAT_NV24,
.bpp = 24,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_444,
- .meram = SH_MOBILE_MERAM_PF_NV24,
}, {
.fourcc = DRM_FORMAT_NV42,
.bpp = 24,
.yuv = true,
.lddfr = LDDFR_CC | LDDFR_YF_444,
- .meram = SH_MOBILE_MERAM_PF_NV24,
},
};
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.h b/drivers/gpu/drm/shmobile/shmob_drm_kms.h
index 06d5b7c..753e281 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_kms.h
+++ b/drivers/gpu/drm/shmobile/shmob_drm_kms.h
@@ -24,7 +24,6 @@ struct shmob_drm_format_info {
unsigned int bpp;
bool yuv;
u32 lddfr;
- unsigned int meram;
};
const struct shmob_drm_format_info *shmob_drm_format_info(u32 fourcc);
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c
index 97f6e4a..1d0359f 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c
@@ -17,8 +17,6 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
-#include <video/sh_mobile_meram.h>
-
#include "shmob_drm_drv.h"
#include "shmob_drm_kms.h"
#include "shmob_drm_plane.h"
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 08747fc..8232b39 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -17,7 +17,6 @@
#include <drm/drm_encoder.h>
#include <drm/drm_modes.h>
#include <drm/drm_of.h>
-#include <drm/drm_panel.h>
#include <uapi/drm/drm_mode.h>
@@ -418,9 +417,6 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
const struct drm_display_mode *mode)
{
- struct drm_panel *panel = tcon->panel;
- struct drm_connector *connector = panel->connector;
- struct drm_display_info display_info = connector->display_info;
unsigned int bp, hsync, vsync;
u8 clk_delay;
u32 val = 0;
@@ -478,27 +474,6 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
if (mode->flags & DRM_MODE_FLAG_PVSYNC)
val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
- /*
- * On A20 and similar SoCs, the only way to achieve Positive Edge
- * (Rising Edge), is setting dclk clock phase to 2/3(240°).
- * By default TCON works in Negative Edge(Falling Edge),
- * this is why phase is set to 0 in that case.
- * Unfortunately there's no way to logically invert dclk through
- * IO_POL register.
- * The only acceptable way to work, triple checked with scope,
- * is using clock phase set to 0° for Negative Edge and set to 240°
- * for Positive Edge.
- * On A33 and similar SoCs there would be a 90° phase option,
- * but it divides also dclk by 2.
- * Following code is a way to avoid quirks all around TCON
- * and DOTCLOCK drivers.
- */
- if (display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_POSEDGE)
- clk_set_phase(tcon->dclk, 240);
-
- if (display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
- clk_set_phase(tcon->dclk, 0);
-
regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | SUN4I_TCON0_IO_POL_VSYNC_POSITIVE,
val);
diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c
index 1ee6855..50a1d42 100644
--- a/drivers/gpu/drm/tinydrm/repaper.c
+++ b/drivers/gpu/drm/tinydrm/repaper.c
@@ -548,7 +548,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb,
DRM_DEBUG("Flushing [FB:%d] st=%ums\n", fb->base.id,
epd->factored_stage_time);
- buf = kmalloc(fb->width * fb->height, GFP_KERNEL);
+ buf = kmalloc_array(fb->width, fb->height, GFP_KERNEL);
if (!buf)
return -ENOMEM;
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c
index 06c94e3..6e2d130 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c
@@ -348,8 +348,9 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free,
if (use_static)
pages_to_free = static_buf;
else
- pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
- GFP_KERNEL);
+ pages_to_free = kmalloc_array(npages_to_free,
+ sizeof(struct page *),
+ GFP_KERNEL);
if (!pages_to_free) {
pr_debug("Failed to allocate memory for pool free operation\n");
return 0;
@@ -547,7 +548,8 @@ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags,
unsigned max_cpages = min(count << order, (unsigned)NUM_PAGES_TO_ALLOC);
/* allocate array for page caching change */
- caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL);
+ caching_array = kmalloc_array(max_cpages, sizeof(struct page *),
+ GFP_KERNEL);
if (!caching_array) {
pr_debug("Unable to allocate table for new pages\n");
diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
index f63d99c..3f14c1c 100644
--- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
+++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
@@ -463,8 +463,9 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free,
if (use_static)
pages_to_free = static_buf;
else
- pages_to_free = kmalloc(npages_to_free * sizeof(struct page *),
- GFP_KERNEL);
+ pages_to_free = kmalloc_array(npages_to_free,
+ sizeof(struct page *),
+ GFP_KERNEL);
if (!pages_to_free) {
pr_debug("%s: Failed to allocate memory for pool free operation\n",
@@ -753,7 +754,8 @@ static int ttm_dma_pool_alloc_new_pages(struct dma_pool *pool,
(unsigned)(PAGE_SIZE/sizeof(struct page *)));
/* allocate array for page caching change */
- caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL);
+ caching_array = kmalloc_array(max_cpages, sizeof(struct page *),
+ GFP_KERNEL);
if (!caching_array) {
pr_debug("%s: Unable to allocate table for new pages\n",
diff --git a/drivers/gpu/drm/v3d/Kconfig b/drivers/gpu/drm/v3d/Kconfig
index a0c0259..1552bf5 100644
--- a/drivers/gpu/drm/v3d/Kconfig
+++ b/drivers/gpu/drm/v3d/Kconfig
@@ -3,6 +3,7 @@ config DRM_V3D
depends on ARCH_BCM || ARCH_BCMSTB || COMPILE_TEST
depends on DRM
depends on COMMON_CLK
+ depends on MMU
select DRM_SCHED
help
Choose this option if you have a system that has a Broadcom
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index 71d44c3..1d34619 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -209,7 +209,7 @@ static void vc4_dlist_write(struct vc4_plane_state *vc4_state, u32 val)
{
if (vc4_state->dlist_count == vc4_state->dlist_size) {
u32 new_size = max(4u, vc4_state->dlist_count * 2);
- u32 *new_dlist = kmalloc(new_size * 4, GFP_KERNEL);
+ u32 *new_dlist = kmalloc_array(new_size, 4, GFP_KERNEL);
if (!new_dlist)
return;
diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c
index d6e84a5..345bda4 100644
--- a/drivers/gpu/drm/via/via_dmablit.c
+++ b/drivers/gpu/drm/via/via_dmablit.c
@@ -235,7 +235,7 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer)
vsg->num_pages = VIA_PFN(xfer->mem_addr + (xfer->num_lines * xfer->mem_stride - 1)) -
first_pfn + 1;
- vsg->pages = vzalloc(sizeof(struct page *) * vsg->num_pages);
+ vsg->pages = vzalloc(array_size(sizeof(struct page *), vsg->num_pages));
if (NULL == vsg->pages)
return -ENOMEM;
ret = get_user_pages_fast((unsigned long)xfer->mem_addr,
diff --git a/drivers/gpu/vga/Kconfig b/drivers/gpu/vga/Kconfig
index 29437ea..b677e5d 100644
--- a/drivers/gpu/vga/Kconfig
+++ b/drivers/gpu/vga/Kconfig
@@ -6,7 +6,7 @@ config VGA_ARB
Some "legacy" VGA devices implemented on PCI typically have the same
hard-decoded addresses as they did on ISA. When multiple PCI devices
are accessed at same time they need some kind of coordination. Please
- see Documentation/vgaarbiter.txt for more details. Select this to
+ see Documentation/gpu/vgaarbiter.rst for more details. Select this to
enable VGA arbiter.
config VGA_ARB_MAX_GPUS
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 1c5e74c..c61b045 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -1,6 +1,6 @@
/*
* vgaarb.c: Implements the VGA arbitration. For details refer to
- * Documentation/vgaarbiter.txt
+ * Documentation/gpu/vgaarbiter.rst
*
*
* (C) Copyright 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 355dc7e..f858cc7 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -134,8 +134,11 @@ static int open_collection(struct hid_parser *parser, unsigned type)
}
if (parser->device->maxcollection == parser->device->collection_size) {
- collection = kmalloc(sizeof(struct hid_collection) *
- parser->device->collection_size * 2, GFP_KERNEL);
+ collection = kmalloc(
+ array3_size(sizeof(struct hid_collection),
+ parser->device->collection_size,
+ 2),
+ GFP_KERNEL);
if (collection == NULL) {
hid_err(parser->device, "failed to reallocate collection array\n");
return -ENOMEM;
@@ -1278,7 +1281,7 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field,
__s32 max = field->logical_maximum;
__s32 *value;
- value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC);
+ value = kmalloc_array(count, sizeof(__s32), GFP_ATOMIC);
if (!value)
return;
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 4f4e7a0..8469b69 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -457,7 +457,7 @@ static char *resolv_usage_page(unsigned page, struct seq_file *f) {
char *buf = NULL;
if (!f) {
- buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
+ buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_ATOMIC);
if (!buf)
return ERR_PTR(-ENOMEM);
}
@@ -685,7 +685,7 @@ void hid_dump_report(struct hid_device *hid, int type, u8 *data,
char *buf;
unsigned int i;
- buf = kmalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_ATOMIC);
+ buf = kmalloc(HID_DEBUG_BUFSIZE, GFP_ATOMIC);
if (!buf)
return;
@@ -1088,7 +1088,7 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
goto out;
}
- if (!(list->hid_debug_buf = kzalloc(sizeof(char) * HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
+ if (!(list->hid_debug_buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
err = -ENOMEM;
kfree(list);
goto out;
diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c
index 7b8e17b..6bf4da7 100644
--- a/drivers/hid/hid-google-hammer.c
+++ b/drivers/hid/hid-google-hammer.c
@@ -124,6 +124,8 @@ static const struct hid_device_id hammer_devices[] = {
USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_STAFF) },
{ HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_WAND) },
+ { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC,
+ USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_WHISKERS) },
{ }
};
MODULE_DEVICE_TABLE(hid, hammer_devices);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index a85634f..c7981dd 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -452,6 +452,7 @@
#define USB_DEVICE_ID_GOOGLE_TOUCH_ROSE 0x5028
#define USB_DEVICE_ID_GOOGLE_STAFF 0x502b
#define USB_DEVICE_ID_GOOGLE_WAND 0x502d
+#define USB_DEVICE_ID_GOOGLE_WHISKERS 0x5030
#define USB_VENDOR_ID_GOTOP 0x08f2
#define USB_DEVICE_ID_SUPER_Q2 0x007f
diff --git a/drivers/hid/hid-picolcd_fb.c b/drivers/hid/hid-picolcd_fb.c
index 7f965e2..864a084 100644
--- a/drivers/hid/hid-picolcd_fb.c
+++ b/drivers/hid/hid-picolcd_fb.c
@@ -394,7 +394,8 @@ static int picolcd_set_par(struct fb_info *info)
return -EINVAL;
o_fb = fbdata->bitmap;
- tmp_fb = kmalloc(PICOLCDFB_SIZE*info->var.bits_per_pixel, GFP_KERNEL);
+ tmp_fb = kmalloc_array(PICOLCDFB_SIZE, info->var.bits_per_pixel,
+ GFP_KERNEL);
if (!tmp_fb)
return -ENOMEM;
diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c
index 25363fc..50af72b 100644
--- a/drivers/hid/hid-sensor-hub.c
+++ b/drivers/hid/hid-sensor-hub.c
@@ -624,7 +624,8 @@ static int sensor_hub_probe(struct hid_device *hdev,
ret = -EINVAL;
goto err_stop_hw;
}
- sd->hid_sensor_hub_client_devs = devm_kzalloc(&hdev->dev, dev_cnt *
+ sd->hid_sensor_hub_client_devs = devm_kcalloc(&hdev->dev,
+ dev_cnt,
sizeof(struct mfd_cell),
GFP_KERNEL);
if (sd->hid_sensor_hub_client_devs == NULL) {
diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c
index cb86cc8..0422ec2 100644
--- a/drivers/hid/hid-steam.c
+++ b/drivers/hid/hid-steam.c
@@ -573,7 +573,7 @@ static bool steam_is_valve_interface(struct hid_device *hdev)
static int steam_client_ll_parse(struct hid_device *hdev)
{
- struct steam_device *steam = hid_get_drvdata(hdev);
+ struct steam_device *steam = hdev->driver_data;
return hid_parse_report(hdev, steam->hdev->dev_rdesc,
steam->hdev->dev_rsize);
@@ -590,7 +590,7 @@ static void steam_client_ll_stop(struct hid_device *hdev)
static int steam_client_ll_open(struct hid_device *hdev)
{
- struct steam_device *steam = hid_get_drvdata(hdev);
+ struct steam_device *steam = hdev->driver_data;
int ret;
ret = hid_hw_open(steam->hdev);
@@ -605,7 +605,7 @@ static int steam_client_ll_open(struct hid_device *hdev)
static void steam_client_ll_close(struct hid_device *hdev)
{
- struct steam_device *steam = hid_get_drvdata(hdev);
+ struct steam_device *steam = hdev->driver_data;
mutex_lock(&steam->mutex);
steam->client_opened = false;
@@ -623,7 +623,7 @@ static int steam_client_ll_raw_request(struct hid_device *hdev,
size_t count, unsigned char report_type,
int reqtype)
{
- struct steam_device *steam = hid_get_drvdata(hdev);
+ struct steam_device *steam = hdev->driver_data;
return hid_hw_raw_request(steam->hdev, reportnum, buf, count,
report_type, reqtype);
@@ -710,7 +710,7 @@ static int steam_probe(struct hid_device *hdev,
ret = PTR_ERR(steam->client_hdev);
goto client_hdev_fail;
}
- hid_set_drvdata(steam->client_hdev, steam);
+ steam->client_hdev->driver_data = steam;
/*
* With the real steam controller interface, do not connect hidraw.
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index b39844a..4a44e48 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -218,7 +218,7 @@ static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t
goto out;
}
- buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
+ buf = kmalloc(count, GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
index 582e449..a2c53ea 100644
--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c
+++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c
@@ -205,8 +205,7 @@ static void ish_remove(struct pci_dev *pdev)
kfree(ishtp_dev);
}
-#ifdef CONFIG_PM
-static struct device *ish_resume_device;
+static struct device __maybe_unused *ish_resume_device;
/* 50ms to get resume response */
#define WAIT_FOR_RESUME_ACK_MS 50
@@ -220,7 +219,7 @@ static struct device *ish_resume_device;
* in that case a simple resume message is enough, others we need
* a reset sequence.
*/
-static void ish_resume_handler(struct work_struct *work)
+static void __maybe_unused ish_resume_handler(struct work_struct *work)
{
struct pci_dev *pdev = to_pci_dev(ish_resume_device);
struct ishtp_device *dev = pci_get_drvdata(pdev);
@@ -262,7 +261,7 @@ static void ish_resume_handler(struct work_struct *work)
*
* Return: 0 to the pm core
*/
-static int ish_suspend(struct device *device)
+static int __maybe_unused ish_suspend(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct ishtp_device *dev = pci_get_drvdata(pdev);
@@ -288,7 +287,7 @@ static int ish_suspend(struct device *device)
return 0;
}
-static DECLARE_WORK(resume_work, ish_resume_handler);
+static __maybe_unused DECLARE_WORK(resume_work, ish_resume_handler);
/**
* ish_resume() - ISH resume callback
* @device: device pointer
@@ -297,7 +296,7 @@ static DECLARE_WORK(resume_work, ish_resume_handler);
*
* Return: 0 to the pm core
*/
-static int ish_resume(struct device *device)
+static int __maybe_unused ish_resume(struct device *device)
{
struct pci_dev *pdev = to_pci_dev(device);
struct ishtp_device *dev = pci_get_drvdata(pdev);
@@ -311,21 +310,14 @@ static int ish_resume(struct device *device)
return 0;
}
-static const struct dev_pm_ops ish_pm_ops = {
- .suspend = ish_suspend,
- .resume = ish_resume,
-};
-#define ISHTP_ISH_PM_OPS (&ish_pm_ops)
-#else
-#define ISHTP_ISH_PM_OPS NULL
-#endif /* CONFIG_PM */
+static SIMPLE_DEV_PM_OPS(ish_pm_ops, ish_suspend, ish_resume);
static struct pci_driver ish_driver = {
.name = KBUILD_MODNAME,
.id_table = ish_pci_tbl,
.probe = ish_probe,
.remove = ish_remove,
- .driver.pm = ISHTP_ISH_PM_OPS,
+ .driver.pm = &ish_pm_ops,
};
module_pci_driver(ish_driver);
diff --git a/drivers/hid/intel-ish-hid/ishtp-hid-client.c b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
index acc2536..2d28cff 100644
--- a/drivers/hid/intel-ish-hid/ishtp-hid-client.c
+++ b/drivers/hid/intel-ish-hid/ishtp-hid-client.c
@@ -121,9 +121,9 @@ static void process_recv(struct ishtp_cl *hid_ishtp_cl, void *recv_buf,
}
client_data->hid_dev_count = (unsigned int)*payload;
if (!client_data->hid_devices)
- client_data->hid_devices = devm_kzalloc(
+ client_data->hid_devices = devm_kcalloc(
&client_data->cl_device->dev,
- client_data->hid_dev_count *
+ client_data->hid_dev_count,
sizeof(struct device_info),
GFP_KERNEL);
if (!client_data->hid_devices) {
diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig
index 0108c59..e50d8fe 100644
--- a/drivers/hid/usbhid/Kconfig
+++ b/drivers/hid/usbhid/Kconfig
@@ -14,7 +14,7 @@ config USB_HID
You can't use this driver and the HIDBP (Boot Protocol) keyboard
and mouse drivers at the same time. More information is available:
- <file:Documentation/input/input.txt>.
+ <file:Documentation/input/input.rst>.
If unsure, say Y.
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index ee7a37e..d679753 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -395,6 +395,14 @@ static void wacom_usage_mapping(struct hid_device *hdev,
}
}
+ /* 2nd-generation Intuos Pro Large has incorrect Y maximum */
+ if (hdev->vendor == USB_VENDOR_ID_WACOM &&
+ hdev->product == 0x0358 &&
+ WACOM_PEN_FIELD(field) &&
+ wacom_equivalent_usage(usage->hid) == HID_GD_Y) {
+ field->logical_maximum = 43200;
+ }
+
switch (usage->hid) {
case HID_GD_X:
features->x_max = field->logical_maximum;
@@ -1363,7 +1371,7 @@ static int wacom_led_groups_alloc_and_register_one(struct device *dev,
if (!devres_open_group(dev, &wacom->led.groups[group_id], GFP_KERNEL))
return -ENOMEM;
- leds = devm_kzalloc(dev, sizeof(struct wacom_led) * count, GFP_KERNEL);
+ leds = devm_kcalloc(dev, count, sizeof(struct wacom_led), GFP_KERNEL);
if (!leds) {
error = -ENOMEM;
goto err;
@@ -1463,7 +1471,7 @@ static int wacom_led_groups_allocate(struct wacom *wacom, int count)
struct wacom_group_leds *groups;
int error;
- groups = devm_kzalloc(dev, sizeof(struct wacom_group_leds) * count,
+ groups = devm_kcalloc(dev, count, sizeof(struct wacom_group_leds),
GFP_KERNEL);
if (!groups)
return -ENOMEM;
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index 9b82549..658dc76 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -190,7 +190,7 @@ int hv_synic_alloc(void)
{
int cpu;
- hv_context.hv_numa_map = kzalloc(sizeof(struct cpumask) * nr_node_ids,
+ hv_context.hv_numa_map = kcalloc(nr_node_ids, sizeof(struct cpumask),
GFP_KERNEL);
if (hv_context.hv_numa_map == NULL) {
pr_err("Unable to allocate NUMA map\n");
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 8699bb9..be3c8b1 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -202,7 +202,7 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
* First page holds struct hv_ring_buffer, do wraparound mapping for
* the rest.
*/
- pages_wraparound = kzalloc(sizeof(struct page *) * (page_cnt * 2 - 1),
+ pages_wraparound = kcalloc(page_cnt * 2 - 1, sizeof(struct page *),
GFP_KERNEL);
if (!pages_wraparound)
return -ENOMEM;
@@ -227,6 +227,8 @@ int hv_ringbuffer_init(struct hv_ring_buffer_info *ring_info,
ring_info->ring_buffer->feature_bits.value = 1;
ring_info->ring_size = page_cnt << PAGE_SHIFT;
+ ring_info->ring_size_div10_reciprocal =
+ reciprocal_value(ring_info->ring_size / 10);
ring_info->ring_datasize = ring_info->ring_size -
sizeof(struct hv_ring_buffer);
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index 14a94d9..34e45b9 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -575,8 +575,9 @@ static int read_domain_devices(struct acpi_power_meter_resource *resource)
if (!pss->package.count)
goto end;
- resource->domain_devices = kzalloc(sizeof(struct acpi_device *) *
- pss->package.count, GFP_KERNEL);
+ resource->domain_devices = kcalloc(pss->package.count,
+ sizeof(struct acpi_device *),
+ GFP_KERNEL);
if (!resource->domain_devices) {
res = -ENOMEM;
goto end;
@@ -796,7 +797,7 @@ static int read_capabilities(struct acpi_power_meter_resource *resource)
goto error;
}
- *str = kzalloc(sizeof(u8) * (element->string.length + 1),
+ *str = kcalloc(element->string.length + 1, sizeof(u8),
GFP_KERNEL);
if (!*str) {
res = -ENOMEM;
diff --git a/drivers/hwmon/aspeed-pwm-tacho.c b/drivers/hwmon/aspeed-pwm-tacho.c
index 693a3d5..5e449ea 100644
--- a/drivers/hwmon/aspeed-pwm-tacho.c
+++ b/drivers/hwmon/aspeed-pwm-tacho.c
@@ -894,7 +894,7 @@ static int aspeed_create_fan(struct device *dev,
count = of_property_count_u8_elems(child, "aspeed,fan-tach-ch");
if (count < 1)
return -EINVAL;
- fan_tach_ch = devm_kzalloc(dev, sizeof(*fan_tach_ch) * count,
+ fan_tach_ch = devm_kcalloc(dev, count, sizeof(*fan_tach_ch),
GFP_KERNEL);
if (!fan_tach_ch)
return -ENOMEM;
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 72c338e..10645c9 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -742,7 +742,7 @@ static int __init coretemp_init(void)
return -ENODEV;
max_packages = topology_max_packages();
- pkg_devices = kzalloc(max_packages * sizeof(struct platform_device *),
+ pkg_devices = kcalloc(max_packages, sizeof(struct platform_device *),
GFP_KERNEL);
if (!pkg_devices)
return -ENOMEM;
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index bf3bb7e..9d3ef87 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -1074,6 +1074,13 @@ static struct dmi_system_id i8k_blacklist_fan_support_dmi_table[] __initdata = {
DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Vostro 3360"),
},
},
+ {
+ .ident = "Dell XPS13 9333",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "XPS13 9333"),
+ },
+ },
{ }
};
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index 5c9a525..a3974cd 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -441,8 +441,8 @@ static int gpio_fan_get_of_data(struct gpio_fan_data *fan_data)
dev_err(dev, "DT properties empty / missing");
return -ENODEV;
}
- gpios = devm_kzalloc(dev,
- fan_data->num_gpios * sizeof(struct gpio_desc *),
+ gpios = devm_kcalloc(dev,
+ fan_data->num_gpios, sizeof(struct gpio_desc *),
GFP_KERNEL);
if (!gpios)
return -ENOMEM;
@@ -471,8 +471,8 @@ static int gpio_fan_get_of_data(struct gpio_fan_data *fan_data)
* Speed map is in the form <RPM ctrl_val RPM ctrl_val ...>
* this needs splitting into pairs to create gpio_fan_speed structs
*/
- speed = devm_kzalloc(dev,
- fan_data->num_speed * sizeof(struct gpio_fan_speed),
+ speed = devm_kcalloc(dev,
+ fan_data->num_speed, sizeof(struct gpio_fan_speed),
GFP_KERNEL);
if (!speed)
return -ENOMEM;
diff --git a/drivers/hwmon/i5k_amb.c b/drivers/hwmon/i5k_amb.c
index 9397d2f..a4edc43 100644
--- a/drivers/hwmon/i5k_amb.c
+++ b/drivers/hwmon/i5k_amb.c
@@ -274,8 +274,9 @@ static int i5k_amb_hwmon_init(struct platform_device *pdev)
num_ambs += hweight16(data->amb_present[i] & 0x7fff);
/* Set up sysfs stuff */
- data->attrs = kzalloc(sizeof(*data->attrs) * num_ambs * KNOBS_PER_AMB,
- GFP_KERNEL);
+ data->attrs = kzalloc(array3_size(num_ambs, KNOBS_PER_AMB,
+ sizeof(*data->attrs)),
+ GFP_KERNEL);
if (!data->attrs)
return -ENOMEM;
data->num_attrs = 0;
diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
index 21b9c72..ab72cab 100644
--- a/drivers/hwmon/ibmpex.c
+++ b/drivers/hwmon/ibmpex.c
@@ -387,7 +387,7 @@ static int ibmpex_find_sensors(struct ibmpex_bmc_data *data)
return -ENOENT;
data->num_sensors = err;
- data->sensors = kzalloc(data->num_sensors * sizeof(*data->sensors),
+ data->sensors = kcalloc(data->num_sensors, sizeof(*data->sensors),
GFP_KERNEL);
if (!data->sensors)
return -ENOMEM;
diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c
index 0298745..f829dad 100644
--- a/drivers/hwmon/ibmpowernv.c
+++ b/drivers/hwmon/ibmpowernv.c
@@ -326,9 +326,9 @@ static int populate_attr_groups(struct platform_device *pdev)
of_node_put(opal);
for (type = 0; type < MAX_SENSOR_TYPE; type++) {
- sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev,
- sizeof(struct attribute *) *
- (sensor_groups[type].attr_count + 1),
+ sensor_groups[type].group.attrs = devm_kcalloc(&pdev->dev,
+ sensor_groups[type].attr_count + 1,
+ sizeof(struct attribute *),
GFP_KERNEL);
if (!sensor_groups[type].group.attrs)
return -ENOMEM;
@@ -409,7 +409,8 @@ static int create_device_attrs(struct platform_device *pdev)
int err = 0;
opal = of_find_node_by_path("/ibm,opal/sensors");
- sdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata),
+ sdata = devm_kcalloc(&pdev->dev,
+ pdata->sensors_count, sizeof(*sdata),
GFP_KERNEL);
if (!sdata) {
err = -ENOMEM;
diff --git a/drivers/hwmon/iio_hwmon.c b/drivers/hwmon/iio_hwmon.c
index 5e5b32a..69031a0 100644
--- a/drivers/hwmon/iio_hwmon.c
+++ b/drivers/hwmon/iio_hwmon.c
@@ -92,8 +92,8 @@ static int iio_hwmon_probe(struct platform_device *pdev)
while (st->channels[st->num_channels].indio_dev)
st->num_channels++;
- st->attrs = devm_kzalloc(dev,
- sizeof(*st->attrs) * (st->num_channels + 1),
+ st->attrs = devm_kcalloc(dev,
+ st->num_channels + 1, sizeof(*st->attrs),
GFP_KERNEL);
if (st->attrs == NULL) {
ret = -ENOMEM;
diff --git a/drivers/hwmon/nct6683.c b/drivers/hwmon/nct6683.c
index b0bc77b..a753464 100644
--- a/drivers/hwmon/nct6683.c
+++ b/drivers/hwmon/nct6683.c
@@ -426,12 +426,12 @@ nct6683_create_attr_group(struct device *dev,
if (group == NULL)
return ERR_PTR(-ENOMEM);
- attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
+ attrs = devm_kcalloc(dev, repeat * count + 1, sizeof(*attrs),
GFP_KERNEL);
if (attrs == NULL)
return ERR_PTR(-ENOMEM);
- su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
+ su = devm_kzalloc(dev, array3_size(repeat, count, sizeof(*su)),
GFP_KERNEL);
if (su == NULL)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index aebce56..f9d1349 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -1190,12 +1190,12 @@ nct6775_create_attr_group(struct device *dev,
if (group == NULL)
return ERR_PTR(-ENOMEM);
- attrs = devm_kzalloc(dev, sizeof(*attrs) * (repeat * count + 1),
+ attrs = devm_kcalloc(dev, repeat * count + 1, sizeof(*attrs),
GFP_KERNEL);
if (attrs == NULL)
return ERR_PTR(-ENOMEM);
- su = devm_kzalloc(dev, sizeof(*su) * repeat * count,
+ su = devm_kzalloc(dev, array3_size(repeat, count, sizeof(*su)),
GFP_KERNEL);
if (su == NULL)
return ERR_PTR(-ENOMEM);
@@ -4175,7 +4175,7 @@ static int nct6775_probe(struct platform_device *pdev)
* The temperature is already monitored if the respective bit in <mask>
* is set.
*/
- for (i = 0; i < 32; i++) {
+ for (i = 0; i < 31; i++) {
if (!(data->temp_mask & BIT(i + 1)))
continue;
if (!reg_temp_alternate[i])
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index f7c47d7..82c3754 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2176,8 +2176,8 @@ static int pmbus_init_debugfs(struct i2c_client *client,
}
/* Allocate the max possible entries we need. */
- entries = devm_kzalloc(data->dev,
- sizeof(*entries) * (data->info->pages * 10),
+ entries = devm_kcalloc(data->dev,
+ data->info->pages * 10, sizeof(*entries),
GFP_KERNEL);
if (!entries)
return -ENOMEM;
diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c
index 70cecb0..ae93885 100644
--- a/drivers/hwmon/pmbus/ucd9000.c
+++ b/drivers/hwmon/pmbus/ucd9000.c
@@ -454,8 +454,8 @@ static int ucd9000_init_debugfs(struct i2c_client *client,
*/
if (mid->driver_data == ucd9090 || mid->driver_data == ucd90160 ||
mid->driver_data == ucd90910) {
- entries = devm_kzalloc(&client->dev,
- sizeof(*entries) * UCD9000_GPI_COUNT,
+ entries = devm_kcalloc(&client->dev,
+ UCD9000_GPI_COUNT, sizeof(*entries),
GFP_KERNEL);
if (!entries)
return -ENOMEM;
diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c
index 70cc0d1..7838af5 100644
--- a/drivers/hwmon/pwm-fan.c
+++ b/drivers/hwmon/pwm-fan.c
@@ -180,7 +180,7 @@ static int pwm_fan_of_get_cooling_data(struct device *dev,
}
num = ret;
- ctx->pwm_fan_cooling_levels = devm_kzalloc(dev, num * sizeof(u32),
+ ctx->pwm_fan_cooling_levels = devm_kcalloc(dev, num, sizeof(u32),
GFP_KERNEL);
if (!ctx->pwm_fan_cooling_levels)
return -ENOMEM;
diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig
index f0f4679..e895d29 100644
--- a/drivers/hwspinlock/Kconfig
+++ b/drivers/hwspinlock/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# Generic HWSPINLOCK framework
#
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
index 4074441..d16e6a3 100644
--- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -1,18 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Hardware spinlock framework
*
* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
*
* Contact: Ohad Ben-Cohen <ohad@wizery.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.
*/
#define pr_fmt(fmt) "%s: " fmt, __func__
@@ -71,10 +63,16 @@ static DEFINE_MUTEX(hwspinlock_tree_lock);
* This function attempts to lock an hwspinlock, and will immediately
* fail if the hwspinlock is already taken.
*
- * Upon a successful return from this function, preemption (and possibly
- * interrupts) is disabled, so the caller must not sleep, and is advised to
- * release the hwspinlock as soon as possible. This is required in order to
- * minimize remote cores polling on the hardware interconnect.
+ * Caution: If the mode is HWLOCK_RAW, that means user must protect the routine
+ * of getting hardware lock with mutex or spinlock. Since in some scenarios,
+ * user need some time-consuming or sleepable operations under the hardware
+ * lock, they need one sleepable lock (like mutex) to protect the operations.
+ *
+ * If the mode is not HWLOCK_RAW, upon a successful return from this function,
+ * preemption (and possibly interrupts) is disabled, so the caller must not
+ * sleep, and is advised to release the hwspinlock as soon as possible. This is
+ * required in order to minimize remote cores polling on the hardware
+ * interconnect.
*
* The user decides whether local interrupts are disabled or not, and if yes,
* whether he wants their previous state to be saved. It is up to the user
@@ -106,12 +104,20 @@ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
* problems with hwspinlock usage (e.g. scheduler checks like
* 'scheduling while atomic' etc.)
*/
- if (mode == HWLOCK_IRQSTATE)
+ switch (mode) {
+ case HWLOCK_IRQSTATE:
ret = spin_trylock_irqsave(&hwlock->lock, *flags);
- else if (mode == HWLOCK_IRQ)
+ break;
+ case HWLOCK_IRQ:
ret = spin_trylock_irq(&hwlock->lock);
- else
+ break;
+ case HWLOCK_RAW:
+ ret = 1;
+ break;
+ default:
ret = spin_trylock(&hwlock->lock);
+ break;
+ }
/* is lock already taken by another context on the local cpu ? */
if (!ret)
@@ -122,12 +128,20 @@ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
/* if hwlock is already taken, undo spin_trylock_* and exit */
if (!ret) {
- if (mode == HWLOCK_IRQSTATE)
+ switch (mode) {
+ case HWLOCK_IRQSTATE:
spin_unlock_irqrestore(&hwlock->lock, *flags);
- else if (mode == HWLOCK_IRQ)
+ break;
+ case HWLOCK_IRQ:
spin_unlock_irq(&hwlock->lock);
- else
+ break;
+ case HWLOCK_RAW:
+ /* Nothing to do */
+ break;
+ default:
spin_unlock(&hwlock->lock);
+ break;
+ }
return -EBUSY;
}
@@ -160,9 +174,14 @@ EXPORT_SYMBOL_GPL(__hwspin_trylock);
* is already taken, the function will busy loop waiting for it to
* be released, but give up after @timeout msecs have elapsed.
*
- * Upon a successful return from this function, preemption is disabled
- * (and possibly local interrupts, too), so the caller must not sleep,
- * and is advised to release the hwspinlock as soon as possible.
+ * Caution: If the mode is HWLOCK_RAW, that means user must protect the routine
+ * of getting hardware lock with mutex or spinlock. Since in some scenarios,
+ * user need some time-consuming or sleepable operations under the hardware
+ * lock, they need one sleepable lock (like mutex) to protect the operations.
+ *
+ * If the mode is not HWLOCK_RAW, upon a successful return from this function,
+ * preemption is disabled (and possibly local interrupts, too), so the caller
+ * must not sleep, and is advised to release the hwspinlock as soon as possible.
* This is required in order to minimize remote cores polling on the
* hardware interconnect.
*
@@ -249,12 +268,20 @@ void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
hwlock->bank->ops->unlock(hwlock);
/* Undo the spin_trylock{_irq, _irqsave} called while locking */
- if (mode == HWLOCK_IRQSTATE)
+ switch (mode) {
+ case HWLOCK_IRQSTATE:
spin_unlock_irqrestore(&hwlock->lock, *flags);
- else if (mode == HWLOCK_IRQ)
+ break;
+ case HWLOCK_IRQ:
spin_unlock_irq(&hwlock->lock);
- else
+ break;
+ case HWLOCK_RAW:
+ /* Nothing to do */
+ break;
+ default:
spin_unlock(&hwlock->lock);
+ break;
+ }
}
EXPORT_SYMBOL_GPL(__hwspin_unlock);
diff --git a/drivers/hwspinlock/hwspinlock_internal.h b/drivers/hwspinlock/hwspinlock_internal.h
index d26f78b..9eb6bd0 100644
--- a/drivers/hwspinlock/hwspinlock_internal.h
+++ b/drivers/hwspinlock/hwspinlock_internal.h
@@ -1,18 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Hardware spinlocks internal header
*
* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
*
* Contact: Ohad Ben-Cohen <ohad@wizery.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 __HWSPINLOCK_HWSPINLOCK_H
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index d897e52..625844e 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* OMAP hardware spinlock driver
*
@@ -6,15 +7,6 @@
* Contact: Simon Que <sque@ti.com>
* Hari Kanigeri <h-kanigeri2@ti.com>
* Ohad Ben-Cohen <ohad@wizery.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/kernel.h>
diff --git a/drivers/hwspinlock/qcom_hwspinlock.c b/drivers/hwspinlock/qcom_hwspinlock.c
index fa6880b..6da7447 100644
--- a/drivers/hwspinlock/qcom_hwspinlock.c
+++ b/drivers/hwspinlock/qcom_hwspinlock.c
@@ -1,15 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
* Copyright (c) 2015, Sony Mobile Communications AB
- *
- * 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/hwspinlock.h>
diff --git a/drivers/hwspinlock/sirf_hwspinlock.c b/drivers/hwspinlock/sirf_hwspinlock.c
index cb38e48..1f625cd 100644
--- a/drivers/hwspinlock/sirf_hwspinlock.c
+++ b/drivers/hwspinlock/sirf_hwspinlock.c
@@ -1,9 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* SIRF hardware spinlock driver
*
* Copyright (c) 2015 Cambridge Silicon Radio Limited, a CSR plc group company.
- *
- * Licensed under GPLv2.
*/
#include <linux/kernel.h>
diff --git a/drivers/hwspinlock/sprd_hwspinlock.c b/drivers/hwspinlock/sprd_hwspinlock.c
index 638e64a..dc42bf5 100644
--- a/drivers/hwspinlock/sprd_hwspinlock.c
+++ b/drivers/hwspinlock/sprd_hwspinlock.c
@@ -1,15 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Spreadtrum hardware spinlock driver
* Copyright (C) 2017 Spreadtrum - http://www.spreadtrum.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/bitops.h>
diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c
index 0128d8f..572ca79 100644
--- a/drivers/hwspinlock/u8500_hsem.c
+++ b/drivers/hwspinlock/u8500_hsem.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* u8500 HWSEM driver
*
@@ -10,15 +11,6 @@
* Simon Que <sque@ti.com>
* Hari Kanigeri <h-kanigeri2@ti.com>
* Ohad Ben-Cohen <ohad@wizery.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/module.h>
diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
index 9b6c555..320d29d 100644
--- a/drivers/hwtracing/coresight/coresight-etb10.c
+++ b/drivers/hwtracing/coresight/coresight-etb10.c
@@ -683,8 +683,8 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
if (drvdata->buffer_depth & 0x80000000)
return -EINVAL;
- drvdata->buf = devm_kzalloc(dev,
- drvdata->buffer_depth * 4, GFP_KERNEL);
+ drvdata->buf = devm_kcalloc(dev,
+ drvdata->buffer_depth, 4, GFP_KERNEL);
if (!drvdata->buf)
return -ENOMEM;
diff --git a/drivers/hwtracing/coresight/of_coresight.c b/drivers/hwtracing/coresight/of_coresight.c
index a33a92e..6880bee 100644
--- a/drivers/hwtracing/coresight/of_coresight.c
+++ b/drivers/hwtracing/coresight/of_coresight.c
@@ -71,21 +71,24 @@ static int of_coresight_alloc_memory(struct device *dev,
struct coresight_platform_data *pdata)
{
/* List of output port on this component */
- pdata->outports = devm_kzalloc(dev, pdata->nr_outport *
+ pdata->outports = devm_kcalloc(dev,
+ pdata->nr_outport,
sizeof(*pdata->outports),
GFP_KERNEL);
if (!pdata->outports)
return -ENOMEM;
/* Children connected to this component via @outports */
- pdata->child_names = devm_kzalloc(dev, pdata->nr_outport *
+ pdata->child_names = devm_kcalloc(dev,
+ pdata->nr_outport,
sizeof(*pdata->child_names),
GFP_KERNEL);
if (!pdata->child_names)
return -ENOMEM;
/* Port number on the child this component is connected to */
- pdata->child_ports = devm_kzalloc(dev, pdata->nr_outport *
+ pdata->child_ports = devm_kcalloc(dev,
+ pdata->nr_outport,
sizeof(*pdata->child_ports),
GFP_KERNEL);
if (!pdata->child_ports)
diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c
index 3df0efd..4a34f31 100644
--- a/drivers/i2c/algos/i2c-algo-bit.c
+++ b/drivers/i2c/algos/i2c-algo-bit.c
@@ -519,9 +519,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
}
}
} else { /* normal 7bit address */
- addr = msg->addr << 1;
- if (flags & I2C_M_RD)
- addr |= 1;
+ addr = i2c_8bit_addr_from_msg(msg);
if (flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
ret = try_address(i2c_adap, addr, retries);
diff --git a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
index e370804..883a290 100644
--- a/drivers/i2c/algos/i2c-algo-pca.c
+++ b/drivers/i2c/algos/i2c-algo-pca.c
@@ -112,11 +112,8 @@ static int pca_address(struct i2c_algo_pca_data *adap,
struct i2c_msg *msg)
{
int sta = pca_get_con(adap);
- int addr;
+ int addr = i2c_8bit_addr_from_msg(msg);
- addr = ((0x7f & msg->addr) << 1);
- if (msg->flags & I2C_M_RD)
- addr |= 1;
DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n",
msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr);
diff --git a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
index 270d84b..5c29a4d 100644
--- a/drivers/i2c/algos/i2c-algo-pcf.c
+++ b/drivers/i2c/algos/i2c-algo-pcf.c
@@ -291,13 +291,9 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
static int pcf_doAddress(struct i2c_algo_pcf_data *adap,
struct i2c_msg *msg)
{
- unsigned short flags = msg->flags;
- unsigned char addr;
+ unsigned char addr = i2c_8bit_addr_from_msg(msg);
- addr = msg->addr << 1;
- if (flags & I2C_M_RD)
- addr |= 1;
- if (flags & I2C_M_REV_DIR_ADDR)
+ if (msg->flags & I2C_M_REV_DIR_ADDR)
addr ^= 1;
i2c_outb(adap, addr);
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index fce9f2c..4f8df2e 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -943,6 +943,7 @@ config I2C_STM32F4
config I2C_STM32F7
tristate "STMicroelectronics STM32F7 I2C support"
depends on ARCH_STM32 || COMPILE_TEST
+ select I2C_SLAVE
help
Enable this option to add support for STM32 I2C controller embedded
in STM32F7 SoCs.
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 189e34b..5a86914 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -94,7 +94,8 @@ obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o
obj-$(CONFIG_I2C_SPRD) += i2c-sprd.o
obj-$(CONFIG_I2C_ST) += i2c-st.o
obj-$(CONFIG_I2C_STM32F4) += i2c-stm32f4.o
-obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7.o
+i2c-stm32f7-drv-objs := i2c-stm32f7.o i2c-stm32.o
+obj-$(CONFIG_I2C_STM32F7) += i2c-stm32f7-drv.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_SUN6I_P2WI) += i2c-sun6i-p2wi.o
obj-$(CONFIG_I2C_SYNQUACER) += i2c-synquacer.o
diff --git a/drivers/i2c/busses/i2c-amd756-s4882.c b/drivers/i2c/busses/i2c-amd756-s4882.c
index 65e32405..a2f5f99 100644
--- a/drivers/i2c/busses/i2c-amd756-s4882.c
+++ b/drivers/i2c/busses/i2c-amd756-s4882.c
@@ -169,12 +169,12 @@ static int __init amd756_s4882_init(void)
printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n");
/* Define the 5 virtual adapters and algorithms structures */
- if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter),
+ if (!(s4882_adapter = kcalloc(5, sizeof(struct i2c_adapter),
GFP_KERNEL))) {
error = -ENOMEM;
goto ERROR1;
}
- if (!(s4882_algo = kzalloc(5 * sizeof(struct i2c_algorithm),
+ if (!(s4882_algo = kcalloc(5, sizeof(struct i2c_algorithm),
GFP_KERNEL))) {
error = -ENOMEM;
goto ERROR2;
diff --git a/drivers/i2c/busses/i2c-aspeed.c b/drivers/i2c/busses/i2c-aspeed.c
index 7d4aeb4..60e4d0e 100644
--- a/drivers/i2c/busses/i2c-aspeed.c
+++ b/drivers/i2c/busses/i2c-aspeed.c
@@ -335,13 +335,12 @@ static void aspeed_i2c_do_start(struct aspeed_i2c_bus *bus)
{
u32 command = ASPEED_I2CD_M_START_CMD | ASPEED_I2CD_M_TX_CMD;
struct i2c_msg *msg = &bus->msgs[bus->msgs_index];
- u8 slave_addr = msg->addr << 1;
+ u8 slave_addr = i2c_8bit_addr_from_msg(msg);
bus->master_state = ASPEED_I2C_MASTER_START;
bus->buf_index = 0;
if (msg->flags & I2C_M_RD) {
- slave_addr |= 1;
command |= ASPEED_I2CD_M_RX_CMD;
/* Need to let the hardware know to NACK after RX. */
if (msg->len == 1 && !(msg->flags & I2C_M_RECV_LEN))
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
index bfd1fdf..3f3e8b3 100644
--- a/drivers/i2c/busses/i2c-at91.c
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -518,8 +518,16 @@ static irqreturn_t atmel_twi_interrupt(int irq, void *dev_id)
* the RXRDY interrupt first in order to not keep garbage data in the
* Receive Holding Register for the next transfer.
*/
- if (irqstatus & AT91_TWI_RXRDY)
- at91_twi_read_next_byte(dev);
+ if (irqstatus & AT91_TWI_RXRDY) {
+ /*
+ * Read all available bytes at once by polling RXRDY usable w/
+ * and w/o FIFO. With FIFO enabled we could also read RXFL and
+ * avoid polling RXRDY.
+ */
+ do {
+ at91_twi_read_next_byte(dev);
+ } while (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY);
+ }
/*
* When a NACK condition is detected, the I2C controller sets the NACK,
diff --git a/drivers/i2c/busses/i2c-axxia.c b/drivers/i2c/busses/i2c-axxia.c
index 13f0748..8e60048 100644
--- a/drivers/i2c/busses/i2c-axxia.c
+++ b/drivers/i2c/busses/i2c-axxia.c
@@ -351,13 +351,15 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
* addr_2: addr[7:0]
*/
addr_1 = 0xF0 | ((msg->addr >> 7) & 0x06);
+ if (i2c_m_rd(msg))
+ addr_1 |= 1; /* Set the R/nW bit of the address */
addr_2 = msg->addr & 0xFF;
} else {
/* 7-bit address
* addr_1: addr[6:0] | (R/nW)
* addr_2: dont care
*/
- addr_1 = (msg->addr << 1) & 0xFF;
+ addr_1 = i2c_8bit_addr_from_msg(msg);
addr_2 = 0;
}
@@ -365,7 +367,6 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
/* I2C read transfer */
rx_xfer = i2c_m_recv_len(msg) ? I2C_SMBUS_BLOCK_MAX : msg->len;
tx_xfer = 0;
- addr_1 |= 1; /* Set the R/nW bit of the address */
} else {
/* I2C write transfer */
rx_xfer = 0;
@@ -532,23 +533,23 @@ static int axxia_i2c_probe(struct platform_device *pdev)
if (idev->bus_clk_rate == 0)
idev->bus_clk_rate = 100000; /* default clock rate */
+ ret = clk_prepare_enable(idev->i2c_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable clock\n");
+ return ret;
+ }
+
ret = axxia_i2c_init(idev);
if (ret) {
dev_err(&pdev->dev, "failed to initialize\n");
- return ret;
+ goto error_disable_clk;
}
ret = devm_request_irq(&pdev->dev, irq, axxia_i2c_isr, 0,
pdev->name, idev);
if (ret) {
dev_err(&pdev->dev, "failed to claim IRQ%d\n", irq);
- return ret;
- }
-
- ret = clk_prepare_enable(idev->i2c_clk);
- if (ret) {
- dev_err(&pdev->dev, "failed to enable clock\n");
- return ret;
+ goto error_disable_clk;
}
i2c_set_adapdata(&idev->adapter, idev);
@@ -563,12 +564,14 @@ static int axxia_i2c_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, idev);
ret = i2c_add_adapter(&idev->adapter);
- if (ret) {
- clk_disable_unprepare(idev->i2c_clk);
- return ret;
- }
+ if (ret)
+ goto error_disable_clk;
return 0;
+
+error_disable_clk:
+ clk_disable_unprepare(idev->i2c_clk);
+ return ret;
}
static int axxia_i2c_remove(struct platform_device *pdev)
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
index 27ebd90..48914df 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -149,18 +149,17 @@ u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset)
return ((ic_clk * (tLOW + tf) + 500000) / 1000000) - 1 + offset;
}
-void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable)
-{
- dw_writel(dev, enable, DW_IC_ENABLE);
-}
-
-void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable)
+void __i2c_dw_disable(struct dw_i2c_dev *dev)
{
int timeout = 100;
do {
- __i2c_dw_enable(dev, enable);
- if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == enable)
+ __i2c_dw_disable_nowait(dev);
+ /*
+ * The enable status register may be unimplemented, but
+ * in that case this test reads zero and exits the loop.
+ */
+ if ((dw_readl(dev, DW_IC_ENABLE_STATUS) & 1) == 0)
return;
/*
@@ -171,8 +170,7 @@ void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable)
usleep_range(25, 250);
} while (timeout--);
- dev_warn(dev->dev, "timeout in %sabling adapter\n",
- enable ? "en" : "dis");
+ dev_warn(dev->dev, "timeout in disabling adapter\n");
}
unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev)
@@ -277,7 +275,7 @@ u32 i2c_dw_func(struct i2c_adapter *adap)
void i2c_dw_disable(struct dw_i2c_dev *dev)
{
/* Disable controller */
- __i2c_dw_enable_and_wait(dev, false);
+ __i2c_dw_disable(dev);
/* Disable all interupts */
dw_writel(dev, 0, DW_IC_INTR_MASK);
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index 8707c76..d690e64 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -297,8 +297,6 @@ u32 dw_readl(struct dw_i2c_dev *dev, int offset);
void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
u32 i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset);
u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset);
-void __i2c_dw_enable(struct dw_i2c_dev *dev, bool enable);
-void __i2c_dw_enable_and_wait(struct dw_i2c_dev *dev, bool enable);
unsigned long i2c_dw_clk_rate(struct dw_i2c_dev *dev);
int i2c_dw_prepare_clk(struct dw_i2c_dev *dev, bool prepare);
int i2c_dw_acquire_lock(struct dw_i2c_dev *dev);
@@ -309,6 +307,18 @@ u32 i2c_dw_func(struct i2c_adapter *adap);
void i2c_dw_disable(struct dw_i2c_dev *dev);
void i2c_dw_disable_int(struct dw_i2c_dev *dev);
+static inline void __i2c_dw_enable(struct dw_i2c_dev *dev)
+{
+ dw_writel(dev, 1, DW_IC_ENABLE);
+}
+
+static inline void __i2c_dw_disable_nowait(struct dw_i2c_dev *dev)
+{
+ dw_writel(dev, 0, DW_IC_ENABLE);
+}
+
+void __i2c_dw_disable(struct dw_i2c_dev *dev);
+
extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev);
extern int i2c_dw_probe(struct dw_i2c_dev *dev);
#if IS_ENABLED(CONFIG_I2C_DESIGNWARE_SLAVE)
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index 0cdba29..27436a9 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -81,7 +81,7 @@ static int i2c_dw_init_master(struct dw_i2c_dev *dev)
comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
/* Disable the adapter */
- __i2c_dw_enable_and_wait(dev, false);
+ __i2c_dw_disable(dev);
/* Set standard and fast speed deviders for high/low periods */
@@ -180,7 +180,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
u32 ic_con, ic_tar = 0;
/* Disable the adapter */
- __i2c_dw_enable_and_wait(dev, false);
+ __i2c_dw_disable(dev);
/* If the slave address is ten bit address, enable 10BITADDR */
ic_con = dw_readl(dev, DW_IC_CON);
@@ -209,7 +209,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
i2c_dw_disable_int(dev);
/* Enable the adapter */
- __i2c_dw_enable(dev, true);
+ __i2c_dw_enable(dev);
/* Dummy read to avoid the register getting stuck on Bay Trail */
dw_readl(dev, DW_IC_ENABLE_STATUS);
@@ -462,7 +462,7 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
* additional interrupts are a hardware bug or this driver doesn't
* handle them correctly yet.
*/
- __i2c_dw_enable(dev, false);
+ __i2c_dw_disable_nowait(dev);
if (dev->msg_err) {
ret = dev->msg_err;
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
index d42558d..8ce2cd3 100644
--- a/drivers/i2c/busses/i2c-designware-slave.c
+++ b/drivers/i2c/busses/i2c-designware-slave.c
@@ -75,7 +75,7 @@ static int i2c_dw_init_slave(struct dw_i2c_dev *dev)
comp_param1 = dw_readl(dev, DW_IC_COMP_PARAM_1);
/* Disable the adapter. */
- __i2c_dw_enable_and_wait(dev, false);
+ __i2c_dw_disable(dev);
/* Configure SDA Hold Time if required. */
reg = dw_readl(dev, DW_IC_COMP_VERSION);
@@ -119,11 +119,11 @@ static int i2c_dw_reg_slave(struct i2c_client *slave)
* Set slave address in the IC_SAR register,
* the address to which the DW_apb_i2c responds.
*/
- __i2c_dw_enable(dev, false);
+ __i2c_dw_disable_nowait(dev);
dw_writel(dev, slave->addr, DW_IC_SAR);
dev->slave = slave;
- __i2c_dw_enable(dev, true);
+ __i2c_dw_enable(dev);
dev->cmd_err = 0;
dev->msg_write_idx = 0;
diff --git a/drivers/i2c/busses/i2c-diolan-u2c.c b/drivers/i2c/busses/i2c-diolan-u2c.c
index f718ee4..3f28317 100644
--- a/drivers/i2c/busses/i2c-diolan-u2c.c
+++ b/drivers/i2c/busses/i2c-diolan-u2c.c
@@ -360,11 +360,11 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
if (ret < 0)
goto abort;
}
+ ret = diolan_i2c_put_byte_ack(dev,
+ i2c_8bit_addr_from_msg(pmsg));
+ if (ret < 0)
+ goto abort;
if (pmsg->flags & I2C_M_RD) {
- ret =
- diolan_i2c_put_byte_ack(dev, (pmsg->addr << 1) | 1);
- if (ret < 0)
- goto abort;
for (j = 0; j < pmsg->len; j++) {
u8 byte;
bool ack = j < pmsg->len - 1;
@@ -393,9 +393,6 @@ static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
pmsg->buf[j] = byte;
}
} else {
- ret = diolan_i2c_put_byte_ack(dev, pmsg->addr << 1);
- if (ret < 0)
- goto abort;
for (j = 0; j < pmsg->len; j++) {
ret = diolan_i2c_put_byte_ack(dev,
pmsg->buf[j]);
diff --git a/drivers/i2c/busses/i2c-efm32.c b/drivers/i2c/busses/i2c-efm32.c
index aa336ba..5f2bab8 100644
--- a/drivers/i2c/busses/i2c-efm32.c
+++ b/drivers/i2c/busses/i2c-efm32.c
@@ -144,8 +144,7 @@ static void efm32_i2c_send_next_msg(struct efm32_i2c_ddata *ddata)
struct i2c_msg *cur_msg = &ddata->msgs[ddata->current_msg];
efm32_i2c_write32(ddata, REG_CMD, REG_CMD_START);
- efm32_i2c_write32(ddata, REG_TXDATA, cur_msg->addr << 1 |
- (cur_msg->flags & I2C_M_RD ? 1 : 0));
+ efm32_i2c_write32(ddata, REG_TXDATA, i2c_8bit_addr_from_msg(cur_msg));
}
static void efm32_i2c_send_next_byte(struct efm32_i2c_ddata *ddata)
diff --git a/drivers/i2c/busses/i2c-eg20t.c b/drivers/i2c/busses/i2c-eg20t.c
index bdeab01..835d54a 100644
--- a/drivers/i2c/busses/i2c-eg20t.c
+++ b/drivers/i2c/busses/i2c-eg20t.c
@@ -414,7 +414,7 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
iowrite32(addr_8_lsb, p + PCH_I2CDR);
} else {
/* set 7 bit slave address and R/W bit as 0 */
- iowrite32(addr << 1, p + PCH_I2CDR);
+ iowrite32(i2c_8bit_addr_from_msg(msgs), p + PCH_I2CDR);
if (first)
pch_i2c_start(adap);
}
@@ -538,8 +538,7 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
} else {
/* 7 address bits + R/W bit */
- addr = (((addr) << 1) | (I2C_RD));
- iowrite32(addr, p + PCH_I2CDR);
+ iowrite32(i2c_8bit_addr_from_msg(msgs), p + PCH_I2CDR);
}
/* check if it is the first message */
diff --git a/drivers/i2c/busses/i2c-emev2.c b/drivers/i2c/busses/i2c-emev2.c
index d2e8448..ba9b6ea 100644
--- a/drivers/i2c/busses/i2c-emev2.c
+++ b/drivers/i2c/busses/i2c-emev2.c
@@ -149,7 +149,7 @@ static int __em_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
em_clear_set_bit(priv, 0, I2C_BIT_STT0, I2C_OFS_IICC0);
/* Send slave address and R/W type */
- writeb((msg->addr << 1) | read, priv->base + I2C_OFS_IIC0);
+ writeb(i2c_8bit_addr_from_msg(msg), priv->base + I2C_OFS_IIC0);
/* Wait for transaction */
status = em_i2c_wait_for_event(priv);
diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c
index 12ec8484..de82ad8 100644
--- a/drivers/i2c/busses/i2c-exynos5.c
+++ b/drivers/i2c/busses/i2c-exynos5.c
@@ -707,7 +707,7 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
struct exynos5_i2c *i2c = adap->algo_data;
- int i = 0, ret = 0, stop = 0;
+ int i, ret;
if (i2c->suspended) {
dev_err(i2c->dev, "HS-I2C is not initialized.\n");
@@ -718,30 +718,15 @@ static int exynos5_i2c_xfer(struct i2c_adapter *adap,
if (ret)
return ret;
- for (i = 0; i < num; i++, msgs++) {
- stop = (i == num - 1);
-
- ret = exynos5_i2c_xfer_msg(i2c, msgs, stop);
-
- if (ret < 0)
- goto out;
- }
-
- if (i == num) {
- ret = num;
- } else {
- /* Only one message, cannot access the device */
- if (i == 1)
- ret = -EREMOTEIO;
- else
- ret = i;
-
- dev_warn(i2c->dev, "xfer message failed\n");
+ for (i = 0; i < num; ++i) {
+ ret = exynos5_i2c_xfer_msg(i2c, msgs + i, i + 1 == num);
+ if (ret)
+ break;
}
- out:
clk_disable(i2c->clk);
- return ret;
+
+ return ret ?: num;
}
static u32 exynos5_i2c_func(struct i2c_adapter *adap)
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 58abb3e..005e6e0 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -11,7 +11,7 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c
index bb68957..061a4bf 100644
--- a/drivers/i2c/busses/i2c-hix5hd2.c
+++ b/drivers/i2c/busses/i2c-hix5hd2.c
@@ -73,7 +73,6 @@
#define I2C_OVER_INTR BIT(0)
#define HIX5I2C_MAX_FREQ 400000 /* 400k */
-#define HIX5I2C_READ_OPERATION 0x01
enum hix5hd2_i2c_state {
HIX5I2C_STAT_RW_ERR = -1,
@@ -311,12 +310,8 @@ static void hix5hd2_i2c_message_start(struct hix5hd2_i2c_priv *priv, int stop)
hix5hd2_i2c_clr_all_irq(priv);
hix5hd2_i2c_enable_irq(priv);
- if (priv->msg->flags & I2C_M_RD)
- writel_relaxed((priv->msg->addr << 1) | HIX5I2C_READ_OPERATION,
- priv->regs + HIX5I2C_TXR);
- else
- writel_relaxed(priv->msg->addr << 1,
- priv->regs + HIX5I2C_TXR);
+ writel_relaxed(i2c_8bit_addr_from_msg(priv->msg),
+ priv->regs + HIX5I2C_TXR);
writel_relaxed(I2C_WRITE | I2C_START, priv->regs + HIX5I2C_COM);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -377,17 +372,7 @@ static int hix5hd2_i2c_xfer(struct i2c_adapter *adap,
goto out;
}
- if (i == num) {
- ret = num;
- } else {
- /* Only one message, cannot access the device */
- if (i == 1)
- ret = -EREMOTEIO;
- else
- ret = i;
-
- dev_warn(priv->dev, "xfer message failed\n");
- }
+ ret = num;
out:
pm_runtime_mark_last_busy(priv->dev);
@@ -471,7 +456,6 @@ static int hix5hd2_i2c_probe(struct platform_device *pdev)
goto err_clk;
}
- pm_suspend_ignore_children(&pdev->dev, true);
pm_runtime_set_autosuspend_delay(priv->dev, MSEC_PER_SEC);
pm_runtime_use_autosuspend(priv->dev);
pm_runtime_set_active(priv->dev);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index e0d59e9..aa72660 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -106,7 +106,7 @@
#if IS_ENABLED(CONFIG_I2C_MUX_GPIO) && defined CONFIG_DMI
#include <linux/gpio.h>
-#include <linux/i2c-mux-gpio.h>
+#include <linux/platform_data/i2c-mux-gpio.h>
#endif
/* I801 SMBus address offsets */
@@ -1710,7 +1710,7 @@ static void i801_shutdown(struct pci_dev *dev)
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int i801_suspend(struct device *dev)
{
struct pci_dev *pci_dev = to_pci_dev(dev);
@@ -1731,8 +1731,7 @@ static int i801_resume(struct device *dev)
}
#endif
-static UNIVERSAL_DEV_PM_OPS(i801_pm_ops, i801_suspend,
- i801_resume, NULL);
+static SIMPLE_DEV_PM_OPS(i801_pm_ops, i801_suspend, i801_resume);
static struct pci_driver i801_driver = {
.name = "i801_smbus",
diff --git a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
index 961c5f4..6f6e1df 100644
--- a/drivers/i2c/busses/i2c-ibm_iic.c
+++ b/drivers/i2c/busses/i2c-ibm_iic.c
@@ -561,9 +561,6 @@ static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num);
- if (!num)
- return 0;
-
/* Check the sanity of the passed messages.
* Uhh, generic i2c layer is more suitable place for such code...
*/
diff --git a/drivers/i2c/busses/i2c-imx-lpi2c.c b/drivers/i2c/busses/i2c-imx-lpi2c.c
index e6da2c7..6d975f5 100644
--- a/drivers/i2c/busses/i2c-imx-lpi2c.c
+++ b/drivers/i2c/busses/i2c-imx-lpi2c.c
@@ -1,18 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* This is i.MX low power i2c controller driver.
*
* Copyright 2016 Freescale Semiconductor, 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.
- *
- * 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>
@@ -180,15 +170,13 @@ static int lpi2c_imx_start(struct lpi2c_imx_struct *lpi2c_imx,
struct i2c_msg *msgs)
{
unsigned int temp;
- u8 read;
temp = readl(lpi2c_imx->base + LPI2C_MCR);
temp |= MCR_RRF | MCR_RTF;
writel(temp, lpi2c_imx->base + LPI2C_MCR);
writel(0x7f00, lpi2c_imx->base + LPI2C_MSR);
- read = msgs->flags & I2C_M_RD;
- temp = (msgs->addr << 1 | read) | (GEN_START << 8);
+ temp = i2c_8bit_addr_from_msg(msgs) | (GEN_START << 8);
writel(temp, lpi2c_imx->base + LPI2C_MTDR);
return lpi2c_imx_bus_busy(lpi2c_imx);
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index d7267dd..0207e19 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1,16 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2002 Motorola GSG-China
*
- * 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.
- *
* Author:
* Darius Augulis, Teltonika Inc.
*
@@ -630,7 +621,7 @@ static int i2c_imx_dma_write(struct imx_i2c_struct *i2c_imx,
* Write slave address.
* The first byte must be transmitted by the CPU.
*/
- imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR);
+ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
reinit_completion(&i2c_imx->dma->cmd_complete);
time_left = wait_for_completion_timeout(
&i2c_imx->dma->cmd_complete,
@@ -760,10 +751,10 @@ static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
int i, result;
dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n",
- __func__, msgs->addr << 1);
+ __func__, i2c_8bit_addr_from_msg(msgs));
/* write slave address */
- imx_i2c_write_reg(msgs->addr << 1, i2c_imx, IMX_I2C_I2DR);
+ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
result = i2c_imx_trx_complete(i2c_imx);
if (result)
return result;
@@ -796,10 +787,10 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs, bo
dev_dbg(&i2c_imx->adapter.dev,
"<%s> write slave address: addr=0x%x\n",
- __func__, (msgs->addr << 1) | 0x01);
+ __func__, i2c_8bit_addr_from_msg(msgs));
/* write slave address */
- imx_i2c_write_reg((msgs->addr << 1) | 0x01, i2c_imx, IMX_I2C_I2DR);
+ imx_i2c_write_reg(i2c_8bit_addr_from_msg(msgs), i2c_imx, IMX_I2C_I2DR);
result = i2c_imx_trx_complete(i2c_imx);
if (result)
return result;
diff --git a/drivers/i2c/busses/i2c-kempld.c b/drivers/i2c/busses/i2c-kempld.c
index e879190..1c874aa 100644
--- a/drivers/i2c/busses/i2c-kempld.c
+++ b/drivers/i2c/busses/i2c-kempld.c
@@ -124,15 +124,14 @@ static int kempld_i2c_process(struct kempld_i2c_data *i2c)
/* 10 bit address? */
if (i2c->msg->flags & I2C_M_TEN) {
addr = 0xf0 | ((i2c->msg->addr >> 7) & 0x6);
+ /* Set read bit if necessary */
+ addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0;
i2c->state = STATE_ADDR10;
} else {
- addr = (i2c->msg->addr << 1);
+ addr = i2c_8bit_addr_from_msg(i2c->msg);
i2c->state = STATE_START;
}
- /* Set read bit if necessary */
- addr |= (i2c->msg->flags & I2C_M_RD) ? 1 : 0;
-
kempld_write8(pld, KEMPLD_I2C_DATA, addr);
kempld_write8(pld, KEMPLD_I2C_CMD, I2C_CMD_START);
diff --git a/drivers/i2c/busses/i2c-mlxcpld.c b/drivers/i2c/busses/i2c-mlxcpld.c
index 4c28fa2..745ed43 100644
--- a/drivers/i2c/busses/i2c-mlxcpld.c
+++ b/drivers/i2c/busses/i2c-mlxcpld.c
@@ -45,13 +45,16 @@
#define MLXCPLD_I2C_VALID_FLAG (I2C_M_RECV_LEN | I2C_M_RD)
#define MLXCPLD_I2C_BUS_NUM 1
#define MLXCPLD_I2C_DATA_REG_SZ 36
+#define MLXCPLD_I2C_DATA_SZ_BIT BIT(5)
+#define MLXCPLD_I2C_DATA_SZ_MASK GENMASK(6, 5)
+#define MLXCPLD_I2C_SMBUS_BLK_BIT BIT(7)
#define MLXCPLD_I2C_MAX_ADDR_LEN 4
#define MLXCPLD_I2C_RETR_NUM 2
#define MLXCPLD_I2C_XFER_TO 500000 /* usec */
#define MLXCPLD_I2C_POLL_TIME 2000 /* usec */
/* LPC I2C registers */
-#define MLXCPLD_LPCI2C_LPF_REG 0x0
+#define MLXCPLD_LPCI2C_CPBLTY_REG 0x0
#define MLXCPLD_LPCI2C_CTRL_REG 0x1
#define MLXCPLD_LPCI2C_HALF_CYC_REG 0x4
#define MLXCPLD_LPCI2C_I2C_HOLD_REG 0x5
@@ -83,6 +86,7 @@ struct mlxcpld_i2c_priv {
struct mutex lock;
struct mlxcpld_i2c_curr_xfer xfer;
struct device *dev;
+ bool smbus_block;
};
static void mlxcpld_i2c_lpc_write_buf(u8 *data, u8 len, u32 addr)
@@ -230,7 +234,7 @@ static void mlxcpld_i2c_set_transf_data(struct mlxcpld_i2c_priv *priv,
* All upper layers currently are never use transfer with more than
* 2 messages. Actually, it's also not so relevant in Mellanox systems
* because of HW limitation. Max size of transfer is not more than 32
- * bytes in the current x86 LPCI2C bridge.
+ * or 68 bytes in the current x86 LPCI2C bridge.
*/
priv->xfer.cmd = msgs[num - 1].flags & I2C_M_RD;
@@ -295,7 +299,7 @@ static int mlxcpld_i2c_wait_for_free(struct mlxcpld_i2c_priv *priv)
static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
{
int status, i, timeout = 0;
- u8 datalen;
+ u8 datalen, val;
do {
usleep_range(MLXCPLD_I2C_POLL_TIME / 2, MLXCPLD_I2C_POLL_TIME);
@@ -324,9 +328,22 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
* Actual read data len will be always the same as
* requested len. 0xff (line pull-up) will be returned
* if slave has no data to return. Thus don't read
- * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD.
+ * MLXCPLD_LPCI2C_NUM_DAT_REG reg from CPLD. Only in case of
+ * SMBus block read transaction data len can be different,
+ * check this case.
*/
- datalen = priv->xfer.data_len;
+ mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val,
+ 1);
+ if (priv->smbus_block && (val & MLXCPLD_I2C_SMBUS_BLK_BIT)) {
+ mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
+ &datalen, 1);
+ if (unlikely(datalen > (I2C_SMBUS_BLOCK_MAX + 1))) {
+ dev_err(priv->dev, "Incorrect smbus block read message len\n");
+ return -E2BIG;
+ }
+ } else {
+ datalen = priv->xfer.data_len;
+ }
mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_DATA_REG,
priv->xfer.msg[i].buf, datalen);
@@ -344,12 +361,20 @@ static int mlxcpld_i2c_wait_for_tc(struct mlxcpld_i2c_priv *priv)
static void mlxcpld_i2c_xfer_msg(struct mlxcpld_i2c_priv *priv)
{
int i, len = 0;
- u8 cmd;
+ u8 cmd, val;
mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_DAT_REG,
&priv->xfer.data_len, 1);
- mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG,
- &priv->xfer.addr_width, 1);
+
+ val = priv->xfer.addr_width;
+ /* Notify HW about SMBus block read transaction */
+ if (priv->smbus_block && priv->xfer.msg_num >= 2 &&
+ priv->xfer.msg[1].len == 1 &&
+ (priv->xfer.msg[1].flags & I2C_M_RECV_LEN) &&
+ (priv->xfer.msg[1].flags & I2C_M_RD))
+ val |= MLXCPLD_I2C_SMBUS_BLK_BIT;
+
+ mlxcpld_i2c_write_comm(priv, MLXCPLD_LPCI2C_NUM_ADDR_REG, &val, 1);
for (i = 0; i < priv->xfer.msg_num; i++) {
if ((priv->xfer.msg[i].flags & I2C_M_RD) != I2C_M_RD) {
@@ -425,7 +450,14 @@ static int mlxcpld_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
static u32 mlxcpld_i2c_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_BLOCK_DATA;
+ struct mlxcpld_i2c_priv *priv = i2c_get_adapdata(adap);
+
+ if (priv->smbus_block)
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_BLOCK_DATA;
+ else
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+ I2C_FUNC_SMBUS_I2C_BLOCK;
}
static const struct i2c_algorithm mlxcpld_i2c_algo = {
@@ -440,6 +472,13 @@ static const struct i2c_adapter_quirks mlxcpld_i2c_quirks = {
.max_comb_1st_msg_len = 4,
};
+static const struct i2c_adapter_quirks mlxcpld_i2c_quirks_ext = {
+ .flags = I2C_AQ_COMB_WRITE_THEN_READ,
+ .max_read_len = MLXCPLD_I2C_DATA_REG_SZ * 2 - MLXCPLD_I2C_MAX_ADDR_LEN,
+ .max_write_len = MLXCPLD_I2C_DATA_REG_SZ * 2,
+ .max_comb_1st_msg_len = 4,
+};
+
static struct i2c_adapter mlxcpld_i2c_adapter = {
.owner = THIS_MODULE,
.name = "i2c-mlxcpld",
@@ -454,6 +493,7 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
{
struct mlxcpld_i2c_priv *priv;
int err;
+ u8 val;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -466,6 +506,16 @@ static int mlxcpld_i2c_probe(struct platform_device *pdev)
/* Register with i2c layer */
mlxcpld_i2c_adapter.timeout = usecs_to_jiffies(MLXCPLD_I2C_XFER_TO);
+ /* Read capability register */
+ mlxcpld_i2c_read_comm(priv, MLXCPLD_LPCI2C_CPBLTY_REG, &val, 1);
+ /* Check support for extended transaction length */
+ if ((val & MLXCPLD_I2C_DATA_SZ_MASK) == MLXCPLD_I2C_DATA_SZ_BIT)
+ mlxcpld_i2c_adapter.quirks = &mlxcpld_i2c_quirks_ext;
+ /* Check support for smbus block transaction */
+ if (val & MLXCPLD_I2C_SMBUS_BLK_BIT)
+ priv->smbus_block = true;
+ if (pdev->id >= -1)
+ mlxcpld_i2c_adapter.nr = pdev->id;
priv->adap = mlxcpld_i2c_adapter;
priv->adap.dev.parent = &pdev->dev;
priv->base_addr = MLXPLAT_CPLD_LPC_I2C_BASE_ADDR;
diff --git a/drivers/i2c/busses/i2c-mt65xx.c b/drivers/i2c/busses/i2c-mt65xx.c
index cf23a74..1e57f58 100644
--- a/drivers/i2c/busses/i2c-mt65xx.c
+++ b/drivers/i2c/busses/i2c-mt65xx.c
@@ -27,6 +27,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/scatterlist.h>
@@ -734,7 +735,6 @@ static int mtk_i2c_parse_dt(struct device_node *np, struct mtk_i2c *i2c)
static int mtk_i2c_probe(struct platform_device *pdev)
{
- const struct of_device_id *of_id;
int ret = 0;
struct mtk_i2c *i2c;
struct clk *clk;
@@ -761,11 +761,7 @@ static int mtk_i2c_probe(struct platform_device *pdev)
init_completion(&i2c->msg_complete);
- of_id = of_match_node(mtk_i2c_of_match, pdev->dev.of_node);
- if (!of_id)
- return -EINVAL;
-
- i2c->dev_comp = of_id->data;
+ i2c->dev_comp = of_device_get_match_data(&pdev->dev);
i2c->adap.dev.of_node = pdev->dev.of_node;
i2c->dev = &pdev->dev;
i2c->adap.dev.parent = &pdev->dev;
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index e617bd6..642c589 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Freescale MXS I2C bus driver
*
@@ -7,12 +8,6 @@
* based on a (non-working) driver which was:
*
* Copyright (C) 2009-2010 Freescale Semiconductor, Inc. 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 as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
*/
#include <linux/slab.h>
@@ -180,9 +175,10 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
struct dma_async_tx_descriptor *desc;
struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
+ i2c->addr_data = i2c_8bit_addr_from_msg(msg);
+
if (msg->flags & I2C_M_RD) {
i2c->dma_read = true;
- i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_READ;
/*
* SELECT command.
@@ -240,7 +236,6 @@ static int mxs_i2c_dma_setup_xfer(struct i2c_adapter *adap,
}
} else {
i2c->dma_read = false;
- i2c->addr_data = (msg->addr << 1) | I2C_SMBUS_WRITE;
/*
* WRITE command.
@@ -371,7 +366,7 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
struct i2c_msg *msg, uint32_t flags)
{
struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
- uint32_t addr_data = msg->addr << 1;
+ uint32_t addr_data = i2c_8bit_addr_from_msg(msg);
uint32_t data = 0;
int i, ret, xlen = 0, xmit = 0;
uint32_t start;
@@ -411,8 +406,6 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
*/
BUG_ON(msg->len > 4);
- addr_data |= I2C_SMBUS_READ;
-
/* SELECT command. */
mxs_i2c_pio_trigger_write_cmd(i2c, MXS_CMD_I2C_SELECT,
addr_data);
@@ -450,7 +443,6 @@ static int mxs_i2c_pio_setup_xfer(struct i2c_adapter *adap,
* fast enough. It is possible to transfer arbitrary amount
* of data using PIO write.
*/
- addr_data |= I2C_SMBUS_WRITE;
/*
* The LSB of data buffer is the first byte blasted across
diff --git a/drivers/i2c/busses/i2c-nforce2-s4985.c b/drivers/i2c/busses/i2c-nforce2-s4985.c
index 88eda09..58a0fbf 100644
--- a/drivers/i2c/busses/i2c-nforce2-s4985.c
+++ b/drivers/i2c/busses/i2c-nforce2-s4985.c
@@ -164,12 +164,12 @@ static int __init nforce2_s4985_init(void)
printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4985\n");
/* Define the 5 virtual adapters and algorithms structures */
- s4985_adapter = kzalloc(5 * sizeof(struct i2c_adapter), GFP_KERNEL);
+ s4985_adapter = kcalloc(5, sizeof(struct i2c_adapter), GFP_KERNEL);
if (!s4985_adapter) {
error = -ENOMEM;
goto ERROR1;
}
- s4985_algo = kzalloc(5 * sizeof(struct i2c_algorithm), GFP_KERNEL);
+ s4985_algo = kcalloc(5, sizeof(struct i2c_algorithm), GFP_KERNEL);
if (!s4985_algo) {
error = -ENOMEM;
goto ERROR2;
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index 3241bb9..f6a1272 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -381,7 +381,7 @@ static int nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)
int res1, res2;
/* we support 2 SMBus adapters */
- smbuses = kzalloc(2 * sizeof(struct nforce2_smbus), GFP_KERNEL);
+ smbuses = kcalloc(2, sizeof(struct nforce2_smbus), GFP_KERNEL);
if (!smbuses)
return -ENOMEM;
pci_set_drvdata(dev, smbuses);
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index 49c7c0c..0ed5a41 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -1012,8 +1012,6 @@ static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
goto err_no_mem;
}
- pm_suspend_ignore_children(&adev->dev, true);
-
dev->clk = devm_clk_get(&adev->dev, NULL);
if (IS_ERR(dev->clk)) {
dev_err(&adev->dev, "could not get i2c clock\n");
diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index 45ae3c0..88444ef 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -21,7 +21,7 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
-#include <linux/i2c-ocores.h>
+#include <linux/platform_data/i2c-ocores.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/log2.h>
@@ -222,10 +222,7 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
i2c->nmsgs = num;
i2c->state = STATE_START;
- oc_setreg(i2c, OCI2C_DATA,
- (i2c->msg->addr << 1) |
- ((i2c->msg->flags & I2C_M_RD) ? 1:0));
-
+ oc_setreg(i2c, OCI2C_DATA, i2c_8bit_addr_from_msg(i2c->msg));
oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START);
if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) ||
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index b9172f0..65d06a8 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -36,7 +36,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/slab.h>
-#include <linux/i2c-omap.h>
+#include <linux/platform_data/i2c-omap.h>
#include <linux/pm_runtime.h>
#include <linux/pinctrl/consumer.h>
diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c
index 0aabb7e..dc2a23f 100644
--- a/drivers/i2c/busses/i2c-opal.c
+++ b/drivers/i2c/busses/i2c-opal.c
@@ -94,8 +94,6 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
*/
memset(&req, 0, sizeof(req));
switch(num) {
- case 0:
- return 0;
case 1:
req.type = (msgs[0].flags & I2C_M_RD) ?
OPAL_I2C_RAW_READ : OPAL_I2C_RAW_WRITE;
@@ -114,8 +112,6 @@ static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
req.size = cpu_to_be32(msgs[1].len);
req.buffer_ra = cpu_to_be64(__pa(msgs[1].buf));
break;
- default:
- return -EOPNOTSUPP;
}
rc = i2c_opal_send_request(opal_id, &req);
diff --git a/drivers/i2c/busses/i2c-pasemi.c b/drivers/i2c/busses/i2c-pasemi.c
index df1dbc9..55fd5c6 100644
--- a/drivers/i2c/busses/i2c-pasemi.c
+++ b/drivers/i2c/busses/i2c-pasemi.c
@@ -121,7 +121,7 @@ static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter,
read = msg->flags & I2C_M_RD ? 1 : 0;
- TXFIFO_WR(smbus, MTXFIFO_START | (msg->addr << 1) | read);
+ TXFIFO_WR(smbus, MTXFIFO_START | i2c_8bit_addr_from_msg(msg));
if (read) {
TXFIFO_WR(smbus, msg->len | MTXFIFO_READ |
diff --git a/drivers/i2c/busses/i2c-pca-platform.c b/drivers/i2c/busses/i2c-pca-platform.c
index bc2707f..de3fe6e 100644
--- a/drivers/i2c/busses/i2c-pca-platform.c
+++ b/drivers/i2c/busses/i2c-pca-platform.c
@@ -20,7 +20,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c-algo-pca.h>
-#include <linux/i2c-pca-platform.h>
+#include <linux/platform_data/i2c-pca-platform.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/io.h>
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index a542041..6e0e546 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -18,7 +18,6 @@
#include <linux/timer.h>
#include <linux/completion.h>
#include <linux/platform_device.h>
-#include <linux/i2c-pnx.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/clk.h>
@@ -29,6 +28,26 @@
#define I2C_PNX_SPEED_KHZ_DEFAULT 100
#define I2C_PNX_REGION_SIZE 0x100
+struct i2c_pnx_mif {
+ int ret; /* Return value */
+ int mode; /* Interface mode */
+ struct completion complete; /* I/O completion */
+ struct timer_list timer; /* Timeout */
+ u8 * buf; /* Data buffer */
+ int len; /* Length of data buffer */
+ int order; /* RX Bytes to order via TX */
+};
+
+struct i2c_pnx_algo_data {
+ void __iomem *ioaddr;
+ struct i2c_pnx_mif mif;
+ int last;
+ struct clk *clk;
+ struct i2c_adapter adapter;
+ int irq;
+ u32 timeout;
+};
+
enum {
mstatus_tdi = 0x00000001,
mstatus_afi = 0x00000002,
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 904dfec..c86c3ae 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -136,8 +136,13 @@
*/
#define TOUT_MIN 2
+/* I2C Frequency Modes */
+#define I2C_STANDARD_FREQ 100000
+#define I2C_FAST_MODE_FREQ 400000
+#define I2C_FAST_MODE_PLUS_FREQ 1000000
+
/* Default values. Use these if FW query fails */
-#define DEFAULT_CLK_FREQ 100000
+#define DEFAULT_CLK_FREQ I2C_STANDARD_FREQ
#define DEFAULT_SRC_CLK 20000000
/*
@@ -150,6 +155,10 @@
/* TAG length for DATA READ in RX FIFO */
#define READ_RX_TAGS_LEN 2
+static unsigned int scl_freq;
+module_param_named(scl_freq, scl_freq, uint, 0444);
+MODULE_PARM_DESC(scl_freq, "SCL frequency override");
+
/*
* count: no of blocks
* pos: current block number
@@ -453,7 +462,7 @@ static void qup_i2c_write_tx_fifo_v1(struct qup_i2c_dev *qup)
{
struct qup_i2c_block *blk = &qup->blk;
struct i2c_msg *msg = qup->msg;
- u32 addr = msg->addr << 1;
+ u32 addr = i2c_8bit_addr_from_msg(msg);
u32 qup_tag;
int idx;
u32 val;
@@ -1648,6 +1657,12 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
clk_disable_unprepare(qup->pclk);
}
+static const struct acpi_device_id qup_i2c_acpi_match[] = {
+ { "QCOM8010"},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_match);
+
static int qup_i2c_probe(struct platform_device *pdev)
{
static const int blk_sizes[] = {4, 16, 32};
@@ -1669,10 +1684,15 @@ static int qup_i2c_probe(struct platform_device *pdev)
init_completion(&qup->xfer);
platform_set_drvdata(pdev, qup);
- ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
- if (ret) {
- dev_notice(qup->dev, "using default clock-frequency %d",
- DEFAULT_CLK_FREQ);
+ if (scl_freq) {
+ dev_notice(qup->dev, "Using override frequency of %u\n", scl_freq);
+ clk_freq = scl_freq;
+ } else {
+ ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
+ if (ret) {
+ dev_notice(qup->dev, "using default clock-frequency %d",
+ DEFAULT_CLK_FREQ);
+ }
}
if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
@@ -1682,7 +1702,10 @@ static int qup_i2c_probe(struct platform_device *pdev)
} else {
qup->adap.algo = &qup_i2c_algo_v2;
is_qup_v1 = false;
- ret = qup_i2c_req_dma(qup);
+ if (acpi_match_device(qup_i2c_acpi_match, qup->dev))
+ goto nodma;
+ else
+ ret = qup_i2c_req_dma(qup);
if (ret == -EPROBE_DEFER)
goto fail_dma;
@@ -1691,8 +1714,8 @@ static int qup_i2c_probe(struct platform_device *pdev)
qup->max_xfer_sg_len = (MX_BLOCKS << 1);
blocks = (MX_DMA_BLOCKS << 1) + 1;
- qup->btx.sg = devm_kzalloc(&pdev->dev,
- sizeof(*qup->btx.sg) * blocks,
+ qup->btx.sg = devm_kcalloc(&pdev->dev,
+ blocks, sizeof(*qup->btx.sg),
GFP_KERNEL);
if (!qup->btx.sg) {
ret = -ENOMEM;
@@ -1700,8 +1723,8 @@ static int qup_i2c_probe(struct platform_device *pdev)
}
sg_init_table(qup->btx.sg, blocks);
- qup->brx.sg = devm_kzalloc(&pdev->dev,
- sizeof(*qup->brx.sg) * blocks,
+ qup->brx.sg = devm_kcalloc(&pdev->dev,
+ blocks, sizeof(*qup->brx.sg),
GFP_KERNEL);
if (!qup->brx.sg) {
ret = -ENOMEM;
@@ -1734,8 +1757,8 @@ static int qup_i2c_probe(struct platform_device *pdev)
}
nodma:
- /* We support frequencies up to FAST Mode (400KHz) */
- if (!clk_freq || clk_freq > 400000) {
+ /* We support frequencies up to FAST Mode Plus (1MHz) */
+ if (!clk_freq || clk_freq > I2C_FAST_MODE_PLUS_FREQ) {
dev_err(qup->dev, "clock frequency not supported %d\n",
clk_freq);
return -EINVAL;
@@ -1839,9 +1862,15 @@ nodma:
size = QUP_INPUT_FIFO_SIZE(io_mode);
qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
- fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
hs_div = 3;
- qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
+ if (clk_freq <= I2C_STANDARD_FREQ) {
+ fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
+ qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
+ } else {
+ /* 33%/66% duty cycle */
+ fs_div = ((src_clk_freq / clk_freq) - 6) * 2 / 3;
+ qup->clk_ctl = ((fs_div / 2) << 16) | (hs_div << 8) | (fs_div & 0xff);
+ }
/*
* Time it takes for a byte to be clocked out on the bus.
@@ -1959,14 +1988,6 @@ static const struct of_device_id qup_i2c_dt_match[] = {
};
MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
-#if IS_ENABLED(CONFIG_ACPI)
-static const struct acpi_device_id qup_i2c_acpi_match[] = {
- { "QCOM8010"},
- { },
-};
-MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_match);
-#endif
-
static struct platform_driver qup_i2c_driver = {
.probe = qup_i2c_probe,
.remove = qup_i2c_remove,
diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c
index c6915b8..5e310ef 100644
--- a/drivers/i2c/busses/i2c-rcar.c
+++ b/drivers/i2c/busses/i2c-rcar.c
@@ -329,7 +329,7 @@ static void rcar_i2c_prepare_msg(struct rcar_i2c_priv *priv)
if (priv->msgs_left == 1)
priv->flags |= ID_LAST_MSG;
- rcar_i2c_write(priv, ICMAR, (priv->msg->addr << 1) | read);
+ rcar_i2c_write(priv, ICMAR, i2c_8bit_addr_from_msg(priv->msg));
/*
* We don't have a test case but the HW engineers say that the write order
* of ICMSR and ICMCR depends on whether we issue START or REP_START. Since
@@ -542,6 +542,8 @@ static void rcar_i2c_irq_recv(struct rcar_i2c_priv *priv, u32 msr)
* If next received data is the _LAST_, go to STOP phase. Might be
* overwritten by REP START when setting up a new msg. Not elegant
* but the only stable sequence for REP START I have found so far.
+ * If you want to change this code, make sure sending one transfer with
+ * four messages (WR-RD-WR-RD) works!
*/
if (priv->pos + 1 >= msg->len)
rcar_i2c_write(priv, ICMCR, RCAR_BUS_PHASE_STOP);
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
index 95c2f1c..5f1fca7 100644
--- a/drivers/i2c/busses/i2c-riic.c
+++ b/drivers/i2c/busses/i2c-riic.c
@@ -167,15 +167,14 @@ static irqreturn_t riic_tdre_isr(int irq, void *data)
return IRQ_NONE;
if (riic->bytes_left == RIIC_INIT_MSG) {
- val = !!(riic->msg->flags & I2C_M_RD);
- if (val)
+ if (riic->msg->flags & I2C_M_RD)
/* On read, switch over to receive interrupt */
riic_clear_set_bit(riic, ICIER_TIE, ICIER_RIE, RIIC_ICIER);
else
/* On write, initialize length */
riic->bytes_left = riic->msg->len;
- val |= (riic->msg->addr << 1);
+ val = i2c_8bit_addr_from_msg(riic->msg);
} else {
val = *riic->buf;
riic->buf++;
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index e1a18d9..b8a2728 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -1326,8 +1326,6 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
if (ret < 0)
goto err_clk_notifier;
- dev_info(&pdev->dev, "Initialized RK3xxx I2C bus at %p\n", i2c->regs);
-
return 0;
err_clk_notifier:
diff --git a/drivers/i2c/busses/i2c-robotfuzz-osif.c b/drivers/i2c/busses/i2c-robotfuzz-osif.c
index 9c0f52b..d848cf5 100644
--- a/drivers/i2c/busses/i2c-robotfuzz-osif.c
+++ b/drivers/i2c/busses/i2c-robotfuzz-osif.c
@@ -62,27 +62,24 @@ static int osif_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
{
struct osif_priv *priv = adapter->algo_data;
struct i2c_msg *pmsg;
- int ret = 0;
- int i, cmd;
+ int ret;
+ int i;
- for (i = 0; ret >= 0 && i < num; i++) {
+ for (i = 0; i < num; i++) {
pmsg = &msgs[i];
if (pmsg->flags & I2C_M_RD) {
- cmd = OSIFI2C_READ;
-
- ret = osif_usb_read(adapter, cmd, pmsg->flags,
- pmsg->addr, pmsg->buf,
- pmsg->len);
+ ret = osif_usb_read(adapter, OSIFI2C_READ,
+ pmsg->flags, pmsg->addr,
+ pmsg->buf, pmsg->len);
if (ret != pmsg->len) {
dev_err(&adapter->dev, "failure reading data\n");
return -EREMOTEIO;
}
} else {
- cmd = OSIFI2C_WRITE;
-
- ret = osif_usb_write(adapter, cmd, pmsg->flags,
- pmsg->addr, pmsg->buf, pmsg->len);
+ ret = osif_usb_write(adapter, OSIFI2C_WRITE,
+ pmsg->flags, pmsg->addr,
+ pmsg->buf, pmsg->len);
if (ret != pmsg->len) {
dev_err(&adapter->dev, "failure writing data\n");
return -EREMOTEIO;
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index 5d97510..9fe2b69 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -154,8 +154,6 @@ static const struct of_device_id s3c24xx_i2c_match[] = {
{ .compatible = "samsung,s3c2440-i2c", .data = (void *)QUIRK_S3C2440 },
{ .compatible = "samsung,s3c2440-hdmiphy-i2c",
.data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) },
- { .compatible = "samsung,exynos5440-i2c",
- .data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) },
{ .compatible = "samsung,exynos5-sata-phy-i2c",
.data = (void *)(QUIRK_S3C2440 | QUIRK_POLL | QUIRK_NO_GPIO) },
{},
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index d856bc2..5fda418 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -899,17 +899,6 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
if (resource_size(res) > 0x17)
pd->flags |= IIC_FLAG_HAS_ICIC67;
- /* Enable Runtime PM for this device.
- *
- * Also tell the Runtime PM core to ignore children
- * for this device since it is valid for us to suspend
- * this I2C master driver even though the slave devices
- * on the I2C bus may not be suspended.
- *
- * The state of the I2C hardware bus is unaffected by
- * the Runtime PM state.
- */
- pm_suspend_ignore_children(&dev->dev, true);
pm_runtime_enable(&dev->dev);
pm_runtime_get_sync(&dev->dev);
diff --git a/drivers/i2c/busses/i2c-stm32.c b/drivers/i2c/busses/i2c-stm32.c
new file mode 100644
index 0000000..d75fbcb
--- /dev/null
+++ b/drivers/i2c/busses/i2c-stm32.c
@@ -0,0 +1,153 @@
+/*
+ * i2c-stm32.c
+ *
+ * Copyright (C) M'boumba Cedric Madianga 2017
+ * Author: M'boumba Cedric Madianga <cedric.madianga@gmail.com>
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include "i2c-stm32.h"
+
+/* Functions for DMA support */
+struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
+ dma_addr_t phy_addr,
+ u32 txdr_offset,
+ u32 rxdr_offset)
+{
+ struct stm32_i2c_dma *dma;
+ struct dma_slave_config dma_sconfig;
+ int ret;
+
+ dma = devm_kzalloc(dev, sizeof(*dma), GFP_KERNEL);
+ if (!dma)
+ return NULL;
+
+ /* Request and configure I2C TX dma channel */
+ dma->chan_tx = dma_request_slave_channel(dev, "tx");
+ if (!dma->chan_tx) {
+ dev_dbg(dev, "can't request DMA tx channel\n");
+ ret = -EINVAL;
+ goto fail_al;
+ }
+
+ memset(&dma_sconfig, 0, sizeof(dma_sconfig));
+ dma_sconfig.dst_addr = phy_addr + txdr_offset;
+ dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ dma_sconfig.dst_maxburst = 1;
+ dma_sconfig.direction = DMA_MEM_TO_DEV;
+ ret = dmaengine_slave_config(dma->chan_tx, &dma_sconfig);
+ if (ret < 0) {
+ dev_err(dev, "can't configure tx channel\n");
+ goto fail_tx;
+ }
+
+ /* Request and configure I2C RX dma channel */
+ dma->chan_rx = dma_request_slave_channel(dev, "rx");
+ if (!dma->chan_rx) {
+ dev_err(dev, "can't request DMA rx channel\n");
+ ret = -EINVAL;
+ goto fail_tx;
+ }
+
+ memset(&dma_sconfig, 0, sizeof(dma_sconfig));
+ dma_sconfig.src_addr = phy_addr + rxdr_offset;
+ dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ dma_sconfig.src_maxburst = 1;
+ dma_sconfig.direction = DMA_DEV_TO_MEM;
+ ret = dmaengine_slave_config(dma->chan_rx, &dma_sconfig);
+ if (ret < 0) {
+ dev_err(dev, "can't configure rx channel\n");
+ goto fail_rx;
+ }
+
+ init_completion(&dma->dma_complete);
+
+ dev_info(dev, "using %s (tx) and %s (rx) for DMA transfers\n",
+ dma_chan_name(dma->chan_tx), dma_chan_name(dma->chan_rx));
+
+ return dma;
+
+fail_rx:
+ dma_release_channel(dma->chan_rx);
+fail_tx:
+ dma_release_channel(dma->chan_tx);
+fail_al:
+ devm_kfree(dev, dma);
+ dev_info(dev, "can't use DMA\n");
+
+ return NULL;
+}
+
+void stm32_i2c_dma_free(struct stm32_i2c_dma *dma)
+{
+ dma->dma_buf = 0;
+ dma->dma_len = 0;
+
+ dma_release_channel(dma->chan_tx);
+ dma->chan_tx = NULL;
+
+ dma_release_channel(dma->chan_rx);
+ dma->chan_rx = NULL;
+
+ dma->chan_using = NULL;
+}
+
+int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma,
+ bool rd_wr, u32 len, u8 *buf,
+ dma_async_tx_callback callback,
+ void *dma_async_param)
+{
+ struct dma_async_tx_descriptor *txdesc;
+ struct device *chan_dev;
+ int ret;
+
+ if (rd_wr) {
+ dma->chan_using = dma->chan_rx;
+ dma->dma_transfer_dir = DMA_DEV_TO_MEM;
+ dma->dma_data_dir = DMA_FROM_DEVICE;
+ } else {
+ dma->chan_using = dma->chan_tx;
+ dma->dma_transfer_dir = DMA_MEM_TO_DEV;
+ dma->dma_data_dir = DMA_TO_DEVICE;
+ }
+
+ dma->dma_len = len;
+ chan_dev = dma->chan_using->device->dev;
+
+ dma->dma_buf = dma_map_single(chan_dev, buf, dma->dma_len,
+ dma->dma_data_dir);
+ if (dma_mapping_error(chan_dev, dma->dma_buf)) {
+ dev_err(dev, "DMA mapping failed\n");
+ return -EINVAL;
+ }
+
+ txdesc = dmaengine_prep_slave_single(dma->chan_using, dma->dma_buf,
+ dma->dma_len,
+ dma->dma_transfer_dir,
+ DMA_PREP_INTERRUPT);
+ if (!txdesc) {
+ dev_err(dev, "Not able to get desc for DMA xfer\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ reinit_completion(&dma->dma_complete);
+
+ txdesc->callback = callback;
+ txdesc->callback_param = dma_async_param;
+ ret = dma_submit_error(dmaengine_submit(txdesc));
+ if (ret < 0) {
+ dev_err(dev, "DMA submit failed\n");
+ goto err;
+ }
+
+ dma_async_issue_pending(dma->chan_using);
+
+ return 0;
+
+err:
+ dma_unmap_single(chan_dev, dma->dma_buf, dma->dma_len,
+ dma->dma_data_dir);
+ return ret;
+}
diff --git a/drivers/i2c/busses/i2c-stm32.h b/drivers/i2c/busses/i2c-stm32.h
index d4f9cef..868755f 100644
--- a/drivers/i2c/busses/i2c-stm32.h
+++ b/drivers/i2c/busses/i2c-stm32.h
@@ -11,6 +11,10 @@
#ifndef _I2C_STM32_H
#define _I2C_STM32_H
+#include <linux/dma-direction.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+
enum stm32_i2c_speed {
STM32_I2C_SPEED_STANDARD, /* 100 kHz */
STM32_I2C_SPEED_FAST, /* 400 kHz */
@@ -18,4 +22,37 @@ enum stm32_i2c_speed {
STM32_I2C_SPEED_END,
};
+/**
+ * struct stm32_i2c_dma - DMA specific data
+ * @chan_tx: dma channel for TX transfer
+ * @chan_rx: dma channel for RX transfer
+ * @chan_using: dma channel used for the current transfer (TX or RX)
+ * @dma_buf: dma buffer
+ * @dma_len: dma buffer len
+ * @dma_transfer_dir: dma transfer direction indicator
+ * @dma_data_dir: dma transfer mode indicator
+ * @dma_complete: dma transfer completion
+ */
+struct stm32_i2c_dma {
+ struct dma_chan *chan_tx;
+ struct dma_chan *chan_rx;
+ struct dma_chan *chan_using;
+ dma_addr_t dma_buf;
+ unsigned int dma_len;
+ enum dma_transfer_direction dma_transfer_dir;
+ enum dma_data_direction dma_data_dir;
+ struct completion dma_complete;
+};
+
+struct stm32_i2c_dma *stm32_i2c_dma_request(struct device *dev,
+ dma_addr_t phy_addr,
+ u32 txdr_offset, u32 rxdr_offset);
+
+void stm32_i2c_dma_free(struct stm32_i2c_dma *dma);
+
+int stm32_i2c_prep_dma_xfer(struct device *dev, struct stm32_i2c_dma *dma,
+ bool rd_wr, u32 len, u8 *buf,
+ dma_async_tx_callback callback,
+ void *dma_async_param);
+
#endif /* _I2C_STM32_H */
diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c
index f273e28..62d023e 100644
--- a/drivers/i2c/busses/i2c-stm32f7.c
+++ b/drivers/i2c/busses/i2c-stm32f7.c
@@ -35,6 +35,9 @@
/* STM32F7 I2C registers */
#define STM32F7_I2C_CR1 0x00
#define STM32F7_I2C_CR2 0x04
+#define STM32F7_I2C_OAR1 0x08
+#define STM32F7_I2C_OAR2 0x0C
+#define STM32F7_I2C_PECR 0x20
#define STM32F7_I2C_TIMINGR 0x10
#define STM32F7_I2C_ISR 0x18
#define STM32F7_I2C_ICR 0x1C
@@ -42,6 +45,10 @@
#define STM32F7_I2C_TXDR 0x28
/* STM32F7 I2C control 1 */
+#define STM32F7_I2C_CR1_PECEN BIT(23)
+#define STM32F7_I2C_CR1_SBC BIT(16)
+#define STM32F7_I2C_CR1_RXDMAEN BIT(15)
+#define STM32F7_I2C_CR1_TXDMAEN BIT(14)
#define STM32F7_I2C_CR1_ANFOFF BIT(12)
#define STM32F7_I2C_CR1_ERRIE BIT(7)
#define STM32F7_I2C_CR1_TCIE BIT(6)
@@ -57,34 +64,77 @@
| STM32F7_I2C_CR1_NACKIE \
| STM32F7_I2C_CR1_RXIE \
| STM32F7_I2C_CR1_TXIE)
+#define STM32F7_I2C_XFER_IRQ_MASK (STM32F7_I2C_CR1_TCIE \
+ | STM32F7_I2C_CR1_STOPIE \
+ | STM32F7_I2C_CR1_NACKIE \
+ | STM32F7_I2C_CR1_RXIE \
+ | STM32F7_I2C_CR1_TXIE)
/* STM32F7 I2C control 2 */
+#define STM32F7_I2C_CR2_PECBYTE BIT(26)
#define STM32F7_I2C_CR2_RELOAD BIT(24)
#define STM32F7_I2C_CR2_NBYTES_MASK GENMASK(23, 16)
#define STM32F7_I2C_CR2_NBYTES(n) (((n) & 0xff) << 16)
#define STM32F7_I2C_CR2_NACK BIT(15)
#define STM32F7_I2C_CR2_STOP BIT(14)
#define STM32F7_I2C_CR2_START BIT(13)
+#define STM32F7_I2C_CR2_HEAD10R BIT(12)
+#define STM32F7_I2C_CR2_ADD10 BIT(11)
#define STM32F7_I2C_CR2_RD_WRN BIT(10)
+#define STM32F7_I2C_CR2_SADD10_MASK GENMASK(9, 0)
+#define STM32F7_I2C_CR2_SADD10(n) (((n) & \
+ STM32F7_I2C_CR2_SADD10_MASK))
#define STM32F7_I2C_CR2_SADD7_MASK GENMASK(7, 1)
#define STM32F7_I2C_CR2_SADD7(n) (((n) & 0x7f) << 1)
+/* STM32F7 I2C Own Address 1 */
+#define STM32F7_I2C_OAR1_OA1EN BIT(15)
+#define STM32F7_I2C_OAR1_OA1MODE BIT(10)
+#define STM32F7_I2C_OAR1_OA1_10_MASK GENMASK(9, 0)
+#define STM32F7_I2C_OAR1_OA1_10(n) (((n) & \
+ STM32F7_I2C_OAR1_OA1_10_MASK))
+#define STM32F7_I2C_OAR1_OA1_7_MASK GENMASK(7, 1)
+#define STM32F7_I2C_OAR1_OA1_7(n) (((n) & 0x7f) << 1)
+#define STM32F7_I2C_OAR1_MASK (STM32F7_I2C_OAR1_OA1_7_MASK \
+ | STM32F7_I2C_OAR1_OA1_10_MASK \
+ | STM32F7_I2C_OAR1_OA1EN \
+ | STM32F7_I2C_OAR1_OA1MODE)
+
+/* STM32F7 I2C Own Address 2 */
+#define STM32F7_I2C_OAR2_OA2EN BIT(15)
+#define STM32F7_I2C_OAR2_OA2MSK_MASK GENMASK(10, 8)
+#define STM32F7_I2C_OAR2_OA2MSK(n) (((n) & 0x7) << 8)
+#define STM32F7_I2C_OAR2_OA2_7_MASK GENMASK(7, 1)
+#define STM32F7_I2C_OAR2_OA2_7(n) (((n) & 0x7f) << 1)
+#define STM32F7_I2C_OAR2_MASK (STM32F7_I2C_OAR2_OA2MSK_MASK \
+ | STM32F7_I2C_OAR2_OA2_7_MASK \
+ | STM32F7_I2C_OAR2_OA2EN)
+
/* STM32F7 I2C Interrupt Status */
+#define STM32F7_I2C_ISR_ADDCODE_MASK GENMASK(23, 17)
+#define STM32F7_I2C_ISR_ADDCODE_GET(n) \
+ (((n) & STM32F7_I2C_ISR_ADDCODE_MASK) >> 17)
+#define STM32F7_I2C_ISR_DIR BIT(16)
#define STM32F7_I2C_ISR_BUSY BIT(15)
+#define STM32F7_I2C_ISR_PECERR BIT(11)
#define STM32F7_I2C_ISR_ARLO BIT(9)
#define STM32F7_I2C_ISR_BERR BIT(8)
#define STM32F7_I2C_ISR_TCR BIT(7)
#define STM32F7_I2C_ISR_TC BIT(6)
#define STM32F7_I2C_ISR_STOPF BIT(5)
#define STM32F7_I2C_ISR_NACKF BIT(4)
+#define STM32F7_I2C_ISR_ADDR BIT(3)
#define STM32F7_I2C_ISR_RXNE BIT(2)
#define STM32F7_I2C_ISR_TXIS BIT(1)
+#define STM32F7_I2C_ISR_TXE BIT(0)
/* STM32F7 I2C Interrupt Clear */
+#define STM32F7_I2C_ICR_PECCF BIT(11)
#define STM32F7_I2C_ICR_ARLOCF BIT(9)
#define STM32F7_I2C_ICR_BERRCF BIT(8)
#define STM32F7_I2C_ICR_STOPCF BIT(5)
#define STM32F7_I2C_ICR_NACKCF BIT(4)
+#define STM32F7_I2C_ICR_ADDRCF BIT(3)
/* STM32F7 I2C Timing */
#define STM32F7_I2C_TIMINGR_PRESC(n) (((n) & 0xf) << 28)
@@ -94,6 +144,8 @@
#define STM32F7_I2C_TIMINGR_SCLL(n) ((n) & 0xff)
#define STM32F7_I2C_MAX_LEN 0xff
+#define STM32F7_I2C_DMA_LEN_MIN 0x16
+#define STM32F7_I2C_MAX_SLAVE 0x2
#define STM32F7_I2C_DNF_DEFAULT 0
#define STM32F7_I2C_DNF_MAX 16
@@ -159,11 +211,12 @@ struct stm32f7_i2c_setup {
/**
* struct stm32f7_i2c_timings - private I2C output parameters
- * @prec: Prescaler value
+ * @node: List entry
+ * @presc: Prescaler value
* @scldel: Data setup time
* @sdadel: Data hold time
* @sclh: SCL high period (master mode)
- * @sclh: SCL low period (master mode)
+ * @scll: SCL low period (master mode)
*/
struct stm32f7_i2c_timings {
struct list_head node;
@@ -176,18 +229,30 @@ struct stm32f7_i2c_timings {
/**
* struct stm32f7_i2c_msg - client specific data
- * @addr: 8-bit slave addr, including r/w bit
+ * @addr: 8-bit or 10-bit slave addr, including r/w bit
* @count: number of bytes to be transferred
* @buf: data buffer
* @result: result of the transfer
* @stop: last I2C msg to be sent, i.e. STOP to be generated
+ * @smbus: boolean to know if the I2C IP is used in SMBus mode
+ * @size: type of SMBus protocol
+ * @read_write: direction of SMBus protocol
+ * SMBus block read and SMBus block write - block read process call protocols
+ * @smbus_buf: buffer to be used for SMBus protocol transfer. It will
+ * contain a maximum of 32 bytes of data + byte command + byte count + PEC
+ * This buffer has to be 32-bit aligned to be compliant with memory address
+ * register in DMA mode.
*/
struct stm32f7_i2c_msg {
- u8 addr;
+ u16 addr;
u32 count;
u8 *buf;
int result;
bool stop;
+ bool smbus;
+ int size;
+ char read_write;
+ u8 smbus_buf[I2C_SMBUS_BLOCK_MAX + 3] __aligned(4);
};
/**
@@ -204,6 +269,13 @@ struct stm32f7_i2c_msg {
* @f7_msg: customized i2c msg for driver usage
* @setup: I2C timing input setup
* @timing: I2C computed timings
+ * @slave: list of slave devices registered on the I2C bus
+ * @slave_running: slave device currently used
+ * @slave_dir: transfer direction for the current slave device
+ * @master_mode: boolean to know in which mode the I2C is running (master or
+ * slave)
+ * @dma: dma data
+ * @use_dma: boolean to know if dma is used in the current transfer
*/
struct stm32f7_i2c_dev {
struct i2c_adapter adap;
@@ -218,6 +290,12 @@ struct stm32f7_i2c_dev {
struct stm32f7_i2c_msg f7_msg;
struct stm32f7_i2c_setup setup;
struct stm32f7_i2c_timings timing;
+ struct i2c_client *slave[STM32F7_I2C_MAX_SLAVE];
+ struct i2c_client *slave_running;
+ u32 slave_dir;
+ bool master_mode;
+ struct stm32_i2c_dma *dma;
+ bool use_dma;
};
/**
@@ -283,6 +361,11 @@ static inline void stm32f7_i2c_clr_bits(void __iomem *reg, u32 mask)
writel_relaxed(readl_relaxed(reg) & ~mask, reg);
}
+static void stm32f7_i2c_disable_irq(struct stm32f7_i2c_dev *i2c_dev, u32 mask)
+{
+ stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, mask);
+}
+
static int stm32f7_i2c_compute_timing(struct stm32f7_i2c_dev *i2c_dev,
struct stm32f7_i2c_setup *setup,
struct stm32f7_i2c_timings *output)
@@ -524,6 +607,25 @@ static int stm32f7_i2c_setup_timing(struct stm32f7_i2c_dev *i2c_dev,
return 0;
}
+static void stm32f7_i2c_disable_dma_req(struct stm32f7_i2c_dev *i2c_dev)
+{
+ void __iomem *base = i2c_dev->base;
+ u32 mask = STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN;
+
+ stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
+}
+
+static void stm32f7_i2c_dma_callback(void *arg)
+{
+ struct stm32f7_i2c_dev *i2c_dev = (struct stm32f7_i2c_dev *)arg;
+ struct stm32_i2c_dma *dma = i2c_dev->dma;
+ struct device *dev = dma->chan_using->device->dev;
+
+ stm32f7_i2c_disable_dma_req(i2c_dev);
+ dma_unmap_single(dev, dma->dma_buf, dma->dma_len, dma->dma_data_dir);
+ complete(&dma->dma_complete);
+}
+
static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev)
{
struct stm32f7_i2c_timings *t = &i2c_dev->timing;
@@ -567,6 +669,9 @@ static void stm32f7_i2c_read_rx_data(struct stm32f7_i2c_dev *i2c_dev)
if (f7_msg->count) {
*f7_msg->buf++ = readb_relaxed(base + STM32F7_I2C_RXDR);
f7_msg->count--;
+ } else {
+ /* Flush RX buffer has no data is expected */
+ readb_relaxed(base + STM32F7_I2C_RXDR);
}
}
@@ -575,6 +680,9 @@ static void stm32f7_i2c_reload(struct stm32f7_i2c_dev *i2c_dev)
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
u32 cr2;
+ if (i2c_dev->use_dma)
+ f7_msg->count -= STM32F7_I2C_MAX_LEN;
+
cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
cr2 &= ~STM32F7_I2C_CR2_NBYTES_MASK;
@@ -588,6 +696,43 @@ static void stm32f7_i2c_reload(struct stm32f7_i2c_dev *i2c_dev)
writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
}
+static void stm32f7_i2c_smbus_reload(struct stm32f7_i2c_dev *i2c_dev)
+{
+ struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+ u32 cr2;
+ u8 *val;
+
+ /*
+ * For I2C_SMBUS_BLOCK_DATA && I2C_SMBUS_BLOCK_PROC_CALL, the first
+ * data received inform us how many data will follow.
+ */
+ stm32f7_i2c_read_rx_data(i2c_dev);
+
+ /*
+ * Update NBYTES with the value read to continue the transfer
+ */
+ val = f7_msg->buf - sizeof(u8);
+ f7_msg->count = *val;
+ cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
+ cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
+ cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
+ writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
+}
+
+static int stm32f7_i2c_release_bus(struct i2c_adapter *i2c_adap)
+{
+ struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
+
+ dev_info(i2c_dev->dev, "Trying to recover bus\n");
+
+ stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1,
+ STM32F7_I2C_CR1_PE);
+
+ stm32f7_i2c_hw_config(i2c_dev);
+
+ return 0;
+}
+
static int stm32f7_i2c_wait_free_bus(struct stm32f7_i2c_dev *i2c_dev)
{
u32 status;
@@ -597,12 +742,18 @@ static int stm32f7_i2c_wait_free_bus(struct stm32f7_i2c_dev *i2c_dev)
status,
!(status & STM32F7_I2C_ISR_BUSY),
10, 1000);
+ if (!ret)
+ return 0;
+
+ dev_info(i2c_dev->dev, "bus busy\n");
+
+ ret = stm32f7_i2c_release_bus(&i2c_dev->adap);
if (ret) {
- dev_dbg(i2c_dev->dev, "bus busy\n");
- ret = -EBUSY;
+ dev_err(i2c_dev->dev, "Failed to recover the bus (%d)\n", ret);
+ return ret;
}
- return ret;
+ return -EBUSY;
}
static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
@@ -611,6 +762,7 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
void __iomem *base = i2c_dev->base;
u32 cr1, cr2;
+ int ret;
f7_msg->addr = msg->addr;
f7_msg->buf = msg->buf;
@@ -629,8 +781,15 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
cr2 |= STM32F7_I2C_CR2_RD_WRN;
/* Set slave address */
- cr2 &= ~STM32F7_I2C_CR2_SADD7_MASK;
- cr2 |= STM32F7_I2C_CR2_SADD7(f7_msg->addr);
+ cr2 &= ~(STM32F7_I2C_CR2_HEAD10R | STM32F7_I2C_CR2_ADD10);
+ if (msg->flags & I2C_M_TEN) {
+ cr2 &= ~STM32F7_I2C_CR2_SADD10_MASK;
+ cr2 |= STM32F7_I2C_CR2_SADD10(f7_msg->addr);
+ cr2 |= STM32F7_I2C_CR2_ADD10;
+ } else {
+ cr2 &= ~STM32F7_I2C_CR2_SADD7_MASK;
+ cr2 |= STM32F7_I2C_CR2_SADD7(f7_msg->addr);
+ }
/* Set nb bytes to transfer and reload if needed */
cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
@@ -645,16 +804,286 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE |
STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE;
- /* Clear TX/RX interrupt */
+ /* Clear DMA req and TX/RX interrupt */
+ cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
+ STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
+
+ /* Configure DMA or enable RX/TX interrupt */
+ i2c_dev->use_dma = false;
+ if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
+ ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
+ msg->flags & I2C_M_RD,
+ f7_msg->count, f7_msg->buf,
+ stm32f7_i2c_dma_callback,
+ i2c_dev);
+ if (!ret)
+ i2c_dev->use_dma = true;
+ else
+ dev_warn(i2c_dev->dev, "can't use DMA\n");
+ }
+
+ if (!i2c_dev->use_dma) {
+ if (msg->flags & I2C_M_RD)
+ cr1 |= STM32F7_I2C_CR1_RXIE;
+ else
+ cr1 |= STM32F7_I2C_CR1_TXIE;
+ } else {
+ if (msg->flags & I2C_M_RD)
+ cr1 |= STM32F7_I2C_CR1_RXDMAEN;
+ else
+ cr1 |= STM32F7_I2C_CR1_TXDMAEN;
+ }
+
+ /* Configure Start/Repeated Start */
+ cr2 |= STM32F7_I2C_CR2_START;
+
+ i2c_dev->master_mode = true;
+
+ /* Write configurations registers */
+ writel_relaxed(cr1, base + STM32F7_I2C_CR1);
+ writel_relaxed(cr2, base + STM32F7_I2C_CR2);
+}
+
+static int stm32f7_i2c_smbus_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
+ unsigned short flags, u8 command,
+ union i2c_smbus_data *data)
+{
+ struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+ struct device *dev = i2c_dev->dev;
+ void __iomem *base = i2c_dev->base;
+ u32 cr1, cr2;
+ int i, ret;
+
+ f7_msg->result = 0;
+ reinit_completion(&i2c_dev->complete);
+
+ cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
+ cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
+
+ /* Set transfer direction */
+ cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+ if (f7_msg->read_write)
+ cr2 |= STM32F7_I2C_CR2_RD_WRN;
+
+ /* Set slave address */
+ cr2 &= ~(STM32F7_I2C_CR2_ADD10 | STM32F7_I2C_CR2_SADD7_MASK);
+ cr2 |= STM32F7_I2C_CR2_SADD7(f7_msg->addr);
+
+ f7_msg->smbus_buf[0] = command;
+ switch (f7_msg->size) {
+ case I2C_SMBUS_QUICK:
+ f7_msg->stop = true;
+ f7_msg->count = 0;
+ break;
+ case I2C_SMBUS_BYTE:
+ f7_msg->stop = true;
+ f7_msg->count = 1;
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ if (f7_msg->read_write) {
+ f7_msg->stop = false;
+ f7_msg->count = 1;
+ cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+ } else {
+ f7_msg->stop = true;
+ f7_msg->count = 2;
+ f7_msg->smbus_buf[1] = data->byte;
+ }
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ if (f7_msg->read_write) {
+ f7_msg->stop = false;
+ f7_msg->count = 1;
+ cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+ } else {
+ f7_msg->stop = true;
+ f7_msg->count = 3;
+ f7_msg->smbus_buf[1] = data->word & 0xff;
+ f7_msg->smbus_buf[2] = data->word >> 8;
+ }
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ if (f7_msg->read_write) {
+ f7_msg->stop = false;
+ f7_msg->count = 1;
+ cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+ } else {
+ f7_msg->stop = true;
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX ||
+ !data->block[0]) {
+ dev_err(dev, "Invalid block write size %d\n",
+ data->block[0]);
+ return -EINVAL;
+ }
+ f7_msg->count = data->block[0] + 2;
+ for (i = 1; i < f7_msg->count; i++)
+ f7_msg->smbus_buf[i] = data->block[i - 1];
+ }
+ break;
+ case I2C_SMBUS_PROC_CALL:
+ f7_msg->stop = false;
+ f7_msg->count = 3;
+ f7_msg->smbus_buf[1] = data->word & 0xff;
+ f7_msg->smbus_buf[2] = data->word >> 8;
+ cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+ f7_msg->read_write = I2C_SMBUS_READ;
+ break;
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ f7_msg->stop = false;
+ if (data->block[0] > I2C_SMBUS_BLOCK_MAX - 1) {
+ dev_err(dev, "Invalid block write size %d\n",
+ data->block[0]);
+ return -EINVAL;
+ }
+ f7_msg->count = data->block[0] + 2;
+ for (i = 1; i < f7_msg->count; i++)
+ f7_msg->smbus_buf[i] = data->block[i - 1];
+ cr2 &= ~STM32F7_I2C_CR2_RD_WRN;
+ f7_msg->read_write = I2C_SMBUS_READ;
+ break;
+ default:
+ dev_err(dev, "Unsupported smbus protocol %d\n", f7_msg->size);
+ return -EOPNOTSUPP;
+ }
+
+ f7_msg->buf = f7_msg->smbus_buf;
+
+ /* Configure PEC */
+ if ((flags & I2C_CLIENT_PEC) && f7_msg->size != I2C_SMBUS_QUICK) {
+ cr1 |= STM32F7_I2C_CR1_PECEN;
+ cr2 |= STM32F7_I2C_CR2_PECBYTE;
+ if (!f7_msg->read_write)
+ f7_msg->count++;
+ } else {
+ cr1 &= ~STM32F7_I2C_CR1_PECEN;
+ cr2 &= ~STM32F7_I2C_CR2_PECBYTE;
+ }
+
+ /* Set number of bytes to be transferred */
+ cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK | STM32F7_I2C_CR2_RELOAD);
+ cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
+
+ /* Enable NACK, STOP, error and transfer complete interrupts */
+ cr1 |= STM32F7_I2C_CR1_ERRIE | STM32F7_I2C_CR1_TCIE |
+ STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE;
+
+ /* Clear DMA req and TX/RX interrupt */
+ cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
+ STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
+
+ /* Configure DMA or enable RX/TX interrupt */
+ i2c_dev->use_dma = false;
+ if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN) {
+ ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
+ cr2 & STM32F7_I2C_CR2_RD_WRN,
+ f7_msg->count, f7_msg->buf,
+ stm32f7_i2c_dma_callback,
+ i2c_dev);
+ if (!ret)
+ i2c_dev->use_dma = true;
+ else
+ dev_warn(i2c_dev->dev, "can't use DMA\n");
+ }
+
+ if (!i2c_dev->use_dma) {
+ if (cr2 & STM32F7_I2C_CR2_RD_WRN)
+ cr1 |= STM32F7_I2C_CR1_RXIE;
+ else
+ cr1 |= STM32F7_I2C_CR1_TXIE;
+ } else {
+ if (cr2 & STM32F7_I2C_CR2_RD_WRN)
+ cr1 |= STM32F7_I2C_CR1_RXDMAEN;
+ else
+ cr1 |= STM32F7_I2C_CR1_TXDMAEN;
+ }
+
+ /* Set Start bit */
+ cr2 |= STM32F7_I2C_CR2_START;
+
+ i2c_dev->master_mode = true;
+
+ /* Write configurations registers */
+ writel_relaxed(cr1, base + STM32F7_I2C_CR1);
+ writel_relaxed(cr2, base + STM32F7_I2C_CR2);
+
+ return 0;
+}
+
+static void stm32f7_i2c_smbus_rep_start(struct stm32f7_i2c_dev *i2c_dev)
+{
+ struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+ void __iomem *base = i2c_dev->base;
+ u32 cr1, cr2;
+ int ret;
+
+ cr2 = readl_relaxed(base + STM32F7_I2C_CR2);
+ cr1 = readl_relaxed(base + STM32F7_I2C_CR1);
+
+ /* Set transfer direction */
+ cr2 |= STM32F7_I2C_CR2_RD_WRN;
+
+ switch (f7_msg->size) {
+ case I2C_SMBUS_BYTE_DATA:
+ f7_msg->count = 1;
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ case I2C_SMBUS_PROC_CALL:
+ f7_msg->count = 2;
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ f7_msg->count = 1;
+ cr2 |= STM32F7_I2C_CR2_RELOAD;
+ break;
+ }
+
+ f7_msg->buf = f7_msg->smbus_buf;
+ f7_msg->stop = true;
+
+ /* Add one byte for PEC if needed */
+ if (cr1 & STM32F7_I2C_CR1_PECEN)
+ f7_msg->count++;
+
+ /* Set number of bytes to be transferred */
+ cr2 &= ~(STM32F7_I2C_CR2_NBYTES_MASK);
+ cr2 |= STM32F7_I2C_CR2_NBYTES(f7_msg->count);
+
+ /*
+ * Configure RX/TX interrupt:
+ */
cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE);
+ cr1 |= STM32F7_I2C_CR1_RXIE;
- /* Enable RX/TX interrupt according to msg direction */
- if (msg->flags & I2C_M_RD)
+ /*
+ * Configure DMA or enable RX/TX interrupt:
+ * For I2C_SMBUS_BLOCK_DATA and I2C_SMBUS_BLOCK_PROC_CALL we don't use
+ * dma as we don't know in advance how many data will be received
+ */
+ cr1 &= ~(STM32F7_I2C_CR1_RXIE | STM32F7_I2C_CR1_TXIE |
+ STM32F7_I2C_CR1_RXDMAEN | STM32F7_I2C_CR1_TXDMAEN);
+
+ i2c_dev->use_dma = false;
+ if (i2c_dev->dma && f7_msg->count >= STM32F7_I2C_DMA_LEN_MIN &&
+ f7_msg->size != I2C_SMBUS_BLOCK_DATA &&
+ f7_msg->size != I2C_SMBUS_BLOCK_PROC_CALL) {
+ ret = stm32_i2c_prep_dma_xfer(i2c_dev->dev, i2c_dev->dma,
+ cr2 & STM32F7_I2C_CR2_RD_WRN,
+ f7_msg->count, f7_msg->buf,
+ stm32f7_i2c_dma_callback,
+ i2c_dev);
+
+ if (!ret)
+ i2c_dev->use_dma = true;
+ else
+ dev_warn(i2c_dev->dev, "can't use DMA\n");
+ }
+
+ if (!i2c_dev->use_dma)
cr1 |= STM32F7_I2C_CR1_RXIE;
else
- cr1 |= STM32F7_I2C_CR1_TXIE;
+ cr1 |= STM32F7_I2C_CR1_RXDMAEN;
- /* Configure Start/Repeated Start */
+ /* Configure Repeated Start */
cr2 |= STM32F7_I2C_CR2_START;
/* Write configurations registers */
@@ -662,9 +1091,278 @@ static void stm32f7_i2c_xfer_msg(struct stm32f7_i2c_dev *i2c_dev,
writel_relaxed(cr2, base + STM32F7_I2C_CR2);
}
-static void stm32f7_i2c_disable_irq(struct stm32f7_i2c_dev *i2c_dev, u32 mask)
+static int stm32f7_i2c_smbus_check_pec(struct stm32f7_i2c_dev *i2c_dev)
{
- stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, mask);
+ struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+ u8 count, internal_pec, received_pec;
+
+ internal_pec = readl_relaxed(i2c_dev->base + STM32F7_I2C_PECR);
+
+ switch (f7_msg->size) {
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ received_pec = f7_msg->smbus_buf[1];
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ case I2C_SMBUS_PROC_CALL:
+ received_pec = f7_msg->smbus_buf[2];
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ count = f7_msg->smbus_buf[0];
+ received_pec = f7_msg->smbus_buf[count];
+ break;
+ default:
+ dev_err(i2c_dev->dev, "Unsupported smbus protocol for PEC\n");
+ return -EINVAL;
+ }
+
+ if (internal_pec != received_pec) {
+ dev_err(i2c_dev->dev, "Bad PEC 0x%02x vs. 0x%02x\n",
+ internal_pec, received_pec);
+ return -EBADMSG;
+ }
+
+ return 0;
+}
+
+static bool stm32f7_i2c_is_addr_match(struct i2c_client *slave, u32 addcode)
+{
+ u32 addr;
+
+ if (!slave)
+ return false;
+
+ if (slave->flags & I2C_CLIENT_TEN) {
+ /*
+ * For 10-bit addr, addcode = 11110XY with
+ * X = Bit 9 of slave address
+ * Y = Bit 8 of slave address
+ */
+ addr = slave->addr >> 8;
+ addr |= 0x78;
+ if (addr == addcode)
+ return true;
+ } else {
+ addr = slave->addr & 0x7f;
+ if (addr == addcode)
+ return true;
+ }
+
+ return false;
+}
+
+static void stm32f7_i2c_slave_start(struct stm32f7_i2c_dev *i2c_dev)
+{
+ struct i2c_client *slave = i2c_dev->slave_running;
+ void __iomem *base = i2c_dev->base;
+ u32 mask;
+ u8 value = 0;
+
+ if (i2c_dev->slave_dir) {
+ /* Notify i2c slave that new read transfer is starting */
+ i2c_slave_event(slave, I2C_SLAVE_READ_REQUESTED, &value);
+
+ /*
+ * Disable slave TX config in case of I2C combined message
+ * (I2C Write followed by I2C Read)
+ */
+ mask = STM32F7_I2C_CR2_RELOAD;
+ stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR2, mask);
+ mask = STM32F7_I2C_CR1_SBC | STM32F7_I2C_CR1_RXIE |
+ STM32F7_I2C_CR1_TCIE;
+ stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR1, mask);
+
+ /* Enable TX empty, STOP, NACK interrupts */
+ mask = STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE |
+ STM32F7_I2C_CR1_TXIE;
+ stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
+
+ } else {
+ /* Notify i2c slave that new write transfer is starting */
+ i2c_slave_event(slave, I2C_SLAVE_WRITE_REQUESTED, &value);
+
+ /* Set reload mode to be able to ACK/NACK each received byte */
+ mask = STM32F7_I2C_CR2_RELOAD;
+ stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
+
+ /*
+ * Set STOP, NACK, RX empty and transfer complete interrupts.*
+ * Set Slave Byte Control to be able to ACK/NACK each data
+ * byte received
+ */
+ mask = STM32F7_I2C_CR1_STOPIE | STM32F7_I2C_CR1_NACKIE |
+ STM32F7_I2C_CR1_SBC | STM32F7_I2C_CR1_RXIE |
+ STM32F7_I2C_CR1_TCIE;
+ stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
+ }
+}
+
+static void stm32f7_i2c_slave_addr(struct stm32f7_i2c_dev *i2c_dev)
+{
+ void __iomem *base = i2c_dev->base;
+ u32 isr, addcode, dir, mask;
+ int i;
+
+ isr = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
+ addcode = STM32F7_I2C_ISR_ADDCODE_GET(isr);
+ dir = isr & STM32F7_I2C_ISR_DIR;
+
+ for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
+ if (stm32f7_i2c_is_addr_match(i2c_dev->slave[i], addcode)) {
+ i2c_dev->slave_running = i2c_dev->slave[i];
+ i2c_dev->slave_dir = dir;
+
+ /* Start I2C slave processing */
+ stm32f7_i2c_slave_start(i2c_dev);
+
+ /* Clear ADDR flag */
+ mask = STM32F7_I2C_ICR_ADDRCF;
+ writel_relaxed(mask, base + STM32F7_I2C_ICR);
+ break;
+ }
+ }
+}
+
+static int stm32f7_i2c_get_slave_id(struct stm32f7_i2c_dev *i2c_dev,
+ struct i2c_client *slave, int *id)
+{
+ int i;
+
+ for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
+ if (i2c_dev->slave[i] == slave) {
+ *id = i;
+ return 0;
+ }
+ }
+
+ dev_err(i2c_dev->dev, "Slave 0x%x not registered\n", slave->addr);
+
+ return -ENODEV;
+}
+
+static int stm32f7_i2c_get_free_slave_id(struct stm32f7_i2c_dev *i2c_dev,
+ struct i2c_client *slave, int *id)
+{
+ struct device *dev = i2c_dev->dev;
+ int i;
+
+ /*
+ * slave[0] supports 7-bit and 10-bit slave address
+ * slave[1] supports 7-bit slave address only
+ */
+ for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
+ if (i == 1 && (slave->flags & I2C_CLIENT_PEC))
+ continue;
+ if (!i2c_dev->slave[i]) {
+ *id = i;
+ return 0;
+ }
+ }
+
+ dev_err(dev, "Slave 0x%x could not be registered\n", slave->addr);
+
+ return -EINVAL;
+}
+
+static bool stm32f7_i2c_is_slave_registered(struct stm32f7_i2c_dev *i2c_dev)
+{
+ int i;
+
+ for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
+ if (i2c_dev->slave[i])
+ return true;
+ }
+
+ return false;
+}
+
+static bool stm32f7_i2c_is_slave_busy(struct stm32f7_i2c_dev *i2c_dev)
+{
+ int i, busy;
+
+ busy = 0;
+ for (i = 0; i < STM32F7_I2C_MAX_SLAVE; i++) {
+ if (i2c_dev->slave[i])
+ busy++;
+ }
+
+ return i == busy;
+}
+
+static irqreturn_t stm32f7_i2c_slave_isr_event(struct stm32f7_i2c_dev *i2c_dev)
+{
+ void __iomem *base = i2c_dev->base;
+ u32 cr2, status, mask;
+ u8 val;
+ int ret;
+
+ status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
+
+ /* Slave transmitter mode */
+ if (status & STM32F7_I2C_ISR_TXIS) {
+ i2c_slave_event(i2c_dev->slave_running,
+ I2C_SLAVE_READ_PROCESSED,
+ &val);
+
+ /* Write data byte */
+ writel_relaxed(val, base + STM32F7_I2C_TXDR);
+ }
+
+ /* Transfer Complete Reload for Slave receiver mode */
+ if (status & STM32F7_I2C_ISR_TCR || status & STM32F7_I2C_ISR_RXNE) {
+ /*
+ * Read data byte then set NBYTES to receive next byte or NACK
+ * the current received byte
+ */
+ val = readb_relaxed(i2c_dev->base + STM32F7_I2C_RXDR);
+ ret = i2c_slave_event(i2c_dev->slave_running,
+ I2C_SLAVE_WRITE_RECEIVED,
+ &val);
+ if (!ret) {
+ cr2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_CR2);
+ cr2 |= STM32F7_I2C_CR2_NBYTES(1);
+ writel_relaxed(cr2, i2c_dev->base + STM32F7_I2C_CR2);
+ } else {
+ mask = STM32F7_I2C_CR2_NACK;
+ stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
+ }
+ }
+
+ /* NACK received */
+ if (status & STM32F7_I2C_ISR_NACKF) {
+ dev_dbg(i2c_dev->dev, "<%s>: Receive NACK\n", __func__);
+ writel_relaxed(STM32F7_I2C_ICR_NACKCF, base + STM32F7_I2C_ICR);
+ }
+
+ /* STOP received */
+ if (status & STM32F7_I2C_ISR_STOPF) {
+ /* Disable interrupts */
+ stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_XFER_IRQ_MASK);
+
+ if (i2c_dev->slave_dir) {
+ /*
+ * Flush TX buffer in order to not used the byte in
+ * TXDR for the next transfer
+ */
+ mask = STM32F7_I2C_ISR_TXE;
+ stm32f7_i2c_set_bits(base + STM32F7_I2C_ISR, mask);
+ }
+
+ /* Clear STOP flag */
+ writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
+
+ /* Notify i2c slave that a STOP flag has been detected */
+ i2c_slave_event(i2c_dev->slave_running, I2C_SLAVE_STOP, &val);
+
+ i2c_dev->slave_running = NULL;
+ }
+
+ /* Address match received */
+ if (status & STM32F7_I2C_ISR_ADDR)
+ stm32f7_i2c_slave_addr(i2c_dev);
+
+ return IRQ_HANDLED;
}
static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
@@ -673,6 +1371,13 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
void __iomem *base = i2c_dev->base;
u32 status, mask;
+ int ret = IRQ_HANDLED;
+
+ /* Check if the interrupt if for a slave device */
+ if (!i2c_dev->master_mode) {
+ ret = stm32f7_i2c_slave_isr_event(i2c_dev);
+ return ret;
+ }
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
@@ -694,12 +1399,21 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
/* STOP detection flag */
if (status & STM32F7_I2C_ISR_STOPF) {
/* Disable interrupts */
- stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
+ if (stm32f7_i2c_is_slave_registered(i2c_dev))
+ mask = STM32F7_I2C_XFER_IRQ_MASK;
+ else
+ mask = STM32F7_I2C_ALL_IRQ_MASK;
+ stm32f7_i2c_disable_irq(i2c_dev, mask);
/* Clear STOP flag */
writel_relaxed(STM32F7_I2C_ICR_STOPCF, base + STM32F7_I2C_ICR);
- complete(&i2c_dev->complete);
+ if (i2c_dev->use_dma) {
+ ret = IRQ_WAKE_THREAD;
+ } else {
+ i2c_dev->master_mode = false;
+ complete(&i2c_dev->complete);
+ }
}
/* Transfer complete */
@@ -707,6 +1421,10 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
if (f7_msg->stop) {
mask = STM32F7_I2C_CR2_STOP;
stm32f7_i2c_set_bits(base + STM32F7_I2C_CR2, mask);
+ } else if (i2c_dev->use_dma) {
+ ret = IRQ_WAKE_THREAD;
+ } else if (f7_msg->smbus) {
+ stm32f7_i2c_smbus_rep_start(i2c_dev);
} else {
i2c_dev->msg_id++;
i2c_dev->msg++;
@@ -714,13 +1432,50 @@ static irqreturn_t stm32f7_i2c_isr_event(int irq, void *data)
}
}
+ if (status & STM32F7_I2C_ISR_TCR) {
+ if (f7_msg->smbus)
+ stm32f7_i2c_smbus_reload(i2c_dev);
+ else
+ stm32f7_i2c_reload(i2c_dev);
+ }
+
+ return ret;
+}
+
+static irqreturn_t stm32f7_i2c_isr_event_thread(int irq, void *data)
+{
+ struct stm32f7_i2c_dev *i2c_dev = data;
+ struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+ struct stm32_i2c_dma *dma = i2c_dev->dma;
+ u32 status;
+ int ret;
+
/*
- * Transfer Complete Reload: 255 data bytes have been transferred
- * We have to prepare the I2C controller to transfer the remaining
- * data.
+ * Wait for dma transfer completion before sending next message or
+ * notity the end of xfer to the client
*/
- if (status & STM32F7_I2C_ISR_TCR)
- stm32f7_i2c_reload(i2c_dev);
+ ret = wait_for_completion_timeout(&i2c_dev->dma->dma_complete, HZ);
+ if (!ret) {
+ dev_dbg(i2c_dev->dev, "<%s>: Timed out\n", __func__);
+ stm32f7_i2c_disable_dma_req(i2c_dev);
+ dmaengine_terminate_all(dma->chan_using);
+ f7_msg->result = -ETIMEDOUT;
+ }
+
+ status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
+
+ if (status & STM32F7_I2C_ISR_TC) {
+ if (f7_msg->smbus) {
+ stm32f7_i2c_smbus_rep_start(i2c_dev);
+ } else {
+ i2c_dev->msg_id++;
+ i2c_dev->msg++;
+ stm32f7_i2c_xfer_msg(i2c_dev, i2c_dev->msg);
+ }
+ } else {
+ i2c_dev->master_mode = false;
+ complete(&i2c_dev->complete);
+ }
return IRQ_HANDLED;
}
@@ -731,7 +1486,8 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
void __iomem *base = i2c_dev->base;
struct device *dev = i2c_dev->dev;
- u32 status;
+ struct stm32_i2c_dma *dma = i2c_dev->dma;
+ u32 mask, status;
status = readl_relaxed(i2c_dev->base + STM32F7_I2C_ISR);
@@ -739,6 +1495,7 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
if (status & STM32F7_I2C_ISR_BERR) {
dev_err(dev, "<%s>: Bus error\n", __func__);
writel_relaxed(STM32F7_I2C_ICR_BERRCF, base + STM32F7_I2C_ICR);
+ stm32f7_i2c_release_bus(&i2c_dev->adap);
f7_msg->result = -EIO;
}
@@ -749,8 +1506,26 @@ static irqreturn_t stm32f7_i2c_isr_error(int irq, void *data)
f7_msg->result = -EAGAIN;
}
- stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
+ if (status & STM32F7_I2C_ISR_PECERR) {
+ dev_err(dev, "<%s>: PEC error in reception\n", __func__);
+ writel_relaxed(STM32F7_I2C_ICR_PECCF, base + STM32F7_I2C_ICR);
+ f7_msg->result = -EINVAL;
+ }
+
+ /* Disable interrupts */
+ if (stm32f7_i2c_is_slave_registered(i2c_dev))
+ mask = STM32F7_I2C_XFER_IRQ_MASK;
+ else
+ mask = STM32F7_I2C_ALL_IRQ_MASK;
+ stm32f7_i2c_disable_irq(i2c_dev, mask);
+
+ /* Disable dma */
+ if (i2c_dev->use_dma) {
+ stm32f7_i2c_disable_dma_req(i2c_dev);
+ dmaengine_terminate_all(dma->chan_using);
+ }
+ i2c_dev->master_mode = false;
complete(&i2c_dev->complete);
return IRQ_HANDLED;
@@ -761,12 +1536,14 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
{
struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(i2c_adap);
struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+ struct stm32_i2c_dma *dma = i2c_dev->dma;
unsigned long time_left;
int ret;
i2c_dev->msg = msgs;
i2c_dev->msg_num = num;
i2c_dev->msg_id = 0;
+ f7_msg->smbus = false;
ret = clk_enable(i2c_dev->clk);
if (ret) {
@@ -787,6 +1564,8 @@ static int stm32f7_i2c_xfer(struct i2c_adapter *i2c_adap,
if (!time_left) {
dev_dbg(i2c_dev->dev, "Access to slave 0x%x timed out\n",
i2c_dev->msg->addr);
+ if (i2c_dev->use_dma)
+ dmaengine_terminate_all(dma->chan_using);
ret = -ETIMEDOUT;
}
@@ -796,14 +1575,209 @@ clk_free:
return (ret < 0) ? ret : num;
}
+static int stm32f7_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char read_write,
+ u8 command, int size,
+ union i2c_smbus_data *data)
+{
+ struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(adapter);
+ struct stm32f7_i2c_msg *f7_msg = &i2c_dev->f7_msg;
+ struct stm32_i2c_dma *dma = i2c_dev->dma;
+ struct device *dev = i2c_dev->dev;
+ unsigned long timeout;
+ int i, ret;
+
+ f7_msg->addr = addr;
+ f7_msg->size = size;
+ f7_msg->read_write = read_write;
+ f7_msg->smbus = true;
+
+ ret = clk_enable(i2c_dev->clk);
+ if (ret) {
+ dev_err(i2c_dev->dev, "Failed to enable clock\n");
+ return ret;
+ }
+
+ ret = stm32f7_i2c_wait_free_bus(i2c_dev);
+ if (ret)
+ goto clk_free;
+
+ ret = stm32f7_i2c_smbus_xfer_msg(i2c_dev, flags, command, data);
+ if (ret)
+ goto clk_free;
+
+ timeout = wait_for_completion_timeout(&i2c_dev->complete,
+ i2c_dev->adap.timeout);
+ ret = f7_msg->result;
+ if (ret)
+ goto clk_free;
+
+ if (!timeout) {
+ dev_dbg(dev, "Access to slave 0x%x timed out\n", f7_msg->addr);
+ if (i2c_dev->use_dma)
+ dmaengine_terminate_all(dma->chan_using);
+ ret = -ETIMEDOUT;
+ goto clk_free;
+ }
+
+ /* Check PEC */
+ if ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK && read_write) {
+ ret = stm32f7_i2c_smbus_check_pec(i2c_dev);
+ if (ret)
+ goto clk_free;
+ }
+
+ if (read_write && size != I2C_SMBUS_QUICK) {
+ switch (size) {
+ case I2C_SMBUS_BYTE:
+ case I2C_SMBUS_BYTE_DATA:
+ data->byte = f7_msg->smbus_buf[0];
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ case I2C_SMBUS_PROC_CALL:
+ data->word = f7_msg->smbus_buf[0] |
+ (f7_msg->smbus_buf[1] << 8);
+ break;
+ case I2C_SMBUS_BLOCK_DATA:
+ case I2C_SMBUS_BLOCK_PROC_CALL:
+ for (i = 0; i <= f7_msg->smbus_buf[0]; i++)
+ data->block[i] = f7_msg->smbus_buf[i];
+ break;
+ default:
+ dev_err(dev, "Unsupported smbus transaction\n");
+ ret = -EINVAL;
+ }
+ }
+
+clk_free:
+ clk_disable(i2c_dev->clk);
+ return ret;
+}
+
+static int stm32f7_i2c_reg_slave(struct i2c_client *slave)
+{
+ struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter);
+ void __iomem *base = i2c_dev->base;
+ struct device *dev = i2c_dev->dev;
+ u32 oar1, oar2, mask;
+ int id, ret;
+
+ if (slave->flags & I2C_CLIENT_PEC) {
+ dev_err(dev, "SMBus PEC not supported in slave mode\n");
+ return -EINVAL;
+ }
+
+ if (stm32f7_i2c_is_slave_busy(i2c_dev)) {
+ dev_err(dev, "Too much slave registered\n");
+ return -EBUSY;
+ }
+
+ ret = stm32f7_i2c_get_free_slave_id(i2c_dev, slave, &id);
+ if (ret)
+ return ret;
+
+ if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) {
+ ret = clk_enable(i2c_dev->clk);
+ if (ret) {
+ dev_err(dev, "Failed to enable clock\n");
+ return ret;
+ }
+ }
+
+ if (id == 0) {
+ /* Configure Own Address 1 */
+ oar1 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR1);
+ oar1 &= ~STM32F7_I2C_OAR1_MASK;
+ if (slave->flags & I2C_CLIENT_TEN) {
+ oar1 |= STM32F7_I2C_OAR1_OA1_10(slave->addr);
+ oar1 |= STM32F7_I2C_OAR1_OA1MODE;
+ } else {
+ oar1 |= STM32F7_I2C_OAR1_OA1_7(slave->addr);
+ }
+ oar1 |= STM32F7_I2C_OAR1_OA1EN;
+ i2c_dev->slave[id] = slave;
+ writel_relaxed(oar1, i2c_dev->base + STM32F7_I2C_OAR1);
+ } else if (id == 1) {
+ /* Configure Own Address 2 */
+ oar2 = readl_relaxed(i2c_dev->base + STM32F7_I2C_OAR2);
+ oar2 &= ~STM32F7_I2C_OAR2_MASK;
+ if (slave->flags & I2C_CLIENT_TEN) {
+ ret = -EOPNOTSUPP;
+ goto exit;
+ }
+
+ oar2 |= STM32F7_I2C_OAR2_OA2_7(slave->addr);
+ oar2 |= STM32F7_I2C_OAR2_OA2EN;
+ i2c_dev->slave[id] = slave;
+ writel_relaxed(oar2, i2c_dev->base + STM32F7_I2C_OAR2);
+ } else {
+ ret = -ENODEV;
+ goto exit;
+ }
+
+ /* Enable ACK */
+ stm32f7_i2c_clr_bits(base + STM32F7_I2C_CR2, STM32F7_I2C_CR2_NACK);
+
+ /* Enable Address match interrupt, error interrupt and enable I2C */
+ mask = STM32F7_I2C_CR1_ADDRIE | STM32F7_I2C_CR1_ERRIE |
+ STM32F7_I2C_CR1_PE;
+ stm32f7_i2c_set_bits(base + STM32F7_I2C_CR1, mask);
+
+ return 0;
+
+exit:
+ if (!(stm32f7_i2c_is_slave_registered(i2c_dev)))
+ clk_disable(i2c_dev->clk);
+
+ return ret;
+}
+
+static int stm32f7_i2c_unreg_slave(struct i2c_client *slave)
+{
+ struct stm32f7_i2c_dev *i2c_dev = i2c_get_adapdata(slave->adapter);
+ void __iomem *base = i2c_dev->base;
+ u32 mask;
+ int id, ret;
+
+ ret = stm32f7_i2c_get_slave_id(i2c_dev, slave, &id);
+ if (ret)
+ return ret;
+
+ WARN_ON(!i2c_dev->slave[id]);
+
+ if (id == 0) {
+ mask = STM32F7_I2C_OAR1_OA1EN;
+ stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR1, mask);
+ } else {
+ mask = STM32F7_I2C_OAR2_OA2EN;
+ stm32f7_i2c_clr_bits(base + STM32F7_I2C_OAR2, mask);
+ }
+
+ i2c_dev->slave[id] = NULL;
+
+ if (!(stm32f7_i2c_is_slave_registered(i2c_dev))) {
+ stm32f7_i2c_disable_irq(i2c_dev, STM32F7_I2C_ALL_IRQ_MASK);
+ clk_disable(i2c_dev->clk);
+ }
+
+ return 0;
+}
+
static u32 stm32f7_i2c_func(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SLAVE |
+ I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
+ I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_PEC;
}
static struct i2c_algorithm stm32f7_i2c_algo = {
.master_xfer = stm32f7_i2c_xfer,
+ .smbus_xfer = stm32f7_i2c_smbus_xfer,
.functionality = stm32f7_i2c_func,
+ .reg_slave = stm32f7_i2c_reg_slave,
+ .unreg_slave = stm32f7_i2c_unreg_slave,
};
static int stm32f7_i2c_probe(struct platform_device *pdev)
@@ -815,6 +1789,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
u32 irq_error, irq_event, clk_rate, rise_time, fall_time;
struct i2c_adapter *adap;
struct reset_control *rst;
+ dma_addr_t phy_addr;
int ret;
i2c_dev = devm_kzalloc(&pdev->dev, sizeof(*i2c_dev), GFP_KERNEL);
@@ -825,6 +1800,7 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
i2c_dev->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(i2c_dev->base))
return PTR_ERR(i2c_dev->base);
+ phy_addr = (dma_addr_t)res->start;
irq_event = irq_of_parse_and_map(np, 0);
if (!irq_event) {
@@ -871,8 +1847,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
i2c_dev->dev = &pdev->dev;
- ret = devm_request_irq(&pdev->dev, irq_event, stm32f7_i2c_isr_event, 0,
- pdev->name, i2c_dev);
+ ret = devm_request_threaded_irq(&pdev->dev, irq_event,
+ stm32f7_i2c_isr_event,
+ stm32f7_i2c_isr_event_thread,
+ IRQF_ONESHOT,
+ pdev->name, i2c_dev);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq event %i\n",
irq_event);
@@ -924,6 +1903,11 @@ static int stm32f7_i2c_probe(struct platform_device *pdev)
init_completion(&i2c_dev->complete);
+ /* Init DMA config if supported */
+ i2c_dev->dma = stm32_i2c_dma_request(i2c_dev->dev, phy_addr,
+ STM32F7_I2C_TXDR,
+ STM32F7_I2C_RXDR);
+
ret = i2c_add_adapter(adap);
if (ret)
goto clk_free;
@@ -946,6 +1930,11 @@ static int stm32f7_i2c_remove(struct platform_device *pdev)
{
struct stm32f7_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+ if (i2c_dev->dma) {
+ stm32_i2c_dma_free(i2c_dev->dma);
+ i2c_dev->dma = NULL;
+ }
+
i2c_del_adapter(&i2c_dev->adap);
clk_unprepare(i2c_dev->clk);
diff --git a/drivers/i2c/busses/i2c-stu300.c b/drivers/i2c/busses/i2c-stu300.c
index dc63236..e866c48 100644
--- a/drivers/i2c/busses/i2c-stu300.c
+++ b/drivers/i2c/busses/i2c-stu300.c
@@ -602,20 +602,24 @@ static int stu300_send_address(struct stu300_dev *dev,
u32 val;
int ret;
- if (msg->flags & I2C_M_TEN)
+ if (msg->flags & I2C_M_TEN) {
/* This is probably how 10 bit addresses look */
val = (0xf0 | (((u32) msg->addr & 0x300) >> 7)) &
I2C_DR_D_MASK;
- else
- val = ((msg->addr << 1) & I2C_DR_D_MASK);
+ if (msg->flags & I2C_M_RD)
+ /* This is the direction bit */
+ val |= 0x01;
+ } else {
+ val = i2c_8bit_addr_from_msg(msg);
+ }
- if (msg->flags & I2C_M_RD) {
- /* This is the direction bit */
- val |= 0x01;
- if (resend)
+ if (resend) {
+ if (msg->flags & I2C_M_RD)
dev_dbg(&dev->pdev->dev, "read resend\n");
- } else if (resend)
- dev_dbg(&dev->pdev->dev, "write resend\n");
+ else
+ dev_dbg(&dev->pdev->dev, "write resend\n");
+ }
+
stu300_wr8(val, dev->virtbase + I2C_DR);
/* For 10bit addressing, await 10bit request (EVENT 9) */
diff --git a/drivers/i2c/busses/i2c-synquacer.c b/drivers/i2c/busses/i2c-synquacer.c
index a021f86..915f5ed 100644
--- a/drivers/i2c/busses/i2c-synquacer.c
+++ b/drivers/i2c/busses/i2c-synquacer.c
@@ -509,7 +509,7 @@ static int synquacer_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
dev_dbg(i2c->dev, "calculated timeout %d ms\n", i2c->timeout_ms);
- for (retry = 0; retry < adap->retries; retry++) {
+ for (retry = 0; retry <= adap->retries; retry++) {
ret = synquacer_i2c_doxfer(i2c, msgs, num);
if (ret != -EAGAIN)
return ret;
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 60292d2..5fccd1f 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -173,7 +173,6 @@ struct tegra_i2c_hw_feature {
* @msg_buf_remaining: size of unsent data in the message buffer
* @msg_read: identifies read transfers
* @bus_clk_rate: current i2c bus clock rate
- * @is_suspended: prevents i2c controller accesses after suspend is called
*/
struct tegra_i2c_dev {
struct device *dev;
@@ -194,7 +193,6 @@ struct tegra_i2c_dev {
int msg_read;
u32 bus_clk_rate;
u16 clk_divisor_non_hs_mode;
- bool is_suspended;
bool is_multimaster_mode;
spinlock_t xfer_lock;
};
@@ -734,9 +732,6 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
int i;
int ret = 0;
- if (i2c_dev->is_suspended)
- return -EBUSY;
-
ret = pm_runtime_get_sync(i2c_dev->dev);
if (ret < 0) {
dev_err(i2c_dev->dev, "runtime resume failed %d\n", ret);
@@ -1051,37 +1046,9 @@ static int tegra_i2c_remove(struct platform_device *pdev)
}
#ifdef CONFIG_PM_SLEEP
-static int tegra_i2c_suspend(struct device *dev)
-{
- struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
-
- i2c_lock_adapter(&i2c_dev->adapter);
- i2c_dev->is_suspended = true;
- i2c_unlock_adapter(&i2c_dev->adapter);
-
- return 0;
-}
-
-static int tegra_i2c_resume(struct device *dev)
-{
- struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
- int ret;
-
- i2c_lock_adapter(&i2c_dev->adapter);
-
- ret = tegra_i2c_init(i2c_dev);
- if (!ret)
- i2c_dev->is_suspended = false;
-
- i2c_unlock_adapter(&i2c_dev->adapter);
-
- return ret;
-}
-
static const struct dev_pm_ops tegra_i2c_pm = {
SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, tegra_i2c_runtime_resume,
NULL)
- SET_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume)
};
#define TEGRA_I2C_PM (&tegra_i2c_pm)
#else
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index c805278..9a71e50 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -33,7 +33,7 @@
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/wait.h>
-#include <linux/i2c-xiic.h>
+#include <linux/platform_data/i2c-xiic.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/of.h>
@@ -143,12 +143,6 @@ struct xiic_i2c {
#define XIIC_TX_RX_INTERRUPTS (XIIC_INTR_RX_FULL_MASK | XIIC_TX_INTERRUPTS)
-/* The following constants are used with the following macros to specify the
- * operation, a read or write operation.
- */
-#define XIIC_READ_OPERATION 1
-#define XIIC_WRITE_OPERATION 0
-
/*
* Tx Fifo upper bit masks.
*/
@@ -415,7 +409,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
clr |= XIIC_INTR_RX_FULL_MASK;
if (!i2c->rx_msg) {
dev_dbg(i2c->adap.dev.parent,
- "%s unexpexted RX IRQ\n", __func__);
+ "%s unexpected RX IRQ\n", __func__);
xiic_clear_rx_fifo(i2c);
goto out;
}
@@ -470,7 +464,7 @@ static irqreturn_t xiic_process(int irq, void *dev_id)
if (!i2c->tx_msg) {
dev_dbg(i2c->adap.dev.parent,
- "%s unexpexted TX IRQ\n", __func__);
+ "%s unexpected TX IRQ\n", __func__);
goto out;
}
@@ -556,8 +550,7 @@ static void xiic_start_recv(struct xiic_i2c *i2c)
if (!(msg->flags & I2C_M_NOSTART))
/* write the address */
xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
- (msg->addr << 1) | XIIC_READ_OPERATION |
- XIIC_TX_DYN_START_MASK);
+ i2c_8bit_addr_from_msg(msg) | XIIC_TX_DYN_START_MASK);
xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
@@ -585,7 +578,7 @@ static void xiic_start_send(struct xiic_i2c *i2c)
if (!(msg->flags & I2C_M_NOSTART)) {
/* write the address */
- u16 data = ((msg->addr << 1) & 0xfe) | XIIC_WRITE_OPERATION |
+ u16 data = i2c_8bit_addr_from_msg(msg) |
XIIC_TX_DYN_START_MASK;
if ((i2c->nmsgs == 1) && msg->len == 0)
/* no data and last message -> add STOP */
diff --git a/drivers/i2c/busses/i2c-xlp9xx.c b/drivers/i2c/busses/i2c-xlp9xx.c
index eb8913e..1f41a4f 100644
--- a/drivers/i2c/busses/i2c-xlp9xx.c
+++ b/drivers/i2c/busses/i2c-xlp9xx.c
@@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/i2c.h>
+#include <linux/i2c-smbus.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -84,6 +85,8 @@ struct xlp9xx_i2c_dev {
struct device *dev;
struct i2c_adapter adapter;
struct completion msg_complete;
+ struct i2c_smbus_alert_setup alert_data;
+ struct i2c_client *ara;
int irq;
bool msg_read;
bool len_recv;
@@ -155,9 +158,30 @@ static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv)
priv->msg_buf += len;
}
+static void xlp9xx_i2c_update_rlen(struct xlp9xx_i2c_dev *priv)
+{
+ u32 val, len;
+
+ /*
+ * Update receive length. Re-read len to get the latest value,
+ * and then add 4 to have a minimum value that can be safely
+ * written. This is to account for the byte read above, the
+ * transfer in progress and any delays in the register I/O
+ */
+ val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL);
+ len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
+ XLP9XX_I2C_FIFO_WCNT_MASK;
+ len = max_t(u32, priv->msg_len, len + 4);
+ if (len >= I2C_SMBUS_BLOCK_MAX + 2)
+ return;
+ val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
+ (len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
+ xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
+}
+
static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
{
- u32 len, i, val;
+ u32 len, i;
u8 rlen, *buf = priv->msg_buf;
len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) &
@@ -167,21 +191,20 @@ static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv)
if (priv->len_recv) {
/* read length byte */
rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO);
- *buf++ = rlen;
- len--;
-
- if (priv->client_pec)
- ++rlen;
- /* update remaining bytes and message length */
- priv->msg_buf_remaining = rlen;
- priv->msg_len = rlen + 1;
+ if (rlen > I2C_SMBUS_BLOCK_MAX || rlen == 0) {
+ rlen = 0; /*abort transfer */
+ priv->msg_buf_remaining = 0;
+ priv->msg_len = 0;
+ } else {
+ *buf++ = rlen;
+ if (priv->client_pec)
+ ++rlen; /* account for error check byte */
+ /* update remaining bytes and message length */
+ priv->msg_buf_remaining = rlen;
+ priv->msg_len = rlen + 1;
+ }
+ xlp9xx_i2c_update_rlen(priv);
priv->len_recv = false;
-
- /* Update transfer length to read only actual data */
- val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL);
- val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
- ((rlen + 1) << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
- xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val);
} else {
len = min(priv->msg_buf_remaining, len);
for (i = 0; i < len; i++, buf++)
@@ -300,10 +323,6 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL,
XLP9XX_I2C_MFIFOCTRL_RST);
- /* set FIFO threshold if reading */
- if (priv->msg_read)
- xlp9xx_i2c_update_rx_fifo_thres(priv);
-
/* set slave addr */
xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_SLAVEADDR,
(msg->addr << XLP9XX_I2C_SLAVEADDR_ADDR_SHIFT) |
@@ -322,9 +341,13 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
val &= ~XLP9XX_I2C_CTRL_ADDMODE;
priv->len_recv = msg->flags & I2C_M_RECV_LEN;
- len = priv->len_recv ? XLP9XX_I2C_FIFO_SIZE : msg->len;
+ len = priv->len_recv ? I2C_SMBUS_BLOCK_MAX + 2 : msg->len;
priv->client_pec = msg->flags & I2C_CLIENT_PEC;
+ /* set FIFO threshold if reading */
+ if (priv->msg_read)
+ xlp9xx_i2c_update_rx_fifo_thres(priv);
+
/* set data length to be transferred */
val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) |
(len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT);
@@ -378,8 +401,11 @@ static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg,
}
/* update msg->len with actual received length */
- if (msg->flags & I2C_M_RECV_LEN)
+ if (msg->flags & I2C_M_RECV_LEN) {
+ if (!priv->msg_len)
+ return -EPROTO;
msg->len = priv->msg_len;
+ }
return 0;
}
@@ -447,6 +473,19 @@ static int xlp9xx_i2c_get_frequency(struct platform_device *pdev,
return 0;
}
+static int xlp9xx_i2c_smbus_setup(struct xlp9xx_i2c_dev *priv,
+ struct platform_device *pdev)
+{
+ if (!priv->alert_data.irq)
+ return -EINVAL;
+
+ priv->ara = i2c_setup_smbus_alert(&priv->adapter, &priv->alert_data);
+ if (!priv->ara)
+ return -ENODEV;
+
+ return 0;
+}
+
static int xlp9xx_i2c_probe(struct platform_device *pdev)
{
struct xlp9xx_i2c_dev *priv;
@@ -467,6 +506,10 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "invalid irq!\n");
return priv->irq;
}
+ /* SMBAlert irq */
+ priv->alert_data.irq = platform_get_irq(pdev, 1);
+ if (priv->alert_data.irq <= 0)
+ priv->alert_data.irq = 0;
xlp9xx_i2c_get_frequency(pdev, priv);
xlp9xx_i2c_init(priv);
@@ -493,6 +536,10 @@ static int xlp9xx_i2c_probe(struct platform_device *pdev)
if (err)
return err;
+ err = xlp9xx_i2c_smbus_setup(priv, pdev);
+ if (err)
+ dev_dbg(&pdev->dev, "No active SMBus alert %d\n", err);
+
platform_set_drvdata(pdev, priv);
dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr);
diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c
index a17f46a..31d16ad 100644
--- a/drivers/i2c/i2c-core-base.c
+++ b/drivers/i2c/i2c-core-base.c
@@ -717,10 +717,6 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
client->adapter = adap;
client->dev.platform_data = info->platform_data;
-
- if (info->archdata)
- client->dev.archdata = *info->archdata;
-
client->flags = info->flags;
client->addr = info->addr;
@@ -746,7 +742,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
client->dev.parent = &client->adapter->dev;
client->dev.bus = &i2c_bus_type;
client->dev.type = &i2c_client_type;
- client->dev.of_node = info->of_node;
+ client->dev.of_node = of_node_get(info->of_node);
client->dev.fwnode = info->fwnode;
i2c_dev_set_name(adap, client, info);
@@ -757,7 +753,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
dev_err(&adap->dev,
"Failed to add properties to client %s: %d\n",
client->name, status);
- goto out_err;
+ goto out_err_put_of_node;
}
}
@@ -773,6 +769,8 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
out_free_props:
if (info->properties)
device_remove_properties(&client->dev);
+out_err_put_of_node:
+ of_node_put(info->of_node);
out_err:
dev_err(&adap->dev,
"Failed to register i2c client %s at 0x%02x (%d)\n",
diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c
index c405270..6cb7ad6 100644
--- a/drivers/i2c/i2c-core-of.c
+++ b/drivers/i2c/i2c-core-of.c
@@ -22,53 +22,64 @@
#include "i2c-core.h"
-static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
- struct device_node *node)
+int of_i2c_get_board_info(struct device *dev, struct device_node *node,
+ struct i2c_board_info *info)
{
- struct i2c_client *client;
- struct i2c_board_info info = {};
- struct dev_archdata dev_ad = {};
u32 addr;
int ret;
- dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
+ memset(info, 0, sizeof(*info));
- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) {
- dev_err(&adap->dev, "of_i2c: modalias failure on %pOF\n",
- node);
- return ERR_PTR(-EINVAL);
+ if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) {
+ dev_err(dev, "of_i2c: modalias failure on %pOF\n", node);
+ return -EINVAL;
}
ret = of_property_read_u32(node, "reg", &addr);
if (ret) {
- dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node);
- return ERR_PTR(ret);
+ dev_err(dev, "of_i2c: invalid reg on %pOF\n", node);
+ return ret;
}
if (addr & I2C_TEN_BIT_ADDRESS) {
addr &= ~I2C_TEN_BIT_ADDRESS;
- info.flags |= I2C_CLIENT_TEN;
+ info->flags |= I2C_CLIENT_TEN;
}
if (addr & I2C_OWN_SLAVE_ADDRESS) {
addr &= ~I2C_OWN_SLAVE_ADDRESS;
- info.flags |= I2C_CLIENT_SLAVE;
+ info->flags |= I2C_CLIENT_SLAVE;
}
- info.addr = addr;
- info.archdata = &dev_ad;
- info.of_node = of_node_get(node);
+ info->addr = addr;
+ info->of_node = node;
if (of_property_read_bool(node, "host-notify"))
- info.flags |= I2C_CLIENT_HOST_NOTIFY;
+ info->flags |= I2C_CLIENT_HOST_NOTIFY;
if (of_get_property(node, "wakeup-source", NULL))
- info.flags |= I2C_CLIENT_WAKE;
+ info->flags |= I2C_CLIENT_WAKE;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_i2c_get_board_info);
+
+static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
+ struct device_node *node)
+{
+ struct i2c_client *client;
+ struct i2c_board_info info;
+ int ret;
+
+ dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node);
+
+ ret = of_i2c_get_board_info(&adap->dev, node, &info);
+ if (ret)
+ return ERR_PTR(ret);
client = i2c_new_device(adap, &info);
if (!client) {
dev_err(&adap->dev, "of_i2c: Failure registering %pOF\n", node);
- of_node_put(node);
return ERR_PTR(-EINVAL);
}
return client;
diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
index b5aec33..f3f6830 100644
--- a/drivers/i2c/i2c-core-smbus.c
+++ b/drivers/i2c/i2c-core-smbus.c
@@ -466,6 +466,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
status = i2c_transfer(adapter, msg, num);
if (status < 0)
return status;
+ if (status != num)
+ return -EIO;
/* Check PEC if last message is a read */
if (i && (msg[num-1].flags & I2C_M_RD)) {
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 1667b6e..1aca742 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -244,7 +244,7 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client,
u8 __user **data_ptrs;
int i, res;
- data_ptrs = kmalloc(nmsgs * sizeof(u8 __user *), GFP_KERNEL);
+ data_ptrs = kmalloc_array(nmsgs, sizeof(u8 __user *), GFP_KERNEL);
if (data_ptrs == NULL) {
kfree(msgs);
return -ENOMEM;
diff --git a/drivers/i2c/i2c-mux.c b/drivers/i2c/i2c-mux.c
index 9669ca4..300ab4b 100644
--- a/drivers/i2c/i2c-mux.c
+++ b/drivers/i2c/i2c-mux.c
@@ -418,7 +418,7 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
snprintf(symlink_name, sizeof(symlink_name), "channel-%u", chan_id);
WARN(sysfs_create_link(&muxc->dev->kobj, &priv->adap.dev.kobj,
symlink_name),
- "can't create symlink for channel %u\n", chan_id);
+ "can't create symlink to channel %u\n", chan_id);
dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
i2c_adapter_id(&priv->adap));
diff --git a/drivers/i2c/i2c-stub.c b/drivers/i2c/i2c-stub.c
index 4a9ad91..f31ec08 100644
--- a/drivers/i2c/i2c-stub.c
+++ b/drivers/i2c/i2c-stub.c
@@ -338,8 +338,9 @@ static int __init i2c_stub_allocate_banks(int i)
chip->bank_mask >>= 1;
}
- chip->bank_words = kzalloc(chip->bank_mask * chip->bank_size *
- sizeof(u16), GFP_KERNEL);
+ chip->bank_words = kcalloc(chip->bank_mask * chip->bank_size,
+ sizeof(u16),
+ GFP_KERNEL);
if (!chip->bank_words)
return -ENOMEM;
diff --git a/drivers/i2c/muxes/i2c-demux-pinctrl.c b/drivers/i2c/muxes/i2c-demux-pinctrl.c
index 33ce032..035032e 100644
--- a/drivers/i2c/muxes/i2c-demux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-demux-pinctrl.c
@@ -18,6 +18,7 @@
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
@@ -105,7 +106,7 @@ static int i2c_demux_activate_master(struct i2c_demux_pinctrl_priv *priv, u32 ne
priv->cur_adap.owner = THIS_MODULE;
priv->cur_adap.algo = &priv->algo;
priv->cur_adap.algo_data = priv;
- priv->cur_adap.dev.parent = priv->dev;
+ priv->cur_adap.dev.parent = &adap->dev;
priv->cur_adap.class = adap->class;
priv->cur_adap.retries = adap->retries;
priv->cur_adap.timeout = adap->timeout;
@@ -254,6 +255,8 @@ static int i2c_demux_pinctrl_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, priv);
+ pm_runtime_no_callbacks(&pdev->dev);
+
/* switch to first parent as active master */
i2c_demux_activate_master(priv, 0);
diff --git a/drivers/i2c/muxes/i2c-mux-gpio.c b/drivers/i2c/muxes/i2c-mux-gpio.c
index 1a9973e..401308e 100644
--- a/drivers/i2c/muxes/i2c-mux-gpio.c
+++ b/drivers/i2c/muxes/i2c-mux-gpio.c
@@ -10,7 +10,7 @@
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
-#include <linux/i2c-mux-gpio.h>
+#include <linux/platform_data/i2c-mux-gpio.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -88,8 +88,8 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
mux->data.n_values = of_get_child_count(np);
- values = devm_kzalloc(&pdev->dev,
- sizeof(*mux->data.values) * mux->data.n_values,
+ values = devm_kcalloc(&pdev->dev,
+ mux->data.n_values, sizeof(*mux->data.values),
GFP_KERNEL);
if (!values) {
dev_err(&pdev->dev, "Cannot allocate values array");
@@ -111,8 +111,9 @@ static int i2c_mux_gpio_probe_dt(struct gpiomux *mux,
return -EINVAL;
}
- gpios = devm_kzalloc(&pdev->dev,
- sizeof(*mux->data.gpios) * mux->data.n_gpios, GFP_KERNEL);
+ gpios = devm_kcalloc(&pdev->dev,
+ mux->data.n_gpios, sizeof(*mux->data.gpios),
+ GFP_KERNEL);
if (!gpios) {
dev_err(&pdev->dev, "Cannot allocate gpios array");
return -ENOMEM;
diff --git a/drivers/i2c/muxes/i2c-mux-ltc4306.c b/drivers/i2c/muxes/i2c-mux-ltc4306.c
index 311b1cc..a9af932 100644
--- a/drivers/i2c/muxes/i2c-mux-ltc4306.c
+++ b/drivers/i2c/muxes/i2c-mux-ltc4306.c
@@ -206,8 +206,7 @@ static const struct of_device_id ltc4306_of_match[] = {
};
MODULE_DEVICE_TABLE(of, ltc4306_of_match);
-static int ltc4306_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ltc4306_probe(struct i2c_client *client)
{
struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
const struct chip_desc *chip;
@@ -221,7 +220,7 @@ static int ltc4306_probe(struct i2c_client *client,
chip = of_device_get_match_data(&client->dev);
if (!chip)
- chip = &chips[id->driver_data];
+ chip = &chips[i2c_match_id(ltc4306_id, client)->driver_data];
idle_disc = device_property_read_bool(&client->dev,
"i2c-mux-idle-disconnect");
@@ -310,7 +309,7 @@ static struct i2c_driver ltc4306_driver = {
.name = "ltc4306",
.of_match_table = of_match_ptr(ltc4306_of_match),
},
- .probe = ltc4306_probe,
+ .probe_new = ltc4306_probe,
.remove = ltc4306_remove,
.id_table = ltc4306_id,
};
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c
index 09bafd3..fbc7480 100644
--- a/drivers/i2c/muxes/i2c-mux-pca954x.c
+++ b/drivers/i2c/muxes/i2c-mux-pca954x.c
@@ -36,6 +36,7 @@
*/
#include <linux/device.h>
+#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
@@ -373,7 +374,6 @@ static int pca954x_probe(struct i2c_client *client,
int num, force, class;
struct i2c_mux_core *muxc;
struct pca954x *data;
- const struct of_device_id *match;
int ret;
if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE))
@@ -389,15 +389,19 @@ static int pca954x_probe(struct i2c_client *client,
i2c_set_clientdata(client, muxc);
data->client = client;
- /* Get the mux out of reset if a reset GPIO is specified. */
- gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_LOW);
+ /* Reset the mux if a reset GPIO is specified. */
+ gpio = devm_gpiod_get_optional(&client->dev, "reset", GPIOD_OUT_HIGH);
if (IS_ERR(gpio))
return PTR_ERR(gpio);
+ if (gpio) {
+ udelay(1);
+ gpiod_set_value_cansleep(gpio, 0);
+ /* Give the chip some time to recover. */
+ udelay(1);
+ }
- match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev);
- if (match)
- data->chip = of_device_get_match_data(&client->dev);
- else
+ data->chip = of_device_get_match_data(&client->dev);
+ if (!data->chip)
data->chip = &chips[id->driver_data];
if (data->chip->id.manufacturer_id != I2C_DEVICE_ID_NONE) {
diff --git a/drivers/i2c/muxes/i2c-mux-reg.c b/drivers/i2c/muxes/i2c-mux-reg.c
index c948e5a..5653295 100644
--- a/drivers/i2c/muxes/i2c-mux-reg.c
+++ b/drivers/i2c/muxes/i2c-mux-reg.c
@@ -124,13 +124,11 @@ static int i2c_mux_reg_probe_dt(struct regmux *mux,
}
mux->data.write_only = of_property_read_bool(np, "write-only");
- values = devm_kzalloc(&pdev->dev,
- sizeof(*mux->data.values) * mux->data.n_values,
+ values = devm_kcalloc(&pdev->dev,
+ mux->data.n_values, sizeof(*mux->data.values),
GFP_KERNEL);
- if (!values) {
- dev_err(&pdev->dev, "Cannot allocate values array");
+ if (!values)
return -ENOMEM;
- }
for_each_child_of_node(np, child) {
of_property_read_u32(child, "reg", values + i);
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index 4b5dc01..e52c58c 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -1455,7 +1455,7 @@ static int hpt366_init_one(struct pci_dev *dev, const struct pci_device_id *id)
if (info == &hpt36x || info == &hpt374)
dev2 = pci_get_slot(dev->bus, dev->devfn + 1);
- dyn_info = kzalloc(sizeof(*dyn_info) * (dev2 ? 2 : 1), GFP_KERNEL);
+ dyn_info = kcalloc(dev2 ? 2 : 1, sizeof(*dyn_info), GFP_KERNEL);
if (dyn_info == NULL) {
printk(KERN_ERR "%s %s: out of memory!\n",
d.name, pci_name(dev));
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 56d7bc2..416a2f3 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -985,8 +985,9 @@ static int hwif_init(ide_hwif_t *hwif)
if (!hwif->sg_max_nents)
hwif->sg_max_nents = PRD_ENTRIES;
- hwif->sg_table = kmalloc(sizeof(struct scatterlist)*hwif->sg_max_nents,
- GFP_KERNEL);
+ hwif->sg_table = kmalloc_array(hwif->sg_max_nents,
+ sizeof(struct scatterlist),
+ GFP_KERNEL);
if (!hwif->sg_table) {
printk(KERN_ERR "%s: unable to allocate SG table.\n", hwif->name);
goto out;
diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c
index 04029d1..36a64c8 100644
--- a/drivers/ide/it821x.c
+++ b/drivers/ide/it821x.c
@@ -652,7 +652,7 @@ static int it821x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
struct it821x_dev *itdevs;
int rc;
- itdevs = kzalloc(2 * sizeof(*itdevs), GFP_KERNEL);
+ itdevs = kcalloc(2, sizeof(*itdevs), GFP_KERNEL);
if (itdevs == NULL) {
printk(KERN_ERR DRV_NAME " %s: out of memory\n", pci_name(dev));
return -ENOMEM;
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 71a5ee6..44b5168 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -624,8 +624,8 @@ static int at91_adc_trigger_init(struct iio_dev *idev)
struct at91_adc_state *st = iio_priv(idev);
int i, ret;
- st->trig = devm_kzalloc(&idev->dev,
- st->trigger_number * sizeof(*st->trig),
+ st->trig = devm_kcalloc(&idev->dev,
+ st->trigger_number, sizeof(*st->trig),
GFP_KERNEL);
if (st->trig == NULL) {
@@ -908,7 +908,8 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
st->registers = &st->caps->registers;
st->num_channels = st->caps->num_channels;
st->trigger_number = of_get_child_count(node);
- st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number *
+ st->trigger_list = devm_kcalloc(&idev->dev,
+ st->trigger_number,
sizeof(struct at91_adc_trigger),
GFP_KERNEL);
if (!st->trigger_list) {
diff --git a/drivers/iio/adc/max1027.c b/drivers/iio/adc/max1027.c
index 375da64..311c1a8 100644
--- a/drivers/iio/adc/max1027.c
+++ b/drivers/iio/adc/max1027.c
@@ -422,8 +422,8 @@ static int max1027_probe(struct spi_device *spi)
indio_dev->num_channels = st->info->num_channels;
indio_dev->available_scan_masks = st->info->available_scan_masks;
- st->buffer = devm_kmalloc(&indio_dev->dev,
- indio_dev->num_channels * 2,
+ st->buffer = devm_kmalloc_array(&indio_dev->dev,
+ indio_dev->num_channels, 2,
GFP_KERNEL);
if (st->buffer == NULL) {
dev_err(&indio_dev->dev, "Can't allocate buffer\n");
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index 7f1848d..7fb4f52 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -1453,8 +1453,10 @@ static int max1363_alloc_scan_masks(struct iio_dev *indio_dev)
int i;
masks = devm_kzalloc(&indio_dev->dev,
- BITS_TO_LONGS(MAX1363_MAX_CHANNELS) * sizeof(long) *
- (st->chip_info->num_modes + 1), GFP_KERNEL);
+ array3_size(BITS_TO_LONGS(MAX1363_MAX_CHANNELS),
+ sizeof(long),
+ st->chip_info->num_modes + 1),
+ GFP_KERNEL);
if (!masks)
return -ENOMEM;
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index dc83f8f..e470510 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -898,9 +898,10 @@ static int twl6030_gpadc_probe(struct platform_device *pdev)
gpadc = iio_priv(indio_dev);
- gpadc->twl6030_cal_tbl = devm_kzalloc(dev,
- sizeof(*gpadc->twl6030_cal_tbl) *
- pdata->nchannels, GFP_KERNEL);
+ gpadc->twl6030_cal_tbl = devm_kcalloc(dev,
+ pdata->nchannels,
+ sizeof(*gpadc->twl6030_cal_tbl),
+ GFP_KERNEL);
if (!gpadc->twl6030_cal_tbl)
return -ENOMEM;
diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c
index 9234c6a..095530c 100644
--- a/drivers/iio/dac/ad5592r-base.c
+++ b/drivers/iio/dac/ad5592r-base.c
@@ -536,8 +536,9 @@ static int ad5592r_alloc_channels(struct ad5592r_state *st)
st->channel_offstate[reg] = tmp;
}
- channels = devm_kzalloc(st->dev,
- (1 + 2 * num_channels) * sizeof(*channels), GFP_KERNEL);
+ channels = devm_kcalloc(st->dev,
+ 1 + 2 * num_channels, sizeof(*channels),
+ GFP_KERNEL);
if (!channels)
return -ENOMEM;
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
index 36607d5..76643c5 100644
--- a/drivers/iio/imu/adis_buffer.c
+++ b/drivers/iio/imu/adis_buffer.c
@@ -38,7 +38,7 @@ int adis_update_scan_mode(struct iio_dev *indio_dev,
if (!adis->xfer)
return -ENOMEM;
- adis->buffer = kzalloc(indio_dev->scan_bytes * 2, GFP_KERNEL);
+ adis->buffer = kcalloc(indio_dev->scan_bytes, 2, GFP_KERNEL);
if (!adis->buffer)
return -ENOMEM;
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index ec98790..06ca3f7 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -436,7 +436,7 @@ struct iio_channel *iio_channel_get_all(struct device *dev)
}
/* NULL terminated array to save passing size */
- chans = kzalloc(sizeof(*chans)*(nummaps + 1), GFP_KERNEL);
+ chans = kcalloc(nummaps + 1, sizeof(*chans), GFP_KERNEL);
if (chans == NULL) {
ret = -ENOMEM;
goto error_ret;
diff --git a/drivers/iio/multiplexer/iio-mux.c b/drivers/iio/multiplexer/iio-mux.c
index 60621cc..e1f44ce 100644
--- a/drivers/iio/multiplexer/iio-mux.c
+++ b/drivers/iio/multiplexer/iio-mux.c
@@ -281,9 +281,10 @@ static int mux_configure_channel(struct device *dev, struct mux *mux,
if (!page)
return -ENOMEM;
}
- child->ext_info_cache = devm_kzalloc(dev,
- sizeof(*child->ext_info_cache) *
- num_ext_info, GFP_KERNEL);
+ child->ext_info_cache = devm_kcalloc(dev,
+ num_ext_info,
+ sizeof(*child->ext_info_cache),
+ GFP_KERNEL);
if (!child->ext_info_cache)
return -ENOMEM;
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 71a34be..81d66f5 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -1245,8 +1245,9 @@ int ib_cache_setup_one(struct ib_device *device)
rwlock_init(&device->cache.lock);
device->cache.ports =
- kzalloc(sizeof(*device->cache.ports) *
- (rdma_end_port(device) - rdma_start_port(device) + 1), GFP_KERNEL);
+ kcalloc(rdma_end_port(device) - rdma_start_port(device) + 1,
+ sizeof(*device->cache.ports),
+ GFP_KERNEL);
if (!device->cache.ports)
return -ENOMEM;
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 6813ee7..bff10ab 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -1855,8 +1855,8 @@ static struct rdma_id_private *cma_new_conn_id(struct rdma_cm_id *listen_id,
rt = &id->route;
rt->num_paths = ib_event->param.req_rcvd.alternate_path ? 2 : 1;
- rt->path_rec = kmalloc(sizeof *rt->path_rec * rt->num_paths,
- GFP_KERNEL);
+ rt->path_rec = kmalloc_array(rt->num_paths, sizeof(*rt->path_rec),
+ GFP_KERNEL);
if (!rt->path_rec)
goto err;
diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c
index 84f5138..6fa4c59 100644
--- a/drivers/infiniband/core/device.c
+++ b/drivers/infiniband/core/device.c
@@ -336,8 +336,8 @@ static int read_port_immutable(struct ib_device *device)
* Therefore port_immutable is declared as a 1 based array with
* potential empty slots at the beginning.
*/
- device->port_immutable = kzalloc(sizeof(*device->port_immutable)
- * (end_port + 1),
+ device->port_immutable = kcalloc(end_port + 1,
+ sizeof(*device->port_immutable),
GFP_KERNEL);
if (!device->port_immutable)
return -ENOMEM;
diff --git a/drivers/infiniband/core/fmr_pool.c b/drivers/infiniband/core/fmr_pool.c
index a0a9ed7..a077500 100644
--- a/drivers/infiniband/core/fmr_pool.c
+++ b/drivers/infiniband/core/fmr_pool.c
@@ -235,8 +235,9 @@ struct ib_fmr_pool *ib_create_fmr_pool(struct ib_pd *pd,
if (params->cache) {
pool->cache_bucket =
- kmalloc(IB_FMR_HASH_SIZE * sizeof *pool->cache_bucket,
- GFP_KERNEL);
+ kmalloc_array(IB_FMR_HASH_SIZE,
+ sizeof(*pool->cache_bucket),
+ GFP_KERNEL);
if (!pool->cache_bucket) {
ret = -ENOMEM;
goto out_free_pool;
diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c
index da12da1..cdb63f3 100644
--- a/drivers/infiniband/core/iwpm_util.c
+++ b/drivers/infiniband/core/iwpm_util.c
@@ -56,14 +56,16 @@ int iwpm_init(u8 nl_client)
int ret = 0;
mutex_lock(&iwpm_admin_lock);
if (atomic_read(&iwpm_admin.refcount) == 0) {
- iwpm_hash_bucket = kzalloc(IWPM_MAPINFO_HASH_SIZE *
- sizeof(struct hlist_head), GFP_KERNEL);
+ iwpm_hash_bucket = kcalloc(IWPM_MAPINFO_HASH_SIZE,
+ sizeof(struct hlist_head),
+ GFP_KERNEL);
if (!iwpm_hash_bucket) {
ret = -ENOMEM;
goto init_exit;
}
- iwpm_reminfo_bucket = kzalloc(IWPM_REMINFO_HASH_SIZE *
- sizeof(struct hlist_head), GFP_KERNEL);
+ iwpm_reminfo_bucket = kcalloc(IWPM_REMINFO_HASH_SIZE,
+ sizeof(struct hlist_head),
+ GFP_KERNEL);
if (!iwpm_reminfo_bucket) {
kfree(iwpm_hash_bucket);
ret = -ENOMEM;
diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c
index 2aadf58..182436b 100644
--- a/drivers/infiniband/core/umem_odp.c
+++ b/drivers/infiniband/core/umem_odp.c
@@ -285,13 +285,15 @@ struct ib_umem *ib_alloc_odp_umem(struct ib_ucontext *context,
mutex_init(&odp_data->umem_mutex);
init_completion(&odp_data->notifier_completion);
- odp_data->page_list = vzalloc(pages * sizeof(*odp_data->page_list));
+ odp_data->page_list =
+ vzalloc(array_size(pages, sizeof(*odp_data->page_list)));
if (!odp_data->page_list) {
ret = -ENOMEM;
goto out_odp_data;
}
- odp_data->dma_list = vzalloc(pages * sizeof(*odp_data->dma_list));
+ odp_data->dma_list =
+ vzalloc(array_size(pages, sizeof(*odp_data->dma_list)));
if (!odp_data->dma_list) {
ret = -ENOMEM;
goto out_page_list;
@@ -371,15 +373,17 @@ int ib_umem_odp_get(struct ib_ucontext *context, struct ib_umem *umem,
init_completion(&umem->odp_data->notifier_completion);
if (ib_umem_num_pages(umem)) {
- umem->odp_data->page_list = vzalloc(ib_umem_num_pages(umem) *
- sizeof(*umem->odp_data->page_list));
+ umem->odp_data->page_list =
+ vzalloc(array_size(sizeof(*umem->odp_data->page_list),
+ ib_umem_num_pages(umem)));
if (!umem->odp_data->page_list) {
ret_val = -ENOMEM;
goto out_odp_data;
}
- umem->odp_data->dma_list = vzalloc(ib_umem_num_pages(umem) *
- sizeof(*umem->odp_data->dma_list));
+ umem->odp_data->dma_list =
+ vzalloc(array_size(sizeof(*umem->odp_data->dma_list),
+ ib_umem_num_pages(umem)));
if (!umem->odp_data->dma_list) {
ret_val = -ENOMEM;
goto out_page_list;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 3179a95..3e90b6a 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -3559,8 +3559,8 @@ int ib_uverbs_ex_create_flow(struct ib_uverbs_file *file,
goto err_uobj;
}
- flow_attr = kzalloc(sizeof(*flow_attr) + cmd.flow_attr.num_of_specs *
- sizeof(union ib_flow_spec), GFP_KERNEL);
+ flow_attr = kzalloc(struct_size(flow_attr, flows,
+ cmd.flow_attr.num_of_specs), GFP_KERNEL);
if (!flow_attr) {
err = -ENOMEM;
goto err_put;
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 3ae2339..2094d13 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -736,10 +736,6 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
if (ret)
return ret;
- if (!file->ucontext &&
- (command != IB_USER_VERBS_CMD_GET_CONTEXT || extended))
- return -EINVAL;
-
if (extended) {
if (count < (sizeof(hdr) + sizeof(ex_hdr)))
return -EINVAL;
@@ -759,6 +755,16 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
goto out;
}
+ /*
+ * Must be after the ib_dev check, as once the RCU clears ib_dev ==
+ * NULL means ucontext == NULL
+ */
+ if (!file->ucontext &&
+ (command != IB_USER_VERBS_CMD_GET_CONTEXT || extended)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
if (!verify_command_mask(ib_dev, command, extended)) {
ret = -EOPNOTSUPP;
goto out;
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 0b56828..9d6beb9 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -1562,11 +1562,12 @@ EXPORT_SYMBOL(ib_destroy_qp);
/* Completion queues */
-struct ib_cq *ib_create_cq(struct ib_device *device,
- ib_comp_handler comp_handler,
- void (*event_handler)(struct ib_event *, void *),
- void *cq_context,
- const struct ib_cq_init_attr *cq_attr)
+struct ib_cq *__ib_create_cq(struct ib_device *device,
+ ib_comp_handler comp_handler,
+ void (*event_handler)(struct ib_event *, void *),
+ void *cq_context,
+ const struct ib_cq_init_attr *cq_attr,
+ const char *caller)
{
struct ib_cq *cq;
@@ -1580,12 +1581,13 @@ struct ib_cq *ib_create_cq(struct ib_device *device,
cq->cq_context = cq_context;
atomic_set(&cq->usecnt, 0);
cq->res.type = RDMA_RESTRACK_CQ;
+ cq->res.kern_name = caller;
rdma_restrack_add(&cq->res);
}
return cq;
}
-EXPORT_SYMBOL(ib_create_cq);
+EXPORT_SYMBOL(__ib_create_cq);
int rdma_set_cq_moderation(struct ib_cq *cq, u16 cq_count, u16 cq_period)
{
diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c
index 3328acc..dcb4bba 100644
--- a/drivers/infiniband/hw/cxgb3/cxio_hal.c
+++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c
@@ -279,7 +279,7 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain,
if (!wq->qpid)
return -ENOMEM;
- wq->rq = kzalloc(depth * sizeof(struct t3_swrq), GFP_KERNEL);
+ wq->rq = kcalloc(depth, sizeof(struct t3_swrq), GFP_KERNEL);
if (!wq->rq)
goto err1;
@@ -287,7 +287,7 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain,
if (!wq->rq_addr)
goto err2;
- wq->sq = kzalloc(depth * sizeof(struct t3_swsq), GFP_KERNEL);
+ wq->sq = kcalloc(depth, sizeof(struct t3_swsq), GFP_KERNEL);
if (!wq->sq)
goto err3;
diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c
index 44161ca..a3c3418 100644
--- a/drivers/infiniband/hw/cxgb4/device.c
+++ b/drivers/infiniband/hw/cxgb4/device.c
@@ -859,8 +859,9 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
rdev->status_page->cq_size = rdev->lldi.vr->cq.size;
if (c4iw_wr_log) {
- rdev->wr_log = kzalloc((1 << c4iw_wr_log_size_order) *
- sizeof(*rdev->wr_log), GFP_KERNEL);
+ rdev->wr_log = kcalloc(1 << c4iw_wr_log_size_order,
+ sizeof(*rdev->wr_log),
+ GFP_KERNEL);
if (rdev->wr_log) {
rdev->wr_log_size = 1 << c4iw_wr_log_size_order;
atomic_set(&rdev->wr_log_idx, 0);
@@ -1445,7 +1446,7 @@ static void recover_queues(struct uld_ctx *ctx)
ctx->dev->db_state = RECOVERY;
idr_for_each(&ctx->dev->qpidr, count_qps, &count);
- qp_list.qps = kzalloc(count * sizeof *qp_list.qps, GFP_ATOMIC);
+ qp_list.qps = kcalloc(count, sizeof(*qp_list.qps), GFP_ATOMIC);
if (!qp_list.qps) {
spin_unlock_irq(&ctx->dev->lock);
return;
diff --git a/drivers/infiniband/hw/cxgb4/id_table.c b/drivers/infiniband/hw/cxgb4/id_table.c
index 5c2cfde..724d232 100644
--- a/drivers/infiniband/hw/cxgb4/id_table.c
+++ b/drivers/infiniband/hw/cxgb4/id_table.c
@@ -92,8 +92,8 @@ int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
alloc->last = 0;
alloc->max = num;
spin_lock_init(&alloc->lock);
- alloc->table = kmalloc(BITS_TO_LONGS(num) * sizeof(long),
- GFP_KERNEL);
+ alloc->table = kmalloc_array(BITS_TO_LONGS(num), sizeof(long),
+ GFP_KERNEL);
if (!alloc->table)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c
index 4106eed..aef5330 100644
--- a/drivers/infiniband/hw/cxgb4/qp.c
+++ b/drivers/infiniband/hw/cxgb4/qp.c
@@ -216,15 +216,15 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
}
if (!user) {
- wq->sq.sw_sq = kzalloc(wq->sq.size * sizeof *wq->sq.sw_sq,
- GFP_KERNEL);
+ wq->sq.sw_sq = kcalloc(wq->sq.size, sizeof(*wq->sq.sw_sq),
+ GFP_KERNEL);
if (!wq->sq.sw_sq) {
ret = -ENOMEM;
goto free_rq_qid;
}
- wq->rq.sw_rq = kzalloc(wq->rq.size * sizeof *wq->rq.sw_rq,
- GFP_KERNEL);
+ wq->rq.sw_rq = kcalloc(wq->rq.size, sizeof(*wq->rq.sw_rq),
+ GFP_KERNEL);
if (!wq->rq.sw_rq) {
ret = -ENOMEM;
goto free_sw_sq;
diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c
index 298e0e3..7fb350b 100644
--- a/drivers/infiniband/hw/hfi1/sdma.c
+++ b/drivers/infiniband/hw/hfi1/sdma.c
@@ -1461,7 +1461,8 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
if (!sde->descq)
goto bail;
sde->tx_ring =
- kvzalloc_node(sizeof(struct sdma_txreq *) * descq_cnt,
+ kvzalloc_node(array_size(descq_cnt,
+ sizeof(struct sdma_txreq *)),
GFP_KERNEL, dd->node);
if (!sde->tx_ring)
goto bail;
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index 0e8dad6..a6e11be 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -3177,7 +3177,7 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp,
struct device *dev = hr_dev->dev;
int ret = -EINVAL;
- context = kzalloc(2 * sizeof(*context), GFP_KERNEL);
+ context = kcalloc(2, sizeof(*context), GFP_KERNEL);
if (!context)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c
index d1fe0e7..eb26a5f 100644
--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
+++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
@@ -144,7 +144,7 @@ static int hns_roce_buddy_init(struct hns_roce_buddy *buddy, int max_order)
buddy->bits[i] = kcalloc(s, sizeof(long), GFP_KERNEL |
__GFP_NOWARN);
if (!buddy->bits[i]) {
- buddy->bits[i] = vzalloc(s * sizeof(long));
+ buddy->bits[i] = vzalloc(array_size(s, sizeof(long)));
if (!buddy->bits[i])
goto err_out_free;
}
diff --git a/drivers/infiniband/hw/mlx4/mad.c b/drivers/infiniband/hw/mlx4/mad.c
index d604b3d..90a3e2642 100644
--- a/drivers/infiniband/hw/mlx4/mad.c
+++ b/drivers/infiniband/hw/mlx4/mad.c
@@ -1613,7 +1613,8 @@ static int mlx4_ib_alloc_pv_bufs(struct mlx4_ib_demux_pv_ctx *ctx,
tun_qp = &ctx->qp[qp_type];
- tun_qp->ring = kzalloc(sizeof (struct mlx4_ib_buf) * MLX4_NUM_TUNNEL_BUFS,
+ tun_qp->ring = kcalloc(MLX4_NUM_TUNNEL_BUFS,
+ sizeof(struct mlx4_ib_buf),
GFP_KERNEL);
if (!tun_qp->ring)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c
index f839bf3..4ec519a 100644
--- a/drivers/infiniband/hw/mlx4/main.c
+++ b/drivers/infiniband/hw/mlx4/main.c
@@ -302,7 +302,8 @@ static int mlx4_ib_add_gid(const union ib_gid *gid,
ctx->refcount++;
}
if (!ret && hw_update) {
- gids = kmalloc(sizeof(*gids) * MLX4_MAX_PORT_GIDS, GFP_ATOMIC);
+ gids = kmalloc_array(MLX4_MAX_PORT_GIDS, sizeof(*gids),
+ GFP_ATOMIC);
if (!gids) {
ret = -ENOMEM;
} else {
@@ -355,7 +356,8 @@ static int mlx4_ib_del_gid(const struct ib_gid_attr *attr, void **context)
if (!ret && hw_update) {
int i;
- gids = kmalloc(sizeof(*gids) * MLX4_MAX_PORT_GIDS, GFP_ATOMIC);
+ gids = kmalloc_array(MLX4_MAX_PORT_GIDS, sizeof(*gids),
+ GFP_ATOMIC);
if (!gids) {
ret = -ENOMEM;
} else {
@@ -2872,9 +2874,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
goto err_counter;
ibdev->ib_uc_qpns_bitmap =
- kmalloc(BITS_TO_LONGS(ibdev->steer_qpn_count) *
- sizeof(long),
- GFP_KERNEL);
+ kmalloc_array(BITS_TO_LONGS(ibdev->steer_qpn_count),
+ sizeof(long),
+ GFP_KERNEL);
if (!ibdev->ib_uc_qpns_bitmap)
goto err_steer_qp_release;
diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c
index ed1f253..c7c85c2 100644
--- a/drivers/infiniband/hw/mlx4/mr.c
+++ b/drivers/infiniband/hw/mlx4/mr.c
@@ -486,8 +486,11 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags,
}
if (flags & IB_MR_REREG_ACCESS) {
- if (ib_access_writable(mr_access_flags) && !mmr->umem->writable)
- return -EPERM;
+ if (ib_access_writable(mr_access_flags) &&
+ !mmr->umem->writable) {
+ err = -EPERM;
+ goto release_mpt_entry;
+ }
err = mlx4_mr_hw_change_access(dev->dev, *pmpt_entry,
convert_access(mr_access_flags));
diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c
index cd2c08c..3b8045f 100644
--- a/drivers/infiniband/hw/mlx4/qp.c
+++ b/drivers/infiniband/hw/mlx4/qp.c
@@ -573,8 +573,8 @@ static int alloc_proxy_bufs(struct ib_device *dev, struct mlx4_ib_qp *qp)
int i;
qp->sqp_proxy_rcv =
- kmalloc(sizeof (struct mlx4_ib_buf) * qp->rq.wqe_cnt,
- GFP_KERNEL);
+ kmalloc_array(qp->rq.wqe_cnt, sizeof(struct mlx4_ib_buf),
+ GFP_KERNEL);
if (!qp->sqp_proxy_rcv)
return -ENOMEM;
for (i = 0; i < qp->rq.wqe_cnt; i++) {
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index e52dd21..e3e330f 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -3199,8 +3199,8 @@ static int flow_counters_set_data(struct ib_counters *ibcounters,
if (!mcounters->hw_cntrs_hndl) {
mcounters->hw_cntrs_hndl = mlx5_fc_create(
to_mdev(ibcounters->device)->mdev, false);
- if (!mcounters->hw_cntrs_hndl) {
- ret = -ENOMEM;
+ if (IS_ERR(mcounters->hw_cntrs_hndl)) {
+ ret = PTR_ERR(mcounters->hw_cntrs_hndl);
goto free;
}
hw_hndl = true;
@@ -3546,29 +3546,35 @@ static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
return ERR_PTR(-ENOMEM);
err = ib_copy_from_udata(ucmd, udata, required_ucmd_sz);
- if (err) {
- kfree(ucmd);
- return ERR_PTR(err);
- }
+ if (err)
+ goto free_ucmd;
}
- if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO)
- return ERR_PTR(-ENOMEM);
+ if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO) {
+ err = -ENOMEM;
+ goto free_ucmd;
+ }
if (domain != IB_FLOW_DOMAIN_USER ||
flow_attr->port > dev->num_ports ||
(flow_attr->flags & ~(IB_FLOW_ATTR_FLAGS_DONT_TRAP |
- IB_FLOW_ATTR_FLAGS_EGRESS)))
- return ERR_PTR(-EINVAL);
+ IB_FLOW_ATTR_FLAGS_EGRESS))) {
+ err = -EINVAL;
+ goto free_ucmd;
+ }
if (is_egress &&
(flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
- flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT))
- return ERR_PTR(-EINVAL);
+ flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) {
+ err = -EINVAL;
+ goto free_ucmd;
+ }
dst = kzalloc(sizeof(*dst), GFP_KERNEL);
- if (!dst)
- return ERR_PTR(-ENOMEM);
+ if (!dst) {
+ err = -ENOMEM;
+ goto free_ucmd;
+ }
mutex_lock(&dev->flow_db->lock);
@@ -3637,8 +3643,8 @@ destroy_ft:
unlock:
mutex_unlock(&dev->flow_db->lock);
kfree(dst);
+free_ucmd:
kfree(ucmd);
- kfree(handler);
return ERR_PTR(err);
}
diff --git a/drivers/infiniband/hw/mlx5/srq.c b/drivers/infiniband/hw/mlx5/srq.c
index 3c7522d..0af7b79 100644
--- a/drivers/infiniband/hw/mlx5/srq.c
+++ b/drivers/infiniband/hw/mlx5/srq.c
@@ -127,7 +127,7 @@ static int create_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq,
goto err_umem;
}
- in->pas = kvzalloc(sizeof(*in->pas) * ncont, GFP_KERNEL);
+ in->pas = kvcalloc(ncont, sizeof(*in->pas), GFP_KERNEL);
if (!in->pas) {
err = -ENOMEM;
goto err_umem;
@@ -189,7 +189,7 @@ static int create_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq,
}
mlx5_ib_dbg(dev, "srq->buf.page_shift = %d\n", srq->buf.page_shift);
- in->pas = kvzalloc(sizeof(*in->pas) * srq->buf.npages, GFP_KERNEL);
+ in->pas = kvcalloc(srq->buf.npages, sizeof(*in->pas), GFP_KERNEL);
if (!in->pas) {
err = -ENOMEM;
goto err_buf;
diff --git a/drivers/infiniband/hw/mthca/mthca_allocator.c b/drivers/infiniband/hw/mthca/mthca_allocator.c
index b4e0cf4..aaf10dd 100644
--- a/drivers/infiniband/hw/mthca/mthca_allocator.c
+++ b/drivers/infiniband/hw/mthca/mthca_allocator.c
@@ -90,8 +90,8 @@ int mthca_alloc_init(struct mthca_alloc *alloc, u32 num, u32 mask,
alloc->max = num;
alloc->mask = mask;
spin_lock_init(&alloc->lock);
- alloc->table = kmalloc(BITS_TO_LONGS(num) * sizeof (long),
- GFP_KERNEL);
+ alloc->table = kmalloc_array(BITS_TO_LONGS(num), sizeof(long),
+ GFP_KERNEL);
if (!alloc->table)
return -ENOMEM;
@@ -162,7 +162,8 @@ int mthca_array_init(struct mthca_array *array, int nent)
int npage = (nent * sizeof (void *) + PAGE_SIZE - 1) / PAGE_SIZE;
int i;
- array->page_list = kmalloc(npage * sizeof *array->page_list, GFP_KERNEL);
+ array->page_list = kmalloc_array(npage, sizeof(*array->page_list),
+ GFP_KERNEL);
if (!array->page_list)
return -ENOMEM;
@@ -220,7 +221,8 @@ int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
npages *= 2;
}
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
+ dma_list = kmalloc_array(npages, sizeof(*dma_list),
+ GFP_KERNEL);
if (!dma_list)
goto err_free;
@@ -231,12 +233,14 @@ int mthca_buf_alloc(struct mthca_dev *dev, int size, int max_direct,
npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
shift = PAGE_SHIFT;
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
+ dma_list = kmalloc_array(npages, sizeof(*dma_list),
+ GFP_KERNEL);
if (!dma_list)
return -ENOMEM;
- buf->page_list = kmalloc(npages * sizeof *buf->page_list,
- GFP_KERNEL);
+ buf->page_list = kmalloc_array(npages,
+ sizeof(*buf->page_list),
+ GFP_KERNEL);
if (!buf->page_list)
goto err_out;
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 419a2a2..83aa47e 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -565,9 +565,9 @@ int mthca_cmd_use_events(struct mthca_dev *dev)
{
int i;
- dev->cmd.context = kmalloc(dev->cmd.max_cmds *
- sizeof (struct mthca_cmd_context),
- GFP_KERNEL);
+ dev->cmd.context = kmalloc_array(dev->cmd.max_cmds,
+ sizeof(struct mthca_cmd_context),
+ GFP_KERNEL);
if (!dev->cmd.context)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
index 6902017..30400ea 100644
--- a/drivers/infiniband/hw/mthca/mthca_eq.c
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c
@@ -479,15 +479,15 @@ static int mthca_create_eq(struct mthca_dev *dev,
eq->nent = roundup_pow_of_two(max(nent, 2));
npages = ALIGN(eq->nent * MTHCA_EQ_ENTRY_SIZE, PAGE_SIZE) / PAGE_SIZE;
- eq->page_list = kmalloc(npages * sizeof *eq->page_list,
- GFP_KERNEL);
+ eq->page_list = kmalloc_array(npages, sizeof(*eq->page_list),
+ GFP_KERNEL);
if (!eq->page_list)
goto err_out;
for (i = 0; i < npages; ++i)
eq->page_list[i].buf = NULL;
- dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
+ dma_list = kmalloc_array(npages, sizeof(*dma_list), GFP_KERNEL);
if (!dma_list)
goto err_out_free;
diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
index 7a31be3..cc9c0c8 100644
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c
@@ -712,9 +712,9 @@ int mthca_init_db_tab(struct mthca_dev *dev)
dev->db_tab->max_group1 = 0;
dev->db_tab->min_group2 = dev->db_tab->npages - 1;
- dev->db_tab->page = kmalloc(dev->db_tab->npages *
- sizeof *dev->db_tab->page,
- GFP_KERNEL);
+ dev->db_tab->page = kmalloc_array(dev->db_tab->npages,
+ sizeof(*dev->db_tab->page),
+ GFP_KERNEL);
if (!dev->db_tab->page) {
kfree(dev->db_tab);
return -ENOMEM;
diff --git a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
index ed9a989..6686042 100644
--- a/drivers/infiniband/hw/mthca/mthca_mr.c
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c
@@ -144,7 +144,7 @@ static int mthca_buddy_init(struct mthca_buddy *buddy, int max_order)
buddy->max_order = max_order;
spin_lock_init(&buddy->lock);
- buddy->bits = kzalloc((buddy->max_order + 1) * sizeof (long *),
+ buddy->bits = kcalloc(buddy->max_order + 1, sizeof(long *),
GFP_KERNEL);
buddy->num_free = kcalloc((buddy->max_order + 1), sizeof *buddy->num_free,
GFP_KERNEL);
@@ -153,7 +153,7 @@ static int mthca_buddy_init(struct mthca_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] = kmalloc(s * sizeof (long), GFP_KERNEL);
+ buddy->bits[i] = kmalloc_array(s, sizeof(long), GFP_KERNEL);
if (!buddy->bits[i])
goto err_out_free;
bitmap_zero(buddy->bits[i],
diff --git a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c
index 15d0644..7ea9707 100644
--- a/drivers/infiniband/hw/mthca/mthca_profile.c
+++ b/drivers/infiniband/hw/mthca/mthca_profile.c
@@ -79,7 +79,7 @@ s64 mthca_make_profile(struct mthca_dev *dev,
struct mthca_resource *profile;
int i, j;
- profile = kzalloc(MTHCA_RES_NUM * sizeof *profile, GFP_KERNEL);
+ profile = kcalloc(MTHCA_RES_NUM, sizeof(*profile), GFP_KERNEL);
if (!profile)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index d21960c..af1c49d 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -1054,8 +1054,8 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
size = PAGE_ALIGN(qp->send_wqe_offset +
(qp->sq.max << qp->sq.wqe_shift));
- qp->wrid = kmalloc((qp->rq.max + qp->sq.max) * sizeof (u64),
- GFP_KERNEL);
+ qp->wrid = kmalloc_array(qp->rq.max + qp->sq.max, sizeof(u64),
+ GFP_KERNEL);
if (!qp->wrid)
goto err_out;
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index d22f970..f79732b 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -155,7 +155,7 @@ static int mthca_alloc_srq_buf(struct mthca_dev *dev, struct mthca_pd *pd,
if (pd->ibpd.uobject)
return 0;
- srq->wrid = kmalloc(srq->max * sizeof (u64), GFP_KERNEL);
+ srq->wrid = kmalloc_array(srq->max, sizeof(u64), GFP_KERNEL);
if (!srq->wrid)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/nes/nes_mgt.c b/drivers/infiniband/hw/nes/nes_mgt.c
index 21e0ebd..9bdb84d 100644
--- a/drivers/infiniband/hw/nes/nes_mgt.c
+++ b/drivers/infiniband/hw/nes/nes_mgt.c
@@ -878,7 +878,8 @@ int nes_init_mgt_qp(struct nes_device *nesdev, struct net_device *netdev, struct
int ret;
/* Allocate space the all mgt QPs once */
- mgtvnic = kzalloc(NES_MGT_QP_COUNT * sizeof(struct nes_vnic_mgt), GFP_KERNEL);
+ mgtvnic = kcalloc(NES_MGT_QP_COUNT, sizeof(struct nes_vnic_mgt),
+ GFP_KERNEL);
if (!mgtvnic)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index 007d5e8..61014e2 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -904,7 +904,7 @@ static void nes_netdev_set_multicast_list(struct net_device *netdev)
int i;
struct netdev_hw_addr *ha;
- addrs = kmalloc(ETH_ALEN * mc_count, GFP_ATOMIC);
+ addrs = kmalloc_array(mc_count, ETH_ALEN, GFP_ATOMIC);
if (!addrs) {
set_allmulti(nesdev, nic_active_bit);
goto unlock;
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c
index 1040a6e..32f2655 100644
--- a/drivers/infiniband/hw/nes/nes_verbs.c
+++ b/drivers/infiniband/hw/nes/nes_verbs.c
@@ -2254,8 +2254,9 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
ibmr = ERR_PTR(-ENOMEM);
goto reg_user_mr_err;
}
- root_vpbl.leaf_vpbl = kzalloc(sizeof(*root_vpbl.leaf_vpbl)*1024,
- GFP_KERNEL);
+ root_vpbl.leaf_vpbl = kcalloc(1024,
+ sizeof(*root_vpbl.leaf_vpbl),
+ GFP_KERNEL);
if (!root_vpbl.leaf_vpbl) {
ib_umem_release(region);
pci_free_consistent(nesdev->pcidev, 8192, root_vpbl.pbl_vbase,
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
index 2c260e1..6c136e5 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -3096,7 +3096,7 @@ static int ocrdma_create_eqs(struct ocrdma_dev *dev)
if (!num_eq)
return -EINVAL;
- dev->eq_tbl = kzalloc(sizeof(struct ocrdma_eq) * num_eq, GFP_KERNEL);
+ dev->eq_tbl = kcalloc(num_eq, sizeof(struct ocrdma_eq), GFP_KERNEL);
if (!dev->eq_tbl)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index eb8b6a9..5962c0e 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -221,19 +221,20 @@ static int ocrdma_register_device(struct ocrdma_dev *dev)
static int ocrdma_alloc_resources(struct ocrdma_dev *dev)
{
mutex_init(&dev->dev_lock);
- dev->cq_tbl = kzalloc(sizeof(struct ocrdma_cq *) *
- OCRDMA_MAX_CQ, GFP_KERNEL);
+ dev->cq_tbl = kcalloc(OCRDMA_MAX_CQ, sizeof(struct ocrdma_cq *),
+ GFP_KERNEL);
if (!dev->cq_tbl)
goto alloc_err;
if (dev->attr.max_qp) {
- dev->qp_tbl = kzalloc(sizeof(struct ocrdma_qp *) *
- OCRDMA_MAX_QP, GFP_KERNEL);
+ dev->qp_tbl = kcalloc(OCRDMA_MAX_QP,
+ sizeof(struct ocrdma_qp *),
+ GFP_KERNEL);
if (!dev->qp_tbl)
goto alloc_err;
}
- dev->stag_arr = kzalloc(sizeof(u64) * OCRDMA_MAX_STAG, GFP_KERNEL);
+ dev->stag_arr = kcalloc(OCRDMA_MAX_STAG, sizeof(u64), GFP_KERNEL);
if (dev->stag_arr == NULL)
goto alloc_err;
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 784ed6b..82e20fc 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -843,8 +843,8 @@ static int ocrdma_build_pbl_tbl(struct ocrdma_dev *dev, struct ocrdma_hw_mr *mr)
void *va;
dma_addr_t pa;
- mr->pbl_table = kzalloc(sizeof(struct ocrdma_pbl) *
- mr->num_pbls, GFP_KERNEL);
+ mr->pbl_table = kcalloc(mr->num_pbls, sizeof(struct ocrdma_pbl),
+ GFP_KERNEL);
if (!mr->pbl_table)
return -ENOMEM;
@@ -1323,12 +1323,12 @@ static void ocrdma_set_qp_db(struct ocrdma_dev *dev, struct ocrdma_qp *qp,
static int ocrdma_alloc_wr_id_tbl(struct ocrdma_qp *qp)
{
qp->wqe_wr_id_tbl =
- kzalloc(sizeof(*(qp->wqe_wr_id_tbl)) * qp->sq.max_cnt,
+ kcalloc(qp->sq.max_cnt, sizeof(*(qp->wqe_wr_id_tbl)),
GFP_KERNEL);
if (qp->wqe_wr_id_tbl == NULL)
return -ENOMEM;
qp->rqe_wr_id_tbl =
- kzalloc(sizeof(u64) * qp->rq.max_cnt, GFP_KERNEL);
+ kcalloc(qp->rq.max_cnt, sizeof(u64), GFP_KERNEL);
if (qp->rqe_wr_id_tbl == NULL)
return -ENOMEM;
@@ -1865,15 +1865,16 @@ struct ib_srq *ocrdma_create_srq(struct ib_pd *ibpd,
if (udata == NULL) {
status = -ENOMEM;
- srq->rqe_wr_id_tbl = kzalloc(sizeof(u64) * srq->rq.max_cnt,
- GFP_KERNEL);
+ srq->rqe_wr_id_tbl = kcalloc(srq->rq.max_cnt, sizeof(u64),
+ GFP_KERNEL);
if (srq->rqe_wr_id_tbl == NULL)
goto arm_err;
srq->bit_fields_len = (srq->rq.max_cnt / 32) +
(srq->rq.max_cnt % 32 ? 1 : 0);
srq->idx_bit_fields =
- kmalloc(srq->bit_fields_len * sizeof(u32), GFP_KERNEL);
+ kmalloc_array(srq->bit_fields_len, sizeof(u32),
+ GFP_KERNEL);
if (srq->idx_bit_fields == NULL)
goto arm_err;
memset(srq->idx_bit_fields, 0xff,
diff --git a/drivers/infiniband/hw/qedr/main.c b/drivers/infiniband/hw/qedr/main.c
index f4cb60b..ad22b32 100644
--- a/drivers/infiniband/hw/qedr/main.c
+++ b/drivers/infiniband/hw/qedr/main.c
@@ -317,8 +317,8 @@ static int qedr_alloc_resources(struct qedr_dev *dev)
u16 n_entries;
int i, rc;
- dev->sgid_tbl = kzalloc(sizeof(union ib_gid) *
- QEDR_MAX_SGID, GFP_KERNEL);
+ dev->sgid_tbl = kcalloc(QEDR_MAX_SGID, sizeof(union ib_gid),
+ GFP_KERNEL);
if (!dev->sgid_tbl)
return -ENOMEM;
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index 710032f..f07b8df 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -1614,7 +1614,7 @@ static int qedr_create_kernel_qp(struct qedr_dev *dev,
qp->sq.max_wr = min_t(u32, attrs->cap.max_send_wr * dev->wq_multiplier,
dev->attr.max_sqe);
- qp->wqe_wr_id = kzalloc(qp->sq.max_wr * sizeof(*qp->wqe_wr_id),
+ qp->wqe_wr_id = kcalloc(qp->sq.max_wr, sizeof(*qp->wqe_wr_id),
GFP_KERNEL);
if (!qp->wqe_wr_id) {
DP_ERR(dev, "create qp: failed SQ shadow memory allocation\n");
@@ -1632,7 +1632,7 @@ static int qedr_create_kernel_qp(struct qedr_dev *dev,
qp->rq.max_wr = (u16) max_t(u32, attrs->cap.max_recv_wr, 1);
/* Allocate driver internal RQ array */
- qp->rqe_wr_id = kzalloc(qp->rq.max_wr * sizeof(*qp->rqe_wr_id),
+ qp->rqe_wr_id = kcalloc(qp->rq.max_wr, sizeof(*qp->rqe_wr_id),
GFP_KERNEL);
if (!qp->rqe_wr_id) {
DP_ERR(dev,
@@ -1957,6 +1957,9 @@ int qedr_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr,
}
if (attr_mask & (IB_QP_AV | IB_QP_PATH_MTU)) {
+ if (rdma_protocol_iwarp(&dev->ibdev, 1))
+ return -EINVAL;
+
if (attr_mask & IB_QP_PATH_MTU) {
if (attr->path_mtu < IB_MTU_256 ||
attr->path_mtu > IB_MTU_4096) {
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index 8a15e5c..fb1ff59 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -2496,15 +2496,16 @@ static void init_6120_cntrnames(struct qib_devdata *dd)
dd->cspec->cntrnamelen = sizeof(cntr6120names) - 1;
else
dd->cspec->cntrnamelen = 1 + s - cntr6120names;
- dd->cspec->cntrs = kmalloc(dd->cspec->ncntrs
- * sizeof(u64), GFP_KERNEL);
+ dd->cspec->cntrs = kmalloc_array(dd->cspec->ncntrs, sizeof(u64),
+ GFP_KERNEL);
for (i = 0, s = (char *)portcntr6120names; s; i++)
s = strchr(s + 1, '\n');
dd->cspec->nportcntrs = i - 1;
dd->cspec->portcntrnamelen = sizeof(portcntr6120names) - 1;
- dd->cspec->portcntrs = kmalloc(dd->cspec->nportcntrs
- * sizeof(u64), GFP_KERNEL);
+ dd->cspec->portcntrs = kmalloc_array(dd->cspec->nportcntrs,
+ sizeof(u64),
+ GFP_KERNEL);
}
static u32 qib_read_6120cntrs(struct qib_devdata *dd, loff_t pos, char **namep,
diff --git a/drivers/infiniband/hw/qib/qib_iba7220.c b/drivers/infiniband/hw/qib/qib_iba7220.c
index bdff232..163a57a 100644
--- a/drivers/infiniband/hw/qib/qib_iba7220.c
+++ b/drivers/infiniband/hw/qib/qib_iba7220.c
@@ -3147,15 +3147,16 @@ static void init_7220_cntrnames(struct qib_devdata *dd)
dd->cspec->cntrnamelen = sizeof(cntr7220names) - 1;
else
dd->cspec->cntrnamelen = 1 + s - cntr7220names;
- dd->cspec->cntrs = kmalloc(dd->cspec->ncntrs
- * sizeof(u64), GFP_KERNEL);
+ dd->cspec->cntrs = kmalloc_array(dd->cspec->ncntrs, sizeof(u64),
+ GFP_KERNEL);
for (i = 0, s = (char *)portcntr7220names; s; i++)
s = strchr(s + 1, '\n');
dd->cspec->nportcntrs = i - 1;
dd->cspec->portcntrnamelen = sizeof(portcntr7220names) - 1;
- dd->cspec->portcntrs = kmalloc(dd->cspec->nportcntrs
- * sizeof(u64), GFP_KERNEL);
+ dd->cspec->portcntrs = kmalloc_array(dd->cspec->nportcntrs,
+ sizeof(u64),
+ GFP_KERNEL);
}
static u32 qib_read_7220cntrs(struct qib_devdata *dd, loff_t pos, char **namep,
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c
index 8414ae4..bf5e222 100644
--- a/drivers/infiniband/hw/qib/qib_iba7322.c
+++ b/drivers/infiniband/hw/qib/qib_iba7322.c
@@ -3648,8 +3648,9 @@ static int qib_do_7322_reset(struct qib_devdata *dd)
if (msix_entries) {
/* can be up to 512 bytes, too big for stack */
- msix_vecsave = kmalloc(2 * dd->cspec->num_msix_entries *
- sizeof(u64), GFP_KERNEL);
+ msix_vecsave = kmalloc_array(2 * dd->cspec->num_msix_entries,
+ sizeof(u64),
+ GFP_KERNEL);
}
/*
@@ -5009,16 +5010,17 @@ static void init_7322_cntrnames(struct qib_devdata *dd)
dd->cspec->cntrnamelen = sizeof(cntr7322names) - 1;
else
dd->cspec->cntrnamelen = 1 + s - cntr7322names;
- dd->cspec->cntrs = kmalloc(dd->cspec->ncntrs
- * sizeof(u64), GFP_KERNEL);
+ dd->cspec->cntrs = kmalloc_array(dd->cspec->ncntrs, sizeof(u64),
+ GFP_KERNEL);
for (i = 0, s = (char *)portcntr7322names; s; i++)
s = strchr(s + 1, '\n');
dd->cspec->nportcntrs = i - 1;
dd->cspec->portcntrnamelen = sizeof(portcntr7322names) - 1;
for (i = 0; i < dd->num_pports; ++i) {
- dd->pport[i].cpspec->portcntrs = kmalloc(dd->cspec->nportcntrs
- * sizeof(u64), GFP_KERNEL);
+ dd->pport[i].cpspec->portcntrs =
+ kmalloc_array(dd->cspec->nportcntrs, sizeof(u64),
+ GFP_KERNEL);
}
}
@@ -6412,12 +6414,15 @@ static int qib_init_7322_variables(struct qib_devdata *dd)
sbufcnt = dd->piobcnt2k + dd->piobcnt4k +
NUM_VL15_BUFS + BITS_PER_LONG - 1;
sbufcnt /= BITS_PER_LONG;
- dd->cspec->sendchkenable = kmalloc(sbufcnt *
- sizeof(*dd->cspec->sendchkenable), GFP_KERNEL);
- dd->cspec->sendgrhchk = kmalloc(sbufcnt *
- sizeof(*dd->cspec->sendgrhchk), GFP_KERNEL);
- dd->cspec->sendibchk = kmalloc(sbufcnt *
- sizeof(*dd->cspec->sendibchk), GFP_KERNEL);
+ dd->cspec->sendchkenable =
+ kmalloc_array(sbufcnt, sizeof(*dd->cspec->sendchkenable),
+ GFP_KERNEL);
+ dd->cspec->sendgrhchk =
+ kmalloc_array(sbufcnt, sizeof(*dd->cspec->sendgrhchk),
+ GFP_KERNEL);
+ dd->cspec->sendibchk =
+ kmalloc_array(sbufcnt, sizeof(*dd->cspec->sendibchk),
+ GFP_KERNEL);
if (!dd->cspec->sendchkenable || !dd->cspec->sendgrhchk ||
!dd->cspec->sendibchk) {
ret = -ENOMEM;
@@ -7290,8 +7295,9 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev,
actual_cnt -= dd->num_pports;
tabsize = actual_cnt;
- dd->cspec->msix_entries = kzalloc(tabsize *
- sizeof(struct qib_msix_entry), GFP_KERNEL);
+ dd->cspec->msix_entries = kcalloc(tabsize,
+ sizeof(struct qib_msix_entry),
+ GFP_KERNEL);
if (!dd->cspec->msix_entries)
tabsize = 0;
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index 0155202..d7cdc77 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -369,11 +369,13 @@ static void init_shadow_tids(struct qib_devdata *dd)
struct page **pages;
dma_addr_t *addrs;
- pages = vzalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(struct page *));
+ pages = vzalloc(array_size(sizeof(struct page *),
+ dd->cfgctxts * dd->rcvtidcnt));
if (!pages)
goto bail;
- addrs = vzalloc(dd->cfgctxts * dd->rcvtidcnt * sizeof(dma_addr_t));
+ addrs = vzalloc(array_size(sizeof(dma_addr_t),
+ dd->cfgctxts * dd->rcvtidcnt));
if (!addrs)
goto bail_free;
@@ -1134,8 +1136,8 @@ struct qib_devdata *qib_alloc_devdata(struct pci_dev *pdev, size_t extra)
if (!qib_cpulist_count) {
u32 count = num_online_cpus();
- qib_cpulist = kzalloc(BITS_TO_LONGS(count) *
- sizeof(long), GFP_KERNEL);
+ qib_cpulist = kcalloc(BITS_TO_LONGS(count), sizeof(long),
+ GFP_KERNEL);
if (qib_cpulist)
qib_cpulist_count = count;
}
@@ -1673,8 +1675,8 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *rcd)
size = rcd->rcvegrbuf_size;
if (!rcd->rcvegrbuf) {
rcd->rcvegrbuf =
- kzalloc_node(chunk * sizeof(rcd->rcvegrbuf[0]),
- GFP_KERNEL, rcd->node_id);
+ kcalloc_node(chunk, sizeof(rcd->rcvegrbuf[0]),
+ GFP_KERNEL, rcd->node_id);
if (!rcd->rcvegrbuf)
goto bail;
}
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
index 912d8ef..bf51365 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_qp_grp.c
@@ -543,7 +543,7 @@ alloc_res_chunk_list(struct usnic_vnic *vnic,
/* Do Nothing */
}
- res_chunk_list = kzalloc(sizeof(*res_chunk_list)*(res_lst_sz+1),
+ res_chunk_list = kcalloc(res_lst_sz + 1, sizeof(*res_chunk_list),
GFP_ATOMIC);
if (!res_chunk_list)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/infiniband/hw/usnic/usnic_vnic.c b/drivers/infiniband/hw/usnic/usnic_vnic.c
index e7b0030..ebe08f3 100644
--- a/drivers/infiniband/hw/usnic/usnic_vnic.c
+++ b/drivers/infiniband/hw/usnic/usnic_vnic.c
@@ -312,7 +312,7 @@ static int usnic_vnic_alloc_res_chunk(struct usnic_vnic *vnic,
}
chunk->cnt = chunk->free_cnt = cnt;
- chunk->res = kzalloc(sizeof(*(chunk->res))*cnt, GFP_KERNEL);
+ chunk->res = kcalloc(cnt, sizeof(*(chunk->res)), GFP_KERNEL);
if (!chunk->res)
return -ENOMEM;
diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c
index 4004613..41183bd 100644
--- a/drivers/infiniband/sw/rdmavt/qp.c
+++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -813,7 +813,7 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
sz = sizeof(struct rvt_sge) *
init_attr->cap.max_send_sge +
sizeof(struct rvt_swqe);
- swq = vzalloc_node(sqsize * sz, rdi->dparms.node);
+ swq = vzalloc_node(array_size(sz, sqsize), rdi->dparms.node);
if (!swq)
return ERR_PTR(-ENOMEM);
@@ -836,11 +836,10 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
RCU_INIT_POINTER(qp->next, NULL);
if (init_attr->qp_type == IB_QPT_RC) {
qp->s_ack_queue =
- kzalloc_node(
- sizeof(*qp->s_ack_queue) *
- rvt_max_atomic(rdi),
- GFP_KERNEL,
- rdi->dparms.node);
+ kcalloc_node(rvt_max_atomic(rdi),
+ sizeof(*qp->s_ack_queue),
+ GFP_KERNEL,
+ rdi->dparms.node);
if (!qp->s_ack_queue)
goto bail_qp;
}
diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c
index f30eeba..8be2723 100644
--- a/drivers/infiniband/sw/rxe/rxe_req.c
+++ b/drivers/infiniband/sw/rxe/rxe_req.c
@@ -645,6 +645,9 @@ next_wqe:
} else {
goto exit;
}
+ if ((wqe->wr.send_flags & IB_SEND_SIGNALED) ||
+ qp->sq_sig_type == IB_SIGNAL_ALL_WR)
+ rxe_run_task(&qp->comp.task, 1);
qp->req.wqe_index = next_index(qp->sq.queue,
qp->req.wqe_index);
goto next_wqe;
@@ -709,6 +712,7 @@ next_wqe:
if (fill_packet(qp, wqe, &pkt, skb, payload)) {
pr_debug("qp#%d Error during fill packet\n", qp_num(qp));
+ kfree_skb(skb);
goto err;
}
@@ -740,7 +744,6 @@ next_wqe:
goto next_wqe;
err:
- kfree_skb(skb);
wqe->status = IB_WC_LOC_PROT_ERR;
wqe->state = wqe_state_error;
__rxe_do_task(&qp->comp.task);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 962fbcb..6535d9b 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -358,7 +358,8 @@ static int ipoib_cm_nonsrq_init_rx(struct net_device *dev, struct ib_cm_id *cm_i
int ret;
int i;
- rx->rx_ring = vzalloc(ipoib_recvq_size * sizeof *rx->rx_ring);
+ rx->rx_ring = vzalloc(array_size(ipoib_recvq_size,
+ sizeof(*rx->rx_ring)));
if (!rx->rx_ring)
return -ENOMEM;
@@ -1145,7 +1146,7 @@ static int ipoib_cm_tx_init(struct ipoib_cm_tx *p, u32 qpn,
int ret;
noio_flag = memalloc_noio_save();
- p->tx_ring = vzalloc(ipoib_sendq_size * sizeof(*p->tx_ring));
+ p->tx_ring = vzalloc(array_size(ipoib_sendq_size, sizeof(*p->tx_ring)));
if (!p->tx_ring) {
memalloc_noio_restore(noio_flag);
ret = -ENOMEM;
@@ -1570,7 +1571,8 @@ static void ipoib_cm_create_srq(struct net_device *dev, int max_sge)
return;
}
- priv->cm.srq_ring = vzalloc(ipoib_recvq_size * sizeof *priv->cm.srq_ring);
+ priv->cm.srq_ring = vzalloc(array_size(ipoib_recvq_size,
+ sizeof(*priv->cm.srq_ring)));
if (!priv->cm.srq_ring) {
ib_destroy_srq(priv->cm.srq);
priv->cm.srq = NULL;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 2ce40a7..26cde95 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1526,7 +1526,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
return -ENOMEM;
set_bit(IPOIB_STOP_NEIGH_GC, &priv->flags);
size = roundup_pow_of_two(arp_tbl.gc_thresh3);
- buckets = kzalloc(size * sizeof(*buckets), GFP_KERNEL);
+ buckets = kcalloc(size, sizeof(*buckets), GFP_KERNEL);
if (!buckets) {
kfree(htbl);
return -ENOMEM;
@@ -1704,12 +1704,14 @@ static int ipoib_dev_init_default(struct net_device *dev)
ipoib_napi_add(dev);
/* Allocate RX/TX "rings" to hold queued skbs */
- priv->rx_ring = kzalloc(ipoib_recvq_size * sizeof *priv->rx_ring,
- GFP_KERNEL);
+ priv->rx_ring = kcalloc(ipoib_recvq_size,
+ sizeof(*priv->rx_ring),
+ GFP_KERNEL);
if (!priv->rx_ring)
goto out;
- priv->tx_ring = vzalloc(ipoib_sendq_size * sizeof *priv->tx_ring);
+ priv->tx_ring = vzalloc(array_size(ipoib_sendq_size,
+ sizeof(*priv->tx_ring)));
if (!priv->tx_ring) {
pr_warn("%s: failed to allocate TX ring (%d entries)\n",
priv->ca->name, ipoib_sendq_size);
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c b/drivers/infiniband/ulp/iser/iser_initiator.c
index ca858d6..2f63885 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -258,8 +258,9 @@ int iser_alloc_rx_descriptors(struct iser_conn *iser_conn,
goto alloc_login_buf_fail;
iser_conn->num_rx_descs = session->cmds_max;
- iser_conn->rx_descs = kmalloc(iser_conn->num_rx_descs *
- sizeof(struct iser_rx_desc), GFP_KERNEL);
+ iser_conn->rx_descs = kmalloc_array(iser_conn->num_rx_descs,
+ sizeof(struct iser_rx_desc),
+ GFP_KERNEL);
if (!iser_conn->rx_descs)
goto rx_desc_alloc_fail;
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index f2f9318..cccbcf0 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -181,8 +181,9 @@ isert_alloc_rx_descriptors(struct isert_conn *isert_conn)
u64 dma_addr;
int i, j;
- isert_conn->rx_descs = kzalloc(ISERT_QP_MAX_RECV_DTOS *
- sizeof(struct iser_rx_desc), GFP_KERNEL);
+ isert_conn->rx_descs = kcalloc(ISERT_QP_MAX_RECV_DTOS,
+ sizeof(struct iser_rx_desc),
+ GFP_KERNEL);
if (!isert_conn->rx_descs)
return -ENOMEM;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index c35d2cd..9786b24 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1035,16 +1035,17 @@ static int srp_alloc_req_data(struct srp_rdma_ch *ch)
for (i = 0; i < target->req_ring_size; ++i) {
req = &ch->req_ring[i];
- mr_list = kmalloc(target->mr_per_cmd * sizeof(void *),
- GFP_KERNEL);
+ mr_list = kmalloc_array(target->mr_per_cmd, sizeof(void *),
+ GFP_KERNEL);
if (!mr_list)
goto out;
if (srp_dev->use_fast_reg) {
req->fr_list = mr_list;
} else {
req->fmr_list = mr_list;
- req->map_page = kmalloc(srp_dev->max_pages_per_mr *
- sizeof(void *), GFP_KERNEL);
+ req->map_page = kmalloc_array(srp_dev->max_pages_per_mr,
+ sizeof(void *),
+ GFP_KERNEL);
if (!req->map_page)
goto out;
}
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index dfec0e1..3081c62 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -720,7 +720,7 @@ static struct srpt_ioctx **srpt_alloc_ioctx_ring(struct srpt_device *sdev,
WARN_ON(ioctx_size != sizeof(struct srpt_recv_ioctx)
&& ioctx_size != sizeof(struct srpt_send_ioctx));
- ring = kmalloc(ring_size * sizeof(ring[0]), GFP_KERNEL);
+ ring = kmalloc_array(ring_size, sizeof(ring[0]), GFP_KERNEL);
if (!ring)
goto out;
for (i = 0; i < ring_size; ++i) {
diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig
index ff80377..c5992cd 100644
--- a/drivers/input/Kconfig
+++ b/drivers/input/Kconfig
@@ -16,7 +16,7 @@ config INPUT
Say N here if you have a headless (no monitor, no keyboard) system.
- More information is available: <file:Documentation/input/input.txt>
+ More information is available: <file:Documentation/input/input.rst>
If unsure, say Y.
@@ -144,7 +144,7 @@ config INPUT_JOYDEV
If unsure, say Y.
- More information is available: <file:Documentation/input/joystick.txt>
+ More information is available: <file:Documentation/input/joydev/joystick.rst>
To compile this driver as a module, choose M here: the
module will be called joydev.
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index 9591fc0..d8f9c6e 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -9,7 +9,7 @@ menuconfig INPUT_JOYSTICK
and the list of supported devices will be displayed. This option
doesn't affect the kernel.
- Please read the file <file:Documentation/input/joystick.txt> which
+ Please read the file <file:Documentation/input/joydev/joystick.rst> which
contains more information.
if INPUT_JOYSTICK
@@ -25,7 +25,7 @@ config JOYSTICK_ANALOG
Flightstick Pro, ThrustMaster FCS, 6 and 8 button gamepads, or
Saitek Cyborg joysticks.
- Please read the file <file:Documentation/input/joystick.txt> which
+ Please read the file <file:Documentation/input/joydev/joystick.rst> which
contains more information.
To compile this driver as a module, choose M here: the
@@ -214,7 +214,7 @@ config JOYSTICK_DB9
gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
Commodore, Amstrad CPC joystick connected to your parallel port.
For more information on how to use the driver please read
- <file:Documentation/input/joystick-parport.txt>.
+ <file:Documentation/input/devices/joystick-parport.rst>.
To compile this driver as a module, choose M here: the
module will be called db9.
@@ -229,7 +229,7 @@ config JOYSTICK_GAMECON
Sony PlayStation gamepad or a Multisystem -- Atari, Amiga,
Commodore, Amstrad CPC joystick connected to your parallel port.
For more information on how to use the driver please read
- <file:Documentation/input/joystick-parport.txt>.
+ <file:Documentation/input/devices/joystick-parport.rst>.
To compile this driver as a module, choose M here: the
module will be called gamecon.
@@ -241,7 +241,7 @@ config JOYSTICK_TURBOGRAFX
Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
and want to use it with Multisystem -- Atari, Amiga, Commodore,
Amstrad CPC joystick. For more information on how to use the driver
- please read <file:Documentation/input/joystick-parport.txt>.
+ please read <file:Documentation/input/devices/joystick-parport.rst>.
To compile this driver as a module, choose M here: the
module will be called turbografx.
@@ -287,7 +287,7 @@ config JOYSTICK_XPAD
and/or "Event interface support" (CONFIG_INPUT_EVDEV) as well.
For information about how to connect the X-Box pad to USB, see
- <file:Documentation/input/xpad.txt>.
+ <file:Documentation/input/devices/xpad.rst>.
To compile this driver as a module, choose M here: the
module will be called xpad.
@@ -313,7 +313,7 @@ config JOYSTICK_WALKERA0701
Say Y or M here if you have a Walkera WK-0701 transmitter which is
supplied with a ready to fly Walkera helicopters such as HM36,
HM37, HM60 and want to use it via parport as a joystick. More
- information is available: <file:Documentation/input/walkera0701.txt>
+ information is available: <file:Documentation/input/devices/walkera0701.rst>
To compile this driver as a module, choose M here: the
module will be called walkera0701.
diff --git a/drivers/input/joystick/iforce/Kconfig b/drivers/input/joystick/iforce/Kconfig
index 8fde22a..ab4dbcb 100644
--- a/drivers/input/joystick/iforce/Kconfig
+++ b/drivers/input/joystick/iforce/Kconfig
@@ -27,6 +27,6 @@ config JOYSTICK_IFORCE_232
connected to your serial (COM) port.
You will need an additional utility called inputattach, see
- <file:Documentation/input/joystick.txt>
- and <file:Documentation/input/ff.txt>.
+ <file:Documentation/input/joydev/joystick.rst>
+ and <file:Documentation/input/ff.rst>.
diff --git a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
index d1c6e48..7f4dff9 100644
--- a/drivers/input/joystick/joydump.c
+++ b/drivers/input/joystick/joydump.c
@@ -80,7 +80,7 @@ static int joydump_connect(struct gameport *gameport, struct gameport_driver *dr
timeout = gameport_time(gameport, 10000); /* 10 ms */
- buf = kmalloc(BUF_SIZE * sizeof(struct joydump), GFP_KERNEL);
+ buf = kmalloc_array(BUF_SIZE, sizeof(struct joydump), GFP_KERNEL);
if (!buf) {
printk(KERN_INFO "joydump: no memory for testing\n");
goto jd_end;
diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c
index 36a5b93..dce313d 100644
--- a/drivers/input/joystick/walkera0701.c
+++ b/drivers/input/joystick/walkera0701.c
@@ -3,7 +3,7 @@
*
* Copyright (c) 2008 Peter Popovec
*
- * More about driver: <file:Documentation/input/walkera0701.txt>
+ * More about driver: <file:Documentation/input/devices/walkera0701.rst>
*/
/*
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 2b469cc..6bd97ff 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -747,4 +747,13 @@ config KEYBOARD_BCM
To compile this driver as a module, choose M here: the
module will be called bcm-keypad.
+config KEYBOARD_MTK_PMIC
+ tristate "MediaTek PMIC keys support"
+ depends on MFD_MT6397
+ help
+ Say Y here if you want to use the pmic keys (powerkey/homekey).
+
+ To compile this driver as a module, choose M here: the
+ module will be called pmic-keys.
+
endif
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 8fab920..182e929 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_KEYBOARD_MATRIX) += matrix_keypad.o
obj-$(CONFIG_KEYBOARD_MAX7359) += max7359_keypad.o
obj-$(CONFIG_KEYBOARD_MCS) += mcs_touchkey.o
obj-$(CONFIG_KEYBOARD_MPR121) += mpr121_touchkey.o
+obj-$(CONFIG_KEYBOARD_MTK_PMIC) += mtk-pmic-keys.o
obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
obj-$(CONFIG_KEYBOARD_NOMADIK) += nomadik-ske-keypad.o
obj-$(CONFIG_KEYBOARD_NSPIRE) += nspire-keypad.o
diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c
index 997e3e9..e319f74 100644
--- a/drivers/input/keyboard/clps711x-keypad.c
+++ b/drivers/input/keyboard/clps711x-keypad.c
@@ -109,8 +109,8 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
if (priv->row_count < 1)
return -EINVAL;
- priv->gpio_data = devm_kzalloc(dev,
- sizeof(*priv->gpio_data) * priv->row_count,
+ priv->gpio_data = devm_kcalloc(dev,
+ priv->row_count, sizeof(*priv->gpio_data),
GFP_KERNEL);
if (!priv->gpio_data)
return -ENOMEM;
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index 41614c1..f51ae09 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -443,9 +443,9 @@ matrix_keypad_parse_dt(struct device *dev)
of_property_read_u32(np, "col-scan-delay-us",
&pdata->col_scan_delay_us);
- gpios = devm_kzalloc(dev,
- sizeof(unsigned int) *
- (pdata->num_row_gpios + pdata->num_col_gpios),
+ gpios = devm_kcalloc(dev,
+ pdata->num_row_gpios + pdata->num_col_gpios,
+ sizeof(unsigned int),
GFP_KERNEL);
if (!gpios) {
dev_err(dev, "could not allocate memory for gpios\n");
diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
new file mode 100644
index 0000000..02c67a1
--- /dev/null
+++ b/drivers/input/keyboard/mtk-pmic-keys.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2017 MediaTek, Inc.
+ *
+ * Author: Chen Zhong <chen.zhong@mediatek.com>
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+#include <linux/mfd/mt6323/registers.h>
+#include <linux/mfd/mt6397/registers.h>
+#include <linux/mfd/mt6397/core.h>
+
+#define MTK_PMIC_PWRKEY_RST_EN_MASK 0x1
+#define MTK_PMIC_PWRKEY_RST_EN_SHIFT 6
+#define MTK_PMIC_HOMEKEY_RST_EN_MASK 0x1
+#define MTK_PMIC_HOMEKEY_RST_EN_SHIFT 5
+#define MTK_PMIC_RST_DU_MASK 0x3
+#define MTK_PMIC_RST_DU_SHIFT 8
+
+#define MTK_PMIC_PWRKEY_RST \
+ (MTK_PMIC_PWRKEY_RST_EN_MASK << MTK_PMIC_PWRKEY_RST_EN_SHIFT)
+#define MTK_PMIC_HOMEKEY_RST \
+ (MTK_PMIC_HOMEKEY_RST_EN_MASK << MTK_PMIC_HOMEKEY_RST_EN_SHIFT)
+
+#define MTK_PMIC_PWRKEY_INDEX 0
+#define MTK_PMIC_HOMEKEY_INDEX 1
+#define MTK_PMIC_MAX_KEY_COUNT 2
+
+struct mtk_pmic_keys_regs {
+ u32 deb_reg;
+ u32 deb_mask;
+ u32 intsel_reg;
+ u32 intsel_mask;
+};
+
+#define MTK_PMIC_KEYS_REGS(_deb_reg, _deb_mask, \
+ _intsel_reg, _intsel_mask) \
+{ \
+ .deb_reg = _deb_reg, \
+ .deb_mask = _deb_mask, \
+ .intsel_reg = _intsel_reg, \
+ .intsel_mask = _intsel_mask, \
+}
+
+struct mtk_pmic_regs {
+ const struct mtk_pmic_keys_regs keys_regs[MTK_PMIC_MAX_KEY_COUNT];
+ u32 pmic_rst_reg;
+};
+
+static const struct mtk_pmic_regs mt6397_regs = {
+ .keys_regs[MTK_PMIC_PWRKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6397_CHRSTATUS,
+ 0x8, MT6397_INT_RSV, 0x10),
+ .keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6397_OCSTATUS2,
+ 0x10, MT6397_INT_RSV, 0x8),
+ .pmic_rst_reg = MT6397_TOP_RST_MISC,
+};
+
+static const struct mtk_pmic_regs mt6323_regs = {
+ .keys_regs[MTK_PMIC_PWRKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
+ 0x2, MT6323_INT_MISC_CON, 0x10),
+ .keys_regs[MTK_PMIC_HOMEKEY_INDEX] =
+ MTK_PMIC_KEYS_REGS(MT6323_CHRSTATUS,
+ 0x4, MT6323_INT_MISC_CON, 0x8),
+ .pmic_rst_reg = MT6323_TOP_RST_MISC,
+};
+
+struct mtk_pmic_keys_info {
+ struct mtk_pmic_keys *keys;
+ const struct mtk_pmic_keys_regs *regs;
+ unsigned int keycode;
+ int irq;
+ bool wakeup:1;
+};
+
+struct mtk_pmic_keys {
+ struct input_dev *input_dev;
+ struct device *dev;
+ struct regmap *regmap;
+ struct mtk_pmic_keys_info keys[MTK_PMIC_MAX_KEY_COUNT];
+};
+
+enum mtk_pmic_keys_lp_mode {
+ LP_DISABLE,
+ LP_ONEKEY,
+ LP_TWOKEY,
+};
+
+static void mtk_pmic_keys_lp_reset_setup(struct mtk_pmic_keys *keys,
+ u32 pmic_rst_reg)
+{
+ int ret;
+ u32 long_press_mode, long_press_debounce;
+
+ ret = of_property_read_u32(keys->dev->of_node,
+ "power-off-time-sec", &long_press_debounce);
+ if (ret)
+ long_press_debounce = 0;
+
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_RST_DU_MASK << MTK_PMIC_RST_DU_SHIFT,
+ long_press_debounce << MTK_PMIC_RST_DU_SHIFT);
+
+ ret = of_property_read_u32(keys->dev->of_node,
+ "mediatek,long-press-mode", &long_press_mode);
+ if (ret)
+ long_press_mode = LP_DISABLE;
+
+ switch (long_press_mode) {
+ case LP_ONEKEY:
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_PWRKEY_RST,
+ MTK_PMIC_PWRKEY_RST);
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_HOMEKEY_RST,
+ 0);
+ break;
+ case LP_TWOKEY:
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_PWRKEY_RST,
+ MTK_PMIC_PWRKEY_RST);
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_HOMEKEY_RST,
+ MTK_PMIC_HOMEKEY_RST);
+ break;
+ case LP_DISABLE:
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_PWRKEY_RST,
+ 0);
+ regmap_update_bits(keys->regmap, pmic_rst_reg,
+ MTK_PMIC_HOMEKEY_RST,
+ 0);
+ break;
+ default:
+ break;
+ }
+}
+
+static irqreturn_t mtk_pmic_keys_irq_handler_thread(int irq, void *data)
+{
+ struct mtk_pmic_keys_info *info = data;
+ u32 key_deb, pressed;
+
+ regmap_read(info->keys->regmap, info->regs->deb_reg, &key_deb);
+
+ key_deb &= info->regs->deb_mask;
+
+ pressed = !key_deb;
+
+ input_report_key(info->keys->input_dev, info->keycode, pressed);
+ input_sync(info->keys->input_dev);
+
+ dev_dbg(info->keys->dev, "(%s) key =%d using PMIC\n",
+ pressed ? "pressed" : "released", info->keycode);
+
+ return IRQ_HANDLED;
+}
+
+static int mtk_pmic_key_setup(struct mtk_pmic_keys *keys,
+ struct mtk_pmic_keys_info *info)
+{
+ int ret;
+
+ info->keys = keys;
+
+ ret = regmap_update_bits(keys->regmap, info->regs->intsel_reg,
+ info->regs->intsel_mask,
+ info->regs->intsel_mask);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_request_threaded_irq(keys->dev, info->irq, NULL,
+ mtk_pmic_keys_irq_handler_thread,
+ IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
+ "mtk-pmic-keys", info);
+ if (ret) {
+ dev_err(keys->dev, "Failed to request IRQ: %d: %d\n",
+ info->irq, ret);
+ return ret;
+ }
+
+ input_set_capability(keys->input_dev, EV_KEY, info->keycode);
+
+ return 0;
+}
+
+static int __maybe_unused mtk_pmic_keys_suspend(struct device *dev)
+{
+ struct mtk_pmic_keys *keys = dev_get_drvdata(dev);
+ int index;
+
+ for (index = 0; index < MTK_PMIC_MAX_KEY_COUNT; index++) {
+ if (keys->keys[index].wakeup)
+ enable_irq_wake(keys->keys[index].irq);
+ }
+
+ return 0;
+}
+
+static int __maybe_unused mtk_pmic_keys_resume(struct device *dev)
+{
+ struct mtk_pmic_keys *keys = dev_get_drvdata(dev);
+ int index;
+
+ for (index = 0; index < MTK_PMIC_MAX_KEY_COUNT; index++) {
+ if (keys->keys[index].wakeup)
+ disable_irq_wake(keys->keys[index].irq);
+ }
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(mtk_pmic_keys_pm_ops, mtk_pmic_keys_suspend,
+ mtk_pmic_keys_resume);
+
+static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = {
+ {
+ .compatible = "mediatek,mt6397-keys",
+ .data = &mt6397_regs,
+ }, {
+ .compatible = "mediatek,mt6323-keys",
+ .data = &mt6323_regs,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(of, of_mtk_pmic_keys_match_tbl);
+
+static int mtk_pmic_keys_probe(struct platform_device *pdev)
+{
+ int error, index = 0;
+ unsigned int keycount;
+ struct mt6397_chip *pmic_chip = dev_get_drvdata(pdev->dev.parent);
+ struct device_node *node = pdev->dev.of_node, *child;
+ struct mtk_pmic_keys *keys;
+ const struct mtk_pmic_regs *mtk_pmic_regs;
+ struct input_dev *input_dev;
+ const struct of_device_id *of_id =
+ of_match_device(of_mtk_pmic_keys_match_tbl, &pdev->dev);
+
+ keys = devm_kzalloc(&pdev->dev, sizeof(*keys), GFP_KERNEL);
+ if (!keys)
+ return -ENOMEM;
+
+ keys->dev = &pdev->dev;
+ keys->regmap = pmic_chip->regmap;
+ mtk_pmic_regs = of_id->data;
+
+ keys->input_dev = input_dev = devm_input_allocate_device(keys->dev);
+ if (!input_dev) {
+ dev_err(keys->dev, "input allocate device fail.\n");
+ return -ENOMEM;
+ }
+
+ input_dev->name = "mtk-pmic-keys";
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0001;
+
+ keycount = of_get_available_child_count(node);
+ if (keycount > MTK_PMIC_MAX_KEY_COUNT) {
+ dev_err(keys->dev, "too many keys defined (%d)\n", keycount);
+ return -EINVAL;
+ }
+
+ for_each_child_of_node(node, child) {
+ keys->keys[index].regs = &mtk_pmic_regs->keys_regs[index];
+
+ keys->keys[index].irq = platform_get_irq(pdev, index);
+ if (keys->keys[index].irq < 0)
+ return keys->keys[index].irq;
+
+ error = of_property_read_u32(child,
+ "linux,keycodes", &keys->keys[index].keycode);
+ if (error) {
+ dev_err(keys->dev,
+ "failed to read key:%d linux,keycode property: %d\n",
+ index, error);
+ return error;
+ }
+
+ if (of_property_read_bool(child, "wakeup-source"))
+ keys->keys[index].wakeup = true;
+
+ error = mtk_pmic_key_setup(keys, &keys->keys[index]);
+ if (error)
+ return error;
+
+ index++;
+ }
+
+ error = input_register_device(input_dev);
+ if (error) {
+ dev_err(&pdev->dev,
+ "register input device failed (%d)\n", error);
+ return error;
+ }
+
+ mtk_pmic_keys_lp_reset_setup(keys, mtk_pmic_regs->pmic_rst_reg);
+
+ platform_set_drvdata(pdev, keys);
+
+ return 0;
+}
+
+static struct platform_driver pmic_keys_pdrv = {
+ .probe = mtk_pmic_keys_probe,
+ .driver = {
+ .name = "mtk-pmic-keys",
+ .of_match_table = of_mtk_pmic_keys_match_tbl,
+ .pm = &mtk_pmic_keys_pm_ops,
+ },
+};
+
+module_platform_driver(pmic_keys_pdrv);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Chen Zhong <chen.zhong@mediatek.com>");
+MODULE_DESCRIPTION("MTK pmic-keys driver v0.1");
diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c
index 940d38b..4640634 100644
--- a/drivers/input/keyboard/omap4-keypad.c
+++ b/drivers/input/keyboard/omap4-keypad.c
@@ -337,7 +337,8 @@ static int omap4_keypad_probe(struct platform_device *pdev)
keypad_data->row_shift = get_count_order(keypad_data->cols);
max_keys = keypad_data->rows << keypad_data->row_shift;
- keypad_data->keymap = kzalloc(max_keys * sizeof(keypad_data->keymap[0]),
+ keypad_data->keymap = kcalloc(max_keys,
+ sizeof(keypad_data->keymap[0]),
GFP_KERNEL);
if (!keypad_data->keymap) {
dev_err(&pdev->dev, "Not enough memory for keymap\n");
diff --git a/drivers/input/keyboard/samsung-keypad.c b/drivers/input/keyboard/samsung-keypad.c
index 3164144..1fe1aa2 100644
--- a/drivers/input/keyboard/samsung-keypad.c
+++ b/drivers/input/keyboard/samsung-keypad.c
@@ -281,7 +281,7 @@ samsung_keypad_parse_dt(struct device *dev)
key_count = of_get_child_count(np);
keymap_data->keymap_size = key_count;
- keymap = devm_kzalloc(dev, sizeof(uint32_t) * key_count, GFP_KERNEL);
+ keymap = devm_kcalloc(dev, key_count, sizeof(uint32_t), GFP_KERNEL);
if (!keymap) {
dev_err(dev, "could not allocate memory for keymap\n");
return ERR_PTR(-ENOMEM);
diff --git a/drivers/input/matrix-keymap.c b/drivers/input/matrix-keymap.c
index 8ccefc1..8b3a575 100644
--- a/drivers/input/matrix-keymap.c
+++ b/drivers/input/matrix-keymap.c
@@ -170,8 +170,8 @@ int matrix_keypad_build_keymap(const struct matrix_keymap_data *keymap_data,
return -EINVAL;
if (!keymap) {
- keymap = devm_kzalloc(input_dev->dev.parent,
- max_keys * sizeof(*keymap),
+ keymap = devm_kcalloc(input_dev->dev.parent,
+ max_keys, sizeof(*keymap),
GFP_KERNEL);
if (!keymap) {
dev_err(input_dev->dev.parent,
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 572b15f..c25606e 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -411,7 +411,7 @@ config INPUT_YEALINK
usb sound driver, so you might want to enable that as well.
For information about how to use these additional functions, see
- <file:Documentation/input/yealink.txt>.
+ <file:Documentation/input/devices/yealink.rst>.
To compile this driver as a module, choose M here: the module will be
called yealink.
@@ -595,7 +595,7 @@ config INPUT_GPIO_ROTARY_ENCODER
depends on GPIOLIB || COMPILE_TEST
help
Say Y here to add support for rotary encoders connected to GPIO lines.
- Check file:Documentation/input/rotary-encoder.txt for more
+ Check file:Documentation/input/devices/rotary-encoder.rst for more
information.
To compile this driver as a module, choose M here: the
diff --git a/drivers/input/misc/rotary_encoder.c b/drivers/input/misc/rotary_encoder.c
index 1588aec..30ec77a 100644
--- a/drivers/input/misc/rotary_encoder.c
+++ b/drivers/input/misc/rotary_encoder.c
@@ -7,7 +7,7 @@
* state machine code inspired by code from Tim Ruetz
*
* A generic driver for rotary encoders connected to GPIO lines.
- * See file:Documentation/input/rotary-encoder.txt for more information
+ * See file:Documentation/input/devices/rotary-encoder.rst for more information
*
* 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
@@ -283,8 +283,8 @@ static int rotary_encoder_probe(struct platform_device *pdev)
}
encoder->irq =
- devm_kzalloc(dev,
- sizeof(*encoder->irq) * encoder->gpios->ndescs,
+ devm_kcalloc(dev,
+ encoder->gpios->ndescs, sizeof(*encoder->irq),
GFP_KERNEL);
if (!encoder->irq)
return -ENOMEM;
diff --git a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
index f27f23f..566a1e3 100644
--- a/drivers/input/mouse/Kconfig
+++ b/drivers/input/mouse/Kconfig
@@ -129,7 +129,7 @@ config MOUSE_PS2_ELANTECH
This driver exposes some configuration registers via sysfs
entries. For further information,
- see <file:Documentation/input/elantech.txt>.
+ see <file:Documentation/input/devices/elantech.rst>.
If unsure, say N.
@@ -228,7 +228,7 @@ config MOUSE_APPLETOUCH
scrolling in X11.
For further information, see
- <file:Documentation/input/appletouch.txt>.
+ <file:Documentation/input/devices/appletouch.rst>.
To compile this driver as a module, choose M here: the
module will be called appletouch.
@@ -251,7 +251,7 @@ config MOUSE_BCM5974
The interface is currently identical to the appletouch interface,
for further information, see
- <file:Documentation/input/appletouch.txt>.
+ <file:Documentation/input/devices/appletouch.rst>.
To compile this driver as a module, choose M here: the
module will be called bcm5974.
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index cb55797..0a6f7ca 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -212,7 +212,7 @@ static void alps_set_abs_params_v7(struct alps_data *priv,
static void alps_set_abs_params_ss4_v2(struct alps_data *priv,
struct input_dev *dev1);
-/* Packet formats are described in Documentation/input/alps.txt */
+/* Packet formats are described in Documentation/input/devices/alps.rst */
static bool alps_is_valid_first_byte(struct alps_data *priv,
unsigned char data)
diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index f595498..7d29053 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -636,9 +636,10 @@ int rmi_read_register_desc(struct rmi_device *d, u16 addr,
rdesc->num_registers = bitmap_weight(rdesc->presense_map,
RMI_REG_DESC_PRESENSE_BITS);
- rdesc->registers = devm_kzalloc(&d->dev, rdesc->num_registers *
- sizeof(struct rmi_register_desc_item),
- GFP_KERNEL);
+ rdesc->registers = devm_kcalloc(&d->dev,
+ rdesc->num_registers,
+ sizeof(struct rmi_register_desc_item),
+ GFP_KERNEL);
if (!rdesc->registers)
return -ENOMEM;
@@ -1061,7 +1062,7 @@ int rmi_probe_interrupts(struct rmi_driver_data *data)
data->num_of_irq_regs = (data->irq_count + 7) / 8;
size = BITS_TO_LONGS(data->irq_count) * sizeof(unsigned long);
- data->irq_memory = devm_kzalloc(dev, size * 4, GFP_KERNEL);
+ data->irq_memory = devm_kcalloc(dev, size, 4, GFP_KERNEL);
if (!data->irq_memory) {
dev_err(dev, "Failed to allocate memory for irq masks.\n");
return -ENOMEM;
diff --git a/drivers/input/rmi4/rmi_f11.c b/drivers/input/rmi4/rmi_f11.c
index bc5e37f..12a2332 100644
--- a/drivers/input/rmi4/rmi_f11.c
+++ b/drivers/input/rmi4/rmi_f11.c
@@ -1190,14 +1190,15 @@ static int rmi_f11_initialize(struct rmi_function *fn)
f11->sensor.attn_size += f11->sensor.nbr_fingers * 2;
/* allocate the in-kernel tracking buffers */
- sensor->tracking_pos = devm_kzalloc(&fn->dev,
- sizeof(struct input_mt_pos) * sensor->nbr_fingers,
+ sensor->tracking_pos = devm_kcalloc(&fn->dev,
+ sensor->nbr_fingers, sizeof(struct input_mt_pos),
+ GFP_KERNEL);
+ sensor->tracking_slots = devm_kcalloc(&fn->dev,
+ sensor->nbr_fingers, sizeof(int), GFP_KERNEL);
+ sensor->objs = devm_kcalloc(&fn->dev,
+ sensor->nbr_fingers,
+ sizeof(struct rmi_2d_sensor_abs_object),
GFP_KERNEL);
- sensor->tracking_slots = devm_kzalloc(&fn->dev,
- sizeof(int) * sensor->nbr_fingers, GFP_KERNEL);
- sensor->objs = devm_kzalloc(&fn->dev,
- sizeof(struct rmi_2d_sensor_abs_object)
- * sensor->nbr_fingers, GFP_KERNEL);
if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs)
return -ENOMEM;
diff --git a/drivers/input/rmi4/rmi_f12.c b/drivers/input/rmi4/rmi_f12.c
index 8b0db08..a3d1aa8 100644
--- a/drivers/input/rmi4/rmi_f12.c
+++ b/drivers/input/rmi4/rmi_f12.c
@@ -502,14 +502,15 @@ static int rmi_f12_probe(struct rmi_function *fn)
}
/* allocate the in-kernel tracking buffers */
- sensor->tracking_pos = devm_kzalloc(&fn->dev,
- sizeof(struct input_mt_pos) * sensor->nbr_fingers,
+ sensor->tracking_pos = devm_kcalloc(&fn->dev,
+ sensor->nbr_fingers, sizeof(struct input_mt_pos),
+ GFP_KERNEL);
+ sensor->tracking_slots = devm_kcalloc(&fn->dev,
+ sensor->nbr_fingers, sizeof(int), GFP_KERNEL);
+ sensor->objs = devm_kcalloc(&fn->dev,
+ sensor->nbr_fingers,
+ sizeof(struct rmi_2d_sensor_abs_object),
GFP_KERNEL);
- sensor->tracking_slots = devm_kzalloc(&fn->dev,
- sizeof(int) * sensor->nbr_fingers, GFP_KERNEL);
- sensor->objs = devm_kzalloc(&fn->dev,
- sizeof(struct rmi_2d_sensor_abs_object)
- * sensor->nbr_fingers, GFP_KERNEL);
if (!sensor->tracking_pos || !sensor->tracking_slots || !sensor->objs)
return -ENOMEM;
diff --git a/drivers/input/rmi4/rmi_f54.c b/drivers/input/rmi4/rmi_f54.c
index 5343f2c..e8a59d1 100644
--- a/drivers/input/rmi4/rmi_f54.c
+++ b/drivers/input/rmi4/rmi_f54.c
@@ -685,7 +685,7 @@ static int rmi_f54_probe(struct rmi_function *fn)
rx = f54->num_rx_electrodes;
tx = f54->num_tx_electrodes;
f54->report_data = devm_kzalloc(&fn->dev,
- sizeof(u16) * tx * rx,
+ array3_size(tx, rx, sizeof(u16)),
GFP_KERNEL);
if (f54->report_data == NULL)
return -ENOMEM;
diff --git a/drivers/input/rmi4/rmi_spi.c b/drivers/input/rmi4/rmi_spi.c
index 082defc..33b8c6e 100644
--- a/drivers/input/rmi4/rmi_spi.c
+++ b/drivers/input/rmi4/rmi_spi.c
@@ -69,7 +69,7 @@ static int rmi_spi_manage_pools(struct rmi_spi_xport *rmi_spi, int len)
buf_size = RMI_SPI_XFER_SIZE_LIMIT;
tmp = rmi_spi->rx_buf;
- buf = devm_kzalloc(&spi->dev, buf_size * 2,
+ buf = devm_kcalloc(&spi->dev, buf_size, 2,
GFP_KERNEL | GFP_DMA);
if (!buf)
return -ENOMEM;
@@ -96,9 +96,10 @@ static int rmi_spi_manage_pools(struct rmi_spi_xport *rmi_spi, int len)
* per byte delays.
*/
tmp = rmi_spi->rx_xfers;
- xfer_buf = devm_kzalloc(&spi->dev,
- (rmi_spi->rx_xfer_count + rmi_spi->tx_xfer_count)
- * sizeof(struct spi_transfer), GFP_KERNEL);
+ xfer_buf = devm_kcalloc(&spi->dev,
+ rmi_spi->rx_xfer_count + rmi_spi->tx_xfer_count,
+ sizeof(struct spi_transfer),
+ GFP_KERNEL);
if (!xfer_buf)
return -ENOMEM;
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
index ca4530e..d90d9f1 100644
--- a/drivers/input/serio/Kconfig
+++ b/drivers/input/serio/Kconfig
@@ -47,7 +47,7 @@ config SERIO_SERPORT
Say Y here if you plan to use an input device (mouse, joystick,
tablet, 6dof) that communicates over the RS232 serial (COM) port.
- More information is available: <file:Documentation/input/input.txt>
+ More information is available: <file:Documentation/input/input.rst>
If unsure, say Y.
@@ -78,7 +78,7 @@ config SERIO_PARKBD
Say Y here if you built a simple parallel port adapter to attach
an additional AT keyboard, XT keyboard or PS/2 mouse.
- More information is available: <file:Documentation/input/input.txt>
+ More information is available: <file:Documentation/input/input.rst>
If unsure, say N.
diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c
index fd714ee..2566b4d 100644
--- a/drivers/input/touchscreen/wm97xx-core.c
+++ b/drivers/input/touchscreen/wm97xx-core.c
@@ -68,7 +68,7 @@
* The default values correspond to Mainstone II in QVGA mode
*
* Please read
- * Documentation/input/input-programming.txt for more details.
+ * Documentation/input/input-programming.rst for more details.
*/
static int abs_x[3] = {150, 4000, 5};
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 8ea77ef..e055d22 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -107,7 +107,6 @@ config IOMMU_PGTABLES_L2
# AMD IOMMU support
config AMD_IOMMU
bool "AMD IOMMU support"
- select DMA_DIRECT_OPS
select SWIOTLB
select PCI_MSI
select PCI_ATS
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 0cea80be..596b95c 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2596,32 +2596,51 @@ static void *alloc_coherent(struct device *dev, size_t size,
unsigned long attrs)
{
u64 dma_mask = dev->coherent_dma_mask;
- struct protection_domain *domain = get_domain(dev);
- bool is_direct = false;
- void *virt_addr;
+ struct protection_domain *domain;
+ struct dma_ops_domain *dma_dom;
+ struct page *page;
+
+ domain = get_domain(dev);
+ if (PTR_ERR(domain) == -EINVAL) {
+ page = alloc_pages(flag, get_order(size));
+ *dma_addr = page_to_phys(page);
+ return page_address(page);
+ } else if (IS_ERR(domain))
+ return NULL;
- if (IS_ERR(domain)) {
- if (PTR_ERR(domain) != -EINVAL)
+ dma_dom = to_dma_ops_domain(domain);
+ size = PAGE_ALIGN(size);
+ dma_mask = dev->coherent_dma_mask;
+ flag &= ~(__GFP_DMA | __GFP_HIGHMEM | __GFP_DMA32);
+ flag |= __GFP_ZERO;
+
+ page = alloc_pages(flag | __GFP_NOWARN, get_order(size));
+ if (!page) {
+ if (!gfpflags_allow_blocking(flag))
return NULL;
- is_direct = true;
- }
- virt_addr = dma_direct_alloc(dev, size, dma_addr, flag, attrs);
- if (!virt_addr || is_direct)
- return virt_addr;
+ page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
+ get_order(size), flag);
+ if (!page)
+ return NULL;
+ }
if (!dma_mask)
dma_mask = *dev->dma_mask;
- *dma_addr = __map_single(dev, to_dma_ops_domain(domain),
- virt_to_phys(virt_addr), PAGE_ALIGN(size),
- DMA_BIDIRECTIONAL, dma_mask);
+ *dma_addr = __map_single(dev, dma_dom, page_to_phys(page),
+ size, DMA_BIDIRECTIONAL, dma_mask);
+
if (*dma_addr == AMD_IOMMU_MAPPING_ERROR)
goto out_free;
- return virt_addr;
+
+ return page_address(page);
out_free:
- dma_direct_free(dev, size, virt_addr, *dma_addr, attrs);
+
+ if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
+ __free_pages(page, get_order(size));
+
return NULL;
}
@@ -2632,17 +2651,24 @@ static void free_coherent(struct device *dev, size_t size,
void *virt_addr, dma_addr_t dma_addr,
unsigned long attrs)
{
- struct protection_domain *domain = get_domain(dev);
+ struct protection_domain *domain;
+ struct dma_ops_domain *dma_dom;
+ struct page *page;
+ page = virt_to_page(virt_addr);
size = PAGE_ALIGN(size);
- if (!IS_ERR(domain)) {
- struct dma_ops_domain *dma_dom = to_dma_ops_domain(domain);
+ domain = get_domain(dev);
+ if (IS_ERR(domain))
+ goto free_mem;
- __unmap_single(dma_dom, dma_addr, size, DMA_BIDIRECTIONAL);
- }
+ dma_dom = to_dma_ops_domain(domain);
+
+ __unmap_single(dma_dom, dma_addr, size, DMA_BIDIRECTIONAL);
- dma_direct_free(dev, size, virt_addr, dma_addr, attrs);
+free_mem:
+ if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
+ __free_pages(page, get_order(size));
}
/*
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 69e7c60..f7a96bc 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2082,7 +2082,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
return -ENODEV;
}
- smmu->irqs = devm_kzalloc(dev, sizeof(*smmu->irqs) * num_irqs,
+ smmu->irqs = devm_kcalloc(dev, num_irqs, sizeof(*smmu->irqs),
GFP_KERNEL);
if (!smmu->irqs) {
dev_err(dev, "failed to allocate %d irqs\n", num_irqs);
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 4321f77..75456b5 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -1458,7 +1458,7 @@ int dmar_enable_qi(struct intel_iommu *iommu)
qi->desc = page_address(desc_page);
- qi->desc_status = kzalloc(QI_LENGTH * sizeof(int), GFP_ATOMIC);
+ qi->desc_status = kcalloc(QI_LENGTH, sizeof(int), GFP_ATOMIC);
if (!qi->desc_status) {
free_page((unsigned long) qi->desc);
kfree(qi);
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 89e49a4..14e4b37 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3189,7 +3189,7 @@ static int copy_translation_tables(struct intel_iommu *iommu)
/* This is too big for the stack - allocate it from slab */
ctxt_table_entries = ext ? 512 : 256;
ret = -ENOMEM;
- ctxt_tbls = kzalloc(ctxt_table_entries * sizeof(void *), GFP_KERNEL);
+ ctxt_tbls = kcalloc(ctxt_table_entries, sizeof(void *), GFP_KERNEL);
if (!ctxt_tbls)
goto out_unmap;
@@ -4032,7 +4032,7 @@ static int iommu_suspend(void)
unsigned long flag;
for_each_active_iommu(iommu, drhd) {
- iommu->iommu_state = kzalloc(sizeof(u32) * MAX_SR_DMAR_REGS,
+ iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
GFP_ATOMIC);
if (!iommu->iommu_state)
goto nomem;
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index c33b7b10..af4a8e7 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1455,7 +1455,7 @@ static int omap_iommu_add_device(struct device *dev)
if (num_iommus < 0)
return 0;
- arch_data = kzalloc((num_iommus + 1) * sizeof(*arch_data), GFP_KERNEL);
+ arch_data = kcalloc(num_iommus + 1, sizeof(*arch_data), GFP_KERNEL);
if (!arch_data)
return -ENOMEM;
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 0468acf..054cd2c 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1135,7 +1135,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
iommu->dev = dev;
iommu->num_mmu = 0;
- iommu->bases = devm_kzalloc(dev, sizeof(*iommu->bases) * num_res,
+ iommu->bases = devm_kcalloc(dev, num_res, sizeof(*iommu->bases),
GFP_KERNEL);
if (!iommu->bases)
return -ENOMEM;
diff --git a/drivers/iommu/tegra-gart.c b/drivers/iommu/tegra-gart.c
index 89ec24c..a004f6d 100644
--- a/drivers/iommu/tegra-gart.c
+++ b/drivers/iommu/tegra-gart.c
@@ -465,7 +465,7 @@ static int tegra_gart_probe(struct platform_device *pdev)
gart->iovmm_base = (dma_addr_t)res_remap->start;
gart->page_count = (resource_size(res_remap) >> GART_PAGE_SHIFT);
- gart->savedata = vmalloc(sizeof(u32) * gart->page_count);
+ gart->savedata = vmalloc(array_size(sizeof(u32), gart->page_count));
if (!gart->savedata) {
dev_err(dev, "failed to allocate context save area\n");
return -ENOMEM;
diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c
index 9b23843..a16b320 100644
--- a/drivers/ipack/carriers/tpci200.c
+++ b/drivers/ipack/carriers/tpci200.c
@@ -457,8 +457,8 @@ static int tpci200_install(struct tpci200_board *tpci200)
{
int res;
- tpci200->slots = kzalloc(
- TPCI200_NB_SLOT * sizeof(struct tpci200_slot), GFP_KERNEL);
+ tpci200->slots = kcalloc(TPCI200_NB_SLOT, sizeof(struct tpci200_slot),
+ GFP_KERNEL);
if (tpci200->slots == NULL)
return -ENOMEM;
diff --git a/drivers/irqchip/irq-alpine-msi.c b/drivers/irqchip/irq-alpine-msi.c
index 63d9809..23a3b87 100644
--- a/drivers/irqchip/irq-alpine-msi.c
+++ b/drivers/irqchip/irq-alpine-msi.c
@@ -268,7 +268,8 @@ static int alpine_msix_init(struct device_node *node,
goto err_priv;
}
- priv->msi_map = kzalloc(sizeof(*priv->msi_map) * BITS_TO_LONGS(priv->num_spis),
+ priv->msi_map = kcalloc(BITS_TO_LONGS(priv->num_spis),
+ sizeof(*priv->msi_map),
GFP_KERNEL);
if (!priv->msi_map) {
ret = -ENOMEM;
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 1ff38af..f5fe010 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -199,7 +199,7 @@ static int gicv2m_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
fail:
irq_domain_free_irqs_parent(domain, virq, nr_irqs);
- gicv2m_unalloc_msi(v2m, hwirq, get_count_order(nr_irqs));
+ gicv2m_unalloc_msi(v2m, hwirq, nr_irqs);
return err;
}
@@ -361,7 +361,7 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
break;
}
- v2m->bm = kzalloc(sizeof(long) * BITS_TO_LONGS(v2m->nr_spis),
+ v2m->bm = kcalloc(BITS_TO_LONGS(v2m->nr_spis), sizeof(long),
GFP_KERNEL);
if (!v2m->bm) {
ret = -ENOMEM;
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 5416f2b..d7842d3 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -182,6 +182,22 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev,
return its->collections + its_dev->event_map.col_map[event];
}
+static struct its_collection *valid_col(struct its_collection *col)
+{
+ if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(0, 15)))
+ return NULL;
+
+ return col;
+}
+
+static struct its_vpe *valid_vpe(struct its_node *its, struct its_vpe *vpe)
+{
+ if (valid_col(its->collections + vpe->col_idx))
+ return vpe;
+
+ return NULL;
+}
+
/*
* ITS command descriptors - parameters to be encoded in a command
* block.
@@ -439,7 +455,7 @@ static struct its_collection *its_build_mapti_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return col;
+ return valid_col(col);
}
static struct its_collection *its_build_movi_cmd(struct its_node *its,
@@ -458,7 +474,7 @@ static struct its_collection *its_build_movi_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return col;
+ return valid_col(col);
}
static struct its_collection *its_build_discard_cmd(struct its_node *its,
@@ -476,7 +492,7 @@ static struct its_collection *its_build_discard_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return col;
+ return valid_col(col);
}
static struct its_collection *its_build_inv_cmd(struct its_node *its,
@@ -494,7 +510,7 @@ static struct its_collection *its_build_inv_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return col;
+ return valid_col(col);
}
static struct its_collection *its_build_int_cmd(struct its_node *its,
@@ -512,7 +528,7 @@ static struct its_collection *its_build_int_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return col;
+ return valid_col(col);
}
static struct its_collection *its_build_clear_cmd(struct its_node *its,
@@ -530,7 +546,7 @@ static struct its_collection *its_build_clear_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return col;
+ return valid_col(col);
}
static struct its_collection *its_build_invall_cmd(struct its_node *its,
@@ -554,7 +570,7 @@ static struct its_vpe *its_build_vinvall_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return desc->its_vinvall_cmd.vpe;
+ return valid_vpe(its, desc->its_vinvall_cmd.vpe);
}
static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
@@ -576,7 +592,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return desc->its_vmapp_cmd.vpe;
+ return valid_vpe(its, desc->its_vmapp_cmd.vpe);
}
static struct its_vpe *its_build_vmapti_cmd(struct its_node *its,
@@ -599,7 +615,7 @@ static struct its_vpe *its_build_vmapti_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return desc->its_vmapti_cmd.vpe;
+ return valid_vpe(its, desc->its_vmapti_cmd.vpe);
}
static struct its_vpe *its_build_vmovi_cmd(struct its_node *its,
@@ -622,7 +638,7 @@ static struct its_vpe *its_build_vmovi_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return desc->its_vmovi_cmd.vpe;
+ return valid_vpe(its, desc->its_vmovi_cmd.vpe);
}
static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
@@ -640,7 +656,7 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
its_fixup_cmd(cmd);
- return desc->its_vmovp_cmd.vpe;
+ return valid_vpe(its, desc->its_vmovp_cmd.vpe);
}
static u64 its_cmd_ptr_to_offset(struct its_node *its,
@@ -1239,7 +1255,7 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
if (!its_dev->event_map.vm) {
struct its_vlpi_map *maps;
- maps = kzalloc(sizeof(*maps) * its_dev->event_map.nr_lpis,
+ maps = kcalloc(its_dev->event_map.nr_lpis, sizeof(*maps),
GFP_KERNEL);
if (!maps) {
ret = -ENOMEM;
@@ -1437,7 +1453,7 @@ static int __init its_lpi_init(u32 id_bits)
{
lpi_chunks = its_lpi_to_chunk(1UL << id_bits);
- lpi_bitmap = kzalloc(BITS_TO_LONGS(lpi_chunks) * sizeof(long),
+ lpi_bitmap = kcalloc(BITS_TO_LONGS(lpi_chunks), sizeof(long),
GFP_KERNEL);
if (!lpi_bitmap) {
lpi_chunks = 0;
@@ -1471,7 +1487,8 @@ static unsigned long *its_lpi_alloc_chunks(int nr_irqs, int *base, int *nr_ids)
if (!nr_chunks)
goto out;
- bitmap = kzalloc(BITS_TO_LONGS(nr_chunks * IRQS_PER_CHUNK) * sizeof (long),
+ bitmap = kcalloc(BITS_TO_LONGS(nr_chunks * IRQS_PER_CHUNK),
+ sizeof(long),
GFP_ATOMIC);
if (!bitmap)
goto out;
@@ -1823,11 +1840,16 @@ static int its_alloc_tables(struct its_node *its)
static int its_alloc_collections(struct its_node *its)
{
- its->collections = kzalloc(nr_cpu_ids * sizeof(*its->collections),
+ int i;
+
+ its->collections = kcalloc(nr_cpu_ids, sizeof(*its->collections),
GFP_KERNEL);
if (!its->collections)
return -ENOMEM;
+ for (i = 0; i < nr_cpu_ids; i++)
+ its->collections[i].target_address = ~0ULL;
+
return 0;
}
@@ -2124,10 +2146,10 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
if (alloc_lpis) {
lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis);
if (lpi_map)
- col_map = kzalloc(sizeof(*col_map) * nr_lpis,
+ col_map = kcalloc(nr_lpis, sizeof(*col_map),
GFP_KERNEL);
} else {
- col_map = kzalloc(sizeof(*col_map) * nr_ites, GFP_KERNEL);
+ col_map = kcalloc(nr_ites, sizeof(*col_map), GFP_KERNEL);
nr_lpis = 0;
lpi_base = 0;
}
@@ -2309,7 +2331,14 @@ static int its_irq_domain_activate(struct irq_domain *domain,
cpu_mask = cpumask_of_node(its_dev->its->numa_node);
/* Bind the LPI to the first possible CPU */
- cpu = cpumask_first(cpu_mask);
+ cpu = cpumask_first_and(cpu_mask, cpu_online_mask);
+ if (cpu >= nr_cpu_ids) {
+ if (its_dev->its->flags & ITS_FLAGS_WORKAROUND_CAVIUM_23144)
+ return -EINVAL;
+
+ cpu = cpumask_first(cpu_online_mask);
+ }
+
its_dev->event_map.col_map[event] = cpu;
irq_data_update_effective_affinity(d, cpumask_of(cpu));
@@ -3183,7 +3212,7 @@ static int its_init_vpe_domain(void)
its = list_first_entry(&its_nodes, struct its_node, entry);
entries = roundup_pow_of_two(nr_cpu_ids);
- vpe_proxy.vpes = kzalloc(sizeof(*vpe_proxy.vpes) * entries,
+ vpe_proxy.vpes = kcalloc(entries, sizeof(*vpe_proxy.vpes),
GFP_KERNEL);
if (!vpe_proxy.vpes) {
pr_err("ITS: Can't allocate GICv4 proxy device array\n");
@@ -3398,6 +3427,16 @@ static int redist_disable_lpis(void)
u64 timeout = USEC_PER_SEC;
u64 val;
+ /*
+ * If coming via a CPU hotplug event, we don't need to disable
+ * LPIs before trying to re-enable them. They are already
+ * configured and all is well in the world. Detect this case
+ * by checking the allocation of the pending table for the
+ * current CPU.
+ */
+ if (gic_data_rdist()->pend_page)
+ return 0;
+
if (!gic_rdists_supports_plpis()) {
pr_info("CPU%d: LPIs not supported\n", smp_processor_id());
return -ENXIO;
@@ -3567,8 +3606,8 @@ static void __init acpi_table_parse_srat_its(void)
if (count <= 0)
return;
- its_srat_maps = kmalloc(count * sizeof(struct its_srat_map),
- GFP_KERNEL);
+ its_srat_maps = kmalloc_array(count, sizeof(struct its_srat_map),
+ GFP_KERNEL);
if (!its_srat_maps) {
pr_warn("SRAT: Failed to allocate memory for its_srat_maps!\n");
return;
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 5a67ec0..76ea56d 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1167,7 +1167,7 @@ static void __init gic_populate_ppi_partitions(struct device_node *gic_node)
if (!nr_parts)
goto out_put_node;
- parts = kzalloc(sizeof(*parts) * nr_parts, GFP_KERNEL);
+ parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL);
if (WARN_ON(!parts))
goto out_put_node;
@@ -1289,7 +1289,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
if (of_property_read_u32(node, "#redistributor-regions", &nr_redist_regions))
nr_redist_regions = 1;
- rdist_regs = kzalloc(sizeof(*rdist_regs) * nr_redist_regions, GFP_KERNEL);
+ rdist_regs = kcalloc(nr_redist_regions, sizeof(*rdist_regs),
+ GFP_KERNEL);
if (!rdist_regs) {
err = -ENOMEM;
goto out_unmap_dist;
diff --git a/drivers/irqchip/irq-imgpdc.c b/drivers/irqchip/irq-imgpdc.c
index e80263e..d00489a 100644
--- a/drivers/irqchip/irq-imgpdc.c
+++ b/drivers/irqchip/irq-imgpdc.c
@@ -354,7 +354,7 @@ static int pdc_intc_probe(struct platform_device *pdev)
priv->nr_syswakes = val;
/* Get peripheral IRQ numbers */
- priv->perip_irqs = devm_kzalloc(&pdev->dev, 4 * priv->nr_perips,
+ priv->perip_irqs = devm_kcalloc(&pdev->dev, 4, priv->nr_perips,
GFP_KERNEL);
if (!priv->perip_irqs) {
dev_err(&pdev->dev, "cannot allocate perip IRQ list\n");
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 1ec3bfe..c671b32 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -93,8 +93,12 @@ static void ls_scfg_msi_compose_msg(struct irq_data *data, struct msi_msg *msg)
msg->address_lo = lower_32_bits(msi_data->msiir_addr);
msg->data = data->hwirq;
- if (msi_affinity_flag)
- msg->data |= cpumask_first(data->common->affinity);
+ if (msi_affinity_flag) {
+ const struct cpumask *mask;
+
+ mask = irq_data_get_effective_affinity_mask(data);
+ msg->data |= cpumask_first(mask);
+ }
iommu_dma_map_msi_msg(data->irq, msg);
}
@@ -121,7 +125,7 @@ static int ls_scfg_msi_set_affinity(struct irq_data *irq_data,
return -EINVAL;
}
- cpumask_copy(irq_data->common->affinity, mask);
+ irq_data_update_effective_affinity(irq_data, cpumask_of(cpu));
return IRQ_SET_MASK_OK;
}
diff --git a/drivers/irqchip/irq-mvebu-gicp.c b/drivers/irqchip/irq-mvebu-gicp.c
index 4e17f70..3be5c5d 100644
--- a/drivers/irqchip/irq-mvebu-gicp.c
+++ b/drivers/irqchip/irq-mvebu-gicp.c
@@ -191,8 +191,8 @@ static int mvebu_gicp_probe(struct platform_device *pdev)
gicp->spi_ranges_cnt = ret / 2;
gicp->spi_ranges =
- devm_kzalloc(&pdev->dev,
- gicp->spi_ranges_cnt *
+ devm_kcalloc(&pdev->dev,
+ gicp->spi_ranges_cnt,
sizeof(struct mvebu_gicp_spi_range),
GFP_KERNEL);
if (!gicp->spi_ranges)
@@ -210,8 +210,8 @@ static int mvebu_gicp_probe(struct platform_device *pdev)
gicp->spi_cnt += gicp->spi_ranges[i].count;
}
- gicp->spi_bitmap = devm_kzalloc(&pdev->dev,
- BITS_TO_LONGS(gicp->spi_cnt) * sizeof(long),
+ gicp->spi_bitmap = devm_kcalloc(&pdev->dev,
+ BITS_TO_LONGS(gicp->spi_cnt), sizeof(long),
GFP_KERNEL);
if (!gicp->spi_bitmap)
return -ENOMEM;
diff --git a/drivers/irqchip/irq-partition-percpu.c b/drivers/irqchip/irq-partition-percpu.c
index ccd72c2..1f7cc59 100644
--- a/drivers/irqchip/irq-partition-percpu.c
+++ b/drivers/irqchip/irq-partition-percpu.c
@@ -229,7 +229,7 @@ struct partition_desc *partition_create_desc(struct fwnode_handle *fwnode,
goto out;
desc->domain = d;
- desc->bitmap = kzalloc(sizeof(long) * BITS_TO_LONGS(nr_parts),
+ desc->bitmap = kcalloc(BITS_TO_LONGS(nr_parts), sizeof(long),
GFP_KERNEL);
if (WARN_ON(!desc->bitmap))
goto out;
diff --git a/drivers/irqchip/irq-s3c24xx.c b/drivers/irqchip/irq-s3c24xx.c
index ec0e6a8..f6fd57e 100644
--- a/drivers/irqchip/irq-s3c24xx.c
+++ b/drivers/irqchip/irq-s3c24xx.c
@@ -1261,7 +1261,7 @@ static int __init s3c_init_intc_of(struct device_node *np,
return -ENOMEM;
intc->domain = domain;
- intc->irqs = kzalloc(sizeof(struct s3c_irq_data) * 32,
+ intc->irqs = kcalloc(32, sizeof(struct s3c_irq_data),
GFP_KERNEL);
if (!intc->irqs) {
kfree(intc);
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index baa1ee2..6e0c281 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1260,7 +1260,7 @@ static int __init capinc_tty_init(void)
if (capi_ttyminors <= 0)
capi_ttyminors = CAPINC_NR_PORTS;
- capiminors = kzalloc(sizeof(struct capiminor *) * capi_ttyminors,
+ capiminors = kcalloc(capi_ttyminors, sizeof(struct capiminor *),
GFP_KERNEL);
if (!capiminors)
return -ENOMEM;
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
index 7ac5179..ee510f9 100644
--- a/drivers/isdn/capi/capidrv.c
+++ b/drivers/isdn/capi/capidrv.c
@@ -2268,7 +2268,8 @@ static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
strcpy(card->name, id);
card->contrnr = contr;
card->nbchan = profp->nbchannel;
- card->bchans = kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC);
+ card->bchans = kmalloc_array(card->nbchan, sizeof(capidrv_bchan),
+ GFP_ATOMIC);
if (!card->bchans) {
printk(KERN_WARNING
"capidrv: (%s) Could not allocate bchan-structs.\n", id);
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 56748af..9cb2ab5 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -252,7 +252,7 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag,
return;
if (l > 64)
l = 64; /* arbitrary limit */
- dbgline = kmalloc(3 * l, GFP_ATOMIC);
+ dbgline = kmalloc_array(3, l, GFP_ATOMIC);
if (!dbgline)
return;
for (i = 0; i < l; i++) {
@@ -272,7 +272,7 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag,
return;
if (l > 64)
l = 64; /* arbitrary limit */
- dbgline = kmalloc(3 * l, GFP_ATOMIC);
+ dbgline = kmalloc_array(3, l, GFP_ATOMIC);
if (!dbgline)
return;
data += CAPIMSG_LEN(data);
@@ -1370,7 +1370,7 @@ static void do_connect_req(struct gigaset_capi_ctr *iif,
cmsg->adr.adrPLCI |= (bcs->channel + 1) << 8;
/* build command table */
- commands = kzalloc(AT_NUM * (sizeof *commands), GFP_KERNEL);
+ commands = kcalloc(AT_NUM, sizeof(*commands), GFP_KERNEL);
if (!commands)
goto oom;
diff --git a/drivers/isdn/gigaset/common.c b/drivers/isdn/gigaset/common.c
index 15482c5..76b5407 100644
--- a/drivers/isdn/gigaset/common.c
+++ b/drivers/isdn/gigaset/common.c
@@ -710,7 +710,7 @@ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels,
cs->mode = M_UNKNOWN;
cs->mstate = MS_UNINITIALIZED;
- cs->bcs = kmalloc(channels * sizeof(struct bc_state), GFP_KERNEL);
+ cs->bcs = kmalloc_array(channels, sizeof(struct bc_state), GFP_KERNEL);
cs->inbuf = kmalloc(sizeof(struct inbuf_t), GFP_KERNEL);
if (!cs->bcs || !cs->inbuf) {
pr_err("out of memory\n");
@@ -1089,7 +1089,7 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors,
drv->owner = owner;
INIT_LIST_HEAD(&drv->list);
- drv->cs = kmalloc(minors * sizeof *drv->cs, GFP_KERNEL);
+ drv->cs = kmalloc_array(minors, sizeof(*drv->cs), GFP_KERNEL);
if (!drv->cs)
goto error;
diff --git a/drivers/isdn/gigaset/i4l.c b/drivers/isdn/gigaset/i4l.c
index 2d753290..b5b389e 100644
--- a/drivers/isdn/gigaset/i4l.c
+++ b/drivers/isdn/gigaset/i4l.c
@@ -243,7 +243,7 @@ static int command_from_LL(isdn_ctrl *cntrl)
dev_kfree_skb(bcs->rx_skb);
gigaset_new_rx_skb(bcs);
- commands = kzalloc(AT_NUM * (sizeof *commands), GFP_ATOMIC);
+ commands = kcalloc(AT_NUM, sizeof(*commands), GFP_ATOMIC);
if (!commands) {
gigaset_free_channel(bcs);
dev_err(cs->dev, "ISDN_CMD_DIAL: out of memory\n");
diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c
index 5ee5489..4ac378e 100644
--- a/drivers/isdn/hardware/avm/b1.c
+++ b/drivers/isdn/hardware/avm/b1.c
@@ -72,7 +72,7 @@ avmcard *b1_alloc_card(int nr_controllers)
if (!card)
return NULL;
- cinfo = kzalloc(sizeof(*cinfo) * nr_controllers, GFP_KERNEL);
+ cinfo = kcalloc(nr_controllers, sizeof(*cinfo), GFP_KERNEL);
if (!cinfo) {
kfree(card);
return NULL;
diff --git a/drivers/isdn/hisax/fsm.c b/drivers/isdn/hisax/fsm.c
index 3e020ec..80ba82f 100644
--- a/drivers/isdn/hisax/fsm.c
+++ b/drivers/isdn/hisax/fsm.c
@@ -27,7 +27,9 @@ FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount)
int i;
fsm->jumpmatrix =
- kzalloc(sizeof(FSMFNPTR) * fsm->state_count * fsm->event_count, GFP_KERNEL);
+ kzalloc(array3_size(sizeof(FSMFNPTR), fsm->state_count,
+ fsm->event_count),
+ GFP_KERNEL);
if (!fsm->jumpmatrix)
return -ENOMEM;
diff --git a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c
index 86b8217..3715fa0 100644
--- a/drivers/isdn/hisax/hfc_2bds0.c
+++ b/drivers/isdn/hisax/hfc_2bds0.c
@@ -1024,7 +1024,7 @@ static unsigned int
int i;
unsigned *send;
- if (!(send = kmalloc(cnt * sizeof(unsigned int), GFP_ATOMIC))) {
+ if (!(send = kmalloc_array(cnt, sizeof(unsigned int), GFP_ATOMIC))) {
printk(KERN_WARNING
"HiSax: No memory for hfcd.send\n");
return (NULL);
diff --git a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c
index 14dada4..34d5999 100644
--- a/drivers/isdn/hisax/hfc_2bs0.c
+++ b/drivers/isdn/hisax/hfc_2bs0.c
@@ -557,7 +557,8 @@ init_send(struct BCState *bcs)
{
int i;
- if (!(bcs->hw.hfc.send = kmalloc(32 * sizeof(unsigned int), GFP_ATOMIC))) {
+ bcs->hw.hfc.send = kmalloc_array(32, sizeof(unsigned int), GFP_ATOMIC);
+ if (!bcs->hw.hfc.send) {
printk(KERN_WARNING
"HiSax: No memory for hfc.send\n");
return;
diff --git a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c
index b7f54fa..e932a15 100644
--- a/drivers/isdn/hisax/netjet.c
+++ b/drivers/isdn/hisax/netjet.c
@@ -912,8 +912,10 @@ setstack_tiger(struct PStack *st, struct BCState *bcs)
void
inittiger(struct IsdnCardState *cs)
{
- if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int),
- GFP_KERNEL | GFP_DMA))) {
+ cs->bcs[0].hw.tiger.send = kmalloc_array(NETJET_DMA_TXSIZE,
+ sizeof(unsigned int),
+ GFP_KERNEL | GFP_DMA);
+ if (!cs->bcs[0].hw.tiger.send) {
printk(KERN_WARNING
"HiSax: No memory for tiger.send\n");
return;
@@ -933,8 +935,10 @@ inittiger(struct IsdnCardState *cs)
cs->hw.njet.base + NETJET_DMA_READ_IRQ);
outl(virt_to_bus(cs->bcs[0].hw.tiger.s_end),
cs->hw.njet.base + NETJET_DMA_READ_END);
- if (!(cs->bcs[0].hw.tiger.rec = kmalloc(NETJET_DMA_RXSIZE * sizeof(unsigned int),
- GFP_KERNEL | GFP_DMA))) {
+ cs->bcs[0].hw.tiger.rec = kmalloc_array(NETJET_DMA_RXSIZE,
+ sizeof(unsigned int),
+ GFP_KERNEL | GFP_DMA);
+ if (!cs->bcs[0].hw.tiger.rec) {
printk(KERN_WARNING
"HiSax: No memory for tiger.rec\n");
return;
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
index 99012c0..7f28b96 100644
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -340,7 +340,7 @@ static void *bsd_alloc(struct isdn_ppp_comp_data *data)
* Allocate space for the dictionary. This may be more than one page in
* length.
*/
- db->dict = vmalloc(hsize * sizeof(struct bsd_dict));
+ db->dict = vmalloc(array_size(hsize, sizeof(struct bsd_dict)));
if (!db->dict) {
bsd_free(db);
return NULL;
@@ -353,7 +353,8 @@ static void *bsd_alloc(struct isdn_ppp_comp_data *data)
if (!decomp)
db->lens = NULL;
else {
- db->lens = vmalloc((maxmaxcode + 1) * sizeof(db->lens[0]));
+ db->lens = vmalloc(array_size(sizeof(db->lens[0]),
+ maxmaxcode + 1));
if (!db->lens) {
bsd_free(db);
return (NULL);
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 7c6f3f5..7a501db 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -2070,14 +2070,14 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
if ((adding) && (d->rcverr))
kfree(d->rcverr);
- if (!(d->rcverr = kzalloc(sizeof(int) * m, GFP_ATOMIC))) {
+ if (!(d->rcverr = kcalloc(m, sizeof(int), GFP_ATOMIC))) {
printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
return -1;
}
if ((adding) && (d->rcvcount))
kfree(d->rcvcount);
- if (!(d->rcvcount = kzalloc(sizeof(int) * m, GFP_ATOMIC))) {
+ if (!(d->rcvcount = kcalloc(m, sizeof(int), GFP_ATOMIC))) {
printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
if (!adding)
kfree(d->rcverr);
@@ -2089,7 +2089,8 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
skb_queue_purge(&d->rpqueue[j]);
kfree(d->rpqueue);
}
- if (!(d->rpqueue = kmalloc(sizeof(struct sk_buff_head) * m, GFP_ATOMIC))) {
+ d->rpqueue = kmalloc_array(m, sizeof(struct sk_buff_head), GFP_ATOMIC);
+ if (!d->rpqueue) {
printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
if (!adding) {
kfree(d->rcvcount);
@@ -2103,7 +2104,8 @@ isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
if ((adding) && (d->rcv_waitq))
kfree(d->rcv_waitq);
- d->rcv_waitq = kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_ATOMIC);
+ d->rcv_waitq = kmalloc(array3_size(sizeof(wait_queue_head_t), 2, m),
+ GFP_ATOMIC);
if (!d->rcv_waitq) {
printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
if (!adding) {
diff --git a/drivers/isdn/mISDN/fsm.c b/drivers/isdn/mISDN/fsm.c
index cabcb90..9a8d08d 100644
--- a/drivers/isdn/mISDN/fsm.c
+++ b/drivers/isdn/mISDN/fsm.c
@@ -32,8 +32,10 @@ mISDN_FsmNew(struct Fsm *fsm,
{
int i;
- fsm->jumpmatrix = kzalloc(sizeof(FSMFNPTR) * fsm->state_count *
- fsm->event_count, GFP_KERNEL);
+ fsm->jumpmatrix =
+ kzalloc(array3_size(sizeof(FSMFNPTR), fsm->state_count,
+ fsm->event_count),
+ GFP_KERNEL);
if (fsm->jumpmatrix == NULL)
return -ENOMEM;
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
index 853b2d3..7ecf080 100644
--- a/drivers/leds/leds-adp5520.c
+++ b/drivers/leds/leds-adp5520.c
@@ -108,7 +108,7 @@ static int adp5520_led_probe(struct platform_device *pdev)
return -EFAULT;
}
- led = devm_kzalloc(&pdev->dev, sizeof(*led) * pdata->num_leds,
+ led = devm_kcalloc(&pdev->dev, pdata->num_leds, sizeof(*led),
GFP_KERNEL);
if (!led)
return -ENOMEM;
diff --git a/drivers/leds/leds-apu.c b/drivers/leds/leds-apu.c
index 90eeedc..8c93d68 100644
--- a/drivers/leds/leds-apu.c
+++ b/drivers/leds/leds-apu.c
@@ -171,8 +171,8 @@ static int apu_led_config(struct device *dev, struct apu_led_pdata *apuld)
int i;
int err;
- apu_led->pled = devm_kzalloc(dev,
- sizeof(struct apu_led_priv) * apu_led->num_led_instances,
+ apu_led->pled = devm_kcalloc(dev,
+ apu_led->num_led_instances, sizeof(struct apu_led_priv),
GFP_KERNEL);
if (!apu_led->pled)
diff --git a/drivers/leds/leds-cr0014114.c b/drivers/leds/leds-cr0014114.c
index a4b1c1d..0e42624 100644
--- a/drivers/leds/leds-cr0014114.c
+++ b/drivers/leds/leds-cr0014114.c
@@ -237,8 +237,7 @@ static int cr0014114_probe(struct spi_device *spi)
return -ENODEV;
}
- priv = devm_kzalloc(&spi->dev,
- sizeof(*priv) + sizeof(*priv->leds) * count,
+ priv = devm_kzalloc(&spi->dev, struct_size(priv, leds, count),
GFP_KERNEL);
if (!priv)
return -ENOMEM;
diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c
index f8c7d82..31d4c94 100644
--- a/drivers/leds/leds-da9052.c
+++ b/drivers/leds/leds-da9052.c
@@ -113,8 +113,8 @@ static int da9052_led_probe(struct platform_device *pdev)
goto err;
}
- led = devm_kzalloc(&pdev->dev,
- sizeof(struct da9052_led) * pled->num_leds,
+ led = devm_kcalloc(&pdev->dev,
+ pled->num_leds, sizeof(struct da9052_led),
GFP_KERNEL);
if (!led) {
error = -ENOMEM;
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 55c0517..99689b5 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -533,8 +533,8 @@ static int lp5521_probe(struct i2c_client *client,
if (!chip)
return -ENOMEM;
- led = devm_kzalloc(&client->dev,
- sizeof(*led) * pdata->num_channels, GFP_KERNEL);
+ led = devm_kcalloc(&client->dev,
+ pdata->num_channels, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 52b6f529..a2e74fe 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -898,8 +898,8 @@ static int lp5523_probe(struct i2c_client *client,
if (!chip)
return -ENOMEM;
- led = devm_kzalloc(&client->dev,
- sizeof(*led) * pdata->num_channels, GFP_KERNEL);
+ led = devm_kcalloc(&client->dev,
+ pdata->num_channels, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c
index 05ffa34..2a9009f 100644
--- a/drivers/leds/leds-lp5562.c
+++ b/drivers/leds/leds-lp5562.c
@@ -534,8 +534,8 @@ static int lp5562_probe(struct i2c_client *client,
if (!chip)
return -ENOMEM;
- led = devm_kzalloc(&client->dev,
- sizeof(*led) * pdata->num_channels, GFP_KERNEL);
+ led = devm_kcalloc(&client->dev,
+ pdata->num_channels, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index 5377f22..3d79a63 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -560,7 +560,7 @@ struct lp55xx_platform_data *lp55xx_of_populate_pdata(struct device *dev,
return ERR_PTR(-EINVAL);
}
- cfg = devm_kzalloc(dev, sizeof(*cfg) * num_channels, GFP_KERNEL);
+ cfg = devm_kcalloc(dev, num_channels, sizeof(*cfg), GFP_KERNEL);
if (!cfg)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c
index 3adb113..4c800b5 100644
--- a/drivers/leds/leds-lp8501.c
+++ b/drivers/leds/leds-lp8501.c
@@ -327,8 +327,8 @@ static int lp8501_probe(struct i2c_client *client,
if (!chip)
return -ENOMEM;
- led = devm_kzalloc(&client->dev,
- sizeof(*led) * pdata->num_channels, GFP_KERNEL);
+ led = devm_kcalloc(&client->dev,
+ pdata->num_channels, sizeof(*led), GFP_KERNEL);
if (!led)
return -ENOMEM;
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
index a7ff510..5ec730a 100644
--- a/drivers/leds/leds-lt3593.c
+++ b/drivers/leds/leds-lt3593.c
@@ -128,8 +128,8 @@ static int lt3593_led_probe(struct platform_device *pdev)
if (!pdata)
return -EBUSY;
- leds_data = devm_kzalloc(&pdev->dev,
- sizeof(struct lt3593_led_data) * pdata->num_leds,
+ leds_data = devm_kcalloc(&pdev->dev,
+ pdata->num_leds, sizeof(struct lt3593_led_data),
GFP_KERNEL);
if (!leds_data)
return -ENOMEM;
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index 2421cf10..47ad7de 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -136,7 +136,7 @@ static struct mc13xxx_leds_platform_data __init *mc13xxx_led_probe_dt(
pdata->num_leds = of_get_child_count(parent);
- pdata->led = devm_kzalloc(dev, pdata->num_leds * sizeof(*pdata->led),
+ pdata->led = devm_kcalloc(dev, pdata->num_leds, sizeof(*pdata->led),
GFP_KERNEL);
if (!pdata->led) {
ret = -ENOMEM;
@@ -210,7 +210,7 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
return -EINVAL;
}
- leds->led = devm_kzalloc(dev, leds->num_leds * sizeof(*leds->led),
+ leds->led = devm_kcalloc(dev, leds->num_leds, sizeof(*leds->led),
GFP_KERNEL);
if (!leds->led)
return -ENOMEM;
diff --git a/drivers/leds/leds-mlxcpld.c b/drivers/leds/leds-mlxcpld.c
index 281482e..f4721f8 100644
--- a/drivers/leds/leds-mlxcpld.c
+++ b/drivers/leds/leds-mlxcpld.c
@@ -329,8 +329,10 @@ static int mlxcpld_led_config(struct device *dev,
int i;
int err;
- cpld->pled = devm_kzalloc(dev, sizeof(struct mlxcpld_led_priv) *
- cpld->num_led_instances, GFP_KERNEL);
+ cpld->pled = devm_kcalloc(dev,
+ cpld->num_led_instances,
+ sizeof(struct mlxcpld_led_priv),
+ GFP_KERNEL);
if (!cpld->pled)
return -ENOMEM;
diff --git a/drivers/leds/leds-netxbig.c b/drivers/leds/leds-netxbig.c
index f48b1ae..62fa0de 100644
--- a/drivers/leds/leds-netxbig.c
+++ b/drivers/leds/leds-netxbig.c
@@ -335,7 +335,7 @@ static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np,
return ret;
}
num_addr = ret;
- addr = devm_kzalloc(dev, num_addr * sizeof(*addr), GFP_KERNEL);
+ addr = devm_kcalloc(dev, num_addr, sizeof(*addr), GFP_KERNEL);
if (!addr)
return -ENOMEM;
@@ -355,7 +355,7 @@ static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np,
return ret;
}
num_data = ret;
- data = devm_kzalloc(dev, num_data * sizeof(*data), GFP_KERNEL);
+ data = devm_kcalloc(dev, num_data, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -415,7 +415,7 @@ static int netxbig_leds_get_of_pdata(struct device *dev,
if (ret % 3)
return -EINVAL;
num_timers = ret / 3;
- timers = devm_kzalloc(dev, num_timers * sizeof(*timers),
+ timers = devm_kcalloc(dev, num_timers, sizeof(*timers),
GFP_KERNEL);
if (!timers)
return -ENOMEM;
@@ -444,7 +444,7 @@ static int netxbig_leds_get_of_pdata(struct device *dev,
return -ENODEV;
}
- leds = devm_kzalloc(dev, num_leds * sizeof(*leds), GFP_KERNEL);
+ leds = devm_kcalloc(dev, num_leds, sizeof(*leds), GFP_KERNEL);
if (!leds)
return -ENOMEM;
@@ -470,8 +470,8 @@ static int netxbig_leds_get_of_pdata(struct device *dev,
goto err_node_put;
mode_val =
- devm_kzalloc(dev,
- NETXBIG_LED_MODE_NUM * sizeof(*mode_val),
+ devm_kcalloc(dev,
+ NETXBIG_LED_MODE_NUM, sizeof(*mode_val),
GFP_KERNEL);
if (!mode_val) {
ret = -ENOMEM;
@@ -560,8 +560,8 @@ static int netxbig_led_probe(struct platform_device *pdev)
return ret;
}
- leds_data = devm_kzalloc(&pdev->dev,
- pdata->num_leds * sizeof(*leds_data),
+ leds_data = devm_kcalloc(&pdev->dev,
+ pdata->num_leds, sizeof(*leds_data),
GFP_KERNEL);
if (!leds_data)
return -ENOMEM;
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index 506b75b..14fe5cd 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -264,7 +264,7 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata)
if (!num_leds)
return -ENODEV;
- leds = devm_kzalloc(dev, num_leds * sizeof(struct ns2_led),
+ leds = devm_kcalloc(dev, num_leds, sizeof(struct ns2_led),
GFP_KERNEL);
if (!leds)
return -ENOMEM;
@@ -298,8 +298,9 @@ ns2_leds_get_of_pdata(struct device *dev, struct ns2_led_platform_data *pdata)
}
num_modes = ret / 3;
- modval = devm_kzalloc(dev,
- num_modes * sizeof(struct ns2_led_modval),
+ modval = devm_kcalloc(dev,
+ num_modes,
+ sizeof(struct ns2_led_modval),
GFP_KERNEL);
if (!modval)
return -ENOMEM;
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index 78183f9..f51b356 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -390,8 +390,8 @@ pca955x_pdata_of_init(struct i2c_client *client, struct pca955x_chipdef *chip)
if (!pdata)
return ERR_PTR(-ENOMEM);
- pdata->leds = devm_kzalloc(&client->dev,
- sizeof(struct pca955x_led) * chip->bits,
+ pdata->leds = devm_kcalloc(&client->dev,
+ chip->bits, sizeof(struct pca955x_led),
GFP_KERNEL);
if (!pdata->leds)
return ERR_PTR(-ENOMEM);
@@ -494,8 +494,8 @@ static int pca955x_probe(struct i2c_client *client,
if (!pca955x)
return -ENOMEM;
- pca955x->leds = devm_kzalloc(&client->dev,
- sizeof(*pca955x_led) * chip->bits, GFP_KERNEL);
+ pca955x->leds = devm_kcalloc(&client->dev,
+ chip->bits, sizeof(*pca955x_led), GFP_KERNEL);
if (!pca955x->leds)
return -ENOMEM;
diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c
index 3bf9a12..5c09081 100644
--- a/drivers/leds/leds-pca963x.c
+++ b/drivers/leds/leds-pca963x.c
@@ -300,8 +300,8 @@ pca963x_dt_init(struct i2c_client *client, struct pca963x_chipdef *chip)
if (!count || count > chip->n_leds)
return ERR_PTR(-ENODEV);
- pca963x_leds = devm_kzalloc(&client->dev,
- sizeof(struct led_info) * chip->n_leds, GFP_KERNEL);
+ pca963x_leds = devm_kcalloc(&client->dev,
+ chip->n_leds, sizeof(struct led_info), GFP_KERNEL);
if (!pca963x_leds)
return ERR_PTR(-ENOMEM);
@@ -407,7 +407,7 @@ static int pca963x_probe(struct i2c_client *client,
GFP_KERNEL);
if (!pca963x_chip)
return -ENOMEM;
- pca963x = devm_kzalloc(&client->dev, chip->n_leds * sizeof(*pca963x),
+ pca963x = devm_kcalloc(&client->dev, chip->n_leds, sizeof(*pca963x),
GFP_KERNEL);
if (!pca963x)
return -ENOMEM;
diff --git a/drivers/leds/leds-tca6507.c b/drivers/leds/leds-tca6507.c
index c12c16f..8f343af 100644
--- a/drivers/leds/leds-tca6507.c
+++ b/drivers/leds/leds-tca6507.c
@@ -697,8 +697,8 @@ tca6507_led_dt_init(struct i2c_client *client)
if (!count || count > NUM_LEDS)
return ERR_PTR(-ENODEV);
- tca_leds = devm_kzalloc(&client->dev,
- sizeof(struct led_info) * NUM_LEDS, GFP_KERNEL);
+ tca_leds = devm_kcalloc(&client->dev,
+ NUM_LEDS, sizeof(struct led_info), GFP_KERNEL);
if (!tca_leds)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/lightnvm/Kconfig b/drivers/lightnvm/Kconfig
index 10c0898..9c03f35 100644
--- a/drivers/lightnvm/Kconfig
+++ b/drivers/lightnvm/Kconfig
@@ -4,7 +4,7 @@
menuconfig NVM
bool "Open-Channel SSD target support"
- depends on BLOCK && HAS_DMA && PCI
+ depends on BLOCK && PCI
select BLK_DEV_NVME
help
Say Y here to get to enable Open-channel SSDs.
diff --git a/drivers/lightnvm/pblk-gc.c b/drivers/lightnvm/pblk-gc.c
index 6a4883e..080469d 100644
--- a/drivers/lightnvm/pblk-gc.c
+++ b/drivers/lightnvm/pblk-gc.c
@@ -88,7 +88,7 @@ static void pblk_gc_line_ws(struct work_struct *work)
up(&gc->gc_sem);
- gc_rq->data = vmalloc(gc_rq->nr_secs * geo->csecs);
+ gc_rq->data = vmalloc(array_size(gc_rq->nr_secs, geo->csecs));
if (!gc_rq->data) {
pr_err("pblk: could not GC line:%d (%d/%d)\n",
line->id, *line->vsc, gc_rq->nr_secs);
diff --git a/drivers/lightnvm/pblk-init.c b/drivers/lightnvm/pblk-init.c
index 491df0f..b57f764d 100644
--- a/drivers/lightnvm/pblk-init.c
+++ b/drivers/lightnvm/pblk-init.c
@@ -187,7 +187,7 @@ static int pblk_rwb_init(struct pblk *pblk)
nr_entries = pblk_rb_calculate_size(buffer_size);
- entries = vzalloc(nr_entries * sizeof(struct pblk_rb_entry));
+ entries = vzalloc(array_size(nr_entries, sizeof(struct pblk_rb_entry)));
if (!entries)
return -ENOMEM;
@@ -379,7 +379,7 @@ static int pblk_core_init(struct pblk *pblk)
return -EINVAL;
}
- pblk->pad_dist = kzalloc((pblk->min_write_pgs - 1) * sizeof(atomic64_t),
+ pblk->pad_dist = kcalloc(pblk->min_write_pgs - 1, sizeof(atomic64_t),
GFP_KERNEL);
if (!pblk->pad_dist)
return -ENOMEM;
@@ -833,8 +833,8 @@ static int pblk_alloc_line_meta(struct pblk *pblk, struct pblk_line *line)
goto free_blk_bitmap;
- line->chks = kmalloc(lm->blk_per_line * sizeof(struct nvm_chk_meta),
- GFP_KERNEL);
+ line->chks = kmalloc_array(lm->blk_per_line,
+ sizeof(struct nvm_chk_meta), GFP_KERNEL);
if (!line->chks)
goto free_erase_bitmap;
diff --git a/drivers/lightnvm/pblk-rb.c b/drivers/lightnvm/pblk-rb.c
index 00cd1f2..55e9442 100644
--- a/drivers/lightnvm/pblk-rb.c
+++ b/drivers/lightnvm/pblk-rb.c
@@ -38,7 +38,7 @@ void pblk_rb_data_free(struct pblk_rb *rb)
/*
* Initialize ring buffer. The data and metadata buffers must be previously
* allocated and their size must be a power of two
- * (Documentation/circular-buffers.txt)
+ * (Documentation/core-api/circular-buffers.rst)
*/
int pblk_rb_init(struct pblk_rb *rb, struct pblk_rb_entry *rb_entry_base,
unsigned int power_size, unsigned int power_seg_sz)
diff --git a/drivers/lightnvm/pblk-recovery.c b/drivers/lightnvm/pblk-recovery.c
index 5983428..3a50691 100644
--- a/drivers/lightnvm/pblk-recovery.c
+++ b/drivers/lightnvm/pblk-recovery.c
@@ -260,7 +260,7 @@ static int pblk_recov_pad_oob(struct pblk *pblk, struct pblk_line *line,
if (!pad_rq)
return -ENOMEM;
- data = vzalloc(pblk->max_write_pgs * geo->csecs);
+ data = vzalloc(array_size(pblk->max_write_pgs, geo->csecs));
if (!data) {
ret = -ENOMEM;
goto free_rq;
diff --git a/drivers/mailbox/hi6220-mailbox.c b/drivers/mailbox/hi6220-mailbox.c
index 519376d..4fa9803 100644
--- a/drivers/mailbox/hi6220-mailbox.c
+++ b/drivers/mailbox/hi6220-mailbox.c
@@ -282,13 +282,13 @@ static int hi6220_mbox_probe(struct platform_device *pdev)
mbox->dev = dev;
mbox->chan_num = MBOX_CHAN_MAX;
- mbox->mchan = devm_kzalloc(dev,
- mbox->chan_num * sizeof(*mbox->mchan), GFP_KERNEL);
+ mbox->mchan = devm_kcalloc(dev,
+ mbox->chan_num, sizeof(*mbox->mchan), GFP_KERNEL);
if (!mbox->mchan)
return -ENOMEM;
- mbox->chan = devm_kzalloc(dev,
- mbox->chan_num * sizeof(*mbox->chan), GFP_KERNEL);
+ mbox->chan = devm_kcalloc(dev,
+ mbox->chan_num, sizeof(*mbox->chan), GFP_KERNEL);
if (!mbox->chan)
return -ENOMEM;
diff --git a/drivers/mailbox/mailbox-sti.c b/drivers/mailbox/mailbox-sti.c
index 41bcd33..779d412 100644
--- a/drivers/mailbox/mailbox-sti.c
+++ b/drivers/mailbox/mailbox-sti.c
@@ -442,8 +442,8 @@ static int sti_mbox_probe(struct platform_device *pdev)
if (!mbox)
return -ENOMEM;
- chans = devm_kzalloc(&pdev->dev,
- sizeof(*chans) * STI_MBOX_CHAN_MAX, GFP_KERNEL);
+ chans = devm_kcalloc(&pdev->dev,
+ STI_MBOX_CHAN_MAX, sizeof(*chans), GFP_KERNEL);
if (!chans)
return -ENOMEM;
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index 2517038..e1e2c08 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -729,7 +729,7 @@ static int omap_mbox_probe(struct platform_device *pdev)
return -ENODEV;
}
- finfoblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*finfoblk),
+ finfoblk = devm_kcalloc(&pdev->dev, info_count, sizeof(*finfoblk),
GFP_KERNEL);
if (!finfoblk)
return -ENOMEM;
@@ -773,23 +773,23 @@ static int omap_mbox_probe(struct platform_device *pdev)
if (IS_ERR(mdev->mbox_base))
return PTR_ERR(mdev->mbox_base);
- mdev->irq_ctx = devm_kzalloc(&pdev->dev, num_users * sizeof(u32),
+ mdev->irq_ctx = devm_kcalloc(&pdev->dev, num_users, sizeof(u32),
GFP_KERNEL);
if (!mdev->irq_ctx)
return -ENOMEM;
/* allocate one extra for marking end of list */
- list = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*list),
+ list = devm_kcalloc(&pdev->dev, info_count + 1, sizeof(*list),
GFP_KERNEL);
if (!list)
return -ENOMEM;
- chnls = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*chnls),
+ chnls = devm_kcalloc(&pdev->dev, info_count + 1, sizeof(*chnls),
GFP_KERNEL);
if (!chnls)
return -ENOMEM;
- mboxblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*mbox),
+ mboxblk = devm_kcalloc(&pdev->dev, info_count, sizeof(*mbox),
GFP_KERNEL);
if (!mboxblk)
return -ENOMEM;
diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
index fc3c237..311e91b 100644
--- a/drivers/mailbox/pcc.c
+++ b/drivers/mailbox/pcc.c
@@ -466,7 +466,8 @@ static int __init acpi_pcc_probe(void)
return -EINVAL;
}
- pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) * count, GFP_KERNEL);
+ pcc_mbox_channels = kcalloc(count, sizeof(struct mbox_chan),
+ GFP_KERNEL);
if (!pcc_mbox_channels) {
pr_err("Could not allocate space for PCC mbox channels\n");
return -ENOMEM;
diff --git a/drivers/mailbox/ti-msgmgr.c b/drivers/mailbox/ti-msgmgr.c
index 78753a8..5d04738 100644
--- a/drivers/mailbox/ti-msgmgr.c
+++ b/drivers/mailbox/ti-msgmgr.c
@@ -568,12 +568,12 @@ static int ti_msgmgr_probe(struct platform_device *pdev)
}
inst->num_valid_queues = queue_count;
- qinst = devm_kzalloc(dev, sizeof(*qinst) * queue_count, GFP_KERNEL);
+ qinst = devm_kcalloc(dev, queue_count, sizeof(*qinst), GFP_KERNEL);
if (!qinst)
return -ENOMEM;
inst->qinsts = qinst;
- chans = devm_kzalloc(dev, sizeof(*chans) * queue_count, GFP_KERNEL);
+ chans = devm_kcalloc(dev, queue_count, sizeof(*chans), GFP_KERNEL);
if (!chans)
return -ENOMEM;
inst->chans = chans;
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index edff083..8b8c123 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -334,6 +334,17 @@ config DM_CACHE_SMQ
of less memory utilization, improved performance and increased
adaptability in the face of changing workloads.
+config DM_WRITECACHE
+ tristate "Writecache target"
+ depends on BLK_DEV_DM
+ ---help---
+ The writecache target caches writes on persistent memory or SSD.
+ It is intended for databases or other programs that need extremely
+ low commit latency.
+
+ The writecache target doesn't cache reads because reads are supposed
+ to be cached in standard RAM.
+
config DM_ERA
tristate "Era target (EXPERIMENTAL)"
depends on BLK_DEV_DM
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 63255f3..822f4e8 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_DM_ERA) += dm-era.o
obj-$(CONFIG_DM_LOG_WRITES) += dm-log-writes.o
obj-$(CONFIG_DM_INTEGRITY) += dm-integrity.o
obj-$(CONFIG_DM_ZONED) += dm-zoned.o
+obj-$(CONFIG_DM_WRITECACHE) += dm-writecache.o
ifeq ($(CONFIG_DM_UEVENT),y)
dm-mod-objs += dm-uevent.o
diff --git a/drivers/md/bcache/Kconfig b/drivers/md/bcache/Kconfig
index 4d20088..17bf109 100644
--- a/drivers/md/bcache/Kconfig
+++ b/drivers/md/bcache/Kconfig
@@ -5,7 +5,7 @@ config BCACHE
Allows a block device to be used as cache for other devices; uses
a btree for indexing and the layout is optimized for SSDs.
- See Documentation/bcache.txt for details.
+ See Documentation/admin-guide/bcache.rst for details.
config BCACHE_DEBUG
bool "Bcache debugging"
diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c
index 2a0968c0..547c9ee 100644
--- a/drivers/md/bcache/btree.c
+++ b/drivers/md/bcache/btree.c
@@ -18,7 +18,7 @@
* as keys are inserted we only sort the pages that have not yet been written.
* When garbage collection is run, we resort the entire node.
*
- * All configuration is done via sysfs; see Documentation/bcache.txt.
+ * All configuration is done via sysfs; see Documentation/admin-guide/bcache.rst.
*/
#include "bcache.h"
diff --git a/drivers/md/bcache/extents.c b/drivers/md/bcache/extents.c
index c334e66..1d09674 100644
--- a/drivers/md/bcache/extents.c
+++ b/drivers/md/bcache/extents.c
@@ -18,7 +18,7 @@
* as keys are inserted we only sort the pages that have not yet been written.
* When garbage collection is run, we resort the entire node.
*
- * All configuration is done via sysfs; see Documentation/bcache.txt.
+ * All configuration is done via sysfs; see Documentation/admin-guide/bcache.rst.
*/
#include "bcache.h"
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index a31e55b..fa4058e 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1715,7 +1715,7 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
iter_size = (sb->bucket_size / sb->block_size + 1) *
sizeof(struct btree_iter_set);
- if (!(c->devices = kzalloc(c->nr_uuids * sizeof(void *), GFP_KERNEL)) ||
+ if (!(c->devices = kcalloc(c->nr_uuids, sizeof(void *), GFP_KERNEL)) ||
mempool_init_slab_pool(&c->search, 32, bch_search_cache) ||
mempool_init_kmalloc_pool(&c->bio_meta, 2,
sizeof(struct bbio) + sizeof(struct bio_vec) *
@@ -2041,10 +2041,11 @@ static int cache_alloc(struct cache *ca)
!init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL) ||
!init_fifo(&ca->free_inc, free << 2, GFP_KERNEL) ||
!init_heap(&ca->heap, free << 3, GFP_KERNEL) ||
- !(ca->buckets = vzalloc(sizeof(struct bucket) *
- ca->sb.nbuckets)) ||
- !(ca->prio_buckets = kzalloc(sizeof(uint64_t) * prio_buckets(ca) *
- 2, GFP_KERNEL)) ||
+ !(ca->buckets = vzalloc(array_size(sizeof(struct bucket),
+ ca->sb.nbuckets))) ||
+ !(ca->prio_buckets = kzalloc(array3_size(sizeof(uint64_t),
+ prio_buckets(ca), 2),
+ GFP_KERNEL)) ||
!(ca->disk_buckets = alloc_bucket_pages(GFP_KERNEL, ca)))
return -ENOMEM;
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
index 8ccbc8f3..225b15a 100644
--- a/drivers/md/bcache/sysfs.c
+++ b/drivers/md/bcache/sysfs.c
@@ -881,7 +881,8 @@ SHOW(__bch_cache)
uint16_t q[31], *p, *cached;
ssize_t ret;
- cached = p = vmalloc(ca->sb.nbuckets * sizeof(uint16_t));
+ cached = p = vmalloc(array_size(sizeof(uint16_t),
+ ca->sb.nbuckets));
if (!p)
return -ENOMEM;
diff --git a/drivers/md/dm-bio-prison-v1.c b/drivers/md/dm-bio-prison-v1.c
index e794e36..b538989 100644
--- a/drivers/md/dm-bio-prison-v1.c
+++ b/drivers/md/dm-bio-prison-v1.c
@@ -19,8 +19,8 @@
struct dm_bio_prison {
spinlock_t lock;
- mempool_t cell_pool;
struct rb_root cells;
+ mempool_t cell_pool;
};
static struct kmem_cache *_cell_cache;
diff --git a/drivers/md/dm-bio-prison-v2.c b/drivers/md/dm-bio-prison-v2.c
index f866bc9..b092cdc 100644
--- a/drivers/md/dm-bio-prison-v2.c
+++ b/drivers/md/dm-bio-prison-v2.c
@@ -21,8 +21,8 @@ struct dm_bio_prison_v2 {
struct workqueue_struct *wq;
spinlock_t lock;
- mempool_t cell_pool;
struct rb_root cells;
+ mempool_t cell_pool;
};
static struct kmem_cache *_cell_cache;
diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
index 4ab23d0..1b5b9ad 100644
--- a/drivers/md/dm-cache-policy-smq.c
+++ b/drivers/md/dm-cache-policy-smq.c
@@ -69,7 +69,7 @@ static int space_init(struct entry_space *es, unsigned nr_entries)
return 0;
}
- es->begin = vzalloc(sizeof(struct entry) * nr_entries);
+ es->begin = vzalloc(array_size(nr_entries, sizeof(struct entry)));
if (!es->begin)
return -ENOMEM;
@@ -588,7 +588,7 @@ static int h_init(struct smq_hash_table *ht, struct entry_space *es, unsigned nr
nr_buckets = roundup_pow_of_two(max(nr_entries / 4u, 16u));
ht->hash_bits = __ffs(nr_buckets);
- ht->buckets = vmalloc(sizeof(*ht->buckets) * nr_buckets);
+ ht->buckets = vmalloc(array_size(nr_buckets, sizeof(*ht->buckets)));
if (!ht->buckets)
return -ENOMEM;
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index 001c712..ce14a3d 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -371,7 +371,13 @@ struct cache_stats {
struct cache {
struct dm_target *ti;
- struct dm_target_callbacks callbacks;
+ spinlock_t lock;
+
+ /*
+ * Fields for converting from sectors to blocks.
+ */
+ int sectors_per_block_shift;
+ sector_t sectors_per_block;
struct dm_cache_metadata *cmd;
@@ -402,13 +408,11 @@ struct cache {
dm_cblock_t cache_size;
/*
- * Fields for converting from sectors to blocks.
+ * Invalidation fields.
*/
- sector_t sectors_per_block;
- int sectors_per_block_shift;
+ spinlock_t invalidation_lock;
+ struct list_head invalidation_requests;
- spinlock_t lock;
- struct bio_list deferred_bios;
sector_t migration_threshold;
wait_queue_head_t migration_wait;
atomic_t nr_allocated_migrations;
@@ -419,13 +423,11 @@ struct cache {
*/
atomic_t nr_io_migrations;
+ struct bio_list deferred_bios;
+
struct rw_semaphore quiesce_lock;
- /*
- * cache_size entries, dirty if set
- */
- atomic_t nr_dirty;
- unsigned long *dirty_bitset;
+ struct dm_target_callbacks callbacks;
/*
* origin_blocks entries, discarded if set.
@@ -442,17 +444,27 @@ struct cache {
const char **ctr_args;
struct dm_kcopyd_client *copier;
- struct workqueue_struct *wq;
struct work_struct deferred_bio_worker;
struct work_struct migration_worker;
+ struct workqueue_struct *wq;
struct delayed_work waker;
struct dm_bio_prison_v2 *prison;
- struct bio_set bs;
- mempool_t migration_pool;
+ /*
+ * cache_size entries, dirty if set
+ */
+ unsigned long *dirty_bitset;
+ atomic_t nr_dirty;
- struct dm_cache_policy *policy;
unsigned policy_nr_args;
+ struct dm_cache_policy *policy;
+
+ /*
+ * Cache features such as write-through.
+ */
+ struct cache_features features;
+
+ struct cache_stats stats;
bool need_tick_bio:1;
bool sized:1;
@@ -461,25 +473,16 @@ struct cache {
bool loaded_mappings:1;
bool loaded_discards:1;
- /*
- * Cache features such as write-through.
- */
- struct cache_features features;
-
- struct cache_stats stats;
+ struct rw_semaphore background_work_lock;
- /*
- * Invalidation fields.
- */
- spinlock_t invalidation_lock;
- struct list_head invalidation_requests;
+ struct batcher committer;
+ struct work_struct commit_ws;
struct io_tracker tracker;
- struct work_struct commit_ws;
- struct batcher committer;
+ mempool_t migration_pool;
- struct rw_semaphore background_work_lock;
+ struct bio_set bs;
};
struct per_bio_data {
diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h
index f21c5d2..7d480c9 100644
--- a/drivers/md/dm-core.h
+++ b/drivers/md/dm-core.h
@@ -31,6 +31,9 @@ struct dm_kobject_holder {
struct mapped_device {
struct mutex suspend_lock;
+ struct mutex table_devices_lock;
+ struct list_head table_devices;
+
/*
* The current mapping (struct dm_table *).
* Use dm_get_live_table{_fast} or take suspend_lock for
@@ -38,17 +41,14 @@ struct mapped_device {
*/
void __rcu *map;
- struct list_head table_devices;
- struct mutex table_devices_lock;
-
unsigned long flags;
- struct request_queue *queue;
- int numa_node_id;
-
- enum dm_queue_mode type;
/* Protect queue and type against concurrent access. */
struct mutex type_lock;
+ enum dm_queue_mode type;
+
+ int numa_node_id;
+ struct request_queue *queue;
atomic_t holders;
atomic_t open_count;
@@ -56,21 +56,21 @@ struct mapped_device {
struct dm_target *immutable_target;
struct target_type *immutable_target_type;
+ char name[16];
struct gendisk *disk;
struct dax_device *dax_dev;
- char name[16];
-
- void *interface_ptr;
/*
* A list of ios that arrived while we were suspended.
*/
- atomic_t pending[2];
- wait_queue_head_t wait;
struct work_struct work;
+ wait_queue_head_t wait;
+ atomic_t pending[2];
spinlock_t deferred_lock;
struct bio_list deferred;
+ void *interface_ptr;
+
/*
* Event handling.
*/
@@ -84,17 +84,17 @@ struct mapped_device {
unsigned internal_suspend_count;
/*
- * Processing queue (flush)
- */
- struct workqueue_struct *wq;
-
- /*
* io objects are allocated from here.
*/
struct bio_set io_bs;
struct bio_set bs;
/*
+ * Processing queue (flush)
+ */
+ struct workqueue_struct *wq;
+
+ /*
* freeze/thaw support require holding onto a super block
*/
struct super_block *frozen_sb;
@@ -102,11 +102,11 @@ struct mapped_device {
/* forced geometry settings */
struct hd_geometry geometry;
- struct block_device *bdev;
-
/* kobject and completion */
struct dm_kobject_holder kobj_holder;
+ struct block_device *bdev;
+
/* zero-length flush that will be cloned and submitted to targets */
struct bio flush_bio;
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index da02f4d..b61b069 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -139,25 +139,13 @@ struct crypt_config {
struct dm_dev *dev;
sector_t start;
- /*
- * pool for per bio private data, crypto requests,
- * encryption requeusts/buffer pages and integrity tags
- */
- mempool_t req_pool;
- mempool_t page_pool;
- mempool_t tag_pool;
- unsigned tag_pool_max_sectors;
-
struct percpu_counter n_allocated_pages;
- struct bio_set bs;
- struct mutex bio_alloc_lock;
-
struct workqueue_struct *io_queue;
struct workqueue_struct *crypt_queue;
- struct task_struct *write_thread;
wait_queue_head_t write_thread_wait;
+ struct task_struct *write_thread;
struct rb_root write_tree;
char *cipher;
@@ -213,6 +201,18 @@ struct crypt_config {
unsigned int integrity_iv_size;
unsigned int on_disk_tag_size;
+ /*
+ * pool for per bio private data, crypto requests,
+ * encryption requeusts/buffer pages and integrity tags
+ */
+ unsigned tag_pool_max_sectors;
+ mempool_t tag_pool;
+ mempool_t req_pool;
+ mempool_t page_pool;
+
+ struct bio_set bs;
+ struct mutex bio_alloc_lock;
+
u8 *authenc_key; /* space for keys in authenc() format (if used) */
u8 key[0];
};
@@ -1878,8 +1878,9 @@ static int crypt_alloc_tfms_skcipher(struct crypt_config *cc, char *ciphermode)
unsigned i;
int err;
- cc->cipher_tfm.tfms = kzalloc(cc->tfms_count *
- sizeof(struct crypto_skcipher *), GFP_KERNEL);
+ cc->cipher_tfm.tfms = kcalloc(cc->tfms_count,
+ sizeof(struct crypto_skcipher *),
+ GFP_KERNEL);
if (!cc->cipher_tfm.tfms)
return -ENOMEM;
diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c
index fc68c7a..86438b2 100644
--- a/drivers/md/dm-integrity.c
+++ b/drivers/md/dm-integrity.c
@@ -2448,7 +2448,9 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
struct scatterlist **sl;
unsigned i;
- sl = kvmalloc(ic->journal_sections * sizeof(struct scatterlist *), GFP_KERNEL | __GFP_ZERO);
+ sl = kvmalloc_array(ic->journal_sections,
+ sizeof(struct scatterlist *),
+ GFP_KERNEL | __GFP_ZERO);
if (!sl)
return NULL;
@@ -2464,7 +2466,8 @@ static struct scatterlist **dm_integrity_alloc_journal_scatterlist(struct dm_int
n_pages = (end_index - start_index + 1);
- s = kvmalloc(n_pages * sizeof(struct scatterlist), GFP_KERNEL);
+ s = kvmalloc_array(n_pages, sizeof(struct scatterlist),
+ GFP_KERNEL);
if (!s) {
dm_integrity_free_journal_scatterlist(ic, sl);
return NULL;
@@ -2643,7 +2646,9 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
goto bad;
}
- sg = kvmalloc((ic->journal_pages + 1) * sizeof(struct scatterlist), GFP_KERNEL);
+ sg = kvmalloc_array(ic->journal_pages + 1,
+ sizeof(struct scatterlist),
+ GFP_KERNEL);
if (!sg) {
*error = "Unable to allocate sg list";
r = -ENOMEM;
@@ -2709,7 +2714,9 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
r = -ENOMEM;
goto bad;
}
- ic->sk_requests = kvmalloc(ic->journal_sections * sizeof(struct skcipher_request *), GFP_KERNEL | __GFP_ZERO);
+ ic->sk_requests = kvmalloc_array(ic->journal_sections,
+ sizeof(struct skcipher_request *),
+ GFP_KERNEL | __GFP_ZERO);
if (!ic->sk_requests) {
*error = "Unable to allocate sk requests";
r = -ENOMEM;
@@ -2743,7 +2750,8 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
r = -ENOMEM;
goto bad;
}
- section_req->iv = kmalloc(ivsize * 2, GFP_KERNEL);
+ section_req->iv = kmalloc_array(ivsize, 2,
+ GFP_KERNEL);
if (!section_req->iv) {
skcipher_request_free(section_req);
*error = "Unable to allocate iv";
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 5acf77d..b810ea7 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1344,7 +1344,8 @@ static int table_load(struct file *filp, struct dm_ioctl *param, size_t param_si
goto err_unlock_md_type;
}
} else if (!is_valid_type(dm_get_md_type(md), dm_table_get_type(t))) {
- DMWARN("can't change device type after initial table load.");
+ DMWARN("can't change device type (old=%u vs new=%u) after initial table load.",
+ dm_get_md_type(md), dm_table_get_type(t));
r = -EINVAL;
goto err_unlock_md_type;
}
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index ce7efc7..3c7547a 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -45,7 +45,6 @@ struct dm_kcopyd_client {
struct dm_io_client *io_client;
wait_queue_head_t destroyq;
- atomic_t nr_jobs;
mempool_t job_pool;
@@ -54,6 +53,8 @@ struct dm_kcopyd_client {
struct dm_kcopyd_throttle *throttle;
+ atomic_t nr_jobs;
+
/*
* We maintain three lists of jobs:
*
diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c
index abf3521..1f76045 100644
--- a/drivers/md/dm-region-hash.c
+++ b/drivers/md/dm-region-hash.c
@@ -63,27 +63,28 @@ struct dm_region_hash {
/* hash table */
rwlock_t hash_lock;
- mempool_t region_pool;
unsigned mask;
unsigned nr_buckets;
unsigned prime;
unsigned shift;
struct list_head *buckets;
+ /*
+ * If there was a flush failure no regions can be marked clean.
+ */
+ int flush_failure;
+
unsigned max_recovery; /* Max # of regions to recover in parallel */
spinlock_t region_lock;
atomic_t recovery_in_flight;
- struct semaphore recovery_count;
struct list_head clean_regions;
struct list_head quiesced_regions;
struct list_head recovered_regions;
struct list_head failed_recovered_regions;
+ struct semaphore recovery_count;
- /*
- * If there was a flush failure no regions can be marked clean.
- */
- int flush_failure;
+ mempool_t region_pool;
void *context;
sector_t target_begin;
@@ -202,7 +203,7 @@ struct dm_region_hash *dm_region_hash_create(
rh->shift = RH_HASH_SHIFT;
rh->prime = RH_HASH_MULT;
- rh->buckets = vmalloc(nr_buckets * sizeof(*rh->buckets));
+ rh->buckets = vmalloc(array_size(nr_buckets, sizeof(*rh->buckets)));
if (!rh->buckets) {
DMERR("unable to allocate region hash bucket memory");
kfree(rh);
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index f745404..97de7a7 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -326,8 +326,8 @@ static int init_origin_hash(void)
{
int i;
- _origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head),
- GFP_KERNEL);
+ _origins = kmalloc_array(ORIGIN_HASH_SIZE, sizeof(struct list_head),
+ GFP_KERNEL);
if (!_origins) {
DMERR("unable to allocate memory for _origins");
return -ENOMEM;
@@ -335,8 +335,9 @@ static int init_origin_hash(void)
for (i = 0; i < ORIGIN_HASH_SIZE; i++)
INIT_LIST_HEAD(_origins + i);
- _dm_origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head),
- GFP_KERNEL);
+ _dm_origins = kmalloc_array(ORIGIN_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!_dm_origins) {
DMERR("unable to allocate memory for _dm_origins");
kfree(_origins);
diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c
index 56059fb..21de30b 100644
--- a/drivers/md/dm-stats.c
+++ b/drivers/md/dm-stats.c
@@ -915,7 +915,9 @@ static int parse_histogram(const char *h, unsigned *n_histogram_entries,
if (*q == ',')
(*n_histogram_entries)++;
- *histogram_boundaries = kmalloc(*n_histogram_entries * sizeof(unsigned long long), GFP_KERNEL);
+ *histogram_boundaries = kmalloc_array(*n_histogram_entries,
+ sizeof(unsigned long long),
+ GFP_KERNEL);
if (!*histogram_boundaries)
return -ENOMEM;
diff --git a/drivers/md/dm-switch.c b/drivers/md/dm-switch.c
index 7924a6a..fae35ca 100644
--- a/drivers/md/dm-switch.c
+++ b/drivers/md/dm-switch.c
@@ -114,7 +114,8 @@ static int alloc_region_table(struct dm_target *ti, unsigned nr_paths)
return -EINVAL;
}
- sctx->region_table = vmalloc(nr_slots * sizeof(region_table_slot_t));
+ sctx->region_table = vmalloc(array_size(nr_slots,
+ sizeof(region_table_slot_t)));
if (!sctx->region_table) {
ti->error = "Cannot allocate region table";
return -ENOMEM;
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index caa51dd..9387667 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -561,7 +561,7 @@ static char **realloc_argv(unsigned *size, char **old_argv)
new_size = 8;
gfp = GFP_NOIO;
}
- argv = kmalloc(new_size * sizeof(*argv), gfp);
+ argv = kmalloc_array(new_size, sizeof(*argv), gfp);
if (argv) {
memcpy(argv, old_argv, *size * sizeof(*argv));
*size = new_size;
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 5772756..7945238d 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -240,9 +240,9 @@ struct pool {
struct dm_bio_prison *prison;
struct dm_kcopyd_client *copier;
+ struct work_struct worker;
struct workqueue_struct *wq;
struct throttle throttle;
- struct work_struct worker;
struct delayed_work waker;
struct delayed_work no_space_timeout;
@@ -260,7 +260,6 @@ struct pool {
struct dm_deferred_set *all_io_ds;
struct dm_thin_new_mapping *next_mapping;
- mempool_t mapping_pool;
process_bio_fn process_bio;
process_bio_fn process_discard;
@@ -273,6 +272,8 @@ struct pool {
process_mapping_fn process_prepared_discard_pt2;
struct dm_bio_prison_cell **cell_sort_array;
+
+ mempool_t mapping_pool;
};
static enum pool_mode get_pool_mode(struct pool *pool);
@@ -2939,7 +2940,9 @@ static struct pool *pool_create(struct mapped_device *pool_md,
goto bad_mapping_pool;
}
- pool->cell_sort_array = vmalloc(sizeof(*pool->cell_sort_array) * CELL_SORT_ARRAY_SIZE);
+ pool->cell_sort_array =
+ vmalloc(array_size(CELL_SORT_ARRAY_SIZE,
+ sizeof(*pool->cell_sort_array)));
if (!pool->cell_sort_array) {
*error = "Error allocating cell sort array";
err_p = ERR_PTR(-ENOMEM);
diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
index fc893f6..12decdbd7 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -797,8 +797,9 @@ static int verity_alloc_most_once(struct dm_verity *v)
return -E2BIG;
}
- v->validated_blocks = kvzalloc(BITS_TO_LONGS(v->data_blocks) *
- sizeof(unsigned long), GFP_KERNEL);
+ v->validated_blocks = kvcalloc(BITS_TO_LONGS(v->data_blocks),
+ sizeof(unsigned long),
+ GFP_KERNEL);
if (!v->validated_blocks) {
ti->error = "failed to allocate bitset for check_at_most_once";
return -ENOMEM;
diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
new file mode 100644
index 0000000..5961c77
--- /dev/null
+++ b/drivers/md/dm-writecache.c
@@ -0,0 +1,2305 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Red Hat. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/device-mapper.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/vmalloc.h>
+#include <linux/kthread.h>
+#include <linux/dm-io.h>
+#include <linux/dm-kcopyd.h>
+#include <linux/dax.h>
+#include <linux/pfn_t.h>
+#include <linux/libnvdimm.h>
+
+#define DM_MSG_PREFIX "writecache"
+
+#define HIGH_WATERMARK 50
+#define LOW_WATERMARK 45
+#define MAX_WRITEBACK_JOBS 0
+#define ENDIO_LATENCY 16
+#define WRITEBACK_LATENCY 64
+#define AUTOCOMMIT_BLOCKS_SSD 65536
+#define AUTOCOMMIT_BLOCKS_PMEM 64
+#define AUTOCOMMIT_MSEC 1000
+
+#define BITMAP_GRANULARITY 65536
+#if BITMAP_GRANULARITY < PAGE_SIZE
+#undef BITMAP_GRANULARITY
+#define BITMAP_GRANULARITY PAGE_SIZE
+#endif
+
+#if IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API) && IS_ENABLED(CONFIG_DAX_DRIVER)
+#define DM_WRITECACHE_HAS_PMEM
+#endif
+
+#ifdef DM_WRITECACHE_HAS_PMEM
+#define pmem_assign(dest, src) \
+do { \
+ typeof(dest) uniq = (src); \
+ memcpy_flushcache(&(dest), &uniq, sizeof(dest)); \
+} while (0)
+#else
+#define pmem_assign(dest, src) ((dest) = (src))
+#endif
+
+#if defined(__HAVE_ARCH_MEMCPY_MCSAFE) && defined(DM_WRITECACHE_HAS_PMEM)
+#define DM_WRITECACHE_HANDLE_HARDWARE_ERRORS
+#endif
+
+#define MEMORY_SUPERBLOCK_MAGIC 0x23489321
+#define MEMORY_SUPERBLOCK_VERSION 1
+
+struct wc_memory_entry {
+ __le64 original_sector;
+ __le64 seq_count;
+};
+
+struct wc_memory_superblock {
+ union {
+ struct {
+ __le32 magic;
+ __le32 version;
+ __le32 block_size;
+ __le32 pad;
+ __le64 n_blocks;
+ __le64 seq_count;
+ };
+ __le64 padding[8];
+ };
+ struct wc_memory_entry entries[0];
+};
+
+struct wc_entry {
+ struct rb_node rb_node;
+ struct list_head lru;
+ unsigned short wc_list_contiguous;
+ bool write_in_progress
+#if BITS_PER_LONG == 64
+ :1
+#endif
+ ;
+ unsigned long index
+#if BITS_PER_LONG == 64
+ :47
+#endif
+ ;
+#ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS
+ uint64_t original_sector;
+ uint64_t seq_count;
+#endif
+};
+
+#ifdef DM_WRITECACHE_HAS_PMEM
+#define WC_MODE_PMEM(wc) ((wc)->pmem_mode)
+#define WC_MODE_FUA(wc) ((wc)->writeback_fua)
+#else
+#define WC_MODE_PMEM(wc) false
+#define WC_MODE_FUA(wc) false
+#endif
+#define WC_MODE_SORT_FREELIST(wc) (!WC_MODE_PMEM(wc))
+
+struct dm_writecache {
+ struct mutex lock;
+ struct list_head lru;
+ union {
+ struct list_head freelist;
+ struct {
+ struct rb_root freetree;
+ struct wc_entry *current_free;
+ };
+ };
+ struct rb_root tree;
+
+ size_t freelist_size;
+ size_t writeback_size;
+ size_t freelist_high_watermark;
+ size_t freelist_low_watermark;
+
+ unsigned uncommitted_blocks;
+ unsigned autocommit_blocks;
+ unsigned max_writeback_jobs;
+
+ int error;
+
+ unsigned long autocommit_jiffies;
+ struct timer_list autocommit_timer;
+ struct wait_queue_head freelist_wait;
+
+ atomic_t bio_in_progress[2];
+ struct wait_queue_head bio_in_progress_wait[2];
+
+ struct dm_target *ti;
+ struct dm_dev *dev;
+ struct dm_dev *ssd_dev;
+ void *memory_map;
+ uint64_t memory_map_size;
+ size_t metadata_sectors;
+ size_t n_blocks;
+ uint64_t seq_count;
+ void *block_start;
+ struct wc_entry *entries;
+ unsigned block_size;
+ unsigned char block_size_bits;
+
+ bool pmem_mode:1;
+ bool writeback_fua:1;
+
+ bool overwrote_committed:1;
+ bool memory_vmapped:1;
+
+ bool high_wm_percent_set:1;
+ bool low_wm_percent_set:1;
+ bool max_writeback_jobs_set:1;
+ bool autocommit_blocks_set:1;
+ bool autocommit_time_set:1;
+ bool writeback_fua_set:1;
+ bool flush_on_suspend:1;
+
+ unsigned writeback_all;
+ struct workqueue_struct *writeback_wq;
+ struct work_struct writeback_work;
+ struct work_struct flush_work;
+
+ struct dm_io_client *dm_io;
+
+ raw_spinlock_t endio_list_lock;
+ struct list_head endio_list;
+ struct task_struct *endio_thread;
+
+ struct task_struct *flush_thread;
+ struct bio_list flush_list;
+
+ struct dm_kcopyd_client *dm_kcopyd;
+ unsigned long *dirty_bitmap;
+ unsigned dirty_bitmap_size;
+
+ struct bio_set bio_set;
+ mempool_t copy_pool;
+};
+
+#define WB_LIST_INLINE 16
+
+struct writeback_struct {
+ struct list_head endio_entry;
+ struct dm_writecache *wc;
+ struct wc_entry **wc_list;
+ unsigned wc_list_n;
+ unsigned page_offset;
+ struct page *page;
+ struct wc_entry *wc_list_inline[WB_LIST_INLINE];
+ struct bio bio;
+};
+
+struct copy_struct {
+ struct list_head endio_entry;
+ struct dm_writecache *wc;
+ struct wc_entry *e;
+ unsigned n_entries;
+ int error;
+};
+
+DECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(dm_writecache_throttle,
+ "A percentage of time allocated for data copying");
+
+static void wc_lock(struct dm_writecache *wc)
+{
+ mutex_lock(&wc->lock);
+}
+
+static void wc_unlock(struct dm_writecache *wc)
+{
+ mutex_unlock(&wc->lock);
+}
+
+#ifdef DM_WRITECACHE_HAS_PMEM
+static int persistent_memory_claim(struct dm_writecache *wc)
+{
+ int r;
+ loff_t s;
+ long p, da;
+ pfn_t pfn;
+ int id;
+ struct page **pages;
+
+ wc->memory_vmapped = false;
+
+ if (!wc->ssd_dev->dax_dev) {
+ r = -EOPNOTSUPP;
+ goto err1;
+ }
+ s = wc->memory_map_size;
+ p = s >> PAGE_SHIFT;
+ if (!p) {
+ r = -EINVAL;
+ goto err1;
+ }
+ if (p != s >> PAGE_SHIFT) {
+ r = -EOVERFLOW;
+ goto err1;
+ }
+
+ id = dax_read_lock();
+
+ da = dax_direct_access(wc->ssd_dev->dax_dev, 0, p, &wc->memory_map, &pfn);
+ if (da < 0) {
+ wc->memory_map = NULL;
+ r = da;
+ goto err2;
+ }
+ if (!pfn_t_has_page(pfn)) {
+ wc->memory_map = NULL;
+ r = -EOPNOTSUPP;
+ goto err2;
+ }
+ if (da != p) {
+ long i;
+ wc->memory_map = NULL;
+ pages = kvmalloc(p * sizeof(struct page *), GFP_KERNEL);
+ if (!pages) {
+ r = -ENOMEM;
+ goto err2;
+ }
+ i = 0;
+ do {
+ long daa;
+ void *dummy_addr;
+ daa = dax_direct_access(wc->ssd_dev->dax_dev, i, p - i,
+ &dummy_addr, &pfn);
+ if (daa <= 0) {
+ r = daa ? daa : -EINVAL;
+ goto err3;
+ }
+ if (!pfn_t_has_page(pfn)) {
+ r = -EOPNOTSUPP;
+ goto err3;
+ }
+ while (daa-- && i < p) {
+ pages[i++] = pfn_t_to_page(pfn);
+ pfn.val++;
+ }
+ } while (i < p);
+ wc->memory_map = vmap(pages, p, VM_MAP, PAGE_KERNEL);
+ if (!wc->memory_map) {
+ r = -ENOMEM;
+ goto err3;
+ }
+ kvfree(pages);
+ wc->memory_vmapped = true;
+ }
+
+ dax_read_unlock(id);
+ return 0;
+err3:
+ kvfree(pages);
+err2:
+ dax_read_unlock(id);
+err1:
+ return r;
+}
+#else
+static int persistent_memory_claim(struct dm_writecache *wc)
+{
+ BUG();
+}
+#endif
+
+static void persistent_memory_release(struct dm_writecache *wc)
+{
+ if (wc->memory_vmapped)
+ vunmap(wc->memory_map);
+}
+
+static struct page *persistent_memory_page(void *addr)
+{
+ if (is_vmalloc_addr(addr))
+ return vmalloc_to_page(addr);
+ else
+ return virt_to_page(addr);
+}
+
+static unsigned persistent_memory_page_offset(void *addr)
+{
+ return (unsigned long)addr & (PAGE_SIZE - 1);
+}
+
+static void persistent_memory_flush_cache(void *ptr, size_t size)
+{
+ if (is_vmalloc_addr(ptr))
+ flush_kernel_vmap_range(ptr, size);
+}
+
+static void persistent_memory_invalidate_cache(void *ptr, size_t size)
+{
+ if (is_vmalloc_addr(ptr))
+ invalidate_kernel_vmap_range(ptr, size);
+}
+
+static struct wc_memory_superblock *sb(struct dm_writecache *wc)
+{
+ return wc->memory_map;
+}
+
+static struct wc_memory_entry *memory_entry(struct dm_writecache *wc, struct wc_entry *e)
+{
+ if (is_power_of_2(sizeof(struct wc_entry)) && 0)
+ return &sb(wc)->entries[e - wc->entries];
+ else
+ return &sb(wc)->entries[e->index];
+}
+
+static void *memory_data(struct dm_writecache *wc, struct wc_entry *e)
+{
+ return (char *)wc->block_start + (e->index << wc->block_size_bits);
+}
+
+static sector_t cache_sector(struct dm_writecache *wc, struct wc_entry *e)
+{
+ return wc->metadata_sectors +
+ ((sector_t)e->index << (wc->block_size_bits - SECTOR_SHIFT));
+}
+
+static uint64_t read_original_sector(struct dm_writecache *wc, struct wc_entry *e)
+{
+#ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS
+ return e->original_sector;
+#else
+ return le64_to_cpu(memory_entry(wc, e)->original_sector);
+#endif
+}
+
+static uint64_t read_seq_count(struct dm_writecache *wc, struct wc_entry *e)
+{
+#ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS
+ return e->seq_count;
+#else
+ return le64_to_cpu(memory_entry(wc, e)->seq_count);
+#endif
+}
+
+static void clear_seq_count(struct dm_writecache *wc, struct wc_entry *e)
+{
+#ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS
+ e->seq_count = -1;
+#endif
+ pmem_assign(memory_entry(wc, e)->seq_count, cpu_to_le64(-1));
+}
+
+static void write_original_sector_seq_count(struct dm_writecache *wc, struct wc_entry *e,
+ uint64_t original_sector, uint64_t seq_count)
+{
+ struct wc_memory_entry me;
+#ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS
+ e->original_sector = original_sector;
+ e->seq_count = seq_count;
+#endif
+ me.original_sector = cpu_to_le64(original_sector);
+ me.seq_count = cpu_to_le64(seq_count);
+ pmem_assign(*memory_entry(wc, e), me);
+}
+
+#define writecache_error(wc, err, msg, arg...) \
+do { \
+ if (!cmpxchg(&(wc)->error, 0, err)) \
+ DMERR(msg, ##arg); \
+ wake_up(&(wc)->freelist_wait); \
+} while (0)
+
+#define writecache_has_error(wc) (unlikely(READ_ONCE((wc)->error)))
+
+static void writecache_flush_all_metadata(struct dm_writecache *wc)
+{
+ if (!WC_MODE_PMEM(wc))
+ memset(wc->dirty_bitmap, -1, wc->dirty_bitmap_size);
+}
+
+static void writecache_flush_region(struct dm_writecache *wc, void *ptr, size_t size)
+{
+ if (!WC_MODE_PMEM(wc))
+ __set_bit(((char *)ptr - (char *)wc->memory_map) / BITMAP_GRANULARITY,
+ wc->dirty_bitmap);
+}
+
+static void writecache_disk_flush(struct dm_writecache *wc, struct dm_dev *dev);
+
+struct io_notify {
+ struct dm_writecache *wc;
+ struct completion c;
+ atomic_t count;
+};
+
+static void writecache_notify_io(unsigned long error, void *context)
+{
+ struct io_notify *endio = context;
+
+ if (unlikely(error != 0))
+ writecache_error(endio->wc, -EIO, "error writing metadata");
+ BUG_ON(atomic_read(&endio->count) <= 0);
+ if (atomic_dec_and_test(&endio->count))
+ complete(&endio->c);
+}
+
+static void ssd_commit_flushed(struct dm_writecache *wc)
+{
+ struct dm_io_region region;
+ struct dm_io_request req;
+ struct io_notify endio = {
+ wc,
+ COMPLETION_INITIALIZER_ONSTACK(endio.c),
+ ATOMIC_INIT(1),
+ };
+ unsigned bitmap_bits = wc->dirty_bitmap_size * BITS_PER_LONG;
+ unsigned i = 0;
+
+ while (1) {
+ unsigned j;
+ i = find_next_bit(wc->dirty_bitmap, bitmap_bits, i);
+ if (unlikely(i == bitmap_bits))
+ break;
+ j = find_next_zero_bit(wc->dirty_bitmap, bitmap_bits, i);
+
+ region.bdev = wc->ssd_dev->bdev;
+ region.sector = (sector_t)i * (BITMAP_GRANULARITY >> SECTOR_SHIFT);
+ region.count = (sector_t)(j - i) * (BITMAP_GRANULARITY >> SECTOR_SHIFT);
+
+ if (unlikely(region.sector >= wc->metadata_sectors))
+ break;
+ if (unlikely(region.sector + region.count > wc->metadata_sectors))
+ region.count = wc->metadata_sectors - region.sector;
+
+ atomic_inc(&endio.count);
+ req.bi_op = REQ_OP_WRITE;
+ req.bi_op_flags = REQ_SYNC;
+ req.mem.type = DM_IO_VMA;
+ req.mem.ptr.vma = (char *)wc->memory_map + (size_t)i * BITMAP_GRANULARITY;
+ req.client = wc->dm_io;
+ req.notify.fn = writecache_notify_io;
+ req.notify.context = &endio;
+
+ /* writing via async dm-io (implied by notify.fn above) won't return an error */
+ (void) dm_io(&req, 1, &region, NULL);
+ i = j;
+ }
+
+ writecache_notify_io(0, &endio);
+ wait_for_completion_io(&endio.c);
+
+ writecache_disk_flush(wc, wc->ssd_dev);
+
+ memset(wc->dirty_bitmap, 0, wc->dirty_bitmap_size);
+}
+
+static void writecache_commit_flushed(struct dm_writecache *wc)
+{
+ if (WC_MODE_PMEM(wc))
+ wmb();
+ else
+ ssd_commit_flushed(wc);
+}
+
+static void writecache_disk_flush(struct dm_writecache *wc, struct dm_dev *dev)
+{
+ int r;
+ struct dm_io_region region;
+ struct dm_io_request req;
+
+ region.bdev = dev->bdev;
+ region.sector = 0;
+ region.count = 0;
+ req.bi_op = REQ_OP_WRITE;
+ req.bi_op_flags = REQ_PREFLUSH;
+ req.mem.type = DM_IO_KMEM;
+ req.mem.ptr.addr = NULL;
+ req.client = wc->dm_io;
+ req.notify.fn = NULL;
+
+ r = dm_io(&req, 1, &region, NULL);
+ if (unlikely(r))
+ writecache_error(wc, r, "error flushing metadata: %d", r);
+}
+
+static void writecache_wait_for_ios(struct dm_writecache *wc, int direction)
+{
+ wait_event(wc->bio_in_progress_wait[direction],
+ !atomic_read(&wc->bio_in_progress[direction]));
+}
+
+#define WFE_RETURN_FOLLOWING 1
+#define WFE_LOWEST_SEQ 2
+
+static struct wc_entry *writecache_find_entry(struct dm_writecache *wc,
+ uint64_t block, int flags)
+{
+ struct wc_entry *e;
+ struct rb_node *node = wc->tree.rb_node;
+
+ if (unlikely(!node))
+ return NULL;
+
+ while (1) {
+ e = container_of(node, struct wc_entry, rb_node);
+ if (read_original_sector(wc, e) == block)
+ break;
+ node = (read_original_sector(wc, e) >= block ?
+ e->rb_node.rb_left : e->rb_node.rb_right);
+ if (unlikely(!node)) {
+ if (!(flags & WFE_RETURN_FOLLOWING)) {
+ return NULL;
+ }
+ if (read_original_sector(wc, e) >= block) {
+ break;
+ } else {
+ node = rb_next(&e->rb_node);
+ if (unlikely(!node)) {
+ return NULL;
+ }
+ e = container_of(node, struct wc_entry, rb_node);
+ break;
+ }
+ }
+ }
+
+ while (1) {
+ struct wc_entry *e2;
+ if (flags & WFE_LOWEST_SEQ)
+ node = rb_prev(&e->rb_node);
+ else
+ node = rb_next(&e->rb_node);
+ if (!node)
+ return e;
+ e2 = container_of(node, struct wc_entry, rb_node);
+ if (read_original_sector(wc, e2) != block)
+ return e;
+ e = e2;
+ }
+}
+
+static void writecache_insert_entry(struct dm_writecache *wc, struct wc_entry *ins)
+{
+ struct wc_entry *e;
+ struct rb_node **node = &wc->tree.rb_node, *parent = NULL;
+
+ while (*node) {
+ e = container_of(*node, struct wc_entry, rb_node);
+ parent = &e->rb_node;
+ if (read_original_sector(wc, e) > read_original_sector(wc, ins))
+ node = &parent->rb_left;
+ else
+ node = &parent->rb_right;
+ }
+ rb_link_node(&ins->rb_node, parent, node);
+ rb_insert_color(&ins->rb_node, &wc->tree);
+ list_add(&ins->lru, &wc->lru);
+}
+
+static void writecache_unlink(struct dm_writecache *wc, struct wc_entry *e)
+{
+ list_del(&e->lru);
+ rb_erase(&e->rb_node, &wc->tree);
+}
+
+static void writecache_add_to_freelist(struct dm_writecache *wc, struct wc_entry *e)
+{
+ if (WC_MODE_SORT_FREELIST(wc)) {
+ struct rb_node **node = &wc->freetree.rb_node, *parent = NULL;
+ if (unlikely(!*node))
+ wc->current_free = e;
+ while (*node) {
+ parent = *node;
+ if (&e->rb_node < *node)
+ node = &parent->rb_left;
+ else
+ node = &parent->rb_right;
+ }
+ rb_link_node(&e->rb_node, parent, node);
+ rb_insert_color(&e->rb_node, &wc->freetree);
+ } else {
+ list_add_tail(&e->lru, &wc->freelist);
+ }
+ wc->freelist_size++;
+}
+
+static struct wc_entry *writecache_pop_from_freelist(struct dm_writecache *wc)
+{
+ struct wc_entry *e;
+
+ if (WC_MODE_SORT_FREELIST(wc)) {
+ struct rb_node *next;
+ if (unlikely(!wc->current_free))
+ return NULL;
+ e = wc->current_free;
+ next = rb_next(&e->rb_node);
+ rb_erase(&e->rb_node, &wc->freetree);
+ if (unlikely(!next))
+ next = rb_first(&wc->freetree);
+ wc->current_free = next ? container_of(next, struct wc_entry, rb_node) : NULL;
+ } else {
+ if (unlikely(list_empty(&wc->freelist)))
+ return NULL;
+ e = container_of(wc->freelist.next, struct wc_entry, lru);
+ list_del(&e->lru);
+ }
+ wc->freelist_size--;
+ if (unlikely(wc->freelist_size + wc->writeback_size <= wc->freelist_high_watermark))
+ queue_work(wc->writeback_wq, &wc->writeback_work);
+
+ return e;
+}
+
+static void writecache_free_entry(struct dm_writecache *wc, struct wc_entry *e)
+{
+ writecache_unlink(wc, e);
+ writecache_add_to_freelist(wc, e);
+ clear_seq_count(wc, e);
+ writecache_flush_region(wc, memory_entry(wc, e), sizeof(struct wc_memory_entry));
+ if (unlikely(waitqueue_active(&wc->freelist_wait)))
+ wake_up(&wc->freelist_wait);
+}
+
+static void writecache_wait_on_freelist(struct dm_writecache *wc)
+{
+ DEFINE_WAIT(wait);
+
+ prepare_to_wait(&wc->freelist_wait, &wait, TASK_UNINTERRUPTIBLE);
+ wc_unlock(wc);
+ io_schedule();
+ finish_wait(&wc->freelist_wait, &wait);
+ wc_lock(wc);
+}
+
+static void writecache_poison_lists(struct dm_writecache *wc)
+{
+ /*
+ * Catch incorrect access to these values while the device is suspended.
+ */
+ memset(&wc->tree, -1, sizeof wc->tree);
+ wc->lru.next = LIST_POISON1;
+ wc->lru.prev = LIST_POISON2;
+ wc->freelist.next = LIST_POISON1;
+ wc->freelist.prev = LIST_POISON2;
+}
+
+static void writecache_flush_entry(struct dm_writecache *wc, struct wc_entry *e)
+{
+ writecache_flush_region(wc, memory_entry(wc, e), sizeof(struct wc_memory_entry));
+ if (WC_MODE_PMEM(wc))
+ writecache_flush_region(wc, memory_data(wc, e), wc->block_size);
+}
+
+static bool writecache_entry_is_committed(struct dm_writecache *wc, struct wc_entry *e)
+{
+ return read_seq_count(wc, e) < wc->seq_count;
+}
+
+static void writecache_flush(struct dm_writecache *wc)
+{
+ struct wc_entry *e, *e2;
+ bool need_flush_after_free;
+
+ wc->uncommitted_blocks = 0;
+ del_timer(&wc->autocommit_timer);
+
+ if (list_empty(&wc->lru))
+ return;
+
+ e = container_of(wc->lru.next, struct wc_entry, lru);
+ if (writecache_entry_is_committed(wc, e)) {
+ if (wc->overwrote_committed) {
+ writecache_wait_for_ios(wc, WRITE);
+ writecache_disk_flush(wc, wc->ssd_dev);
+ wc->overwrote_committed = false;
+ }
+ return;
+ }
+ while (1) {
+ writecache_flush_entry(wc, e);
+ if (unlikely(e->lru.next == &wc->lru))
+ break;
+ e2 = container_of(e->lru.next, struct wc_entry, lru);
+ if (writecache_entry_is_committed(wc, e2))
+ break;
+ e = e2;
+ cond_resched();
+ }
+ writecache_commit_flushed(wc);
+
+ writecache_wait_for_ios(wc, WRITE);
+
+ wc->seq_count++;
+ pmem_assign(sb(wc)->seq_count, cpu_to_le64(wc->seq_count));
+ writecache_flush_region(wc, &sb(wc)->seq_count, sizeof sb(wc)->seq_count);
+ writecache_commit_flushed(wc);
+
+ wc->overwrote_committed = false;
+
+ need_flush_after_free = false;
+ while (1) {
+ /* Free another committed entry with lower seq-count */
+ struct rb_node *rb_node = rb_prev(&e->rb_node);
+
+ if (rb_node) {
+ e2 = container_of(rb_node, struct wc_entry, rb_node);
+ if (read_original_sector(wc, e2) == read_original_sector(wc, e) &&
+ likely(!e2->write_in_progress)) {
+ writecache_free_entry(wc, e2);
+ need_flush_after_free = true;
+ }
+ }
+ if (unlikely(e->lru.prev == &wc->lru))
+ break;
+ e = container_of(e->lru.prev, struct wc_entry, lru);
+ cond_resched();
+ }
+
+ if (need_flush_after_free)
+ writecache_commit_flushed(wc);
+}
+
+static void writecache_flush_work(struct work_struct *work)
+{
+ struct dm_writecache *wc = container_of(work, struct dm_writecache, flush_work);
+
+ wc_lock(wc);
+ writecache_flush(wc);
+ wc_unlock(wc);
+}
+
+static void writecache_autocommit_timer(struct timer_list *t)
+{
+ struct dm_writecache *wc = from_timer(wc, t, autocommit_timer);
+ if (!writecache_has_error(wc))
+ queue_work(wc->writeback_wq, &wc->flush_work);
+}
+
+static void writecache_schedule_autocommit(struct dm_writecache *wc)
+{
+ if (!timer_pending(&wc->autocommit_timer))
+ mod_timer(&wc->autocommit_timer, jiffies + wc->autocommit_jiffies);
+}
+
+static void writecache_discard(struct dm_writecache *wc, sector_t start, sector_t end)
+{
+ struct wc_entry *e;
+ bool discarded_something = false;
+
+ e = writecache_find_entry(wc, start, WFE_RETURN_FOLLOWING | WFE_LOWEST_SEQ);
+ if (unlikely(!e))
+ return;
+
+ while (read_original_sector(wc, e) < end) {
+ struct rb_node *node = rb_next(&e->rb_node);
+
+ if (likely(!e->write_in_progress)) {
+ if (!discarded_something) {
+ writecache_wait_for_ios(wc, READ);
+ writecache_wait_for_ios(wc, WRITE);
+ discarded_something = true;
+ }
+ writecache_free_entry(wc, e);
+ }
+
+ if (!node)
+ break;
+
+ e = container_of(node, struct wc_entry, rb_node);
+ }
+
+ if (discarded_something)
+ writecache_commit_flushed(wc);
+}
+
+static bool writecache_wait_for_writeback(struct dm_writecache *wc)
+{
+ if (wc->writeback_size) {
+ writecache_wait_on_freelist(wc);
+ return true;
+ }
+ return false;
+}
+
+static void writecache_suspend(struct dm_target *ti)
+{
+ struct dm_writecache *wc = ti->private;
+ bool flush_on_suspend;
+
+ del_timer_sync(&wc->autocommit_timer);
+
+ wc_lock(wc);
+ writecache_flush(wc);
+ flush_on_suspend = wc->flush_on_suspend;
+ if (flush_on_suspend) {
+ wc->flush_on_suspend = false;
+ wc->writeback_all++;
+ queue_work(wc->writeback_wq, &wc->writeback_work);
+ }
+ wc_unlock(wc);
+
+ flush_workqueue(wc->writeback_wq);
+
+ wc_lock(wc);
+ if (flush_on_suspend)
+ wc->writeback_all--;
+ while (writecache_wait_for_writeback(wc));
+
+ if (WC_MODE_PMEM(wc))
+ persistent_memory_flush_cache(wc->memory_map, wc->memory_map_size);
+
+ writecache_poison_lists(wc);
+
+ wc_unlock(wc);
+}
+
+static int writecache_alloc_entries(struct dm_writecache *wc)
+{
+ size_t b;
+
+ if (wc->entries)
+ return 0;
+ wc->entries = vmalloc(sizeof(struct wc_entry) * wc->n_blocks);
+ if (!wc->entries)
+ return -ENOMEM;
+ for (b = 0; b < wc->n_blocks; b++) {
+ struct wc_entry *e = &wc->entries[b];
+ e->index = b;
+ e->write_in_progress = false;
+ }
+
+ return 0;
+}
+
+static void writecache_resume(struct dm_target *ti)
+{
+ struct dm_writecache *wc = ti->private;
+ size_t b;
+ bool need_flush = false;
+ __le64 sb_seq_count;
+ int r;
+
+ wc_lock(wc);
+
+ if (WC_MODE_PMEM(wc))
+ persistent_memory_invalidate_cache(wc->memory_map, wc->memory_map_size);
+
+ wc->tree = RB_ROOT;
+ INIT_LIST_HEAD(&wc->lru);
+ if (WC_MODE_SORT_FREELIST(wc)) {
+ wc->freetree = RB_ROOT;
+ wc->current_free = NULL;
+ } else {
+ INIT_LIST_HEAD(&wc->freelist);
+ }
+ wc->freelist_size = 0;
+
+ r = memcpy_mcsafe(&sb_seq_count, &sb(wc)->seq_count, sizeof(uint64_t));
+ if (r) {
+ writecache_error(wc, r, "hardware memory error when reading superblock: %d", r);
+ sb_seq_count = cpu_to_le64(0);
+ }
+ wc->seq_count = le64_to_cpu(sb_seq_count);
+
+#ifdef DM_WRITECACHE_HANDLE_HARDWARE_ERRORS
+ for (b = 0; b < wc->n_blocks; b++) {
+ struct wc_entry *e = &wc->entries[b];
+ struct wc_memory_entry wme;
+ if (writecache_has_error(wc)) {
+ e->original_sector = -1;
+ e->seq_count = -1;
+ continue;
+ }
+ r = memcpy_mcsafe(&wme, memory_entry(wc, e), sizeof(struct wc_memory_entry));
+ if (r) {
+ writecache_error(wc, r, "hardware memory error when reading metadata entry %lu: %d",
+ (unsigned long)b, r);
+ e->original_sector = -1;
+ e->seq_count = -1;
+ } else {
+ e->original_sector = le64_to_cpu(wme.original_sector);
+ e->seq_count = le64_to_cpu(wme.seq_count);
+ }
+ }
+#endif
+ for (b = 0; b < wc->n_blocks; b++) {
+ struct wc_entry *e = &wc->entries[b];
+ if (!writecache_entry_is_committed(wc, e)) {
+ if (read_seq_count(wc, e) != -1) {
+erase_this:
+ clear_seq_count(wc, e);
+ need_flush = true;
+ }
+ writecache_add_to_freelist(wc, e);
+ } else {
+ struct wc_entry *old;
+
+ old = writecache_find_entry(wc, read_original_sector(wc, e), 0);
+ if (!old) {
+ writecache_insert_entry(wc, e);
+ } else {
+ if (read_seq_count(wc, old) == read_seq_count(wc, e)) {
+ writecache_error(wc, -EINVAL,
+ "two identical entries, position %llu, sector %llu, sequence %llu",
+ (unsigned long long)b, (unsigned long long)read_original_sector(wc, e),
+ (unsigned long long)read_seq_count(wc, e));
+ }
+ if (read_seq_count(wc, old) > read_seq_count(wc, e)) {
+ goto erase_this;
+ } else {
+ writecache_free_entry(wc, old);
+ writecache_insert_entry(wc, e);
+ need_flush = true;
+ }
+ }
+ }
+ cond_resched();
+ }
+
+ if (need_flush) {
+ writecache_flush_all_metadata(wc);
+ writecache_commit_flushed(wc);
+ }
+
+ wc_unlock(wc);
+}
+
+static int process_flush_mesg(unsigned argc, char **argv, struct dm_writecache *wc)
+{
+ if (argc != 1)
+ return -EINVAL;
+
+ wc_lock(wc);
+ if (dm_suspended(wc->ti)) {
+ wc_unlock(wc);
+ return -EBUSY;
+ }
+ if (writecache_has_error(wc)) {
+ wc_unlock(wc);
+ return -EIO;
+ }
+
+ writecache_flush(wc);
+ wc->writeback_all++;
+ queue_work(wc->writeback_wq, &wc->writeback_work);
+ wc_unlock(wc);
+
+ flush_workqueue(wc->writeback_wq);
+
+ wc_lock(wc);
+ wc->writeback_all--;
+ if (writecache_has_error(wc)) {
+ wc_unlock(wc);
+ return -EIO;
+ }
+ wc_unlock(wc);
+
+ return 0;
+}
+
+static int process_flush_on_suspend_mesg(unsigned argc, char **argv, struct dm_writecache *wc)
+{
+ if (argc != 1)
+ return -EINVAL;
+
+ wc_lock(wc);
+ wc->flush_on_suspend = true;
+ wc_unlock(wc);
+
+ return 0;
+}
+
+static int writecache_message(struct dm_target *ti, unsigned argc, char **argv,
+ char *result, unsigned maxlen)
+{
+ int r = -EINVAL;
+ struct dm_writecache *wc = ti->private;
+
+ if (!strcasecmp(argv[0], "flush"))
+ r = process_flush_mesg(argc, argv, wc);
+ else if (!strcasecmp(argv[0], "flush_on_suspend"))
+ r = process_flush_on_suspend_mesg(argc, argv, wc);
+ else
+ DMERR("unrecognised message received: %s", argv[0]);
+
+ return r;
+}
+
+static void bio_copy_block(struct dm_writecache *wc, struct bio *bio, void *data)
+{
+ void *buf;
+ unsigned long flags;
+ unsigned size;
+ int rw = bio_data_dir(bio);
+ unsigned remaining_size = wc->block_size;
+
+ do {
+ struct bio_vec bv = bio_iter_iovec(bio, bio->bi_iter);
+ buf = bvec_kmap_irq(&bv, &flags);
+ size = bv.bv_len;
+ if (unlikely(size > remaining_size))
+ size = remaining_size;
+
+ if (rw == READ) {
+ int r;
+ r = memcpy_mcsafe(buf, data, size);
+ flush_dcache_page(bio_page(bio));
+ if (unlikely(r)) {
+ writecache_error(wc, r, "hardware memory error when reading data: %d", r);
+ bio->bi_status = BLK_STS_IOERR;
+ }
+ } else {
+ flush_dcache_page(bio_page(bio));
+ memcpy_flushcache(data, buf, size);
+ }
+
+ bvec_kunmap_irq(buf, &flags);
+
+ data = (char *)data + size;
+ remaining_size -= size;
+ bio_advance(bio, size);
+ } while (unlikely(remaining_size));
+}
+
+static int writecache_flush_thread(void *data)
+{
+ struct dm_writecache *wc = data;
+
+ while (1) {
+ struct bio *bio;
+
+ wc_lock(wc);
+ bio = bio_list_pop(&wc->flush_list);
+ if (!bio) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ wc_unlock(wc);
+
+ if (unlikely(kthread_should_stop())) {
+ set_current_state(TASK_RUNNING);
+ break;
+ }
+
+ schedule();
+ continue;
+ }
+
+ if (bio_op(bio) == REQ_OP_DISCARD) {
+ writecache_discard(wc, bio->bi_iter.bi_sector,
+ bio_end_sector(bio));
+ wc_unlock(wc);
+ bio_set_dev(bio, wc->dev->bdev);
+ generic_make_request(bio);
+ } else {
+ writecache_flush(wc);
+ wc_unlock(wc);
+ if (writecache_has_error(wc))
+ bio->bi_status = BLK_STS_IOERR;
+ bio_endio(bio);
+ }
+ }
+
+ return 0;
+}
+
+static void writecache_offload_bio(struct dm_writecache *wc, struct bio *bio)
+{
+ if (bio_list_empty(&wc->flush_list))
+ wake_up_process(wc->flush_thread);
+ bio_list_add(&wc->flush_list, bio);
+}
+
+static int writecache_map(struct dm_target *ti, struct bio *bio)
+{
+ struct wc_entry *e;
+ struct dm_writecache *wc = ti->private;
+
+ bio->bi_private = NULL;
+
+ wc_lock(wc);
+
+ if (unlikely(bio->bi_opf & REQ_PREFLUSH)) {
+ if (writecache_has_error(wc))
+ goto unlock_error;
+ if (WC_MODE_PMEM(wc)) {
+ writecache_flush(wc);
+ if (writecache_has_error(wc))
+ goto unlock_error;
+ goto unlock_submit;
+ } else {
+ writecache_offload_bio(wc, bio);
+ goto unlock_return;
+ }
+ }
+
+ bio->bi_iter.bi_sector = dm_target_offset(ti, bio->bi_iter.bi_sector);
+
+ if (unlikely((((unsigned)bio->bi_iter.bi_sector | bio_sectors(bio)) &
+ (wc->block_size / 512 - 1)) != 0)) {
+ DMERR("I/O is not aligned, sector %llu, size %u, block size %u",
+ (unsigned long long)bio->bi_iter.bi_sector,
+ bio->bi_iter.bi_size, wc->block_size);
+ goto unlock_error;
+ }
+
+ if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) {
+ if (writecache_has_error(wc))
+ goto unlock_error;
+ if (WC_MODE_PMEM(wc)) {
+ writecache_discard(wc, bio->bi_iter.bi_sector, bio_end_sector(bio));
+ goto unlock_remap_origin;
+ } else {
+ writecache_offload_bio(wc, bio);
+ goto unlock_return;
+ }
+ }
+
+ if (bio_data_dir(bio) == READ) {
+read_next_block:
+ e = writecache_find_entry(wc, bio->bi_iter.bi_sector, WFE_RETURN_FOLLOWING);
+ if (e && read_original_sector(wc, e) == bio->bi_iter.bi_sector) {
+ if (WC_MODE_PMEM(wc)) {
+ bio_copy_block(wc, bio, memory_data(wc, e));
+ if (bio->bi_iter.bi_size)
+ goto read_next_block;
+ goto unlock_submit;
+ } else {
+ dm_accept_partial_bio(bio, wc->block_size >> SECTOR_SHIFT);
+ bio_set_dev(bio, wc->ssd_dev->bdev);
+ bio->bi_iter.bi_sector = cache_sector(wc, e);
+ if (!writecache_entry_is_committed(wc, e))
+ writecache_wait_for_ios(wc, WRITE);
+ goto unlock_remap;
+ }
+ } else {
+ if (e) {
+ sector_t next_boundary =
+ read_original_sector(wc, e) - bio->bi_iter.bi_sector;
+ if (next_boundary < bio->bi_iter.bi_size >> SECTOR_SHIFT) {
+ dm_accept_partial_bio(bio, next_boundary);
+ }
+ }
+ goto unlock_remap_origin;
+ }
+ } else {
+ do {
+ if (writecache_has_error(wc))
+ goto unlock_error;
+ e = writecache_find_entry(wc, bio->bi_iter.bi_sector, 0);
+ if (e) {
+ if (!writecache_entry_is_committed(wc, e))
+ goto bio_copy;
+ if (!WC_MODE_PMEM(wc) && !e->write_in_progress) {
+ wc->overwrote_committed = true;
+ goto bio_copy;
+ }
+ }
+ e = writecache_pop_from_freelist(wc);
+ if (unlikely(!e)) {
+ writecache_wait_on_freelist(wc);
+ continue;
+ }
+ write_original_sector_seq_count(wc, e, bio->bi_iter.bi_sector, wc->seq_count);
+ writecache_insert_entry(wc, e);
+ wc->uncommitted_blocks++;
+bio_copy:
+ if (WC_MODE_PMEM(wc)) {
+ bio_copy_block(wc, bio, memory_data(wc, e));
+ } else {
+ dm_accept_partial_bio(bio, wc->block_size >> SECTOR_SHIFT);
+ bio_set_dev(bio, wc->ssd_dev->bdev);
+ bio->bi_iter.bi_sector = cache_sector(wc, e);
+ if (unlikely(wc->uncommitted_blocks >= wc->autocommit_blocks)) {
+ wc->uncommitted_blocks = 0;
+ queue_work(wc->writeback_wq, &wc->flush_work);
+ } else {
+ writecache_schedule_autocommit(wc);
+ }
+ goto unlock_remap;
+ }
+ } while (bio->bi_iter.bi_size);
+
+ if (unlikely(wc->uncommitted_blocks >= wc->autocommit_blocks))
+ writecache_flush(wc);
+ else
+ writecache_schedule_autocommit(wc);
+ goto unlock_submit;
+ }
+
+unlock_remap_origin:
+ bio_set_dev(bio, wc->dev->bdev);
+ wc_unlock(wc);
+ return DM_MAPIO_REMAPPED;
+
+unlock_remap:
+ /* make sure that writecache_end_io decrements bio_in_progress: */
+ bio->bi_private = (void *)1;
+ atomic_inc(&wc->bio_in_progress[bio_data_dir(bio)]);
+ wc_unlock(wc);
+ return DM_MAPIO_REMAPPED;
+
+unlock_submit:
+ wc_unlock(wc);
+ bio_endio(bio);
+ return DM_MAPIO_SUBMITTED;
+
+unlock_return:
+ wc_unlock(wc);
+ return DM_MAPIO_SUBMITTED;
+
+unlock_error:
+ wc_unlock(wc);
+ bio_io_error(bio);
+ return DM_MAPIO_SUBMITTED;
+}
+
+static int writecache_end_io(struct dm_target *ti, struct bio *bio, blk_status_t *status)
+{
+ struct dm_writecache *wc = ti->private;
+
+ if (bio->bi_private != NULL) {
+ int dir = bio_data_dir(bio);
+ if (atomic_dec_and_test(&wc->bio_in_progress[dir]))
+ if (unlikely(waitqueue_active(&wc->bio_in_progress_wait[dir])))
+ wake_up(&wc->bio_in_progress_wait[dir]);
+ }
+ return 0;
+}
+
+static int writecache_iterate_devices(struct dm_target *ti,
+ iterate_devices_callout_fn fn, void *data)
+{
+ struct dm_writecache *wc = ti->private;
+
+ return fn(ti, wc->dev, 0, ti->len, data);
+}
+
+static void writecache_io_hints(struct dm_target *ti, struct queue_limits *limits)
+{
+ struct dm_writecache *wc = ti->private;
+
+ if (limits->logical_block_size < wc->block_size)
+ limits->logical_block_size = wc->block_size;
+
+ if (limits->physical_block_size < wc->block_size)
+ limits->physical_block_size = wc->block_size;
+
+ if (limits->io_min < wc->block_size)
+ limits->io_min = wc->block_size;
+}
+
+
+static void writecache_writeback_endio(struct bio *bio)
+{
+ struct writeback_struct *wb = container_of(bio, struct writeback_struct, bio);
+ struct dm_writecache *wc = wb->wc;
+ unsigned long flags;
+
+ raw_spin_lock_irqsave(&wc->endio_list_lock, flags);
+ if (unlikely(list_empty(&wc->endio_list)))
+ wake_up_process(wc->endio_thread);
+ list_add_tail(&wb->endio_entry, &wc->endio_list);
+ raw_spin_unlock_irqrestore(&wc->endio_list_lock, flags);
+}
+
+static void writecache_copy_endio(int read_err, unsigned long write_err, void *ptr)
+{
+ struct copy_struct *c = ptr;
+ struct dm_writecache *wc = c->wc;
+
+ c->error = likely(!(read_err | write_err)) ? 0 : -EIO;
+
+ raw_spin_lock_irq(&wc->endio_list_lock);
+ if (unlikely(list_empty(&wc->endio_list)))
+ wake_up_process(wc->endio_thread);
+ list_add_tail(&c->endio_entry, &wc->endio_list);
+ raw_spin_unlock_irq(&wc->endio_list_lock);
+}
+
+static void __writecache_endio_pmem(struct dm_writecache *wc, struct list_head *list)
+{
+ unsigned i;
+ struct writeback_struct *wb;
+ struct wc_entry *e;
+ unsigned long n_walked = 0;
+
+ do {
+ wb = list_entry(list->next, struct writeback_struct, endio_entry);
+ list_del(&wb->endio_entry);
+
+ if (unlikely(wb->bio.bi_status != BLK_STS_OK))
+ writecache_error(wc, blk_status_to_errno(wb->bio.bi_status),
+ "write error %d", wb->bio.bi_status);
+ i = 0;
+ do {
+ e = wb->wc_list[i];
+ BUG_ON(!e->write_in_progress);
+ e->write_in_progress = false;
+ INIT_LIST_HEAD(&e->lru);
+ if (!writecache_has_error(wc))
+ writecache_free_entry(wc, e);
+ BUG_ON(!wc->writeback_size);
+ wc->writeback_size--;
+ n_walked++;
+ if (unlikely(n_walked >= ENDIO_LATENCY)) {
+ writecache_commit_flushed(wc);
+ wc_unlock(wc);
+ wc_lock(wc);
+ n_walked = 0;
+ }
+ } while (++i < wb->wc_list_n);
+
+ if (wb->wc_list != wb->wc_list_inline)
+ kfree(wb->wc_list);
+ bio_put(&wb->bio);
+ } while (!list_empty(list));
+}
+
+static void __writecache_endio_ssd(struct dm_writecache *wc, struct list_head *list)
+{
+ struct copy_struct *c;
+ struct wc_entry *e;
+
+ do {
+ c = list_entry(list->next, struct copy_struct, endio_entry);
+ list_del(&c->endio_entry);
+
+ if (unlikely(c->error))
+ writecache_error(wc, c->error, "copy error");
+
+ e = c->e;
+ do {
+ BUG_ON(!e->write_in_progress);
+ e->write_in_progress = false;
+ INIT_LIST_HEAD(&e->lru);
+ if (!writecache_has_error(wc))
+ writecache_free_entry(wc, e);
+
+ BUG_ON(!wc->writeback_size);
+ wc->writeback_size--;
+ e++;
+ } while (--c->n_entries);
+ mempool_free(c, &wc->copy_pool);
+ } while (!list_empty(list));
+}
+
+static int writecache_endio_thread(void *data)
+{
+ struct dm_writecache *wc = data;
+
+ while (1) {
+ struct list_head list;
+
+ raw_spin_lock_irq(&wc->endio_list_lock);
+ if (!list_empty(&wc->endio_list))
+ goto pop_from_list;
+ set_current_state(TASK_INTERRUPTIBLE);
+ raw_spin_unlock_irq(&wc->endio_list_lock);
+
+ if (unlikely(kthread_should_stop())) {
+ set_current_state(TASK_RUNNING);
+ break;
+ }
+
+ schedule();
+
+ continue;
+
+pop_from_list:
+ list = wc->endio_list;
+ list.next->prev = list.prev->next = &list;
+ INIT_LIST_HEAD(&wc->endio_list);
+ raw_spin_unlock_irq(&wc->endio_list_lock);
+
+ if (!WC_MODE_FUA(wc))
+ writecache_disk_flush(wc, wc->dev);
+
+ wc_lock(wc);
+
+ if (WC_MODE_PMEM(wc)) {
+ __writecache_endio_pmem(wc, &list);
+ } else {
+ __writecache_endio_ssd(wc, &list);
+ writecache_wait_for_ios(wc, READ);
+ }
+
+ writecache_commit_flushed(wc);
+
+ wc_unlock(wc);
+ }
+
+ return 0;
+}
+
+static bool wc_add_block(struct writeback_struct *wb, struct wc_entry *e, gfp_t gfp)
+{
+ struct dm_writecache *wc = wb->wc;
+ unsigned block_size = wc->block_size;
+ void *address = memory_data(wc, e);
+
+ persistent_memory_flush_cache(address, block_size);
+ return bio_add_page(&wb->bio, persistent_memory_page(address),
+ block_size, persistent_memory_page_offset(address)) != 0;
+}
+
+struct writeback_list {
+ struct list_head list;
+ size_t size;
+};
+
+static void __writeback_throttle(struct dm_writecache *wc, struct writeback_list *wbl)
+{
+ if (unlikely(wc->max_writeback_jobs)) {
+ if (READ_ONCE(wc->writeback_size) - wbl->size >= wc->max_writeback_jobs) {
+ wc_lock(wc);
+ while (wc->writeback_size - wbl->size >= wc->max_writeback_jobs)
+ writecache_wait_on_freelist(wc);
+ wc_unlock(wc);
+ }
+ }
+ cond_resched();
+}
+
+static void __writecache_writeback_pmem(struct dm_writecache *wc, struct writeback_list *wbl)
+{
+ struct wc_entry *e, *f;
+ struct bio *bio;
+ struct writeback_struct *wb;
+ unsigned max_pages;
+
+ while (wbl->size) {
+ wbl->size--;
+ e = container_of(wbl->list.prev, struct wc_entry, lru);
+ list_del(&e->lru);
+
+ max_pages = e->wc_list_contiguous;
+
+ bio = bio_alloc_bioset(GFP_NOIO, max_pages, &wc->bio_set);
+ wb = container_of(bio, struct writeback_struct, bio);
+ wb->wc = wc;
+ wb->bio.bi_end_io = writecache_writeback_endio;
+ bio_set_dev(&wb->bio, wc->dev->bdev);
+ wb->bio.bi_iter.bi_sector = read_original_sector(wc, e);
+ wb->page_offset = PAGE_SIZE;
+ if (max_pages <= WB_LIST_INLINE ||
+ unlikely(!(wb->wc_list = kmalloc(max_pages * sizeof(struct wc_entry *),
+ GFP_NOIO | __GFP_NORETRY |
+ __GFP_NOMEMALLOC | __GFP_NOWARN)))) {
+ wb->wc_list = wb->wc_list_inline;
+ max_pages = WB_LIST_INLINE;
+ }
+
+ BUG_ON(!wc_add_block(wb, e, GFP_NOIO));
+
+ wb->wc_list[0] = e;
+ wb->wc_list_n = 1;
+
+ while (wbl->size && wb->wc_list_n < max_pages) {
+ f = container_of(wbl->list.prev, struct wc_entry, lru);
+ if (read_original_sector(wc, f) !=
+ read_original_sector(wc, e) + (wc->block_size >> SECTOR_SHIFT))
+ break;
+ if (!wc_add_block(wb, f, GFP_NOWAIT | __GFP_NOWARN))
+ break;
+ wbl->size--;
+ list_del(&f->lru);
+ wb->wc_list[wb->wc_list_n++] = f;
+ e = f;
+ }
+ bio_set_op_attrs(&wb->bio, REQ_OP_WRITE, WC_MODE_FUA(wc) * REQ_FUA);
+ if (writecache_has_error(wc)) {
+ bio->bi_status = BLK_STS_IOERR;
+ bio_endio(&wb->bio);
+ } else {
+ submit_bio(&wb->bio);
+ }
+
+ __writeback_throttle(wc, wbl);
+ }
+}
+
+static void __writecache_writeback_ssd(struct dm_writecache *wc, struct writeback_list *wbl)
+{
+ struct wc_entry *e, *f;
+ struct dm_io_region from, to;
+ struct copy_struct *c;
+
+ while (wbl->size) {
+ unsigned n_sectors;
+
+ wbl->size--;
+ e = container_of(wbl->list.prev, struct wc_entry, lru);
+ list_del(&e->lru);
+
+ n_sectors = e->wc_list_contiguous << (wc->block_size_bits - SECTOR_SHIFT);
+
+ from.bdev = wc->ssd_dev->bdev;
+ from.sector = cache_sector(wc, e);
+ from.count = n_sectors;
+ to.bdev = wc->dev->bdev;
+ to.sector = read_original_sector(wc, e);
+ to.count = n_sectors;
+
+ c = mempool_alloc(&wc->copy_pool, GFP_NOIO);
+ c->wc = wc;
+ c->e = e;
+ c->n_entries = e->wc_list_contiguous;
+
+ while ((n_sectors -= wc->block_size >> SECTOR_SHIFT)) {
+ wbl->size--;
+ f = container_of(wbl->list.prev, struct wc_entry, lru);
+ BUG_ON(f != e + 1);
+ list_del(&f->lru);
+ e = f;
+ }
+
+ dm_kcopyd_copy(wc->dm_kcopyd, &from, 1, &to, 0, writecache_copy_endio, c);
+
+ __writeback_throttle(wc, wbl);
+ }
+}
+
+static void writecache_writeback(struct work_struct *work)
+{
+ struct dm_writecache *wc = container_of(work, struct dm_writecache, writeback_work);
+ struct blk_plug plug;
+ struct wc_entry *e, *f, *g;
+ struct rb_node *node, *next_node;
+ struct list_head skipped;
+ struct writeback_list wbl;
+ unsigned long n_walked;
+
+ wc_lock(wc);
+restart:
+ if (writecache_has_error(wc)) {
+ wc_unlock(wc);
+ return;
+ }
+
+ if (unlikely(wc->writeback_all)) {
+ if (writecache_wait_for_writeback(wc))
+ goto restart;
+ }
+
+ if (wc->overwrote_committed) {
+ writecache_wait_for_ios(wc, WRITE);
+ }
+
+ n_walked = 0;
+ INIT_LIST_HEAD(&skipped);
+ INIT_LIST_HEAD(&wbl.list);
+ wbl.size = 0;
+ while (!list_empty(&wc->lru) &&
+ (wc->writeback_all ||
+ wc->freelist_size + wc->writeback_size <= wc->freelist_low_watermark)) {
+
+ n_walked++;
+ if (unlikely(n_walked > WRITEBACK_LATENCY) &&
+ likely(!wc->writeback_all) && likely(!dm_suspended(wc->ti))) {
+ queue_work(wc->writeback_wq, &wc->writeback_work);
+ break;
+ }
+
+ e = container_of(wc->lru.prev, struct wc_entry, lru);
+ BUG_ON(e->write_in_progress);
+ if (unlikely(!writecache_entry_is_committed(wc, e))) {
+ writecache_flush(wc);
+ }
+ node = rb_prev(&e->rb_node);
+ if (node) {
+ f = container_of(node, struct wc_entry, rb_node);
+ if (unlikely(read_original_sector(wc, f) ==
+ read_original_sector(wc, e))) {
+ BUG_ON(!f->write_in_progress);
+ list_del(&e->lru);
+ list_add(&e->lru, &skipped);
+ cond_resched();
+ continue;
+ }
+ }
+ wc->writeback_size++;
+ list_del(&e->lru);
+ list_add(&e->lru, &wbl.list);
+ wbl.size++;
+ e->write_in_progress = true;
+ e->wc_list_contiguous = 1;
+
+ f = e;
+
+ while (1) {
+ next_node = rb_next(&f->rb_node);
+ if (unlikely(!next_node))
+ break;
+ g = container_of(next_node, struct wc_entry, rb_node);
+ if (read_original_sector(wc, g) ==
+ read_original_sector(wc, f)) {
+ f = g;
+ continue;
+ }
+ if (read_original_sector(wc, g) !=
+ read_original_sector(wc, f) + (wc->block_size >> SECTOR_SHIFT))
+ break;
+ if (unlikely(g->write_in_progress))
+ break;
+ if (unlikely(!writecache_entry_is_committed(wc, g)))
+ break;
+
+ if (!WC_MODE_PMEM(wc)) {
+ if (g != f + 1)
+ break;
+ }
+
+ n_walked++;
+ //if (unlikely(n_walked > WRITEBACK_LATENCY) && likely(!wc->writeback_all))
+ // break;
+
+ wc->writeback_size++;
+ list_del(&g->lru);
+ list_add(&g->lru, &wbl.list);
+ wbl.size++;
+ g->write_in_progress = true;
+ g->wc_list_contiguous = BIO_MAX_PAGES;
+ f = g;
+ e->wc_list_contiguous++;
+ if (unlikely(e->wc_list_contiguous == BIO_MAX_PAGES))
+ break;
+ }
+ cond_resched();
+ }
+
+ if (!list_empty(&skipped)) {
+ list_splice_tail(&skipped, &wc->lru);
+ /*
+ * If we didn't do any progress, we must wait until some
+ * writeback finishes to avoid burning CPU in a loop
+ */
+ if (unlikely(!wbl.size))
+ writecache_wait_for_writeback(wc);
+ }
+
+ wc_unlock(wc);
+
+ blk_start_plug(&plug);
+
+ if (WC_MODE_PMEM(wc))
+ __writecache_writeback_pmem(wc, &wbl);
+ else
+ __writecache_writeback_ssd(wc, &wbl);
+
+ blk_finish_plug(&plug);
+
+ if (unlikely(wc->writeback_all)) {
+ wc_lock(wc);
+ while (writecache_wait_for_writeback(wc));
+ wc_unlock(wc);
+ }
+}
+
+static int calculate_memory_size(uint64_t device_size, unsigned block_size,
+ size_t *n_blocks_p, size_t *n_metadata_blocks_p)
+{
+ uint64_t n_blocks, offset;
+ struct wc_entry e;
+
+ n_blocks = device_size;
+ do_div(n_blocks, block_size + sizeof(struct wc_memory_entry));
+
+ while (1) {
+ if (!n_blocks)
+ return -ENOSPC;
+ /* Verify the following entries[n_blocks] won't overflow */
+ if (n_blocks >= ((size_t)-sizeof(struct wc_memory_superblock) /
+ sizeof(struct wc_memory_entry)))
+ return -EFBIG;
+ offset = offsetof(struct wc_memory_superblock, entries[n_blocks]);
+ offset = (offset + block_size - 1) & ~(uint64_t)(block_size - 1);
+ if (offset + n_blocks * block_size <= device_size)
+ break;
+ n_blocks--;
+ }
+
+ /* check if the bit field overflows */
+ e.index = n_blocks;
+ if (e.index != n_blocks)
+ return -EFBIG;
+
+ if (n_blocks_p)
+ *n_blocks_p = n_blocks;
+ if (n_metadata_blocks_p)
+ *n_metadata_blocks_p = offset >> __ffs(block_size);
+ return 0;
+}
+
+static int init_memory(struct dm_writecache *wc)
+{
+ size_t b;
+ int r;
+
+ r = calculate_memory_size(wc->memory_map_size, wc->block_size, &wc->n_blocks, NULL);
+ if (r)
+ return r;
+
+ r = writecache_alloc_entries(wc);
+ if (r)
+ return r;
+
+ for (b = 0; b < ARRAY_SIZE(sb(wc)->padding); b++)
+ pmem_assign(sb(wc)->padding[b], cpu_to_le64(0));
+ pmem_assign(sb(wc)->version, cpu_to_le32(MEMORY_SUPERBLOCK_VERSION));
+ pmem_assign(sb(wc)->block_size, cpu_to_le32(wc->block_size));
+ pmem_assign(sb(wc)->n_blocks, cpu_to_le64(wc->n_blocks));
+ pmem_assign(sb(wc)->seq_count, cpu_to_le64(0));
+
+ for (b = 0; b < wc->n_blocks; b++)
+ write_original_sector_seq_count(wc, &wc->entries[b], -1, -1);
+
+ writecache_flush_all_metadata(wc);
+ writecache_commit_flushed(wc);
+ pmem_assign(sb(wc)->magic, cpu_to_le32(MEMORY_SUPERBLOCK_MAGIC));
+ writecache_flush_region(wc, &sb(wc)->magic, sizeof sb(wc)->magic);
+ writecache_commit_flushed(wc);
+
+ return 0;
+}
+
+static void writecache_dtr(struct dm_target *ti)
+{
+ struct dm_writecache *wc = ti->private;
+
+ if (!wc)
+ return;
+
+ if (wc->endio_thread)
+ kthread_stop(wc->endio_thread);
+
+ if (wc->flush_thread)
+ kthread_stop(wc->flush_thread);
+
+ bioset_exit(&wc->bio_set);
+
+ mempool_exit(&wc->copy_pool);
+
+ if (wc->writeback_wq)
+ destroy_workqueue(wc->writeback_wq);
+
+ if (wc->dev)
+ dm_put_device(ti, wc->dev);
+
+ if (wc->ssd_dev)
+ dm_put_device(ti, wc->ssd_dev);
+
+ if (wc->entries)
+ vfree(wc->entries);
+
+ if (wc->memory_map) {
+ if (WC_MODE_PMEM(wc))
+ persistent_memory_release(wc);
+ else
+ vfree(wc->memory_map);
+ }
+
+ if (wc->dm_kcopyd)
+ dm_kcopyd_client_destroy(wc->dm_kcopyd);
+
+ if (wc->dm_io)
+ dm_io_client_destroy(wc->dm_io);
+
+ if (wc->dirty_bitmap)
+ vfree(wc->dirty_bitmap);
+
+ kfree(wc);
+}
+
+static int writecache_ctr(struct dm_target *ti, unsigned argc, char **argv)
+{
+ struct dm_writecache *wc;
+ struct dm_arg_set as;
+ const char *string;
+ unsigned opt_params;
+ size_t offset, data_size;
+ int i, r;
+ char dummy;
+ int high_wm_percent = HIGH_WATERMARK;
+ int low_wm_percent = LOW_WATERMARK;
+ uint64_t x;
+ struct wc_memory_superblock s;
+
+ static struct dm_arg _args[] = {
+ {0, 10, "Invalid number of feature args"},
+ };
+
+ as.argc = argc;
+ as.argv = argv;
+
+ wc = kzalloc(sizeof(struct dm_writecache), GFP_KERNEL);
+ if (!wc) {
+ ti->error = "Cannot allocate writecache structure";
+ r = -ENOMEM;
+ goto bad;
+ }
+ ti->private = wc;
+ wc->ti = ti;
+
+ mutex_init(&wc->lock);
+ writecache_poison_lists(wc);
+ init_waitqueue_head(&wc->freelist_wait);
+ timer_setup(&wc->autocommit_timer, writecache_autocommit_timer, 0);
+
+ for (i = 0; i < 2; i++) {
+ atomic_set(&wc->bio_in_progress[i], 0);
+ init_waitqueue_head(&wc->bio_in_progress_wait[i]);
+ }
+
+ wc->dm_io = dm_io_client_create();
+ if (IS_ERR(wc->dm_io)) {
+ r = PTR_ERR(wc->dm_io);
+ ti->error = "Unable to allocate dm-io client";
+ wc->dm_io = NULL;
+ goto bad;
+ }
+
+ wc->writeback_wq = alloc_workqueue("writecache-writeabck", WQ_MEM_RECLAIM, 1);
+ if (!wc->writeback_wq) {
+ r = -ENOMEM;
+ ti->error = "Could not allocate writeback workqueue";
+ goto bad;
+ }
+ INIT_WORK(&wc->writeback_work, writecache_writeback);
+ INIT_WORK(&wc->flush_work, writecache_flush_work);
+
+ raw_spin_lock_init(&wc->endio_list_lock);
+ INIT_LIST_HEAD(&wc->endio_list);
+ wc->endio_thread = kthread_create(writecache_endio_thread, wc, "writecache_endio");
+ if (IS_ERR(wc->endio_thread)) {
+ r = PTR_ERR(wc->endio_thread);
+ wc->endio_thread = NULL;
+ ti->error = "Couldn't spawn endio thread";
+ goto bad;
+ }
+ wake_up_process(wc->endio_thread);
+
+ /*
+ * Parse the mode (pmem or ssd)
+ */
+ string = dm_shift_arg(&as);
+ if (!string)
+ goto bad_arguments;
+
+ if (!strcasecmp(string, "s")) {
+ wc->pmem_mode = false;
+ } else if (!strcasecmp(string, "p")) {
+#ifdef DM_WRITECACHE_HAS_PMEM
+ wc->pmem_mode = true;
+ wc->writeback_fua = true;
+#else
+ /*
+ * If the architecture doesn't support persistent memory or
+ * the kernel doesn't support any DAX drivers, this driver can
+ * only be used in SSD-only mode.
+ */
+ r = -EOPNOTSUPP;
+ ti->error = "Persistent memory or DAX not supported on this system";
+ goto bad;
+#endif
+ } else {
+ goto bad_arguments;
+ }
+
+ if (WC_MODE_PMEM(wc)) {
+ r = bioset_init(&wc->bio_set, BIO_POOL_SIZE,
+ offsetof(struct writeback_struct, bio),
+ BIOSET_NEED_BVECS);
+ if (r) {
+ ti->error = "Could not allocate bio set";
+ goto bad;
+ }
+ } else {
+ r = mempool_init_kmalloc_pool(&wc->copy_pool, 1, sizeof(struct copy_struct));
+ if (r) {
+ ti->error = "Could not allocate mempool";
+ goto bad;
+ }
+ }
+
+ /*
+ * Parse the origin data device
+ */
+ string = dm_shift_arg(&as);
+ if (!string)
+ goto bad_arguments;
+ r = dm_get_device(ti, string, dm_table_get_mode(ti->table), &wc->dev);
+ if (r) {
+ ti->error = "Origin data device lookup failed";
+ goto bad;
+ }
+
+ /*
+ * Parse cache data device (be it pmem or ssd)
+ */
+ string = dm_shift_arg(&as);
+ if (!string)
+ goto bad_arguments;
+
+ r = dm_get_device(ti, string, dm_table_get_mode(ti->table), &wc->ssd_dev);
+ if (r) {
+ ti->error = "Cache data device lookup failed";
+ goto bad;
+ }
+ wc->memory_map_size = i_size_read(wc->ssd_dev->bdev->bd_inode);
+
+ if (WC_MODE_PMEM(wc)) {
+ r = persistent_memory_claim(wc);
+ if (r) {
+ ti->error = "Unable to map persistent memory for cache";
+ goto bad;
+ }
+ }
+
+ /*
+ * Parse the cache block size
+ */
+ string = dm_shift_arg(&as);
+ if (!string)
+ goto bad_arguments;
+ if (sscanf(string, "%u%c", &wc->block_size, &dummy) != 1 ||
+ wc->block_size < 512 || wc->block_size > PAGE_SIZE ||
+ (wc->block_size & (wc->block_size - 1))) {
+ r = -EINVAL;
+ ti->error = "Invalid block size";
+ goto bad;
+ }
+ wc->block_size_bits = __ffs(wc->block_size);
+
+ wc->max_writeback_jobs = MAX_WRITEBACK_JOBS;
+ wc->autocommit_blocks = !WC_MODE_PMEM(wc) ? AUTOCOMMIT_BLOCKS_SSD : AUTOCOMMIT_BLOCKS_PMEM;
+ wc->autocommit_jiffies = msecs_to_jiffies(AUTOCOMMIT_MSEC);
+
+ /*
+ * Parse optional arguments
+ */
+ r = dm_read_arg_group(_args, &as, &opt_params, &ti->error);
+ if (r)
+ goto bad;
+
+ while (opt_params) {
+ string = dm_shift_arg(&as), opt_params--;
+ if (!strcasecmp(string, "high_watermark") && opt_params >= 1) {
+ string = dm_shift_arg(&as), opt_params--;
+ if (sscanf(string, "%d%c", &high_wm_percent, &dummy) != 1)
+ goto invalid_optional;
+ if (high_wm_percent < 0 || high_wm_percent > 100)
+ goto invalid_optional;
+ wc->high_wm_percent_set = true;
+ } else if (!strcasecmp(string, "low_watermark") && opt_params >= 1) {
+ string = dm_shift_arg(&as), opt_params--;
+ if (sscanf(string, "%d%c", &low_wm_percent, &dummy) != 1)
+ goto invalid_optional;
+ if (low_wm_percent < 0 || low_wm_percent > 100)
+ goto invalid_optional;
+ wc->low_wm_percent_set = true;
+ } else if (!strcasecmp(string, "writeback_jobs") && opt_params >= 1) {
+ string = dm_shift_arg(&as), opt_params--;
+ if (sscanf(string, "%u%c", &wc->max_writeback_jobs, &dummy) != 1)
+ goto invalid_optional;
+ wc->max_writeback_jobs_set = true;
+ } else if (!strcasecmp(string, "autocommit_blocks") && opt_params >= 1) {
+ string = dm_shift_arg(&as), opt_params--;
+ if (sscanf(string, "%u%c", &wc->autocommit_blocks, &dummy) != 1)
+ goto invalid_optional;
+ wc->autocommit_blocks_set = true;
+ } else if (!strcasecmp(string, "autocommit_time") && opt_params >= 1) {
+ unsigned autocommit_msecs;
+ string = dm_shift_arg(&as), opt_params--;
+ if (sscanf(string, "%u%c", &autocommit_msecs, &dummy) != 1)
+ goto invalid_optional;
+ if (autocommit_msecs > 3600000)
+ goto invalid_optional;
+ wc->autocommit_jiffies = msecs_to_jiffies(autocommit_msecs);
+ wc->autocommit_time_set = true;
+ } else if (!strcasecmp(string, "fua")) {
+ if (WC_MODE_PMEM(wc)) {
+ wc->writeback_fua = true;
+ wc->writeback_fua_set = true;
+ } else goto invalid_optional;
+ } else if (!strcasecmp(string, "nofua")) {
+ if (WC_MODE_PMEM(wc)) {
+ wc->writeback_fua = false;
+ wc->writeback_fua_set = true;
+ } else goto invalid_optional;
+ } else {
+invalid_optional:
+ r = -EINVAL;
+ ti->error = "Invalid optional argument";
+ goto bad;
+ }
+ }
+
+ if (high_wm_percent < low_wm_percent) {
+ r = -EINVAL;
+ ti->error = "High watermark must be greater than or equal to low watermark";
+ goto bad;
+ }
+
+ if (!WC_MODE_PMEM(wc)) {
+ struct dm_io_region region;
+ struct dm_io_request req;
+ size_t n_blocks, n_metadata_blocks;
+ uint64_t n_bitmap_bits;
+
+ bio_list_init(&wc->flush_list);
+ wc->flush_thread = kthread_create(writecache_flush_thread, wc, "dm_writecache_flush");
+ if (IS_ERR(wc->flush_thread)) {
+ r = PTR_ERR(wc->flush_thread);
+ wc->flush_thread = NULL;
+ ti->error = "Couldn't spawn endio thread";
+ goto bad;
+ }
+ wake_up_process(wc->flush_thread);
+
+ r = calculate_memory_size(wc->memory_map_size, wc->block_size,
+ &n_blocks, &n_metadata_blocks);
+ if (r) {
+ ti->error = "Invalid device size";
+ goto bad;
+ }
+
+ n_bitmap_bits = (((uint64_t)n_metadata_blocks << wc->block_size_bits) +
+ BITMAP_GRANULARITY - 1) / BITMAP_GRANULARITY;
+ /* this is limitation of test_bit functions */
+ if (n_bitmap_bits > 1U << 31) {
+ r = -EFBIG;
+ ti->error = "Invalid device size";
+ goto bad;
+ }
+
+ wc->memory_map = vmalloc(n_metadata_blocks << wc->block_size_bits);
+ if (!wc->memory_map) {
+ r = -ENOMEM;
+ ti->error = "Unable to allocate memory for metadata";
+ goto bad;
+ }
+
+ wc->dm_kcopyd = dm_kcopyd_client_create(&dm_kcopyd_throttle);
+ if (IS_ERR(wc->dm_kcopyd)) {
+ r = PTR_ERR(wc->dm_kcopyd);
+ ti->error = "Unable to allocate dm-kcopyd client";
+ wc->dm_kcopyd = NULL;
+ goto bad;
+ }
+
+ wc->metadata_sectors = n_metadata_blocks << (wc->block_size_bits - SECTOR_SHIFT);
+ wc->dirty_bitmap_size = (n_bitmap_bits + BITS_PER_LONG - 1) /
+ BITS_PER_LONG * sizeof(unsigned long);
+ wc->dirty_bitmap = vzalloc(wc->dirty_bitmap_size);
+ if (!wc->dirty_bitmap) {
+ r = -ENOMEM;
+ ti->error = "Unable to allocate dirty bitmap";
+ goto bad;
+ }
+
+ region.bdev = wc->ssd_dev->bdev;
+ region.sector = 0;
+ region.count = wc->metadata_sectors;
+ req.bi_op = REQ_OP_READ;
+ req.bi_op_flags = REQ_SYNC;
+ req.mem.type = DM_IO_VMA;
+ req.mem.ptr.vma = (char *)wc->memory_map;
+ req.client = wc->dm_io;
+ req.notify.fn = NULL;
+
+ r = dm_io(&req, 1, &region, NULL);
+ if (r) {
+ ti->error = "Unable to read metadata";
+ goto bad;
+ }
+ }
+
+ r = memcpy_mcsafe(&s, sb(wc), sizeof(struct wc_memory_superblock));
+ if (r) {
+ ti->error = "Hardware memory error when reading superblock";
+ goto bad;
+ }
+ if (!le32_to_cpu(s.magic) && !le32_to_cpu(s.version)) {
+ r = init_memory(wc);
+ if (r) {
+ ti->error = "Unable to initialize device";
+ goto bad;
+ }
+ r = memcpy_mcsafe(&s, sb(wc), sizeof(struct wc_memory_superblock));
+ if (r) {
+ ti->error = "Hardware memory error when reading superblock";
+ goto bad;
+ }
+ }
+
+ if (le32_to_cpu(s.magic) != MEMORY_SUPERBLOCK_MAGIC) {
+ ti->error = "Invalid magic in the superblock";
+ r = -EINVAL;
+ goto bad;
+ }
+
+ if (le32_to_cpu(s.version) != MEMORY_SUPERBLOCK_VERSION) {
+ ti->error = "Invalid version in the superblock";
+ r = -EINVAL;
+ goto bad;
+ }
+
+ if (le32_to_cpu(s.block_size) != wc->block_size) {
+ ti->error = "Block size does not match superblock";
+ r = -EINVAL;
+ goto bad;
+ }
+
+ wc->n_blocks = le64_to_cpu(s.n_blocks);
+
+ offset = wc->n_blocks * sizeof(struct wc_memory_entry);
+ if (offset / sizeof(struct wc_memory_entry) != le64_to_cpu(sb(wc)->n_blocks)) {
+overflow:
+ ti->error = "Overflow in size calculation";
+ r = -EINVAL;
+ goto bad;
+ }
+ offset += sizeof(struct wc_memory_superblock);
+ if (offset < sizeof(struct wc_memory_superblock))
+ goto overflow;
+ offset = (offset + wc->block_size - 1) & ~(size_t)(wc->block_size - 1);
+ data_size = wc->n_blocks * (size_t)wc->block_size;
+ if (!offset || (data_size / wc->block_size != wc->n_blocks) ||
+ (offset + data_size < offset))
+ goto overflow;
+ if (offset + data_size > wc->memory_map_size) {
+ ti->error = "Memory area is too small";
+ r = -EINVAL;
+ goto bad;
+ }
+
+ wc->metadata_sectors = offset >> SECTOR_SHIFT;
+ wc->block_start = (char *)sb(wc) + offset;
+
+ x = (uint64_t)wc->n_blocks * (100 - high_wm_percent);
+ x += 50;
+ do_div(x, 100);
+ wc->freelist_high_watermark = x;
+ x = (uint64_t)wc->n_blocks * (100 - low_wm_percent);
+ x += 50;
+ do_div(x, 100);
+ wc->freelist_low_watermark = x;
+
+ r = writecache_alloc_entries(wc);
+ if (r) {
+ ti->error = "Cannot allocate memory";
+ goto bad;
+ }
+
+ ti->num_flush_bios = 1;
+ ti->flush_supported = true;
+ ti->num_discard_bios = 1;
+
+ if (WC_MODE_PMEM(wc))
+ persistent_memory_flush_cache(wc->memory_map, wc->memory_map_size);
+
+ return 0;
+
+bad_arguments:
+ r = -EINVAL;
+ ti->error = "Bad arguments";
+bad:
+ writecache_dtr(ti);
+ return r;
+}
+
+static void writecache_status(struct dm_target *ti, status_type_t type,
+ unsigned status_flags, char *result, unsigned maxlen)
+{
+ struct dm_writecache *wc = ti->private;
+ unsigned extra_args;
+ unsigned sz = 0;
+ uint64_t x;
+
+ switch (type) {
+ case STATUSTYPE_INFO:
+ DMEMIT("%ld %llu %llu %llu", writecache_has_error(wc),
+ (unsigned long long)wc->n_blocks, (unsigned long long)wc->freelist_size,
+ (unsigned long long)wc->writeback_size);
+ break;
+ case STATUSTYPE_TABLE:
+ DMEMIT("%c %s %s %u ", WC_MODE_PMEM(wc) ? 'p' : 's',
+ wc->dev->name, wc->ssd_dev->name, wc->block_size);
+ extra_args = 0;
+ if (wc->high_wm_percent_set)
+ extra_args += 2;
+ if (wc->low_wm_percent_set)
+ extra_args += 2;
+ if (wc->max_writeback_jobs_set)
+ extra_args += 2;
+ if (wc->autocommit_blocks_set)
+ extra_args += 2;
+ if (wc->autocommit_time_set)
+ extra_args += 2;
+ if (wc->writeback_fua_set)
+ extra_args++;
+
+ DMEMIT("%u", extra_args);
+ if (wc->high_wm_percent_set) {
+ x = (uint64_t)wc->freelist_high_watermark * 100;
+ x += wc->n_blocks / 2;
+ do_div(x, (size_t)wc->n_blocks);
+ DMEMIT(" high_watermark %u", 100 - (unsigned)x);
+ }
+ if (wc->low_wm_percent_set) {
+ x = (uint64_t)wc->freelist_low_watermark * 100;
+ x += wc->n_blocks / 2;
+ do_div(x, (size_t)wc->n_blocks);
+ DMEMIT(" low_watermark %u", 100 - (unsigned)x);
+ }
+ if (wc->max_writeback_jobs_set)
+ DMEMIT(" writeback_jobs %u", wc->max_writeback_jobs);
+ if (wc->autocommit_blocks_set)
+ DMEMIT(" autocommit_blocks %u", wc->autocommit_blocks);
+ if (wc->autocommit_time_set)
+ DMEMIT(" autocommit_time %u", jiffies_to_msecs(wc->autocommit_jiffies));
+ if (wc->writeback_fua_set)
+ DMEMIT(" %sfua", wc->writeback_fua ? "" : "no");
+ break;
+ }
+}
+
+static struct target_type writecache_target = {
+ .name = "writecache",
+ .version = {1, 0, 0},
+ .module = THIS_MODULE,
+ .ctr = writecache_ctr,
+ .dtr = writecache_dtr,
+ .status = writecache_status,
+ .postsuspend = writecache_suspend,
+ .resume = writecache_resume,
+ .message = writecache_message,
+ .map = writecache_map,
+ .end_io = writecache_end_io,
+ .iterate_devices = writecache_iterate_devices,
+ .io_hints = writecache_io_hints,
+};
+
+static int __init dm_writecache_init(void)
+{
+ int r;
+
+ r = dm_register_target(&writecache_target);
+ if (r < 0) {
+ DMERR("register failed %d", r);
+ return r;
+ }
+
+ return 0;
+}
+
+static void __exit dm_writecache_exit(void)
+{
+ dm_unregister_target(&writecache_target);
+}
+
+module_init(dm_writecache_init);
+module_exit(dm_writecache_exit);
+
+MODULE_DESCRIPTION(DM_NAME " writecache target");
+MODULE_AUTHOR("Mikulas Patocka <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/md/dm-zoned-target.c b/drivers/md/dm-zoned-target.c
index 30602d1..3c0e45f 100644
--- a/drivers/md/dm-zoned-target.c
+++ b/drivers/md/dm-zoned-target.c
@@ -52,9 +52,9 @@ struct dmz_target {
struct dmz_reclaim *reclaim;
/* For chunk work */
- struct mutex chunk_lock;
struct radix_tree_root chunk_rxtree;
struct workqueue_struct *chunk_wq;
+ struct mutex chunk_lock;
/* For cloned BIOs to zones */
struct bio_set bio_set;
diff --git a/drivers/md/md-bitmap.c b/drivers/md/md-bitmap.c
index 239c7bb..f983c3f 100644
--- a/drivers/md/md-bitmap.c
+++ b/drivers/md/md-bitmap.c
@@ -789,8 +789,8 @@ static int bitmap_storage_alloc(struct bitmap_storage *store,
num_pages = DIV_ROUND_UP(bytes, PAGE_SIZE);
offset = slot_number * num_pages;
- store->filemap = kmalloc(sizeof(struct page *)
- * num_pages, GFP_KERNEL);
+ store->filemap = kmalloc_array(num_pages, sizeof(struct page *),
+ GFP_KERNEL);
if (!store->filemap)
return -ENOMEM;
@@ -2117,7 +2117,7 @@ int bitmap_resize(struct bitmap *bitmap, sector_t blocks,
pages = DIV_ROUND_UP(chunks, PAGE_COUNTER_RATIO);
- new_bp = kzalloc(pages * sizeof(*new_bp), GFP_KERNEL);
+ new_bp = kcalloc(pages, sizeof(*new_bp), GFP_KERNEL);
ret = -ENOMEM;
if (!new_bp) {
bitmap_file_unmap(&store);
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index 79bfbc8..021cbf9 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -1380,9 +1380,9 @@ static int lock_all_bitmaps(struct mddev *mddev)
char str[64];
struct md_cluster_info *cinfo = mddev->cluster_info;
- cinfo->other_bitmap_lockres = kzalloc((mddev->bitmap_info.nodes - 1) *
- sizeof(struct dlm_lock_resource *),
- GFP_KERNEL);
+ cinfo->other_bitmap_lockres =
+ kcalloc(mddev->bitmap_info.nodes - 1,
+ sizeof(struct dlm_lock_resource *), GFP_KERNEL);
if (!cinfo->other_bitmap_lockres) {
pr_err("md: can't alloc mem for other bitmap locks\n");
return 0;
diff --git a/drivers/md/md-multipath.c b/drivers/md/md-multipath.c
index f71fcdb..881487d 100644
--- a/drivers/md/md-multipath.c
+++ b/drivers/md/md-multipath.c
@@ -399,7 +399,8 @@ static int multipath_run (struct mddev *mddev)
if (!conf)
goto out;
- conf->multipaths = kzalloc(sizeof(struct multipath_info)*mddev->raid_disks,
+ conf->multipaths = kcalloc(mddev->raid_disks,
+ sizeof(struct multipath_info),
GFP_KERNEL);
if (!conf->multipaths)
goto out_free_conf;
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 65ae47a..ac1cffd 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -159,12 +159,14 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
}
err = -ENOMEM;
- conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
- conf->nr_strip_zones, GFP_KERNEL);
+ conf->strip_zone = kcalloc(conf->nr_strip_zones,
+ sizeof(struct strip_zone),
+ GFP_KERNEL);
if (!conf->strip_zone)
goto abort;
- conf->devlist = kzalloc(sizeof(struct md_rdev*)*
- conf->nr_strip_zones*mddev->raid_disks,
+ conf->devlist = kzalloc(array3_size(sizeof(struct md_rdev *),
+ conf->nr_strip_zones,
+ mddev->raid_disks),
GFP_KERNEL);
if (!conf->devlist)
goto abort;
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 0b344d0..8e05c10 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -126,8 +126,8 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data)
if (!r1_bio)
return NULL;
- rps = kmalloc(sizeof(struct resync_pages) * pi->raid_disks,
- gfp_flags);
+ rps = kmalloc_array(pi->raid_disks, sizeof(struct resync_pages),
+ gfp_flags);
if (!rps)
goto out_free_r1bio;
@@ -2936,9 +2936,9 @@ static struct r1conf *setup_conf(struct mddev *mddev)
if (!conf->barrier)
goto abort;
- conf->mirrors = kzalloc(sizeof(struct raid1_info)
- * mddev->raid_disks * 2,
- GFP_KERNEL);
+ conf->mirrors = kzalloc(array3_size(sizeof(struct raid1_info),
+ mddev->raid_disks, 2),
+ GFP_KERNEL);
if (!conf->mirrors)
goto abort;
@@ -3241,7 +3241,8 @@ static int raid1_reshape(struct mddev *mddev)
kfree(newpoolinfo);
return ret;
}
- newmirrors = kzalloc(sizeof(struct raid1_info) * raid_disks * 2,
+ newmirrors = kzalloc(array3_size(sizeof(struct raid1_info),
+ raid_disks, 2),
GFP_KERNEL);
if (!newmirrors) {
kfree(newpoolinfo);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 1147ae5..478cf44 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -175,7 +175,7 @@ static void * r10buf_pool_alloc(gfp_t gfp_flags, void *data)
nalloc_rp = nalloc;
else
nalloc_rp = nalloc * 2;
- rps = kmalloc(sizeof(struct resync_pages) * nalloc_rp, gfp_flags);
+ rps = kmalloc_array(nalloc_rp, sizeof(struct resync_pages), gfp_flags);
if (!rps)
goto out_free_r10bio;
@@ -3688,8 +3688,8 @@ static struct r10conf *setup_conf(struct mddev *mddev)
goto out;
/* FIXME calc properly */
- conf->mirrors = kzalloc(sizeof(struct raid10_info)*(mddev->raid_disks +
- max(0,-mddev->delta_disks)),
+ conf->mirrors = kcalloc(mddev->raid_disks + max(0, -mddev->delta_disks),
+ sizeof(struct raid10_info),
GFP_KERNEL);
if (!conf->mirrors)
goto out;
@@ -4129,11 +4129,10 @@ static int raid10_check_reshape(struct mddev *mddev)
conf->mirrors_new = NULL;
if (mddev->delta_disks > 0) {
/* allocate new 'mirrors' list */
- conf->mirrors_new = kzalloc(
- sizeof(struct raid10_info)
- *(mddev->raid_disks +
- mddev->delta_disks),
- GFP_KERNEL);
+ conf->mirrors_new =
+ kcalloc(mddev->raid_disks + mddev->delta_disks,
+ sizeof(struct raid10_info),
+ GFP_KERNEL);
if (!conf->mirrors_new)
return -ENOMEM;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 7348944..2031506 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2396,7 +2396,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
* is completely stalled, so now is a good time to resize
* conf->disks and the scribble region
*/
- ndisks = kzalloc(newsize * sizeof(struct disk_info), GFP_NOIO);
+ ndisks = kcalloc(newsize, sizeof(struct disk_info), GFP_NOIO);
if (ndisks) {
for (i = 0; i < conf->pool_size; i++)
ndisks[i] = conf->disks[i];
@@ -6664,9 +6664,9 @@ static int alloc_thread_groups(struct r5conf *conf, int cnt,
}
*group_cnt = num_possible_nodes();
size = sizeof(struct r5worker) * cnt;
- workers = kzalloc(size * *group_cnt, GFP_NOIO);
- *worker_groups = kzalloc(sizeof(struct r5worker_group) *
- *group_cnt, GFP_NOIO);
+ workers = kcalloc(size, *group_cnt, GFP_NOIO);
+ *worker_groups = kcalloc(*group_cnt, sizeof(struct r5worker_group),
+ GFP_NOIO);
if (!*worker_groups || !workers) {
kfree(workers);
kfree(*worker_groups);
@@ -6894,8 +6894,9 @@ static struct r5conf *setup_conf(struct mddev *mddev)
goto abort;
INIT_LIST_HEAD(&conf->free_list);
INIT_LIST_HEAD(&conf->pending_list);
- conf->pending_data = kzalloc(sizeof(struct r5pending_data) *
- PENDING_IO_MAX, GFP_KERNEL);
+ conf->pending_data = kcalloc(PENDING_IO_MAX,
+ sizeof(struct r5pending_data),
+ GFP_KERNEL);
if (!conf->pending_data)
goto abort;
for (i = 0; i < PENDING_IO_MAX; i++)
@@ -6944,7 +6945,7 @@ static struct r5conf *setup_conf(struct mddev *mddev)
conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks;
max_disks = max(conf->raid_disks, conf->previous_raid_disks);
- conf->disks = kzalloc(max_disks * sizeof(struct disk_info),
+ conf->disks = kcalloc(max_disks, sizeof(struct disk_info),
GFP_KERNEL);
if (!conf->disks)
diff --git a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
index 9b64f4f..abd4c78 100644
--- a/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
+++ b/drivers/media/common/v4l2-tpg/v4l2-tpg-core.c
@@ -119,12 +119,14 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
unsigned pixelsz = plane ? 2 : 4;
- tpg->lines[pat][plane] = vzalloc(max_w * 2 * pixelsz);
+ tpg->lines[pat][plane] =
+ vzalloc(array3_size(max_w, 2, pixelsz));
if (!tpg->lines[pat][plane])
return -ENOMEM;
if (plane == 0)
continue;
- tpg->downsampled_lines[pat][plane] = vzalloc(max_w * 2 * pixelsz);
+ tpg->downsampled_lines[pat][plane] =
+ vzalloc(array3_size(max_w, 2, pixelsz));
if (!tpg->downsampled_lines[pat][plane])
return -ENOMEM;
}
@@ -132,13 +134,16 @@ int tpg_alloc(struct tpg_data *tpg, unsigned max_w)
for (plane = 0; plane < TPG_MAX_PLANES; plane++) {
unsigned pixelsz = plane ? 2 : 4;
- tpg->contrast_line[plane] = vzalloc(max_w * pixelsz);
+ tpg->contrast_line[plane] =
+ vzalloc(array_size(pixelsz, max_w));
if (!tpg->contrast_line[plane])
return -ENOMEM;
- tpg->black_line[plane] = vzalloc(max_w * pixelsz);
+ tpg->black_line[plane] =
+ vzalloc(array_size(pixelsz, max_w));
if (!tpg->black_line[plane])
return -ENOMEM;
- tpg->random_line[plane] = vzalloc(max_w * 2 * pixelsz);
+ tpg->random_line[plane] =
+ vzalloc(array3_size(max_w, 2, pixelsz));
if (!tpg->random_line[plane])
return -ENOMEM;
}
diff --git a/drivers/media/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index cb078d6..d548f98 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -1417,7 +1417,8 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
if (dmxdev->demux->open(dmxdev->demux) < 0)
return -EUSERS;
- dmxdev->filter = vmalloc(dmxdev->filternum * sizeof(struct dmxdev_filter));
+ dmxdev->filter = vmalloc(array_size(sizeof(struct dmxdev_filter),
+ dmxdev->filternum));
if (!dmxdev->filter)
return -ENOMEM;
diff --git a/drivers/media/dvb-core/dvb_demux.c b/drivers/media/dvb-core/dvb_demux.c
index f450912..39a2c6c 100644
--- a/drivers/media/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb-core/dvb_demux.c
@@ -1247,12 +1247,14 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
dvbdemux->cnt_storage = NULL;
dvbdemux->users = 0;
- dvbdemux->filter = vmalloc(dvbdemux->filternum * sizeof(struct dvb_demux_filter));
+ dvbdemux->filter = vmalloc(array_size(sizeof(struct dvb_demux_filter),
+ dvbdemux->filternum));
if (!dvbdemux->filter)
return -ENOMEM;
- dvbdemux->feed = vmalloc(dvbdemux->feednum * sizeof(struct dvb_demux_feed));
+ dvbdemux->feed = vmalloc(array_size(sizeof(struct dvb_demux_feed),
+ dvbdemux->feednum));
if (!dvbdemux->feed) {
vfree(dvbdemux->filter);
dvbdemux->filter = NULL;
diff --git a/drivers/media/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb-core/dvb_ringbuffer.c
index 4330b6f..d1d471a 100644
--- a/drivers/media/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb-core/dvb_ringbuffer.c
@@ -55,7 +55,7 @@ int dvb_ringbuffer_empty(struct dvb_ringbuffer *rbuf)
* this pairs with smp_store_release() in dvb_ringbuffer_write(),
* dvb_ringbuffer_write_user(), or dvb_ringbuffer_reset()
*
- * for memory barriers also see Documentation/circular-buffers.txt
+ * for memory barriers also see Documentation/core-api/circular-buffers.rst
*/
return (rbuf->pread == smp_load_acquire(&rbuf->pwrite));
}
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 55e36a4..9ecaa9d 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -324,7 +324,7 @@ config DVB_SP8870
A DVB-T tuner module. Say Y when you want to support this frontend.
This driver needs external firmware. Please use the command
- "<kerneldir>/Documentation/dvb/get_dvb_firmware sp8870" to
+ "<kerneldir>/scripts/get_dvb_firmware sp8870" to
download/extract it, and then copy it to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
@@ -336,7 +336,7 @@ config DVB_SP887X
A DVB-T tuner module. Say Y when you want to support this frontend.
This driver needs external firmware. Please use the command
- "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
+ "<kerneldir>/scripts/get_dvb_firmware sp887x" to
download/extract it, and then copy it to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
@@ -387,8 +387,8 @@ config DVB_TDA1004X
A DVB-T tuner module. Say Y when you want to support this frontend.
This driver needs external firmware. Please use the commands
- "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
+ "<kerneldir>/scripts/get_dvb_firmware tda10045",
+ "<kerneldir>/scripts/get_dvb_firmware tda10046" to
download/extract them, and then copy them to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
@@ -591,8 +591,8 @@ config DVB_NXT200X
to support this frontend.
This driver needs external firmware. Please use the commands
- "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" and
- "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
+ "<kerneldir>/scripts/get_dvb_firmware nxt2002" and
+ "<kerneldir>/scripts/get_dvb_firmware nxt2004" to
download/extract them, and then copy them to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
@@ -604,7 +604,7 @@ config DVB_OR51211
An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
This driver needs external firmware. Please use the command
- "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
+ "<kerneldir>/scripts/get_dvb_firmware or51211" to
download it, and then copy it to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
@@ -617,8 +617,8 @@ config DVB_OR51132
to support this frontend.
This driver needs external firmware. Please use the commands
- "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_vsb" and/or
- "<kerneldir>/Documentation/dvb/get_dvb_firmware or51132_qam" to
+ "<kerneldir>/scripts/get_dvb_firmware or51132_vsb" and/or
+ "<kerneldir>/scripts/get_dvb_firmware or51132_qam" to
download firmwares for 8VSB and QAM64/256, respectively. Copy them to
/usr/lib/hotplug/firmware or /lib/firmware (depending on
configuration of firmware hotplug).
diff --git a/drivers/media/dvb-frontends/dib3000.h b/drivers/media/dvb-frontends/dib3000.h
index d5dfafb..d2b7523 100644
--- a/drivers/media/dvb-frontends/dib3000.h
+++ b/drivers/media/dvb-frontends/dib3000.h
@@ -17,7 +17,7 @@
* Amaury Demol from DiBcom for providing specs and driver
* sources, on which this driver (and the dvb-dibusb) are based.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*
*/
diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c
index de3ce27..5861f34 100644
--- a/drivers/media/dvb-frontends/dib3000mb.c
+++ b/drivers/media/dvb-frontends/dib3000mb.c
@@ -17,7 +17,7 @@
* Amaury Demol from DiBcom for providing specs and driver
* sources, on which this driver (and the dvb-dibusb) are based.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*
*/
diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c
index 902af48..5a8dbc0 100644
--- a/drivers/media/dvb-frontends/dib7000p.c
+++ b/drivers/media/dvb-frontends/dib7000p.c
@@ -2018,10 +2018,10 @@ static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
};
int ret = 0;
- tx = kzalloc(2*sizeof(u8), GFP_KERNEL);
+ tx = kzalloc(2, GFP_KERNEL);
if (!tx)
return -ENOMEM;
- rx = kzalloc(2*sizeof(u8), GFP_KERNEL);
+ rx = kzalloc(2, GFP_KERNEL);
if (!rx) {
ret = -ENOMEM;
goto rx_memory_error;
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c
index 6f35173..22eec8f 100644
--- a/drivers/media/dvb-frontends/dib8000.c
+++ b/drivers/media/dvb-frontends/dib8000.c
@@ -4271,12 +4271,12 @@ static int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
u8 new_addr = 0;
struct i2c_device client = {.adap = host };
- client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+ client.i2c_write_buffer = kzalloc(4, GFP_KERNEL);
if (!client.i2c_write_buffer) {
dprintk("%s: not enough memory\n", __func__);
return -ENOMEM;
}
- client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+ client.i2c_read_buffer = kzalloc(4, GFP_KERNEL);
if (!client.i2c_read_buffer) {
dprintk("%s: not enough memory\n", __func__);
ret = -ENOMEM;
diff --git a/drivers/media/dvb-frontends/dib9000.c b/drivers/media/dvb-frontends/dib9000.c
index f9289f4..b8edb55 100644
--- a/drivers/media/dvb-frontends/dib9000.c
+++ b/drivers/media/dvb-frontends/dib9000.c
@@ -2381,12 +2381,12 @@ int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defaul
u8 new_addr = 0;
struct i2c_device client = {.i2c_adap = i2c };
- client.i2c_write_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+ client.i2c_write_buffer = kzalloc(4, GFP_KERNEL);
if (!client.i2c_write_buffer) {
dprintk("%s: not enough memory\n", __func__);
return -ENOMEM;
}
- client.i2c_read_buffer = kzalloc(4 * sizeof(u8), GFP_KERNEL);
+ client.i2c_read_buffer = kzalloc(4, GFP_KERNEL);
if (!client.i2c_read_buffer) {
dprintk("%s: not enough memory\n", __func__);
ret = -ENOMEM;
diff --git a/drivers/media/dvb-frontends/eds1547.h b/drivers/media/dvb-frontends/eds1547.h
index c983f2f..30f067f 100644
--- a/drivers/media/dvb-frontends/eds1547.h
+++ b/drivers/media/dvb-frontends/eds1547.h
@@ -6,7 +6,7 @@
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
-* see Documentation/dvb/README.dvb-usb for more information
+* see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef EDS1547
diff --git a/drivers/media/dvb-frontends/nxt200x.c b/drivers/media/dvb-frontends/nxt200x.c
index 7aa7440..a6cc495 100644
--- a/drivers/media/dvb-frontends/nxt200x.c
+++ b/drivers/media/dvb-frontends/nxt200x.c
@@ -27,8 +27,8 @@
* ATI HDTV Wonder (NXT2004)
*
* This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2002" or
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware nxt2004" to
+ * "<kerneldir>/scripts/get_dvb_firmware nxt2002" or
+ * "<kerneldir>/scripts/get_dvb_firmware nxt2004" to
* download/extract the appropriate firmware, and then copy it to
* /usr/lib/hotplug/firmware/ or /lib/firmware/
* (depending on configuration of firmware hotplug).
diff --git a/drivers/media/dvb-frontends/or51211.c b/drivers/media/dvb-frontends/or51211.c
index a1b7c30..b65ba34 100644
--- a/drivers/media/dvb-frontends/or51211.c
+++ b/drivers/media/dvb-frontends/or51211.c
@@ -22,7 +22,7 @@
/*
* This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware or51211" to
+ * "<kerneldir>/scripts/get_dvb_firmware or51211" to
* download/extract it, and then copy it to /usr/lib/hotplug/firmware
* or /lib/firmware (depending on configuration of firmware hotplug).
*/
diff --git a/drivers/media/dvb-frontends/sp8870.c b/drivers/media/dvb-frontends/sp8870.c
index 9a726f3..1d57a20 100644
--- a/drivers/media/dvb-frontends/sp8870.c
+++ b/drivers/media/dvb-frontends/sp8870.c
@@ -21,7 +21,7 @@
*/
/*
* This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware alps_tdlb7" to
+ * "<kerneldir>/scripts/get_dvb_firmware alps_tdlb7" to
* download/extract it, and then copy it to /usr/lib/hotplug/firmware
* or /lib/firmware (depending on configuration of firmware hotplug).
*/
diff --git a/drivers/media/dvb-frontends/sp887x.c b/drivers/media/dvb-frontends/sp887x.c
index f39d566..57a0d0a 100644
--- a/drivers/media/dvb-frontends/sp887x.c
+++ b/drivers/media/dvb-frontends/sp887x.c
@@ -4,7 +4,7 @@
/*
* This driver needs external firmware. Please use the command
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware sp887x" to
+ * "<kerneldir>/scripts/get_dvb_firmware sp887x" to
* download/extract it, and then copy it to /usr/lib/hotplug/firmware
* or /lib/firmware (depending on configuration of firmware hotplug).
*/
diff --git a/drivers/media/dvb-frontends/tda1004x.c b/drivers/media/dvb-frontends/tda1004x.c
index 58e3bef..7dcfb4a 100644
--- a/drivers/media/dvb-frontends/tda1004x.c
+++ b/drivers/media/dvb-frontends/tda1004x.c
@@ -21,8 +21,8 @@
*/
/*
* This driver needs external firmware. Please use the commands
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10045",
- * "<kerneldir>/Documentation/dvb/get_dvb_firmware tda10046" to
+ * "<kerneldir>/scripts/get_dvb_firmware tda10045",
+ * "<kerneldir>/scripts/get_dvb_firmware tda10046" to
* download/extract them, and then copy them to /usr/lib/hotplug/firmware
* or /lib/firmware (depending on configuration of firmware hotplug).
*/
diff --git a/drivers/media/dvb-frontends/tda10071.c b/drivers/media/dvb-frontends/tda10071.c
index a59f4fd..1ed67c0 100644
--- a/drivers/media/dvb-frontends/tda10071.c
+++ b/drivers/media/dvb-frontends/tda10071.c
@@ -852,7 +852,7 @@ static int tda10071_init(struct dvb_frontend *fe)
ret = request_firmware(&fw, fw_file, &client->dev);
if (ret) {
dev_err(&client->dev,
- "did not find the firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)\n",
+ "did not find the firmware file '%s' (status %d). You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware\n",
fw_file, ret);
goto error;
}
diff --git a/drivers/media/dvb-frontends/z0194a.h b/drivers/media/dvb-frontends/z0194a.h
index 96d86d6..0871c1a 100644
--- a/drivers/media/dvb-frontends/z0194a.h
+++ b/drivers/media/dvb-frontends/z0194a.h
@@ -6,7 +6,7 @@
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
-* see Documentation/dvb/README.dvb-usb for more information
+* see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef Z0194A
diff --git a/drivers/media/i2c/max2175.c b/drivers/media/i2c/max2175.c
index 87cba15..008a082 100644
--- a/drivers/media/i2c/max2175.c
+++ b/drivers/media/i2c/max2175.c
@@ -1202,7 +1202,7 @@ static const struct v4l2_ctrl_ops max2175_ctrl_ops = {
/*
* I2S output enable/disable configuration. This is a private control.
- * Refer to Documentation/media/v4l-drivers/max2175 for more details.
+ * Refer to Documentation/media/v4l-drivers/max2175.rst for more details.
*/
static const struct v4l2_ctrl_config max2175_i2s_en = {
.ops = &max2175_ctrl_ops,
@@ -1218,7 +1218,7 @@ static const struct v4l2_ctrl_config max2175_i2s_en = {
/*
* HSLS value control LO freq adjacent location configuration.
- * Refer to Documentation/media/v4l-drivers/max2175 for more details.
+ * Refer to Documentation/media/v4l-drivers/max2175.rst for more details.
*/
static const struct v4l2_ctrl_config max2175_hsls = {
.ops = &max2175_ctrl_ops,
@@ -1234,7 +1234,7 @@ static const struct v4l2_ctrl_config max2175_hsls = {
/*
* Rx modes below are a set of preset configurations that decides the tuner's
* sck and sample rate of transmission. They are separate for EU & NA regions.
- * Refer to Documentation/media/v4l-drivers/max2175 for more details.
+ * Refer to Documentation/media/v4l-drivers/max2175.rst for more details.
*/
static const char * const max2175_ctrl_eu_rx_modes[] = {
[MAX2175_EU_FM_1_2] = "EU FM 1.2",
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index ff46d2c..5007c96 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -373,7 +373,7 @@ static int s5k5baf_fw_parse(struct device *dev, struct s5k5baf_fw **fw,
data += S5K5BAG_FW_TAG_LEN;
count -= S5K5BAG_FW_TAG_LEN;
- d = devm_kzalloc(dev, count * sizeof(u16), GFP_KERNEL);
+ d = devm_kcalloc(dev, count, sizeof(u16), GFP_KERNEL);
if (!d)
return -ENOMEM;
diff --git a/drivers/media/pci/bt8xx/Kconfig b/drivers/media/pci/bt8xx/Kconfig
index 4a93f6d..bc89e37 100644
--- a/drivers/media/pci/bt8xx/Kconfig
+++ b/drivers/media/pci/bt8xx/Kconfig
@@ -16,7 +16,7 @@ config VIDEO_BT848
---help---
Support for BT848 based frame grabber/overlay boards. This includes
the Miro, Hauppauge and STB boards. Please read the material in
- <file:Documentation/video4linux/bttv/> for more information.
+ <file:Documentation/media/v4l-drivers/bttv.rst> for more information.
To compile this driver as a module, choose M here: the
module will be called bttv.
diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c
index 6a6be0b..74aff68 100644
--- a/drivers/media/pci/bt8xx/bttv-risc.c
+++ b/drivers/media/pci/bt8xx/bttv-risc.c
@@ -256,7 +256,8 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc,
u32 addr;
/* skip list for window clipping */
- if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL)))
+ skips = kmalloc_array(ov->nclips, sizeof(*skips),GFP_KERNEL);
+ if (NULL == skips)
return -ENOMEM;
/* estimate risc mem: worst case is (1.5*clip+1) * lines instructions
diff --git a/drivers/media/pci/cx18/cx18-dvb.c b/drivers/media/pci/cx18/cx18-dvb.c
index 010f39e..a3a7f70 100644
--- a/drivers/media/pci/cx18/cx18-dvb.c
+++ b/drivers/media/pci/cx18/cx18-dvb.c
@@ -152,7 +152,7 @@ static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream,
if (ret) {
CX18_ERR("The MPC718 board variant with the MT352 DVB-T demodulator will not work without it\n");
- CX18_ERR("Run 'linux/Documentation/dvb/get_dvb_firmware mpc718' if you need the firmware\n");
+ CX18_ERR("Run 'linux/scripts/get_dvb_firmware mpc718' if you need the firmware\n");
}
return ret;
}
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
index a594cfd..b36f4ce 100644
--- a/drivers/media/pci/cx18/cx18-streams.c
+++ b/drivers/media/pci/cx18/cx18-streams.c
@@ -853,7 +853,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
/*
* Audio related reset according to
- * Documentation/video4linux/cx2341x/fw-encoder-api.txt
+ * Documentation/media/v4l-drivers/cx2341x.rst
*/
if (atomic_read(&cx->ana_capturing) == 0)
cx18_vapi(cx, CX18_CPU_SET_MISC_PARAMETERS, 2,
@@ -861,7 +861,7 @@ int cx18_start_v4l2_encode_stream(struct cx18_stream *s)
/*
* Number of lines for Field 1 & Field 2 according to
- * Documentation/video4linux/cx2341x/fw-encoder-api.txt
+ * Documentation/media/v4l-drivers/cx2341x.rst
* Field 1 is 312 for 625 line systems in BT.656
* Field 2 is 313 for 625 line systems in BT.656
*/
diff --git a/drivers/media/pci/cx23885/cx23885-alsa.c b/drivers/media/pci/cx23885/cx23885-alsa.c
index 20b3cb1..db1e8ff 100644
--- a/drivers/media/pci/cx23885/cx23885-alsa.c
+++ b/drivers/media/pci/cx23885/cx23885-alsa.c
@@ -95,7 +95,7 @@ static int cx23885_alsa_dma_init(struct cx23885_audio_dev *chip, int nr_pages)
memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
buf->nr_pages = nr_pages;
- buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
+ buf->sglist = vzalloc(array_size(sizeof(*buf->sglist), buf->nr_pages));
if (NULL == buf->sglist)
goto vzalloc_err;
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
index 3a1c551..9f50748 100644
--- a/drivers/media/pci/cx23885/cx23885-cards.c
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
@@ -2426,7 +2426,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
ret = request_firmware(&fw, filename, &dev->pci->dev);
if (ret != 0)
- pr_err("did not find the firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems.",
+ pr_err("did not find the firmware file '%s'. You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware.",
filename);
else
altera_init(&netup_config, fw);
diff --git a/drivers/media/pci/cx25821/cx25821-alsa.c b/drivers/media/pci/cx25821/cx25821-alsa.c
index a45bf03..ef63806 100644
--- a/drivers/media/pci/cx25821/cx25821-alsa.c
+++ b/drivers/media/pci/cx25821/cx25821-alsa.c
@@ -159,7 +159,7 @@ static int cx25821_alsa_dma_init(struct cx25821_audio_dev *chip, int nr_pages)
memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
buf->nr_pages = nr_pages;
- buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
+ buf->sglist = vzalloc(array_size(sizeof(*buf->sglist), buf->nr_pages));
if (NULL == buf->sglist)
goto vzalloc_err;
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index 8a28fda..e5c3387 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -298,7 +298,7 @@ static int cx88_alsa_dma_init(struct cx88_audio_dev *chip, int nr_pages)
memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
buf->nr_pages = nr_pages;
- buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
+ buf->sglist = vzalloc(array_size(sizeof(*buf->sglist), buf->nr_pages));
if (!buf->sglist)
goto vzalloc_err;
diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
index 8e62b8b..b19058e 100644
--- a/drivers/media/pci/ivtv/ivtvfb.c
+++ b/drivers/media/pci/ivtv/ivtvfb.c
@@ -1077,7 +1077,7 @@ static int ivtvfb_init_vidmode(struct ivtv *itv)
/* Allocate the pseudo palette */
oi->ivtvfb_info.pseudo_palette =
- kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
+ kmalloc_array(16, sizeof(u32), GFP_KERNEL|__GFP_NOWARN);
if (!oi->ivtvfb_info.pseudo_palette) {
IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
diff --git a/drivers/media/pci/meye/Kconfig b/drivers/media/pci/meye/Kconfig
index 2e60334..9a50f54 100644
--- a/drivers/media/pci/meye/Kconfig
+++ b/drivers/media/pci/meye/Kconfig
@@ -5,7 +5,7 @@ config VIDEO_MEYE
---help---
This is the video4linux driver for the Motion Eye camera found
in the Vaio Picturebook laptops. Please read the material in
- <file:Documentation/video4linux/meye.txt> for more information.
+ <file:Documentation/media/v4l-drivers/meye.rst> for more information.
If you say Y or M here, you need to say Y or M to "Sony Laptop
Extras" in the misc device section.
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
index dedcdb5..8001d3e 100644
--- a/drivers/media/pci/meye/meye.c
+++ b/drivers/media/pci/meye/meye.c
@@ -1625,7 +1625,7 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
ret = -ENOMEM;
meye.mchip_dev = pcidev;
- meye.grab_temp = vmalloc(MCHIP_NB_PAGES_MJPEG * PAGE_SIZE);
+ meye.grab_temp = vmalloc(array_size(PAGE_SIZE, MCHIP_NB_PAGES_MJPEG));
if (!meye.grab_temp)
goto outvmalloc;
diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c
index 5708f69..fda969a 100644
--- a/drivers/media/pci/pt1/pt1.c
+++ b/drivers/media/pci/pt1/pt1.c
@@ -615,7 +615,7 @@ static int pt1_init_tables(struct pt1 *pt1)
if (!pt1_nr_tables)
return 0;
- tables = vmalloc(sizeof(struct pt1_table) * pt1_nr_tables);
+ tables = vmalloc(array_size(pt1_nr_tables, sizeof(struct pt1_table)));
if (tables == NULL)
return -ENOMEM;
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
index 7231144..b90cfde 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -279,7 +279,7 @@ static int saa7134_alsa_dma_init(struct saa7134_dev *dev, int nr_pages)
memset(dma->vaddr, 0, nr_pages << PAGE_SHIFT);
dma->nr_pages = nr_pages;
- dma->sglist = vzalloc(dma->nr_pages * sizeof(*dma->sglist));
+ dma->sglist = vzalloc(array_size(sizeof(*dma->sglist), dma->nr_pages));
if (NULL == dma->sglist)
goto vzalloc_err;
diff --git a/drivers/media/pci/ttpci/Kconfig b/drivers/media/pci/ttpci/Kconfig
index 7b83151..dfba74d 100644
--- a/drivers/media/pci/ttpci/Kconfig
+++ b/drivers/media/pci/ttpci/Kconfig
@@ -24,7 +24,7 @@ config DVB_AV7110
onboard MPEG2 decoder.
This driver needs an external firmware. Please use the script
- "<kerneldir>/Documentation/dvb/get_dvb_firmware av7110" to
+ "<kerneldir>/scripts/get_dvb_firmware av7110" to
download/extract it, and then copy it to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
diff --git a/drivers/media/pci/ttpci/av7110_ipack.c b/drivers/media/pci/ttpci/av7110_ipack.c
index 5aff265..ec528fa 100644
--- a/drivers/media/pci/ttpci/av7110_ipack.c
+++ b/drivers/media/pci/ttpci/av7110_ipack.c
@@ -24,7 +24,7 @@ void av7110_ipack_reset(struct ipack *p)
int av7110_ipack_init(struct ipack *p, int size,
void (*func)(u8 *buf, int size, void *priv))
{
- if (!(p->buf = vmalloc(size*sizeof(u8)))) {
+ if (!(p->buf = vmalloc(size))) {
printk(KERN_WARNING "Couldn't allocate memory for ipack\n");
return -ENOMEM;
}
diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c
index 58ebc22..b05738a 100644
--- a/drivers/media/platform/am437x/am437x-vpfe.c
+++ b/drivers/media/platform/am437x/am437x-vpfe.c
@@ -2586,8 +2586,10 @@ static int vpfe_probe(struct platform_device *pdev)
pm_runtime_put_sync(&pdev->dev);
- vpfe->sd = devm_kzalloc(&pdev->dev, sizeof(struct v4l2_subdev *) *
- ARRAY_SIZE(vpfe->cfg->asd), GFP_KERNEL);
+ vpfe->sd = devm_kcalloc(&pdev->dev,
+ ARRAY_SIZE(vpfe->cfg->asd),
+ sizeof(struct v4l2_subdev *),
+ GFP_KERNEL);
if (!vpfe->sd) {
ret = -ENOMEM;
goto probe_out_v4l2_unregister;
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index 9364cdf..a96f53c 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -1528,8 +1528,10 @@ vpif_capture_get_pdata(struct platform_device *pdev)
if (!pdata)
return NULL;
pdata->subdev_info =
- devm_kzalloc(&pdev->dev, sizeof(*pdata->subdev_info) *
- VPIF_CAPTURE_NUM_CHANNELS, GFP_KERNEL);
+ devm_kcalloc(&pdev->dev,
+ VPIF_CAPTURE_NUM_CHANNELS,
+ sizeof(*pdata->subdev_info),
+ GFP_KERNEL);
if (!pdata->subdev_info)
return NULL;
@@ -1546,9 +1548,9 @@ vpif_capture_get_pdata(struct platform_device *pdev)
sdinfo = &pdata->subdev_info[i];
chan = &pdata->chan_config[i];
- chan->inputs = devm_kzalloc(&pdev->dev,
- sizeof(*chan->inputs) *
+ chan->inputs = devm_kcalloc(&pdev->dev,
VPIF_CAPTURE_NUM_CHANNELS,
+ sizeof(*chan->inputs),
GFP_KERNEL);
if (!chan->inputs)
return NULL;
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index 3cf3000..6d9f0ab 100644
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -12,7 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c
index 4d5a26b..d85ffbf 100644
--- a/drivers/media/platform/pxa_camera.c
+++ b/drivers/media/platform/pxa_camera.c
@@ -1021,7 +1021,7 @@ static void pxa_camera_wakeup(struct pxa_camera_dev *pcdev,
* - a videobuffer is queued on the pcdev->capture list
*
* Please check the "DMA hot chaining timeslice issue" in
- * Documentation/video4linux/pxa_camera.txt
+ * Documentation/media/v4l-drivers/pxa_camera.rst
*
* Context: should only be called within the dma irq handler
*/
@@ -1443,7 +1443,7 @@ static void pxac_vb2_queue(struct vb2_buffer *vb)
/*
* Please check the DMA prepared buffer structure in :
- * Documentation/video4linux/pxa_camera.txt
+ * Documentation/media/v4l-drivers/pxa_camera.rst
* Please check also in pxa_camera_check_link_miss() to understand why DMA chain
* modification while DMA chain is running will work anyway.
*/
diff --git a/drivers/media/platform/qcom/camss-8x16/camss-csid.c b/drivers/media/platform/qcom/camss-8x16/camss-csid.c
index 64df828..226f36e 100644
--- a/drivers/media/platform/qcom/camss-8x16/camss-csid.c
+++ b/drivers/media/platform/qcom/camss-8x16/camss-csid.c
@@ -845,7 +845,7 @@ int msm_csid_subdev_init(struct csid_device *csid,
while (res->clock[csid->nclocks])
csid->nclocks++;
- csid->clock = devm_kzalloc(dev, csid->nclocks * sizeof(*csid->clock),
+ csid->clock = devm_kcalloc(dev, csid->nclocks, sizeof(*csid->clock),
GFP_KERNEL);
if (!csid->clock)
return -ENOMEM;
@@ -868,8 +868,10 @@ int msm_csid_subdev_init(struct csid_device *csid,
continue;
}
- clock->freq = devm_kzalloc(dev, clock->nfreqs *
- sizeof(*clock->freq), GFP_KERNEL);
+ clock->freq = devm_kcalloc(dev,
+ clock->nfreqs,
+ sizeof(*clock->freq),
+ GFP_KERNEL);
if (!clock->freq)
return -ENOMEM;
diff --git a/drivers/media/platform/qcom/camss-8x16/camss-csiphy.c b/drivers/media/platform/qcom/camss-8x16/camss-csiphy.c
index 072c6cf..7e61cab 100644
--- a/drivers/media/platform/qcom/camss-8x16/camss-csiphy.c
+++ b/drivers/media/platform/qcom/camss-8x16/camss-csiphy.c
@@ -732,8 +732,9 @@ int msm_csiphy_subdev_init(struct csiphy_device *csiphy,
while (res->clock[csiphy->nclocks])
csiphy->nclocks++;
- csiphy->clock = devm_kzalloc(dev, csiphy->nclocks *
- sizeof(*csiphy->clock), GFP_KERNEL);
+ csiphy->clock = devm_kcalloc(dev,
+ csiphy->nclocks, sizeof(*csiphy->clock),
+ GFP_KERNEL);
if (!csiphy->clock)
return -ENOMEM;
@@ -755,8 +756,10 @@ int msm_csiphy_subdev_init(struct csiphy_device *csiphy,
continue;
}
- clock->freq = devm_kzalloc(dev, clock->nfreqs *
- sizeof(*clock->freq), GFP_KERNEL);
+ clock->freq = devm_kcalloc(dev,
+ clock->nfreqs,
+ sizeof(*clock->freq),
+ GFP_KERNEL);
if (!clock->freq)
return -ENOMEM;
diff --git a/drivers/media/platform/qcom/camss-8x16/camss-ispif.c b/drivers/media/platform/qcom/camss-8x16/camss-ispif.c
index 24da529..9d1af93 100644
--- a/drivers/media/platform/qcom/camss-8x16/camss-ispif.c
+++ b/drivers/media/platform/qcom/camss-8x16/camss-ispif.c
@@ -948,7 +948,8 @@ int msm_ispif_subdev_init(struct ispif_device *ispif,
while (res->clock[ispif->nclocks])
ispif->nclocks++;
- ispif->clock = devm_kzalloc(dev, ispif->nclocks * sizeof(*ispif->clock),
+ ispif->clock = devm_kcalloc(dev,
+ ispif->nclocks, sizeof(*ispif->clock),
GFP_KERNEL);
if (!ispif->clock)
return -ENOMEM;
@@ -968,8 +969,10 @@ int msm_ispif_subdev_init(struct ispif_device *ispif,
while (res->clock_for_reset[ispif->nclocks_for_reset])
ispif->nclocks_for_reset++;
- ispif->clock_for_reset = devm_kzalloc(dev, ispif->nclocks_for_reset *
- sizeof(*ispif->clock_for_reset), GFP_KERNEL);
+ ispif->clock_for_reset = devm_kcalloc(dev,
+ ispif->nclocks_for_reset,
+ sizeof(*ispif->clock_for_reset),
+ GFP_KERNEL);
if (!ispif->clock_for_reset)
return -ENOMEM;
diff --git a/drivers/media/platform/qcom/camss-8x16/camss-vfe.c b/drivers/media/platform/qcom/camss-8x16/camss-vfe.c
index 55232a9..a6329a8 100644
--- a/drivers/media/platform/qcom/camss-8x16/camss-vfe.c
+++ b/drivers/media/platform/qcom/camss-8x16/camss-vfe.c
@@ -2794,7 +2794,7 @@ int msm_vfe_subdev_init(struct vfe_device *vfe, const struct resources *res)
while (res->clock[vfe->nclocks])
vfe->nclocks++;
- vfe->clock = devm_kzalloc(dev, vfe->nclocks * sizeof(*vfe->clock),
+ vfe->clock = devm_kcalloc(dev, vfe->nclocks, sizeof(*vfe->clock),
GFP_KERNEL);
if (!vfe->clock)
return -ENOMEM;
@@ -2817,8 +2817,10 @@ int msm_vfe_subdev_init(struct vfe_device *vfe, const struct resources *res)
continue;
}
- clock->freq = devm_kzalloc(dev, clock->nfreqs *
- sizeof(*clock->freq), GFP_KERNEL);
+ clock->freq = devm_kcalloc(dev,
+ clock->nfreqs,
+ sizeof(*clock->freq),
+ GFP_KERNEL);
if (!clock->freq)
return -ENOMEM;
diff --git a/drivers/media/platform/qcom/camss-8x16/camss.c b/drivers/media/platform/qcom/camss-8x16/camss.c
index 05f06c9..23fda62 100644
--- a/drivers/media/platform/qcom/camss-8x16/camss.c
+++ b/drivers/media/platform/qcom/camss-8x16/camss.c
@@ -271,7 +271,8 @@ static int camss_of_parse_endpoint_node(struct device *dev,
lncfg->clk.pol = mipi_csi2->lane_polarities[0];
lncfg->num_data = mipi_csi2->num_data_lanes;
- lncfg->data = devm_kzalloc(dev, lncfg->num_data * sizeof(*lncfg->data),
+ lncfg->data = devm_kcalloc(dev,
+ lncfg->num_data, sizeof(*lncfg->data),
GFP_KERNEL);
if (!lncfg->data)
return -ENOMEM;
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 242342f..9897213 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -1111,7 +1111,7 @@ static void sh_mobile_ceu_put_formats(struct soc_camera_device *icd)
/*
* CEU can scale and crop, but we don't want to waste bandwidth and kill the
* framerate by always requesting the maximum image from the client. See
- * Documentation/video4linux/sh_mobile_ceu_camera.txt for a description of
+ * Documentation/media/v4l-drivers/sh_mobile_ceu_camera.rst for a description of
* scaling and cropping algorithms and for the meaning of referenced here steps.
*/
static int sh_mobile_ceu_set_selection(struct soc_camera_device *icd,
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 69f0d8e..66d6136 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -481,7 +481,8 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
return -ENXIO;
icd->user_formats =
- vmalloc(fmts * sizeof(struct soc_camera_format_xlate));
+ vmalloc(array_size(fmts,
+ sizeof(struct soc_camera_format_xlate)));
if (!icd->user_formats)
return -ENOMEM;
diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c
index f01c3e8..c8bb82f 100644
--- a/drivers/media/platform/via-camera.c
+++ b/drivers/media/platform/via-camera.c
@@ -27,7 +27,12 @@
#include <linux/via-core.h>
#include <linux/via-gpio.h>
#include <linux/via_i2c.h>
+
+#ifdef CONFIG_X86
#include <asm/olpc.h>
+#else
+#define machine_is_olpc(x) 0
+#endif
#include "via-camera.h"
diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index 82ec216..31db363 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -844,10 +844,10 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
tpg_init(&dev->tpg, 640, 360);
if (tpg_alloc(&dev->tpg, MAX_ZOOM * MAX_WIDTH))
goto free_dev;
- dev->scaled_line = vzalloc(MAX_ZOOM * MAX_WIDTH);
+ dev->scaled_line = vzalloc(array_size(MAX_WIDTH, MAX_ZOOM));
if (!dev->scaled_line)
goto free_dev;
- dev->blended_line = vzalloc(MAX_ZOOM * MAX_WIDTH);
+ dev->blended_line = vzalloc(array_size(MAX_WIDTH, MAX_ZOOM));
if (!dev->blended_line)
goto free_dev;
@@ -859,8 +859,9 @@ static int vivid_create_instance(struct platform_device *pdev, int inst)
/* create a string array containing the names of all the preset timings */
while (v4l2_dv_timings_presets[dev->query_dv_timings_size].bt.width)
dev->query_dv_timings_size++;
- dev->query_dv_timings_qmenu = kmalloc(dev->query_dv_timings_size *
- (sizeof(void *) + 32), GFP_KERNEL);
+ dev->query_dv_timings_qmenu = kmalloc_array(dev->query_dv_timings_size,
+ (sizeof(void *) + 32),
+ GFP_KERNEL);
if (dev->query_dv_timings_qmenu == NULL)
goto free_dev;
for (i = 0; i < dev->query_dv_timings_size; i++) {
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index da276a8..36a29e1 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -630,7 +630,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
entity->source_pad = num_pads - 1;
/* Allocate and initialize pads. */
- entity->pads = devm_kzalloc(vsp1->dev, num_pads * sizeof(*entity->pads),
+ entity->pads = devm_kcalloc(vsp1->dev,
+ num_pads, sizeof(*entity->pads),
GFP_KERNEL);
if (entity->pads == NULL)
return -ENOMEM;
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c b/drivers/media/platform/xilinx/xilinx-vipp.c
index 6bb28cd..6d95ec1 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -532,7 +532,7 @@ static int xvip_graph_init(struct xvip_composite_device *xdev)
/* Register the subdevices notifier. */
num_subdevs = xdev->num_subdevs;
- subdevs = devm_kzalloc(xdev->dev, sizeof(*subdevs) * num_subdevs,
+ subdevs = devm_kcalloc(xdev->dev, num_subdevs, sizeof(*subdevs),
GFP_KERNEL);
if (subdevs == NULL) {
ret = -ENOMEM;
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 39b04ad..9b99dfb 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -35,7 +35,7 @@ config RADIO_SI476X
In order to control your radio card, you will need to use programs
that are compatible with the Video For Linux 2 API. Information on
this API and pointers to "v4l2" programs may be found at
- <file:Documentation/video4linux/API.html>.
+ <file:Documentation/media/media_uapi.rst>.
To compile this driver as a module, choose M here: the
module will be called radio-si476x.
@@ -75,7 +75,7 @@ config RADIO_MAXIRADIO
In order to control your radio card, you will need to use programs
that are compatible with the Video For Linux API. Information on
this API and pointers to "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
+ <file:Documentation/media/media_uapi.rst>.
To compile this driver as a module, choose M here: the
module will be called radio-maxiradio.
@@ -93,7 +93,7 @@ config RADIO_SHARK
In order to control your radio card, you will need to use programs
that are compatible with the Video For Linux API. Information on
this API and pointers to "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
+ <file:Documentation/media/media_uapi.rst>.
To compile this driver as a module, choose M here: the
module will be called radio-shark.
@@ -110,7 +110,7 @@ config RADIO_SHARK2
In order to control your radio card, you will need to use programs
that are compatible with the Video For Linux API. Information on
this API and pointers to "v4l" programs may be found at
- <file:Documentation/video4linux/API.html>.
+ <file:Documentation/media/media_uapi.rst>.
To compile this driver as a module, choose M here: the
module will be called radio-shark2.
@@ -217,7 +217,7 @@ config RADIO_WL1273
In order to control your radio card, you will need to use programs
that are compatible with the Video For Linux 2 API. Information on
this API and pointers to "v4l2" programs may be found at
- <file:Documentation/video4linux/API.html>.
+ <file:Documentation/media/media_uapi.rst>.
To compile this driver as a module, choose M here: the
module will be called radio-wl1273.
@@ -272,7 +272,7 @@ config RADIO_RTRACK
been reported to be used by these cards.
More information is contained in the file
- <file:Documentation/video4linux/radiotrack.txt>.
+ <file:Documentation/media/v4l-drivers/radiotrack.rst>.
To compile this driver as a module, choose M here: the
module will be called radio-aimslab.
diff --git a/drivers/media/radio/si470x/Kconfig b/drivers/media/radio/si470x/Kconfig
index a21172e..6dbb158 100644
--- a/drivers/media/radio/si470x/Kconfig
+++ b/drivers/media/radio/si470x/Kconfig
@@ -29,7 +29,7 @@ config USB_SI470X
Please have a look at the documentation, especially on how
to redirect the audio stream from the radio to your sound device:
- Documentation/video4linux/si470x.txt
+ Documentation/media/v4l-drivers/si470x.rst
Say Y here if you want to connect this type of radio to your
computer's USB port.
diff --git a/drivers/media/radio/wl128x/Kconfig b/drivers/media/radio/wl128x/Kconfig
index 2add222..64b66bb 100644
--- a/drivers/media/radio/wl128x/Kconfig
+++ b/drivers/media/radio/wl128x/Kconfig
@@ -12,6 +12,6 @@ config RADIO_WL128X
In order to control your radio card, you will need to use programs
that are compatible with the Video For Linux 2 API. Information on
this API and pointers to "v4l2" programs may be found at
- <file:Documentation/video4linux/API.html>.
+ <file:Documentation/media/media_uapi.rst>.
endmenu
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 49265f0..8a93f74 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -22,7 +22,6 @@
#include <linux/hrtimer.h>
#include <media/rc-core.h>
-#include <linux/platform_data/media/ir-rx51.h>
#define WBUF_LEN 256
@@ -31,7 +30,6 @@ struct ir_rx51 {
struct pwm_device *pwm;
struct hrtimer timer;
struct device *dev;
- struct ir_rx51_platform_data *pdata;
wait_queue_head_t wqueue;
unsigned int freq; /* carrier frequency */
@@ -130,10 +128,9 @@ static int ir_rx51_tx(struct rc_dev *dev, unsigned int *buffer,
ir_rx51->wbuf[count] = -1; /* Insert termination mark */
/*
- * Adjust latency requirements so the device doesn't go in too
- * deep sleep states
+ * REVISIT: Adjust latency requirements so the device doesn't go in too
+ * deep sleep states with pm_qos_add_request().
*/
- ir_rx51->pdata->set_max_mpu_wakeup_lat(ir_rx51->dev, 50);
ir_rx51_on(ir_rx51);
ir_rx51->wbuf_index = 1;
@@ -146,8 +143,7 @@ static int ir_rx51_tx(struct rc_dev *dev, unsigned int *buffer,
*/
wait_event_interruptible(ir_rx51->wqueue, ir_rx51->wbuf_index < 0);
- /* We can sleep again */
- ir_rx51->pdata->set_max_mpu_wakeup_lat(ir_rx51->dev, -1);
+ /* REVISIT: Remove pm_qos constraint, we can sleep again */
return count;
}
@@ -244,13 +240,6 @@ static int ir_rx51_probe(struct platform_device *dev)
struct pwm_device *pwm;
struct rc_dev *rcdev;
- ir_rx51.pdata = dev->dev.platform_data;
-
- if (!ir_rx51.pdata) {
- dev_err(&dev->dev, "Platform Data is missing\n");
- return -ENXIO;
- }
-
pwm = pwm_get(&dev->dev, NULL);
if (IS_ERR(pwm)) {
int err = PTR_ERR(pwm);
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 964cd7b..70e1879 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -217,14 +217,14 @@ static int au0828_init_isoc(struct au0828_dev *dev, int max_packets,
dev->isoc_ctl.isoc_copy = isoc_copy;
dev->isoc_ctl.num_bufs = num_bufs;
- dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+ dev->isoc_ctl.urb = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL);
if (!dev->isoc_ctl.urb) {
au0828_isocdbg("cannot alloc memory for usb buffers\n");
return -ENOMEM;
}
- dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
- GFP_KERNEL);
+ dev->isoc_ctl.transfer_buffer = kcalloc(num_bufs, sizeof(void *),
+ GFP_KERNEL);
if (!dev->isoc_ctl.transfer_buffer) {
au0828_isocdbg("cannot allocate memory for usb transfer\n");
kfree(dev->isoc_ctl.urb);
diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c
index b51fc37..a771e0a 100644
--- a/drivers/media/usb/cpia2/cpia2_usb.c
+++ b/drivers/media/usb/cpia2/cpia2_usb.c
@@ -663,7 +663,8 @@ static int submit_urbs(struct camera_data *cam)
if (cam->sbuf[i].data)
continue;
cam->sbuf[i].data =
- kmalloc(FRAMES_PER_DESC * FRAME_SIZE_PER_DESC, GFP_KERNEL);
+ kmalloc_array(FRAME_SIZE_PER_DESC, FRAMES_PER_DESC,
+ GFP_KERNEL);
if (!cam->sbuf[i].data) {
while (--i >= 0) {
kfree(cam->sbuf[i].data);
diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c
index d96236d..c4a84fb 100644
--- a/drivers/media/usb/cx231xx/cx231xx-audio.c
+++ b/drivers/media/usb/cx231xx/cx231xx-audio.c
@@ -710,7 +710,7 @@ static int cx231xx_audio_init(struct cx231xx *dev)
dev_info(dev->dev,
"audio EndPoint Addr 0x%x, Alternate settings: %i\n",
adev->end_point_addr, adev->num_alt);
- adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL);
+ adev->alt_max_pkt_size = kmalloc_array(32, adev->num_alt, GFP_KERNEL);
if (!adev->alt_max_pkt_size) {
err = -ENOMEM;
goto err_free_card;
diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c
index 4f43668..53d846d 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -1034,7 +1034,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
dma_q->partial_buf[i] = 0;
dev->video_mode.isoc_ctl.urb =
- kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+ kcalloc(num_bufs, sizeof(void *), GFP_KERNEL);
if (!dev->video_mode.isoc_ctl.urb) {
dev_err(dev->dev,
"cannot alloc memory for usb buffers\n");
@@ -1042,7 +1042,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
}
dev->video_mode.isoc_ctl.transfer_buffer =
- kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+ kcalloc(num_bufs, sizeof(void *), GFP_KERNEL);
if (!dev->video_mode.isoc_ctl.transfer_buffer) {
dev_err(dev->dev,
"cannot allocate memory for usbtransfer\n");
@@ -1169,7 +1169,7 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets,
dma_q->partial_buf[i] = 0;
dev->video_mode.bulk_ctl.urb =
- kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+ kcalloc(num_bufs, sizeof(void *), GFP_KERNEL);
if (!dev->video_mode.bulk_ctl.urb) {
dev_err(dev->dev,
"cannot alloc memory for usb buffers\n");
@@ -1177,7 +1177,7 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets,
}
dev->video_mode.bulk_ctl.transfer_buffer =
- kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+ kcalloc(num_bufs, sizeof(void *), GFP_KERNEL);
if (!dev->video_mode.bulk_ctl.transfer_buffer) {
dev_err(dev->dev,
"cannot allocate memory for usbtransfer\n");
diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c
index d3bfe8e..b621cf1 100644
--- a/drivers/media/usb/cx231xx/cx231xx-vbi.c
+++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c
@@ -415,7 +415,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
for (i = 0; i < 8; i++)
dma_q->partial_buf[i] = 0;
- dev->vbi_mode.bulk_ctl.urb = kzalloc(sizeof(void *) * num_bufs,
+ dev->vbi_mode.bulk_ctl.urb = kcalloc(num_bufs, sizeof(void *),
GFP_KERNEL);
if (!dev->vbi_mode.bulk_ctl.urb) {
dev_err(dev->dev,
@@ -424,7 +424,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
}
dev->vbi_mode.bulk_ctl.transfer_buffer =
- kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
+ kcalloc(num_bufs, sizeof(void *), GFP_KERNEL);
if (!dev->vbi_mode.bulk_ctl.transfer_buffer) {
dev_err(dev->dev,
"cannot allocate memory for usbtransfer\n");
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
index 3705347..082b8d6 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -6,7 +6,7 @@ config DVB_USB_V2
USB1.1 and USB2.0 DVB devices.
Almost every USB device needs a firmware, please look into
- <file:Documentation/dvb/README.dvb-usb>.
+ <file:Documentation/media/dvb-drivers/dvb-usb.rst>.
For a complete list of supported USB devices see the LinuxTV DVB Wiki:
<https://linuxtv.org/wiki/index.php/DVB_USB>
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
index afdcdbf..955318a 100644
--- a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
+++ b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
@@ -47,7 +47,7 @@ static int dvb_usbv2_download_firmware(struct dvb_usb_device *d,
ret = request_firmware(&fw, name, &d->udev->dev);
if (ret < 0) {
dev_err(&d->udev->dev,
- "%s: Did not find the firmware file '%s'. Please see linux/Documentation/dvb/ for more details on firmware-problems. Status %d\n",
+ "%s: Did not find the firmware file '%s' (status %d). You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware\n",
KBUILD_MODNAME, name, ret);
goto err;
}
diff --git a/drivers/media/usb/dvb-usb-v2/gl861.c b/drivers/media/usb/dvb-usb-v2/gl861.c
index 4817dfd..9d154fd 100644
--- a/drivers/media/usb/dvb-usb-v2/gl861.c
+++ b/drivers/media/usb/dvb-usb-v2/gl861.c
@@ -4,7 +4,7 @@
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "gl861.h"
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index be26c02..0750a97 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -21,7 +21,7 @@
*
* LME2510C + M88RS2000
*
- * For firmware see Documentation/dvb/lmedm04.txt
+ * For firmware see Documentation/media/dvb-drivers/lmedm04.rst
*
* I2C addresses:
* 0xd0 - STV0288 - Demodulator
@@ -49,7 +49,7 @@
* GNU General Public License for more details.
*
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*
* Known Issues :
* LME2510: Non Intel USB chipsets fail to maintain High Speed on
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.h b/drivers/media/usb/dvb-usb-v2/lmedm04.h
index e9c2072..c4ae37c 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.h
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.h
@@ -16,7 +16,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
* *
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef _DVB_USB_LME2510_H_
#define _DVB_USB_LME2510_H_
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index 6795336..4713ba6 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -5,7 +5,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include <linux/vmalloc.h>
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.h b/drivers/media/usb/dvb-usb-v2/mxl111sf.h
index 3e6f588..22253d4 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.h
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.h
@@ -5,7 +5,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef _DVB_USB_MXL111SF_H_
diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
index 2651ae2..b8a1c62 100644
--- a/drivers/media/usb/dvb-usb/Kconfig
+++ b/drivers/media/usb/dvb-usb/Kconfig
@@ -6,7 +6,7 @@ config DVB_USB
USB1.1 and USB2.0 DVB devices.
Almost every USB device needs a firmware, please look into
- <file:Documentation/dvb/README.dvb-usb>.
+ <file:Documentation/media/dvb-drivers/dvb-usb.rst>.
For a complete list of supported USB devices see the LinuxTV DVB Wiki:
<https://linuxtv.org/wiki/index.php/DVB_USB>
diff --git a/drivers/media/usb/dvb-usb/a800.c b/drivers/media/usb/dvb-usb/a800.c
index 540886b..198bd5e 100644
--- a/drivers/media/usb/dvb-usb/a800.c
+++ b/drivers/media/usb/dvb-usb/a800.c
@@ -11,7 +11,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "dibusb.h"
diff --git a/drivers/media/usb/dvb-usb/af9005-fe.c b/drivers/media/usb/dvb-usb/af9005-fe.c
index 544bdf1..7fbbc95 100644
--- a/drivers/media/usb/dvb-usb/af9005-fe.c
+++ b/drivers/media/usb/dvb-usb/af9005-fe.c
@@ -15,7 +15,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "af9005.h"
#include "af9005-script.h"
diff --git a/drivers/media/usb/dvb-usb/af9005-remote.c b/drivers/media/usb/dvb-usb/af9005-remote.c
index 9b29ffa..f7cdcc8 100644
--- a/drivers/media/usb/dvb-usb/af9005-remote.c
+++ b/drivers/media/usb/dvb-usb/af9005-remote.c
@@ -17,7 +17,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "af9005.h"
/* debug */
diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c
index 986763b..16e946e 100644
--- a/drivers/media/usb/dvb-usb/af9005.c
+++ b/drivers/media/usb/dvb-usb/af9005.c
@@ -15,7 +15,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "af9005.h"
diff --git a/drivers/media/usb/dvb-usb/af9005.h b/drivers/media/usb/dvb-usb/af9005.h
index a1eae0f..7ae4dc3 100644
--- a/drivers/media/usb/dvb-usb/af9005.h
+++ b/drivers/media/usb/dvb-usb/af9005.h
@@ -15,7 +15,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef _DVB_USB_AF9005_H_
#define _DVB_USB_AF9005_H_
diff --git a/drivers/media/usb/dvb-usb/az6027.c b/drivers/media/usb/dvb-usb/az6027.c
index f0d10ac..6321b8e 100644
--- a/drivers/media/usb/dvb-usb/az6027.c
+++ b/drivers/media/usb/dvb-usb/az6027.c
@@ -7,7 +7,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "az6027.h"
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index b70d289..5b51ed7 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -21,7 +21,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include <media/tuner.h>
#include <linux/vmalloc.h>
diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c
index bcacb0f..fb1b4f2 100644
--- a/drivers/media/usb/dvb-usb/dibusb-common.c
+++ b/drivers/media/usb/dvb-usb/dibusb-common.c
@@ -6,7 +6,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "dibusb.h"
diff --git a/drivers/media/usb/dvb-usb/dibusb-mb.c b/drivers/media/usb/dvb-usb/dibusb-mb.c
index a005764..4089205 100644
--- a/drivers/media/usb/dvb-usb/dibusb-mb.c
+++ b/drivers/media/usb/dvb-usb/dibusb-mb.c
@@ -10,7 +10,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "dibusb.h"
diff --git a/drivers/media/usb/dvb-usb/dibusb-mc-common.c b/drivers/media/usb/dvb-usb/dibusb-mc-common.c
index 0c2bc97..ec3a20a 100644
--- a/drivers/media/usb/dvb-usb/dibusb-mc-common.c
+++ b/drivers/media/usb/dvb-usb/dibusb-mc-common.c
@@ -6,7 +6,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "dibusb.h"
diff --git a/drivers/media/usb/dvb-usb/dibusb-mc.c b/drivers/media/usb/dvb-usb/dibusb-mc.c
index 08fb8a3..bce8ffe 100644
--- a/drivers/media/usb/dvb-usb/dibusb-mc.c
+++ b/drivers/media/usb/dvb-usb/dibusb-mc.c
@@ -10,7 +10,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "dibusb.h"
diff --git a/drivers/media/usb/dvb-usb/dibusb.h b/drivers/media/usb/dvb-usb/dibusb.h
index 697be2a..943df579b 100644
--- a/drivers/media/usb/dvb-usb/dibusb.h
+++ b/drivers/media/usb/dvb-usb/dibusb.h
@@ -6,7 +6,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef _DVB_USB_DIBUSB_H_
#define _DVB_USB_DIBUSB_H_
diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c
index 475a3c0..49b9d63 100644
--- a/drivers/media/usb/dvb-usb/digitv.c
+++ b/drivers/media/usb/dvb-usb/digitv.c
@@ -9,7 +9,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "digitv.h"
diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c
index 00f565f..7e75aae 100644
--- a/drivers/media/usb/dvb-usb/dtt200u-fe.c
+++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c
@@ -7,7 +7,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "dtt200u.h"
diff --git a/drivers/media/usb/dvb-usb/dtt200u.c b/drivers/media/usb/dvb-usb/dtt200u.c
index 5123707..f03d269 100644
--- a/drivers/media/usb/dvb-usb/dtt200u.c
+++ b/drivers/media/usb/dvb-usb/dtt200u.c
@@ -9,7 +9,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "dtt200u.h"
diff --git a/drivers/media/usb/dvb-usb/dtt200u.h b/drivers/media/usb/dvb-usb/dtt200u.h
index efccc39..ea2a096 100644
--- a/drivers/media/usb/dvb-usb/dtt200u.h
+++ b/drivers/media/usb/dvb-usb/dtt200u.h
@@ -7,7 +7,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef _DVB_USB_DTT200U_H_
#define _DVB_USB_DTT200U_H_
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
index 15c153e..42c207a 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-firmware.c
@@ -90,7 +90,7 @@ int dvb_usb_download_firmware(struct usb_device *udev, struct dvb_usb_device_pro
const struct firmware *fw = NULL;
if ((ret = request_firmware(&fw, props->firmware, &udev->dev)) != 0) {
- err("did not find the firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+ err("did not find the firmware file '%s' (status %d). You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware",
props->firmware,ret);
return ret;
}
diff --git a/drivers/media/usb/dvb-usb/dvb-usb-init.c b/drivers/media/usb/dvb-usb/dvb-usb-init.c
index 8430856..40ca4ea 100644
--- a/drivers/media/usb/dvb-usb/dvb-usb-init.c
+++ b/drivers/media/usb/dvb-usb/dvb-usb-init.c
@@ -9,7 +9,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "dvb-usb-common.h"
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index 346946f..0d4fdd34 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -11,7 +11,7 @@
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include <media/dvb-usb-ids.h>
#include "dw2102.h"
@@ -61,9 +61,7 @@
#define P1100_FIRMWARE "dvb-usb-p1100.fw"
#define P7500_FIRMWARE "dvb-usb-p7500.fw"
-#define err_str "did not find the firmware file. (%s) " \
- "Please see linux/Documentation/dvb/ for more details " \
- "on firmware-problems."
+#define err_str "did not find the firmware file '%s'. You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware"
struct dw2102_state {
u8 initialized;
diff --git a/drivers/media/usb/dvb-usb/friio-fe.c b/drivers/media/usb/dvb-usb/friio-fe.c
index b2830c1..932f262 100644
--- a/drivers/media/usb/dvb-usb/friio-fe.c
+++ b/drivers/media/usb/dvb-usb/friio-fe.c
@@ -8,7 +8,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include <linux/init.h>
#include <linux/string.h>
diff --git a/drivers/media/usb/dvb-usb/friio.c b/drivers/media/usb/dvb-usb/friio.c
index 1687594..fe799a7 100644
--- a/drivers/media/usb/dvb-usb/friio.c
+++ b/drivers/media/usb/dvb-usb/friio.c
@@ -8,7 +8,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "friio.h"
diff --git a/drivers/media/usb/dvb-usb/friio.h b/drivers/media/usb/dvb-usb/friio.h
index 0f461ca..a53af56 100644
--- a/drivers/media/usb/dvb-usb/friio.h
+++ b/drivers/media/usb/dvb-usb/friio.h
@@ -8,7 +8,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef _DVB_USB_FRIIO_H_
#define _DVB_USB_FRIIO_H_
diff --git a/drivers/media/usb/dvb-usb/gp8psk.c b/drivers/media/usb/dvb-usb/gp8psk.c
index 334b9fb..13e96b0 100644
--- a/drivers/media/usb/dvb-usb/gp8psk.c
+++ b/drivers/media/usb/dvb-usb/gp8psk.c
@@ -12,7 +12,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "gp8psk.h"
#include "gp8psk-fe.h"
@@ -135,7 +135,7 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)
u8 *buf;
if ((ret = request_firmware(&fw, bcm4500_firmware,
&d->udev->dev)) != 0) {
- err("did not find the bcm4500 firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems. (%d)",
+ err("did not find the bcm4500 firmware file '%s' (status %d). You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware",
bcm4500_firmware,ret);
return ret;
}
diff --git a/drivers/media/usb/dvb-usb/gp8psk.h b/drivers/media/usb/dvb-usb/gp8psk.h
index d8975b8..fd063e3 100644
--- a/drivers/media/usb/dvb-usb/gp8psk.h
+++ b/drivers/media/usb/dvb-usb/gp8psk.h
@@ -12,7 +12,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef _DVB_USB_GP8PSK_H_
#define _DVB_USB_GP8PSK_H_
diff --git a/drivers/media/usb/dvb-usb/m920x.c b/drivers/media/usb/dvb-usb/m920x.c
index 32081c2..51b026f 100644
--- a/drivers/media/usb/dvb-usb/m920x.c
+++ b/drivers/media/usb/dvb-usb/m920x.c
@@ -6,7 +6,7 @@
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "m920x.h"
diff --git a/drivers/media/usb/dvb-usb/nova-t-usb2.c b/drivers/media/usb/dvb-usb/nova-t-usb2.c
index 1babd33..43e0e0f 100644
--- a/drivers/media/usb/dvb-usb/nova-t-usb2.c
+++ b/drivers/media/usb/dvb-usb/nova-t-usb2.c
@@ -7,7 +7,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "dibusb.h"
diff --git a/drivers/media/usb/dvb-usb/opera1.c b/drivers/media/usb/dvb-usb/opera1.c
index 946a5cc..61a377e 100644
--- a/drivers/media/usb/dvb-usb/opera1.c
+++ b/drivers/media/usb/dvb-usb/opera1.c
@@ -7,7 +7,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
-* see Documentation/dvb/README.dvb-usb for more information
+* see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#define DVB_USB_LOG_PREFIX "opera"
@@ -453,7 +453,7 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev,
info("start downloading fpga firmware %s",filename);
if ((ret = request_firmware(&fw, filename, &dev->dev)) != 0) {
- err("did not find the firmware file. (%s) Please see linux/Documentation/dvb/ for more details on firmware-problems.",
+ err("did not find the firmware file '%s'. You can use <kernel_dir>/scripts/get_dvb_firmware to get the firmware",
filename);
return ret;
} else {
diff --git a/drivers/media/usb/dvb-usb/ttusb2.c b/drivers/media/usb/dvb-usb/ttusb2.c
index 12de8966..b4d6811 100644
--- a/drivers/media/usb/dvb-usb/ttusb2.c
+++ b/drivers/media/usb/dvb-usb/ttusb2.c
@@ -20,7 +20,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#define DVB_USB_LOG_PREFIX "ttusb2"
#include "dvb-usb.h"
diff --git a/drivers/media/usb/dvb-usb/ttusb2.h b/drivers/media/usb/dvb-usb/ttusb2.h
index 52a63af..8b6525e 100644
--- a/drivers/media/usb/dvb-usb/ttusb2.h
+++ b/drivers/media/usb/dvb-usb/ttusb2.h
@@ -9,7 +9,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef _DVB_USB_TTUSB2_H_
#define _DVB_USB_TTUSB2_H_
diff --git a/drivers/media/usb/dvb-usb/umt-010.c b/drivers/media/usb/dvb-usb/umt-010.c
index 58ad5b4..920bc67 100644
--- a/drivers/media/usb/dvb-usb/umt-010.c
+++ b/drivers/media/usb/dvb-usb/umt-010.c
@@ -7,7 +7,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "dibusb.h"
diff --git a/drivers/media/usb/dvb-usb/vp702x-fe.c b/drivers/media/usb/dvb-usb/vp702x-fe.c
index 7ff31ba..ae48146 100644
--- a/drivers/media/usb/dvb-usb/vp702x-fe.c
+++ b/drivers/media/usb/dvb-usb/vp702x-fe.c
@@ -15,7 +15,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*
*/
#include "vp702x.h"
diff --git a/drivers/media/usb/dvb-usb/vp702x.c b/drivers/media/usb/dvb-usb/vp702x.c
index 40de33d..c3529ea 100644
--- a/drivers/media/usb/dvb-usb/vp702x.c
+++ b/drivers/media/usb/dvb-usb/vp702x.c
@@ -12,7 +12,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "vp702x.h"
#include <linux/mutex.h>
diff --git a/drivers/media/usb/dvb-usb/vp7045-fe.c b/drivers/media/usb/dvb-usb/vp7045-fe.c
index 4520ad9..f860401 100644
--- a/drivers/media/usb/dvb-usb/vp7045-fe.c
+++ b/drivers/media/usb/dvb-usb/vp7045-fe.c
@@ -9,7 +9,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*
*/
#include "vp7045.h"
diff --git a/drivers/media/usb/dvb-usb/vp7045.c b/drivers/media/usb/dvb-usb/vp7045.c
index 2527b88..e2c8a85 100644
--- a/drivers/media/usb/dvb-usb/vp7045.c
+++ b/drivers/media/usb/dvb-usb/vp7045.c
@@ -10,7 +10,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#include "vp7045.h"
diff --git a/drivers/media/usb/dvb-usb/vp7045.h b/drivers/media/usb/dvb-usb/vp7045.h
index 6649993..2fdafd8 100644
--- a/drivers/media/usb/dvb-usb/vp7045.h
+++ b/drivers/media/usb/dvb-usb/vp7045.h
@@ -9,7 +9,7 @@
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 2.
*
- * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/media/dvb-drivers/dvb-usb.rst for more information
*/
#ifndef _DVB_USB_VP7045_H_
#define _DVB_USB_VP7045_H_
diff --git a/drivers/media/usb/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c
index 87b4fc4..24f5b61 100644
--- a/drivers/media/usb/go7007/go7007-fw.c
+++ b/drivers/media/usb/go7007/go7007-fw.c
@@ -1579,7 +1579,7 @@ int go7007_construct_fw_image(struct go7007 *go, u8 **fw, int *fwlen)
GO7007_FW_NAME);
return -1;
}
- code = kzalloc(codespace * 2, GFP_KERNEL);
+ code = kcalloc(codespace, 2, GFP_KERNEL);
if (code == NULL)
goto fw_failed;
diff --git a/drivers/media/usb/go7007/go7007-usb.c b/drivers/media/usb/go7007/go7007-usb.c
index ed9bcaf..19c6a03 100644
--- a/drivers/media/usb/go7007/go7007-usb.c
+++ b/drivers/media/usb/go7007/go7007-usb.c
@@ -1143,7 +1143,8 @@ static int go7007_usb_probe(struct usb_interface *intf,
usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
if (usb->intr_urb == NULL)
goto allocfail;
- usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL);
+ usb->intr_urb->transfer_buffer = kmalloc_array(2, sizeof(u16),
+ GFP_KERNEL);
if (usb->intr_urb->transfer_buffer == NULL)
goto allocfail;
diff --git a/drivers/media/usb/gspca/m5602/Kconfig b/drivers/media/usb/gspca/m5602/Kconfig
index 5a69016..13a0039 100644
--- a/drivers/media/usb/gspca/m5602/Kconfig
+++ b/drivers/media/usb/gspca/m5602/Kconfig
@@ -5,7 +5,5 @@ config USB_M5602
Say Y here if you want support for cameras based on the
ALi m5602 connected to various image sensors.
- See <file:Documentation/video4linux/m5602.txt> for more info.
-
To compile this driver as a module, choose M here: the
module will be called gspca_m5602.
diff --git a/drivers/media/usb/gspca/t613.c b/drivers/media/usb/gspca/t613.c
index 0ae557c..4457829 100644
--- a/drivers/media/usb/gspca/t613.c
+++ b/drivers/media/usb/gspca/t613.c
@@ -363,7 +363,7 @@ static void reg_w_ixbuf(struct gspca_dev *gspca_dev,
if (len * 2 <= USB_BUF_SZ) {
p = tmpbuf = gspca_dev->usb_buf;
} else {
- p = tmpbuf = kmalloc(len * 2, GFP_KERNEL);
+ p = tmpbuf = kmalloc_array(len, 2, GFP_KERNEL);
if (!tmpbuf) {
pr_err("Out of memory\n");
return;
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index e035316..a8519da 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -2413,7 +2413,7 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
hdw->control_cnt = CTRLDEF_COUNT;
hdw->control_cnt += MPEGDEF_COUNT;
- hdw->controls = kzalloc(sizeof(struct pvr2_ctrl) * hdw->control_cnt,
+ hdw->controls = kcalloc(hdw->control_cnt, sizeof(struct pvr2_ctrl),
GFP_KERNEL);
if (!hdw->controls) goto fail;
hdw->hdw_desc = hdw_desc;
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-std.c b/drivers/media/usb/pvrusb2/pvrusb2-std.c
index 21bb20d..6b651f8 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-std.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-std.c
@@ -361,7 +361,7 @@ struct v4l2_standard *pvr2_std_create_enum(unsigned int *countptr,
std_cnt);
if (!std_cnt) return NULL; // paranoia
- stddefs = kzalloc(sizeof(struct v4l2_standard) * std_cnt,
+ stddefs = kcalloc(std_cnt, sizeof(struct v4l2_standard),
GFP_KERNEL);
if (!stddefs)
return NULL;
diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c
index 72bd893..468f5cc 100644
--- a/drivers/media/usb/stk1160/stk1160-core.c
+++ b/drivers/media/usb/stk1160/stk1160-core.c
@@ -290,8 +290,9 @@ static int stk1160_probe(struct usb_interface *interface,
return -ENODEV;
/* Alloc an array for all possible max_pkt_size */
- alt_max_pkt_size = kmalloc(sizeof(alt_max_pkt_size[0]) *
- interface->num_altsetting, GFP_KERNEL);
+ alt_max_pkt_size = kmalloc_array(interface->num_altsetting,
+ sizeof(alt_max_pkt_size[0]),
+ GFP_KERNEL);
if (alt_max_pkt_size == NULL)
return -ENOMEM;
diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
index 423c03a..2811f61 100644
--- a/drivers/media/usb/stk1160/stk1160-video.c
+++ b/drivers/media/usb/stk1160/stk1160-video.c
@@ -439,14 +439,14 @@ int stk1160_alloc_isoc(struct stk1160 *dev)
dev->isoc_ctl.buf = NULL;
dev->isoc_ctl.max_pkt_size = dev->max_pkt_size;
- dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+ dev->isoc_ctl.urb = kcalloc(num_bufs, sizeof(void *), GFP_KERNEL);
if (!dev->isoc_ctl.urb) {
stk1160_err("out of memory for urb array\n");
return -ENOMEM;
}
- dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
- GFP_KERNEL);
+ dev->isoc_ctl.transfer_buffer = kcalloc(num_bufs, sizeof(void *),
+ GFP_KERNEL);
if (!dev->isoc_ctl.transfer_buffer) {
stk1160_err("out of memory for usb transfers\n");
kfree(dev->isoc_ctl.urb);
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
index 22389b5..5accb52 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.c
+++ b/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -567,8 +567,9 @@ static int stk_prepare_sio_buffers(struct stk_camera *dev, unsigned n_sbufs)
if (dev->sio_bufs != NULL)
pr_err("sio_bufs already allocated\n");
else {
- dev->sio_bufs = kzalloc(n_sbufs * sizeof(struct stk_sio_buffer),
- GFP_KERNEL);
+ dev->sio_bufs = kcalloc(n_sbufs,
+ sizeof(struct stk_sio_buffer),
+ GFP_KERNEL);
if (dev->sio_bufs == NULL)
return -ENOMEM;
for (i = 0; i < n_sbufs; i++) {
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index aa85fe31..96055de 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
+++ b/drivers/media/usb/tm6000/tm6000-video.c
@@ -463,11 +463,12 @@ static int tm6000_alloc_urb_buffers(struct tm6000_core *dev)
if (dev->urb_buffer)
return 0;
- dev->urb_buffer = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+ dev->urb_buffer = kmalloc_array(num_bufs, sizeof(void *), GFP_KERNEL);
if (!dev->urb_buffer)
return -ENOMEM;
- dev->urb_dma = kmalloc(sizeof(dma_addr_t *)*num_bufs, GFP_KERNEL);
+ dev->urb_dma = kmalloc_array(num_bufs, sizeof(dma_addr_t *),
+ GFP_KERNEL);
if (!dev->urb_dma)
return -ENOMEM;
@@ -583,12 +584,14 @@ static int tm6000_prepare_isoc(struct tm6000_core *dev)
dev->isoc_ctl.num_bufs = num_bufs;
- dev->isoc_ctl.urb = kmalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+ dev->isoc_ctl.urb = kmalloc_array(num_bufs, sizeof(void *),
+ GFP_KERNEL);
if (!dev->isoc_ctl.urb)
return -ENOMEM;
- dev->isoc_ctl.transfer_buffer = kmalloc(sizeof(void *)*num_bufs,
- GFP_KERNEL);
+ dev->isoc_ctl.transfer_buffer = kmalloc_array(num_bufs,
+ sizeof(void *),
+ GFP_KERNEL);
if (!dev->isoc_ctl.transfer_buffer) {
kfree(dev->isoc_ctl.urb);
return -ENOMEM;
diff --git a/drivers/media/usb/ttusb-dec/Kconfig b/drivers/media/usb/ttusb-dec/Kconfig
index 290254a..b205903 100644
--- a/drivers/media/usb/ttusb-dec/Kconfig
+++ b/drivers/media/usb/ttusb-dec/Kconfig
@@ -12,9 +12,9 @@ config DVB_TTUSB_DEC
an external software decoder to watch TV on your computer.
This driver needs external firmware. Please use the commands
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2000t",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec2540t",
- "<kerneldir>/Documentation/dvb/get_dvb_firmware dec3000s",
+ "<kerneldir>/scripts/get_dvb_firmware dec2000t",
+ "<kerneldir>/scripts/get_dvb_firmware dec2540t",
+ "<kerneldir>/scripts/get_dvb_firmware dec3000s",
download/extract them, and then copy them to /usr/lib/hotplug/firmware
or /lib/firmware (depending on configuration of firmware hotplug).
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index ce79df6..36a9a40 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -507,7 +507,7 @@ static struct urb *usbtv_setup_iso_transfer(struct usbtv *usbtv)
ip->pipe = usb_rcvisocpipe(usbtv->udev, USBTV_VIDEO_ENDP);
ip->interval = 1;
ip->transfer_flags = URB_ISO_ASAP;
- ip->transfer_buffer = kzalloc(size * USBTV_ISOC_PACKETS,
+ ip->transfer_buffer = kcalloc(USBTV_ISOC_PACKETS, size,
GFP_KERNEL);
if (!ip->transfer_buffer) {
usb_free_urb(ip);
diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c
index 0f5954a..f29d1be 100644
--- a/drivers/media/usb/usbvision/usbvision-video.c
+++ b/drivers/media/usb/usbvision/usbvision-video.c
@@ -1492,7 +1492,8 @@ static int usbvision_probe(struct usb_interface *intf,
usbvision->num_alt = uif->num_altsetting;
PDEBUG(DBG_PROBE, "Alternate settings: %i", usbvision->num_alt);
- usbvision->alt_max_pkt_size = kmalloc(32 * usbvision->num_alt, GFP_KERNEL);
+ usbvision->alt_max_pkt_size = kmalloc_array(32, usbvision->num_alt,
+ GFP_KERNEL);
if (!usbvision->alt_max_pkt_size) {
ret = -ENOMEM;
goto err_pkt;
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index b28c997..a88b2e5 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -513,8 +513,8 @@ static int uvc_video_clock_init(struct uvc_streaming *stream)
spin_lock_init(&clock->lock);
clock->size = 32;
- clock->samples = kmalloc(clock->size * sizeof(*clock->samples),
- GFP_KERNEL);
+ clock->samples = kmalloc_array(clock->size, sizeof(*clock->samples),
+ GFP_KERNEL);
if (clock->samples == NULL)
return -ENOMEM;
diff --git a/drivers/media/usb/zr364xx/Kconfig b/drivers/media/usb/zr364xx/Kconfig
index 0f58566..ac429bc 100644
--- a/drivers/media/usb/zr364xx/Kconfig
+++ b/drivers/media/usb/zr364xx/Kconfig
@@ -6,7 +6,7 @@ config USB_ZR364XX
---help---
Say Y here if you want to connect this type of camera to your
computer's USB port.
- See <file:Documentation/video4linux/zr364xx.txt> for more info
+ See <file:Documentation/media/v4l-drivers/zr364xx.rst> for more info
and list of supported cameras.
To compile this driver as a module, choose M here: the
diff --git a/drivers/media/v4l2-core/v4l2-event.c b/drivers/media/v4l2-core/v4l2-event.c
index 968c2eb..127fe6e 100644
--- a/drivers/media/v4l2-core/v4l2-event.c
+++ b/drivers/media/v4l2-core/v4l2-event.c
@@ -215,8 +215,7 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
if (elems < 1)
elems = 1;
- sev = kvzalloc(sizeof(*sev) + sizeof(struct v4l2_kevent) * elems,
- GFP_KERNEL);
+ sev = kvzalloc(struct_size(sev, events, elems), GFP_KERNEL);
if (!sev)
return -ENOMEM;
for (i = 0; i < elems; i++)
diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c
index 4ceef21..215b480 100644
--- a/drivers/media/v4l2-core/v4l2-flash-led-class.c
+++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c
@@ -412,9 +412,10 @@ static int v4l2_flash_init_controls(struct v4l2_flash *v4l2_flash,
struct v4l2_ctrl_config *ctrl_cfg;
int i, ret, num_ctrls = 0;
- v4l2_flash->ctrls = devm_kzalloc(v4l2_flash->sd.dev,
- sizeof(*v4l2_flash->ctrls) *
- (STROBE_SOURCE + 1), GFP_KERNEL);
+ v4l2_flash->ctrls = devm_kcalloc(v4l2_flash->sd.dev,
+ STROBE_SOURCE + 1,
+ sizeof(*v4l2_flash->ctrls),
+ GFP_KERNEL);
if (!v4l2_flash->ctrls)
return -ENOMEM;
diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c
index 2e5c346..08929c0 100644
--- a/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c
@@ -69,7 +69,7 @@ static struct scatterlist *videobuf_vmalloc_to_sg(unsigned char *virt,
struct page *pg;
int i;
- sglist = vzalloc(nr_pages * sizeof(*sglist));
+ sglist = vzalloc(array_size(nr_pages, sizeof(*sglist)));
if (NULL == sglist)
return NULL;
sg_init_table(sglist, nr_pages);
@@ -100,7 +100,7 @@ static struct scatterlist *videobuf_pages_to_sg(struct page **pages,
if (NULL == pages[0])
return NULL;
- sglist = vmalloc(nr_pages * sizeof(*sglist));
+ sglist = vmalloc(array_size(nr_pages, sizeof(*sglist)));
if (NULL == sglist)
return NULL;
sg_init_table(sglist, nr_pages);
@@ -175,7 +175,8 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
dma->offset = data & ~PAGE_MASK;
dma->size = size;
dma->nr_pages = last-first+1;
- dma->pages = kmalloc(dma->nr_pages * sizeof(struct page *), GFP_KERNEL);
+ dma->pages = kmalloc_array(dma->nr_pages, sizeof(struct page *),
+ GFP_KERNEL);
if (NULL == dma->pages)
return -ENOMEM;
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 19a0e83..8d731d6 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -104,16 +104,6 @@ config MVEBU_DEVBUS
Armada 370 and Armada XP. This controller allows to handle flash
devices such as NOR, NAND, SRAM, and FPGA.
-config TEGRA20_MC
- bool "Tegra20 Memory Controller(MC) driver"
- default y
- depends on ARCH_TEGRA_2x_SOC
- help
- This driver is for the Memory Controller(MC) module available
- in Tegra20 SoCs, mainly for a address translation fault
- analysis, especially for IOMMU/GART(Graphics Address
- Relocation Table) module.
-
config FSL_CORENET_CF
tristate "Freescale CoreNet Error Reporting"
depends on FSL_SOC_BOOKE
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index 66f5524..a01ab3e 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -16,7 +16,6 @@ obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o
obj-$(CONFIG_FSL_CORENET_CF) += fsl-corenet-cf.o
obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
obj-$(CONFIG_MVEBU_DEVBUS) += mvebu-devbus.o
-obj-$(CONFIG_TEGRA20_MC) += tegra20-mc.o
obj-$(CONFIG_JZ4780_NEMC) += jz4780-nemc.o
obj-$(CONFIG_MTK_SMI) += mtk-smi.o
obj-$(CONFIG_DA8XX_DDRCTL) += da8xx-ddrctl.o
diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c
index e9c1485..04599ec 100644
--- a/drivers/memory/brcmstb_dpfe.c
+++ b/drivers/memory/brcmstb_dpfe.c
@@ -176,7 +176,6 @@ struct private_data {
void __iomem *dmem;
void __iomem *imem;
struct device *dev;
- unsigned int index;
struct mutex lock;
};
@@ -674,10 +673,8 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct private_data *priv;
- struct device *dpfe_dev;
struct init_data init;
struct resource *res;
- u32 index;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -687,11 +684,6 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
mutex_init(&priv->lock);
platform_set_drvdata(pdev, priv);
- /* Cell index is optional; default to 0 if not present. */
- ret = of_property_read_u32(dev->of_node, "cell-index", &index);
- if (ret)
- index = 0;
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-cpu");
priv->regs = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->regs)) {
@@ -715,35 +707,20 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev)
ret = brcmstb_dpfe_download_firmware(pdev, &init);
if (ret)
- goto err;
-
- dpfe_dev = devm_kzalloc(dev, sizeof(*dpfe_dev), GFP_KERNEL);
- if (!dpfe_dev) {
- ret = -ENOMEM;
- goto err;
- }
-
- priv->dev = dpfe_dev;
- priv->index = index;
+ return ret;
- dpfe_dev->parent = dev;
- dpfe_dev->groups = dpfe_groups;
- dpfe_dev->of_node = dev->of_node;
- dev_set_drvdata(dpfe_dev, priv);
- dev_set_name(dpfe_dev, "dpfe%u", index);
+ ret = sysfs_create_groups(&pdev->dev.kobj, dpfe_groups);
+ if (!ret)
+ dev_info(dev, "registered.\n");
- ret = device_register(dpfe_dev);
- if (ret)
- goto err;
+ return ret;
+}
- dev_info(dev, "registered.\n");
+static int brcmstb_dpfe_remove(struct platform_device *pdev)
+{
+ sysfs_remove_groups(&pdev->dev.kobj, dpfe_groups);
return 0;
-
-err:
- dev_err(dev, "failed to initialize -- error %d\n", ret);
-
- return ret;
}
static const struct of_device_id brcmstb_dpfe_of_match[] = {
@@ -758,6 +735,7 @@ static struct platform_driver brcmstb_dpfe_driver = {
.of_match_table = brcmstb_dpfe_of_match,
},
.probe = brcmstb_dpfe_probe,
+ .remove = brcmstb_dpfe_remove,
.resume = brcmstb_dpfe_resume,
};
diff --git a/drivers/memory/of_memory.c b/drivers/memory/of_memory.c
index 568f05e..2f5ed73 100644
--- a/drivers/memory/of_memory.c
+++ b/drivers/memory/of_memory.c
@@ -126,8 +126,8 @@ const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
arr_sz++;
if (arr_sz)
- timings = devm_kzalloc(dev, sizeof(*timings) * arr_sz,
- GFP_KERNEL);
+ timings = devm_kcalloc(dev, arr_sz, sizeof(*timings),
+ GFP_KERNEL);
if (!timings)
goto default_timings;
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 90a66b3..c215287 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -2060,8 +2060,8 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
* timings.
*/
name = gpmc_cs_get_name(cs);
- if (name && child->name && of_node_cmp(child->name, name) == 0)
- goto no_timings;
+ if (name && of_node_cmp(child->name, name) == 0)
+ goto no_timings;
ret = gpmc_cs_request(cs, resource_size(&res), &base);
if (ret < 0) {
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
index ce87a94..94ab16b 100644
--- a/drivers/memory/tegra/Makefile
+++ b/drivers/memory/tegra/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
tegra-mc-y := mc.o
+tegra-mc-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20.o
tegra-mc-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30.o
tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o
tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index a4803ac..bb93cc5 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -7,6 +7,7 @@
*/
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -20,14 +21,6 @@
#include "mc.h"
#define MC_INTSTATUS 0x000
-#define MC_INT_DECERR_MTS (1 << 16)
-#define MC_INT_SECERR_SEC (1 << 13)
-#define MC_INT_DECERR_VPR (1 << 12)
-#define MC_INT_INVALID_APB_ASID_UPDATE (1 << 11)
-#define MC_INT_INVALID_SMMU_PAGE (1 << 10)
-#define MC_INT_ARBITRATION_EMEM (1 << 9)
-#define MC_INT_SECURITY_VIOLATION (1 << 8)
-#define MC_INT_DECERR_EMEM (1 << 6)
#define MC_INTMASK 0x004
@@ -45,6 +38,9 @@
#define MC_ERR_ADR 0x0c
+#define MC_DECERR_EMEM_OTHERS_STATUS 0x58
+#define MC_SECURITY_VIOLATION_STATUS 0x74
+
#define MC_EMEM_ARB_CFG 0x90
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE(x) (((x) & 0x1ff) << 0)
#define MC_EMEM_ARB_CFG_CYCLES_PER_UPDATE_MASK 0x1ff
@@ -54,6 +50,9 @@
#define MC_EMEM_ADR_CFG_EMEM_NUMDEV BIT(0)
static const struct of_device_id tegra_mc_of_match[] = {
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+ { .compatible = "nvidia,tegra20-mc", .data = &tegra20_mc_soc },
+#endif
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
{ .compatible = "nvidia,tegra30-mc", .data = &tegra30_mc_soc },
#endif
@@ -73,6 +72,207 @@ static const struct of_device_id tegra_mc_of_match[] = {
};
MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
+static int terga_mc_block_dma_common(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst)
+{
+ unsigned long flags;
+ u32 value;
+
+ spin_lock_irqsave(&mc->lock, flags);
+
+ value = mc_readl(mc, rst->control) | BIT(rst->bit);
+ mc_writel(mc, value, rst->control);
+
+ spin_unlock_irqrestore(&mc->lock, flags);
+
+ return 0;
+}
+
+static bool terga_mc_dma_idling_common(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst)
+{
+ return (mc_readl(mc, rst->status) & BIT(rst->bit)) != 0;
+}
+
+static int terga_mc_unblock_dma_common(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst)
+{
+ unsigned long flags;
+ u32 value;
+
+ spin_lock_irqsave(&mc->lock, flags);
+
+ value = mc_readl(mc, rst->control) & ~BIT(rst->bit);
+ mc_writel(mc, value, rst->control);
+
+ spin_unlock_irqrestore(&mc->lock, flags);
+
+ return 0;
+}
+
+static int terga_mc_reset_status_common(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst)
+{
+ return (mc_readl(mc, rst->control) & BIT(rst->bit)) != 0;
+}
+
+const struct tegra_mc_reset_ops terga_mc_reset_ops_common = {
+ .block_dma = terga_mc_block_dma_common,
+ .dma_idling = terga_mc_dma_idling_common,
+ .unblock_dma = terga_mc_unblock_dma_common,
+ .reset_status = terga_mc_reset_status_common,
+};
+
+static inline struct tegra_mc *reset_to_mc(struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct tegra_mc, reset);
+}
+
+static const struct tegra_mc_reset *tegra_mc_reset_find(struct tegra_mc *mc,
+ unsigned long id)
+{
+ unsigned int i;
+
+ for (i = 0; i < mc->soc->num_resets; i++)
+ if (mc->soc->resets[i].id == id)
+ return &mc->soc->resets[i];
+
+ return NULL;
+}
+
+static int tegra_mc_hotreset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct tegra_mc *mc = reset_to_mc(rcdev);
+ const struct tegra_mc_reset_ops *rst_ops;
+ const struct tegra_mc_reset *rst;
+ int retries = 500;
+ int err;
+
+ rst = tegra_mc_reset_find(mc, id);
+ if (!rst)
+ return -ENODEV;
+
+ rst_ops = mc->soc->reset_ops;
+ if (!rst_ops)
+ return -ENODEV;
+
+ if (rst_ops->block_dma) {
+ /* block clients DMA requests */
+ err = rst_ops->block_dma(mc, rst);
+ if (err) {
+ dev_err(mc->dev, "Failed to block %s DMA: %d\n",
+ rst->name, err);
+ return err;
+ }
+ }
+
+ if (rst_ops->dma_idling) {
+ /* wait for completion of the outstanding DMA requests */
+ while (!rst_ops->dma_idling(mc, rst)) {
+ if (!retries--) {
+ dev_err(mc->dev, "Failed to flush %s DMA\n",
+ rst->name);
+ return -EBUSY;
+ }
+
+ usleep_range(10, 100);
+ }
+ }
+
+ if (rst_ops->hotreset_assert) {
+ /* clear clients DMA requests sitting before arbitration */
+ err = rst_ops->hotreset_assert(mc, rst);
+ if (err) {
+ dev_err(mc->dev, "Failed to hot reset %s: %d\n",
+ rst->name, err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int tegra_mc_hotreset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct tegra_mc *mc = reset_to_mc(rcdev);
+ const struct tegra_mc_reset_ops *rst_ops;
+ const struct tegra_mc_reset *rst;
+ int err;
+
+ rst = tegra_mc_reset_find(mc, id);
+ if (!rst)
+ return -ENODEV;
+
+ rst_ops = mc->soc->reset_ops;
+ if (!rst_ops)
+ return -ENODEV;
+
+ if (rst_ops->hotreset_deassert) {
+ /* take out client from hot reset */
+ err = rst_ops->hotreset_deassert(mc, rst);
+ if (err) {
+ dev_err(mc->dev, "Failed to deassert hot reset %s: %d\n",
+ rst->name, err);
+ return err;
+ }
+ }
+
+ if (rst_ops->unblock_dma) {
+ /* allow new DMA requests to proceed to arbitration */
+ err = rst_ops->unblock_dma(mc, rst);
+ if (err) {
+ dev_err(mc->dev, "Failed to unblock %s DMA : %d\n",
+ rst->name, err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int tegra_mc_hotreset_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct tegra_mc *mc = reset_to_mc(rcdev);
+ const struct tegra_mc_reset_ops *rst_ops;
+ const struct tegra_mc_reset *rst;
+
+ rst = tegra_mc_reset_find(mc, id);
+ if (!rst)
+ return -ENODEV;
+
+ rst_ops = mc->soc->reset_ops;
+ if (!rst_ops)
+ return -ENODEV;
+
+ return rst_ops->reset_status(mc, rst);
+}
+
+static const struct reset_control_ops tegra_mc_reset_ops = {
+ .assert = tegra_mc_hotreset_assert,
+ .deassert = tegra_mc_hotreset_deassert,
+ .status = tegra_mc_hotreset_status,
+};
+
+static int tegra_mc_reset_setup(struct tegra_mc *mc)
+{
+ int err;
+
+ mc->reset.ops = &tegra_mc_reset_ops;
+ mc->reset.owner = THIS_MODULE;
+ mc->reset.of_node = mc->dev->of_node;
+ mc->reset.of_reset_n_cells = 1;
+ mc->reset.nr_resets = mc->soc->num_resets;
+
+ err = reset_controller_register(&mc->reset);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
static int tegra_mc_setup_latency_allowance(struct tegra_mc *mc)
{
unsigned long long tick;
@@ -229,6 +429,7 @@ static int tegra_mc_setup_timings(struct tegra_mc *mc)
static const char *const status_names[32] = {
[ 1] = "External interrupt",
[ 6] = "EMEM address decode error",
+ [ 7] = "GART page fault",
[ 8] = "Security violation",
[ 9] = "EMEM arbitration error",
[10] = "Page fault",
@@ -248,12 +449,13 @@ static const char *const error_names[8] = {
static irqreturn_t tegra_mc_irq(int irq, void *data)
{
struct tegra_mc *mc = data;
- unsigned long status, mask;
+ unsigned long status;
unsigned int bit;
/* mask all interrupts to avoid flooding */
- status = mc_readl(mc, MC_INTSTATUS);
- mask = mc_readl(mc, MC_INTMASK);
+ status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
+ if (!status)
+ return IRQ_NONE;
for_each_set_bit(bit, &status, 32) {
const char *error = status_names[bit] ?: "unknown";
@@ -341,12 +543,78 @@ static irqreturn_t tegra_mc_irq(int irq, void *data)
return IRQ_HANDLED;
}
+static __maybe_unused irqreturn_t tegra20_mc_irq(int irq, void *data)
+{
+ struct tegra_mc *mc = data;
+ unsigned long status;
+ unsigned int bit;
+
+ /* mask all interrupts to avoid flooding */
+ status = mc_readl(mc, MC_INTSTATUS) & mc->soc->intmask;
+ if (!status)
+ return IRQ_NONE;
+
+ for_each_set_bit(bit, &status, 32) {
+ const char *direction = "read", *secure = "";
+ const char *error = status_names[bit];
+ const char *client, *desc;
+ phys_addr_t addr;
+ u32 value, reg;
+ u8 id, type;
+
+ switch (BIT(bit)) {
+ case MC_INT_DECERR_EMEM:
+ reg = MC_DECERR_EMEM_OTHERS_STATUS;
+ value = mc_readl(mc, reg);
+
+ id = value & mc->soc->client_id_mask;
+ desc = error_names[2];
+
+ if (value & BIT(31))
+ direction = "write";
+ break;
+
+ case MC_INT_INVALID_GART_PAGE:
+ dev_err_ratelimited(mc->dev, "%s\n", error);
+ continue;
+
+ case MC_INT_SECURITY_VIOLATION:
+ reg = MC_SECURITY_VIOLATION_STATUS;
+ value = mc_readl(mc, reg);
+
+ id = value & mc->soc->client_id_mask;
+ type = (value & BIT(30)) ? 4 : 3;
+ desc = error_names[type];
+ secure = "secure ";
+
+ if (value & BIT(31))
+ direction = "write";
+ break;
+
+ default:
+ continue;
+ }
+
+ client = mc->soc->clients[id].name;
+ addr = mc_readl(mc, reg + sizeof(u32));
+
+ dev_err_ratelimited(mc->dev, "%s: %s%s @%pa: %s (%s)\n",
+ client, secure, direction, &addr, error,
+ desc);
+ }
+
+ /* clear interrupts */
+ mc_writel(mc, status, MC_INTSTATUS);
+
+ return IRQ_HANDLED;
+}
+
static int tegra_mc_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
struct resource *res;
struct tegra_mc *mc;
- u32 value;
+ void *isr;
int err;
match = of_match_node(tegra_mc_of_match, pdev->dev.of_node);
@@ -358,6 +626,7 @@ static int tegra_mc_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, mc);
+ spin_lock_init(&mc->lock);
mc->soc = match->data;
mc->dev = &pdev->dev;
@@ -369,18 +638,32 @@ static int tegra_mc_probe(struct platform_device *pdev)
if (IS_ERR(mc->regs))
return PTR_ERR(mc->regs);
- mc->clk = devm_clk_get(&pdev->dev, "mc");
- if (IS_ERR(mc->clk)) {
- dev_err(&pdev->dev, "failed to get MC clock: %ld\n",
- PTR_ERR(mc->clk));
- return PTR_ERR(mc->clk);
- }
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+ if (mc->soc == &tegra20_mc_soc) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ mc->regs2 = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mc->regs2))
+ return PTR_ERR(mc->regs2);
- err = tegra_mc_setup_latency_allowance(mc);
- if (err < 0) {
- dev_err(&pdev->dev, "failed to setup latency allowance: %d\n",
- err);
- return err;
+ isr = tegra20_mc_irq;
+ } else
+#endif
+ {
+ mc->clk = devm_clk_get(&pdev->dev, "mc");
+ if (IS_ERR(mc->clk)) {
+ dev_err(&pdev->dev, "failed to get MC clock: %ld\n",
+ PTR_ERR(mc->clk));
+ return PTR_ERR(mc->clk);
+ }
+
+ err = tegra_mc_setup_latency_allowance(mc);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to setup latency allowance: %d\n",
+ err);
+ return err;
+ }
+
+ isr = tegra_mc_irq;
}
err = tegra_mc_setup_timings(mc);
@@ -389,13 +672,11 @@ static int tegra_mc_probe(struct platform_device *pdev)
return err;
}
- if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) {
- mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
- if (IS_ERR(mc->smmu)) {
- dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
- PTR_ERR(mc->smmu));
- return PTR_ERR(mc->smmu);
- }
+ err = tegra_mc_reset_setup(mc);
+ if (err < 0) {
+ dev_err(&pdev->dev, "failed to register reset controller: %d\n",
+ err);
+ return err;
}
mc->irq = platform_get_irq(pdev, 0);
@@ -404,7 +685,11 @@ static int tegra_mc_probe(struct platform_device *pdev)
return mc->irq;
}
- err = devm_request_irq(&pdev->dev, mc->irq, tegra_mc_irq, IRQF_SHARED,
+ WARN(!mc->soc->client_id_mask, "Missing client ID mask for this SoC\n");
+
+ mc_writel(mc, mc->soc->intmask, MC_INTMASK);
+
+ err = devm_request_irq(&pdev->dev, mc->irq, isr, IRQF_SHARED,
dev_name(&pdev->dev), mc);
if (err < 0) {
dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", mc->irq,
@@ -412,13 +697,14 @@ static int tegra_mc_probe(struct platform_device *pdev)
return err;
}
- WARN(!mc->soc->client_id_mask, "Missing client ID mask for this SoC\n");
-
- value = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
- MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
- MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM;
-
- mc_writel(mc, value, MC_INTMASK);
+ if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) {
+ mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
+ if (IS_ERR(mc->smmu)) {
+ dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
+ PTR_ERR(mc->smmu));
+ return PTR_ERR(mc->smmu);
+ }
+ }
return 0;
}
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
index ddb1667..01065f1 100644
--- a/drivers/memory/tegra/mc.h
+++ b/drivers/memory/tegra/mc.h
@@ -14,17 +14,39 @@
#include <soc/tegra/mc.h>
+#define MC_INT_DECERR_MTS (1 << 16)
+#define MC_INT_SECERR_SEC (1 << 13)
+#define MC_INT_DECERR_VPR (1 << 12)
+#define MC_INT_INVALID_APB_ASID_UPDATE (1 << 11)
+#define MC_INT_INVALID_SMMU_PAGE (1 << 10)
+#define MC_INT_ARBITRATION_EMEM (1 << 9)
+#define MC_INT_SECURITY_VIOLATION (1 << 8)
+#define MC_INT_INVALID_GART_PAGE (1 << 7)
+#define MC_INT_DECERR_EMEM (1 << 6)
+
static inline u32 mc_readl(struct tegra_mc *mc, unsigned long offset)
{
+ if (mc->regs2 && offset >= 0x24)
+ return readl(mc->regs2 + offset - 0x3c);
+
return readl(mc->regs + offset);
}
static inline void mc_writel(struct tegra_mc *mc, u32 value,
unsigned long offset)
{
+ if (mc->regs2 && offset >= 0x24)
+ return writel(value, mc->regs2 + offset - 0x3c);
+
writel(value, mc->regs + offset);
}
+extern const struct tegra_mc_reset_ops terga_mc_reset_ops_common;
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+extern const struct tegra_mc_soc tegra20_mc_soc;
+#endif
+
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
extern const struct tegra_mc_soc tegra30_mc_soc;
#endif
diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c
index b20e6e3..6560a51 100644
--- a/drivers/memory/tegra/tegra114.c
+++ b/drivers/memory/tegra/tegra114.c
@@ -938,6 +938,34 @@ static const struct tegra_smmu_soc tegra114_smmu_soc = {
.num_asids = 4,
};
+#define TEGRA114_MC_RESET(_name, _control, _status, _bit) \
+ { \
+ .name = #_name, \
+ .id = TEGRA114_MC_RESET_##_name, \
+ .control = _control, \
+ .status = _status, \
+ .bit = _bit, \
+ }
+
+static const struct tegra_mc_reset tegra114_mc_resets[] = {
+ TEGRA114_MC_RESET(AVPC, 0x200, 0x204, 1),
+ TEGRA114_MC_RESET(DC, 0x200, 0x204, 2),
+ TEGRA114_MC_RESET(DCB, 0x200, 0x204, 3),
+ TEGRA114_MC_RESET(EPP, 0x200, 0x204, 4),
+ TEGRA114_MC_RESET(2D, 0x200, 0x204, 5),
+ TEGRA114_MC_RESET(HC, 0x200, 0x204, 6),
+ TEGRA114_MC_RESET(HDA, 0x200, 0x204, 7),
+ TEGRA114_MC_RESET(ISP, 0x200, 0x204, 8),
+ TEGRA114_MC_RESET(MPCORE, 0x200, 0x204, 9),
+ TEGRA114_MC_RESET(MPCORELP, 0x200, 0x204, 10),
+ TEGRA114_MC_RESET(MPE, 0x200, 0x204, 11),
+ TEGRA114_MC_RESET(3D, 0x200, 0x204, 12),
+ TEGRA114_MC_RESET(3D2, 0x200, 0x204, 13),
+ TEGRA114_MC_RESET(PPCS, 0x200, 0x204, 14),
+ TEGRA114_MC_RESET(VDE, 0x200, 0x204, 16),
+ TEGRA114_MC_RESET(VI, 0x200, 0x204, 17),
+};
+
const struct tegra_mc_soc tegra114_mc_soc = {
.clients = tegra114_mc_clients,
.num_clients = ARRAY_SIZE(tegra114_mc_clients),
@@ -945,4 +973,9 @@ const struct tegra_mc_soc tegra114_mc_soc = {
.atom_size = 32,
.client_id_mask = 0x7f,
.smmu = &tegra114_smmu_soc,
+ .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
+ MC_INT_DECERR_EMEM,
+ .reset_ops = &terga_mc_reset_ops_common,
+ .resets = tegra114_mc_resets,
+ .num_resets = ARRAY_SIZE(tegra114_mc_resets),
};
diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c
index 8b6360e..b561a1f 100644
--- a/drivers/memory/tegra/tegra124.c
+++ b/drivers/memory/tegra/tegra124.c
@@ -1012,6 +1012,42 @@ static const struct tegra_smmu_group_soc tegra124_groups[] = {
},
};
+#define TEGRA124_MC_RESET(_name, _control, _status, _bit) \
+ { \
+ .name = #_name, \
+ .id = TEGRA124_MC_RESET_##_name, \
+ .control = _control, \
+ .status = _status, \
+ .bit = _bit, \
+ }
+
+static const struct tegra_mc_reset tegra124_mc_resets[] = {
+ TEGRA124_MC_RESET(AFI, 0x200, 0x204, 0),
+ TEGRA124_MC_RESET(AVPC, 0x200, 0x204, 1),
+ TEGRA124_MC_RESET(DC, 0x200, 0x204, 2),
+ TEGRA124_MC_RESET(DCB, 0x200, 0x204, 3),
+ TEGRA124_MC_RESET(HC, 0x200, 0x204, 6),
+ TEGRA124_MC_RESET(HDA, 0x200, 0x204, 7),
+ TEGRA124_MC_RESET(ISP2, 0x200, 0x204, 8),
+ TEGRA124_MC_RESET(MPCORE, 0x200, 0x204, 9),
+ TEGRA124_MC_RESET(MPCORELP, 0x200, 0x204, 10),
+ TEGRA124_MC_RESET(MSENC, 0x200, 0x204, 11),
+ TEGRA124_MC_RESET(PPCS, 0x200, 0x204, 14),
+ TEGRA124_MC_RESET(SATA, 0x200, 0x204, 15),
+ TEGRA124_MC_RESET(VDE, 0x200, 0x204, 16),
+ TEGRA124_MC_RESET(VI, 0x200, 0x204, 17),
+ TEGRA124_MC_RESET(VIC, 0x200, 0x204, 18),
+ TEGRA124_MC_RESET(XUSB_HOST, 0x200, 0x204, 19),
+ TEGRA124_MC_RESET(XUSB_DEV, 0x200, 0x204, 20),
+ TEGRA124_MC_RESET(TSEC, 0x200, 0x204, 21),
+ TEGRA124_MC_RESET(SDMMC1, 0x200, 0x204, 22),
+ TEGRA124_MC_RESET(SDMMC2, 0x200, 0x204, 23),
+ TEGRA124_MC_RESET(SDMMC3, 0x200, 0x204, 25),
+ TEGRA124_MC_RESET(SDMMC4, 0x970, 0x974, 0),
+ TEGRA124_MC_RESET(ISP2B, 0x970, 0x974, 1),
+ TEGRA124_MC_RESET(GPU, 0x970, 0x974, 2),
+};
+
#ifdef CONFIG_ARCH_TEGRA_124_SOC
static const struct tegra_smmu_soc tegra124_smmu_soc = {
.clients = tegra124_mc_clients,
@@ -1035,6 +1071,12 @@ const struct tegra_mc_soc tegra124_mc_soc = {
.smmu = &tegra124_smmu_soc,
.emem_regs = tegra124_mc_emem_regs,
.num_emem_regs = ARRAY_SIZE(tegra124_mc_emem_regs),
+ .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
+ MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
+ MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
+ .reset_ops = &terga_mc_reset_ops_common,
+ .resets = tegra124_mc_resets,
+ .num_resets = ARRAY_SIZE(tegra124_mc_resets),
};
#endif /* CONFIG_ARCH_TEGRA_124_SOC */
@@ -1059,5 +1101,11 @@ const struct tegra_mc_soc tegra132_mc_soc = {
.atom_size = 32,
.client_id_mask = 0x7f,
.smmu = &tegra132_smmu_soc,
+ .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
+ MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
+ MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
+ .reset_ops = &terga_mc_reset_ops_common,
+ .resets = tegra124_mc_resets,
+ .num_resets = ARRAY_SIZE(tegra124_mc_resets),
};
#endif /* CONFIG_ARCH_TEGRA_132_SOC */
diff --git a/drivers/memory/tegra/tegra20.c b/drivers/memory/tegra/tegra20.c
new file mode 100644
index 0000000..7119e53
--- /dev/null
+++ b/drivers/memory/tegra/tegra20.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2012 NVIDIA 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 <dt-bindings/memory/tegra20-mc.h>
+
+#include "mc.h"
+
+static const struct tegra_mc_client tegra20_mc_clients[] = {
+ {
+ .id = 0x00,
+ .name = "display0a",
+ }, {
+ .id = 0x01,
+ .name = "display0ab",
+ }, {
+ .id = 0x02,
+ .name = "display0b",
+ }, {
+ .id = 0x03,
+ .name = "display0bb",
+ }, {
+ .id = 0x04,
+ .name = "display0c",
+ }, {
+ .id = 0x05,
+ .name = "display0cb",
+ }, {
+ .id = 0x06,
+ .name = "display1b",
+ }, {
+ .id = 0x07,
+ .name = "display1bb",
+ }, {
+ .id = 0x08,
+ .name = "eppup",
+ }, {
+ .id = 0x09,
+ .name = "g2pr",
+ }, {
+ .id = 0x0a,
+ .name = "g2sr",
+ }, {
+ .id = 0x0b,
+ .name = "mpeunifbr",
+ }, {
+ .id = 0x0c,
+ .name = "viruv",
+ }, {
+ .id = 0x0d,
+ .name = "avpcarm7r",
+ }, {
+ .id = 0x0e,
+ .name = "displayhc",
+ }, {
+ .id = 0x0f,
+ .name = "displayhcb",
+ }, {
+ .id = 0x10,
+ .name = "fdcdrd",
+ }, {
+ .id = 0x11,
+ .name = "g2dr",
+ }, {
+ .id = 0x12,
+ .name = "host1xdmar",
+ }, {
+ .id = 0x13,
+ .name = "host1xr",
+ }, {
+ .id = 0x14,
+ .name = "idxsrd",
+ }, {
+ .id = 0x15,
+ .name = "mpcorer",
+ }, {
+ .id = 0x16,
+ .name = "mpe_ipred",
+ }, {
+ .id = 0x17,
+ .name = "mpeamemrd",
+ }, {
+ .id = 0x18,
+ .name = "mpecsrd",
+ }, {
+ .id = 0x19,
+ .name = "ppcsahbdmar",
+ }, {
+ .id = 0x1a,
+ .name = "ppcsahbslvr",
+ }, {
+ .id = 0x1b,
+ .name = "texsrd",
+ }, {
+ .id = 0x1c,
+ .name = "vdebsevr",
+ }, {
+ .id = 0x1d,
+ .name = "vdember",
+ }, {
+ .id = 0x1e,
+ .name = "vdemcer",
+ }, {
+ .id = 0x1f,
+ .name = "vdetper",
+ }, {
+ .id = 0x20,
+ .name = "eppu",
+ }, {
+ .id = 0x21,
+ .name = "eppv",
+ }, {
+ .id = 0x22,
+ .name = "eppy",
+ }, {
+ .id = 0x23,
+ .name = "mpeunifbw",
+ }, {
+ .id = 0x24,
+ .name = "viwsb",
+ }, {
+ .id = 0x25,
+ .name = "viwu",
+ }, {
+ .id = 0x26,
+ .name = "viwv",
+ }, {
+ .id = 0x27,
+ .name = "viwy",
+ }, {
+ .id = 0x28,
+ .name = "g2dw",
+ }, {
+ .id = 0x29,
+ .name = "avpcarm7w",
+ }, {
+ .id = 0x2a,
+ .name = "fdcdwr",
+ }, {
+ .id = 0x2b,
+ .name = "host1xw",
+ }, {
+ .id = 0x2c,
+ .name = "ispw",
+ }, {
+ .id = 0x2d,
+ .name = "mpcorew",
+ }, {
+ .id = 0x2e,
+ .name = "mpecswr",
+ }, {
+ .id = 0x2f,
+ .name = "ppcsahbdmaw",
+ }, {
+ .id = 0x30,
+ .name = "ppcsahbslvw",
+ }, {
+ .id = 0x31,
+ .name = "vdebsevw",
+ }, {
+ .id = 0x32,
+ .name = "vdembew",
+ }, {
+ .id = 0x33,
+ .name = "vdetpmw",
+ },
+};
+
+#define TEGRA20_MC_RESET(_name, _control, _status, _reset, _bit) \
+ { \
+ .name = #_name, \
+ .id = TEGRA20_MC_RESET_##_name, \
+ .control = _control, \
+ .status = _status, \
+ .reset = _reset, \
+ .bit = _bit, \
+ }
+
+static const struct tegra_mc_reset tegra20_mc_resets[] = {
+ TEGRA20_MC_RESET(AVPC, 0x100, 0x140, 0x104, 0),
+ TEGRA20_MC_RESET(DC, 0x100, 0x144, 0x104, 1),
+ TEGRA20_MC_RESET(DCB, 0x100, 0x148, 0x104, 2),
+ TEGRA20_MC_RESET(EPP, 0x100, 0x14c, 0x104, 3),
+ TEGRA20_MC_RESET(2D, 0x100, 0x150, 0x104, 4),
+ TEGRA20_MC_RESET(HC, 0x100, 0x154, 0x104, 5),
+ TEGRA20_MC_RESET(ISP, 0x100, 0x158, 0x104, 6),
+ TEGRA20_MC_RESET(MPCORE, 0x100, 0x15c, 0x104, 7),
+ TEGRA20_MC_RESET(MPEA, 0x100, 0x160, 0x104, 8),
+ TEGRA20_MC_RESET(MPEB, 0x100, 0x164, 0x104, 9),
+ TEGRA20_MC_RESET(MPEC, 0x100, 0x168, 0x104, 10),
+ TEGRA20_MC_RESET(3D, 0x100, 0x16c, 0x104, 11),
+ TEGRA20_MC_RESET(PPCS, 0x100, 0x170, 0x104, 12),
+ TEGRA20_MC_RESET(VDE, 0x100, 0x174, 0x104, 13),
+ TEGRA20_MC_RESET(VI, 0x100, 0x178, 0x104, 14),
+};
+
+static int terga20_mc_hotreset_assert(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst)
+{
+ unsigned long flags;
+ u32 value;
+
+ spin_lock_irqsave(&mc->lock, flags);
+
+ value = mc_readl(mc, rst->reset);
+ mc_writel(mc, value & ~BIT(rst->bit), rst->reset);
+
+ spin_unlock_irqrestore(&mc->lock, flags);
+
+ return 0;
+}
+
+static int terga20_mc_hotreset_deassert(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst)
+{
+ unsigned long flags;
+ u32 value;
+
+ spin_lock_irqsave(&mc->lock, flags);
+
+ value = mc_readl(mc, rst->reset);
+ mc_writel(mc, value | BIT(rst->bit), rst->reset);
+
+ spin_unlock_irqrestore(&mc->lock, flags);
+
+ return 0;
+}
+
+static int terga20_mc_block_dma(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst)
+{
+ unsigned long flags;
+ u32 value;
+
+ spin_lock_irqsave(&mc->lock, flags);
+
+ value = mc_readl(mc, rst->control) & ~BIT(rst->bit);
+ mc_writel(mc, value, rst->control);
+
+ spin_unlock_irqrestore(&mc->lock, flags);
+
+ return 0;
+}
+
+static bool terga20_mc_dma_idling(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst)
+{
+ return mc_readl(mc, rst->status) == 0;
+}
+
+static int terga20_mc_reset_status(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst)
+{
+ return (mc_readl(mc, rst->reset) & BIT(rst->bit)) == 0;
+}
+
+static int terga20_mc_unblock_dma(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst)
+{
+ unsigned long flags;
+ u32 value;
+
+ spin_lock_irqsave(&mc->lock, flags);
+
+ value = mc_readl(mc, rst->control) | BIT(rst->bit);
+ mc_writel(mc, value, rst->control);
+
+ spin_unlock_irqrestore(&mc->lock, flags);
+
+ return 0;
+}
+
+const struct tegra_mc_reset_ops terga20_mc_reset_ops = {
+ .hotreset_assert = terga20_mc_hotreset_assert,
+ .hotreset_deassert = terga20_mc_hotreset_deassert,
+ .block_dma = terga20_mc_block_dma,
+ .dma_idling = terga20_mc_dma_idling,
+ .unblock_dma = terga20_mc_unblock_dma,
+ .reset_status = terga20_mc_reset_status,
+};
+
+const struct tegra_mc_soc tegra20_mc_soc = {
+ .clients = tegra20_mc_clients,
+ .num_clients = ARRAY_SIZE(tegra20_mc_clients),
+ .num_address_bits = 32,
+ .client_id_mask = 0x3f,
+ .intmask = MC_INT_SECURITY_VIOLATION | MC_INT_INVALID_GART_PAGE |
+ MC_INT_DECERR_EMEM,
+ .reset_ops = &terga20_mc_reset_ops,
+ .resets = tegra20_mc_resets,
+ .num_resets = ARRAY_SIZE(tegra20_mc_resets),
+};
diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c
index d398bcd..d00a771 100644
--- a/drivers/memory/tegra/tegra210.c
+++ b/drivers/memory/tegra/tegra210.c
@@ -6,11 +6,6 @@
* published by the Free Software Foundation.
*/
-#include <linux/of.h>
-#include <linux/mm.h>
-
-#include <asm/cacheflush.h>
-
#include <dt-bindings/memory/tegra210-mc.h>
#include "mc.h"
@@ -1085,6 +1080,48 @@ static const struct tegra_smmu_soc tegra210_smmu_soc = {
.num_asids = 128,
};
+#define TEGRA210_MC_RESET(_name, _control, _status, _bit) \
+ { \
+ .name = #_name, \
+ .id = TEGRA210_MC_RESET_##_name, \
+ .control = _control, \
+ .status = _status, \
+ .bit = _bit, \
+ }
+
+static const struct tegra_mc_reset tegra210_mc_resets[] = {
+ TEGRA210_MC_RESET(AFI, 0x200, 0x204, 0),
+ TEGRA210_MC_RESET(AVPC, 0x200, 0x204, 1),
+ TEGRA210_MC_RESET(DC, 0x200, 0x204, 2),
+ TEGRA210_MC_RESET(DCB, 0x200, 0x204, 3),
+ TEGRA210_MC_RESET(HC, 0x200, 0x204, 6),
+ TEGRA210_MC_RESET(HDA, 0x200, 0x204, 7),
+ TEGRA210_MC_RESET(ISP2, 0x200, 0x204, 8),
+ TEGRA210_MC_RESET(MPCORE, 0x200, 0x204, 9),
+ TEGRA210_MC_RESET(NVENC, 0x200, 0x204, 11),
+ TEGRA210_MC_RESET(PPCS, 0x200, 0x204, 14),
+ TEGRA210_MC_RESET(SATA, 0x200, 0x204, 15),
+ TEGRA210_MC_RESET(VI, 0x200, 0x204, 17),
+ TEGRA210_MC_RESET(VIC, 0x200, 0x204, 18),
+ TEGRA210_MC_RESET(XUSB_HOST, 0x200, 0x204, 19),
+ TEGRA210_MC_RESET(XUSB_DEV, 0x200, 0x204, 20),
+ TEGRA210_MC_RESET(A9AVP, 0x200, 0x204, 21),
+ TEGRA210_MC_RESET(TSEC, 0x200, 0x204, 22),
+ TEGRA210_MC_RESET(SDMMC1, 0x200, 0x204, 29),
+ TEGRA210_MC_RESET(SDMMC2, 0x200, 0x204, 30),
+ TEGRA210_MC_RESET(SDMMC3, 0x200, 0x204, 31),
+ TEGRA210_MC_RESET(SDMMC4, 0x970, 0x974, 0),
+ TEGRA210_MC_RESET(ISP2B, 0x970, 0x974, 1),
+ TEGRA210_MC_RESET(GPU, 0x970, 0x974, 2),
+ TEGRA210_MC_RESET(NVDEC, 0x970, 0x974, 5),
+ TEGRA210_MC_RESET(APE, 0x970, 0x974, 6),
+ TEGRA210_MC_RESET(SE, 0x970, 0x974, 7),
+ TEGRA210_MC_RESET(NVJPG, 0x970, 0x974, 8),
+ TEGRA210_MC_RESET(AXIAP, 0x970, 0x974, 11),
+ TEGRA210_MC_RESET(ETR, 0x970, 0x974, 12),
+ TEGRA210_MC_RESET(TSECB, 0x970, 0x974, 13),
+};
+
const struct tegra_mc_soc tegra210_mc_soc = {
.clients = tegra210_mc_clients,
.num_clients = ARRAY_SIZE(tegra210_mc_clients),
@@ -1092,4 +1129,10 @@ const struct tegra_mc_soc tegra210_mc_soc = {
.atom_size = 64,
.client_id_mask = 0xff,
.smmu = &tegra210_smmu_soc,
+ .intmask = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
+ MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
+ MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
+ .reset_ops = &terga_mc_reset_ops_common,
+ .resets = tegra210_mc_resets,
+ .num_resets = ARRAY_SIZE(tegra210_mc_resets),
};
diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c
index d756c83..bee5314 100644
--- a/drivers/memory/tegra/tegra30.c
+++ b/drivers/memory/tegra/tegra30.c
@@ -960,6 +960,36 @@ static const struct tegra_smmu_soc tegra30_smmu_soc = {
.num_asids = 4,
};
+#define TEGRA30_MC_RESET(_name, _control, _status, _bit) \
+ { \
+ .name = #_name, \
+ .id = TEGRA30_MC_RESET_##_name, \
+ .control = _control, \
+ .status = _status, \
+ .bit = _bit, \
+ }
+
+static const struct tegra_mc_reset tegra30_mc_resets[] = {
+ TEGRA30_MC_RESET(AFI, 0x200, 0x204, 0),
+ TEGRA30_MC_RESET(AVPC, 0x200, 0x204, 1),
+ TEGRA30_MC_RESET(DC, 0x200, 0x204, 2),
+ TEGRA30_MC_RESET(DCB, 0x200, 0x204, 3),
+ TEGRA30_MC_RESET(EPP, 0x200, 0x204, 4),
+ TEGRA30_MC_RESET(2D, 0x200, 0x204, 5),
+ TEGRA30_MC_RESET(HC, 0x200, 0x204, 6),
+ TEGRA30_MC_RESET(HDA, 0x200, 0x204, 7),
+ TEGRA30_MC_RESET(ISP, 0x200, 0x204, 8),
+ TEGRA30_MC_RESET(MPCORE, 0x200, 0x204, 9),
+ TEGRA30_MC_RESET(MPCORELP, 0x200, 0x204, 10),
+ TEGRA30_MC_RESET(MPE, 0x200, 0x204, 11),
+ TEGRA30_MC_RESET(3D, 0x200, 0x204, 12),
+ TEGRA30_MC_RESET(3D2, 0x200, 0x204, 13),
+ TEGRA30_MC_RESET(PPCS, 0x200, 0x204, 14),
+ TEGRA30_MC_RESET(SATA, 0x200, 0x204, 15),
+ TEGRA30_MC_RESET(VDE, 0x200, 0x204, 16),
+ TEGRA30_MC_RESET(VI, 0x200, 0x204, 17),
+};
+
const struct tegra_mc_soc tegra30_mc_soc = {
.clients = tegra30_mc_clients,
.num_clients = ARRAY_SIZE(tegra30_mc_clients),
@@ -967,4 +997,9 @@ const struct tegra_mc_soc tegra30_mc_soc = {
.atom_size = 16,
.client_id_mask = 0x7f,
.smmu = &tegra30_smmu_soc,
+ .intmask = MC_INT_INVALID_SMMU_PAGE | MC_INT_SECURITY_VIOLATION |
+ MC_INT_DECERR_EMEM,
+ .reset_ops = &terga_mc_reset_ops_common,
+ .resets = tegra30_mc_resets,
+ .num_resets = ARRAY_SIZE(tegra30_mc_resets),
};
diff --git a/drivers/memory/tegra20-mc.c b/drivers/memory/tegra20-mc.c
deleted file mode 100644
index cc309a0..0000000
--- a/drivers/memory/tegra20-mc.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Tegra20 Memory Controller
- *
- * Copyright (c) 2012, 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/ratelimit.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-
-#define DRV_NAME "tegra20-mc"
-
-#define MC_INTSTATUS 0x0
-#define MC_INTMASK 0x4
-
-#define MC_INT_ERR_SHIFT 6
-#define MC_INT_ERR_MASK (0x1f << MC_INT_ERR_SHIFT)
-#define MC_INT_DECERR_EMEM BIT(MC_INT_ERR_SHIFT)
-#define MC_INT_INVALID_GART_PAGE BIT(MC_INT_ERR_SHIFT + 1)
-#define MC_INT_SECURITY_VIOLATION BIT(MC_INT_ERR_SHIFT + 2)
-#define MC_INT_ARBITRATION_EMEM BIT(MC_INT_ERR_SHIFT + 3)
-
-#define MC_GART_ERROR_REQ 0x30
-#define MC_DECERR_EMEM_OTHERS_STATUS 0x58
-#define MC_SECURITY_VIOLATION_STATUS 0x74
-
-#define SECURITY_VIOLATION_TYPE BIT(30) /* 0=TRUSTZONE, 1=CARVEOUT */
-
-#define MC_CLIENT_ID_MASK 0x3f
-
-#define NUM_MC_REG_BANKS 2
-
-struct tegra20_mc {
- void __iomem *regs[NUM_MC_REG_BANKS];
- struct device *dev;
-};
-
-static inline u32 mc_readl(struct tegra20_mc *mc, u32 offs)
-{
- u32 val = 0;
-
- if (offs < 0x24)
- val = readl(mc->regs[0] + offs);
- else if (offs < 0x400)
- val = readl(mc->regs[1] + offs - 0x3c);
-
- return val;
-}
-
-static inline void mc_writel(struct tegra20_mc *mc, u32 val, u32 offs)
-{
- if (offs < 0x24)
- writel(val, mc->regs[0] + offs);
- else if (offs < 0x400)
- writel(val, mc->regs[1] + offs - 0x3c);
-}
-
-static const char * const tegra20_mc_client[] = {
- "cbr_display0a",
- "cbr_display0ab",
- "cbr_display0b",
- "cbr_display0bb",
- "cbr_display0c",
- "cbr_display0cb",
- "cbr_display1b",
- "cbr_display1bb",
- "cbr_eppup",
- "cbr_g2pr",
- "cbr_g2sr",
- "cbr_mpeunifbr",
- "cbr_viruv",
- "csr_avpcarm7r",
- "csr_displayhc",
- "csr_displayhcb",
- "csr_fdcdrd",
- "csr_g2dr",
- "csr_host1xdmar",
- "csr_host1xr",
- "csr_idxsrd",
- "csr_mpcorer",
- "csr_mpe_ipred",
- "csr_mpeamemrd",
- "csr_mpecsrd",
- "csr_ppcsahbdmar",
- "csr_ppcsahbslvr",
- "csr_texsrd",
- "csr_vdebsevr",
- "csr_vdember",
- "csr_vdemcer",
- "csr_vdetper",
- "cbw_eppu",
- "cbw_eppv",
- "cbw_eppy",
- "cbw_mpeunifbw",
- "cbw_viwsb",
- "cbw_viwu",
- "cbw_viwv",
- "cbw_viwy",
- "ccw_g2dw",
- "csw_avpcarm7w",
- "csw_fdcdwr",
- "csw_host1xw",
- "csw_ispw",
- "csw_mpcorew",
- "csw_mpecswr",
- "csw_ppcsahbdmaw",
- "csw_ppcsahbslvw",
- "csw_vdebsevw",
- "csw_vdembew",
- "csw_vdetpmw",
-};
-
-static void tegra20_mc_decode(struct tegra20_mc *mc, int n)
-{
- u32 addr, req;
- const char *client = "Unknown";
- int idx, cid;
- const struct reg_info {
- u32 offset;
- u32 write_bit; /* 0=READ, 1=WRITE */
- int cid_shift;
- char *message;
- } reg[] = {
- {
- .offset = MC_DECERR_EMEM_OTHERS_STATUS,
- .write_bit = 31,
- .message = "MC_DECERR",
- },
- {
- .offset = MC_GART_ERROR_REQ,
- .cid_shift = 1,
- .message = "MC_GART_ERR",
-
- },
- {
- .offset = MC_SECURITY_VIOLATION_STATUS,
- .write_bit = 31,
- .message = "MC_SECURITY_ERR",
- },
- };
-
- idx = n - MC_INT_ERR_SHIFT;
- if ((idx < 0) || (idx >= ARRAY_SIZE(reg))) {
- dev_err_ratelimited(mc->dev, "Unknown interrupt status %08lx\n",
- BIT(n));
- return;
- }
-
- req = mc_readl(mc, reg[idx].offset);
- cid = (req >> reg[idx].cid_shift) & MC_CLIENT_ID_MASK;
- if (cid < ARRAY_SIZE(tegra20_mc_client))
- client = tegra20_mc_client[cid];
-
- addr = mc_readl(mc, reg[idx].offset + sizeof(u32));
-
- dev_err_ratelimited(mc->dev, "%s (0x%08x): 0x%08x %s (%s %s)\n",
- reg[idx].message, req, addr, client,
- (req & BIT(reg[idx].write_bit)) ? "write" : "read",
- (reg[idx].offset == MC_SECURITY_VIOLATION_STATUS) ?
- ((req & SECURITY_VIOLATION_TYPE) ?
- "carveout" : "trustzone") : "");
-}
-
-static const struct of_device_id tegra20_mc_of_match[] = {
- { .compatible = "nvidia,tegra20-mc", },
- {},
-};
-
-static irqreturn_t tegra20_mc_isr(int irq, void *data)
-{
- u32 stat, mask, bit;
- struct tegra20_mc *mc = data;
-
- stat = mc_readl(mc, MC_INTSTATUS);
- mask = mc_readl(mc, MC_INTMASK);
- mask &= stat;
- if (!mask)
- return IRQ_NONE;
- while ((bit = ffs(mask)) != 0) {
- tegra20_mc_decode(mc, bit - 1);
- mask &= ~BIT(bit - 1);
- }
-
- mc_writel(mc, stat, MC_INTSTATUS);
- return IRQ_HANDLED;
-}
-
-static int tegra20_mc_probe(struct platform_device *pdev)
-{
- struct resource *irq;
- struct tegra20_mc *mc;
- int i, err;
- u32 intmask;
-
- mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
- if (!mc)
- return -ENOMEM;
- mc->dev = &pdev->dev;
-
- for (i = 0; i < ARRAY_SIZE(mc->regs); i++) {
- struct resource *res;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, i);
- mc->regs[i] = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(mc->regs[i]))
- return PTR_ERR(mc->regs[i]);
- }
-
- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!irq)
- return -ENODEV;
- err = devm_request_irq(&pdev->dev, irq->start, tegra20_mc_isr,
- IRQF_SHARED, dev_name(&pdev->dev), mc);
- if (err)
- return -ENODEV;
-
- platform_set_drvdata(pdev, mc);
-
- intmask = MC_INT_INVALID_GART_PAGE |
- MC_INT_DECERR_EMEM | MC_INT_SECURITY_VIOLATION;
- mc_writel(mc, intmask, MC_INTMASK);
- return 0;
-}
-
-static struct platform_driver tegra20_mc_driver = {
- .probe = tegra20_mc_probe,
- .driver = {
- .name = DRV_NAME,
- .of_match_table = tegra20_mc_of_match,
- },
-};
-module_platform_driver(tegra20_mc_driver);
-
-MODULE_AUTHOR("Hiroshi DOYU <hdoyu@nvidia.com>");
-MODULE_DESCRIPTION("Tegra20 MC driver");
-MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c
index 2744b1b..31112f6 100644
--- a/drivers/memory/ti-aemif.c
+++ b/drivers/memory/ti-aemif.c
@@ -339,9 +339,6 @@ static int aemif_probe(struct platform_device *pdev)
struct aemif_platform_data *pdata;
struct of_dev_auxdata *dev_lookup;
- if (np == NULL)
- return 0;
-
aemif = devm_kzalloc(dev, sizeof(*aemif), GFP_KERNEL);
if (!aemif)
return -ENOMEM;
@@ -363,8 +360,10 @@ static int aemif_probe(struct platform_device *pdev)
aemif->clk_rate = clk_get_rate(aemif->clk) / MSEC_PER_SEC;
- if (of_device_is_compatible(np, "ti,da850-aemif"))
+ if (np && of_device_is_compatible(np, "ti,da850-aemif"))
aemif->cs_offset = 2;
+ else if (pdata)
+ aemif->cs_offset = pdata->cs_offset;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
aemif->base = devm_ioremap_resource(dev, res);
@@ -373,15 +372,23 @@ static int aemif_probe(struct platform_device *pdev)
goto error;
}
- /*
- * For every controller device node, there is a cs device node that
- * describe the bus configuration parameters. This functions iterate
- * over these nodes and update the cs data array.
- */
- for_each_available_child_of_node(np, child_np) {
- ret = of_aemif_parse_abus_config(pdev, child_np);
- if (ret < 0)
- goto error;
+ if (np) {
+ /*
+ * For every controller device node, there is a cs device node
+ * that describe the bus configuration parameters. This
+ * functions iterate over these nodes and update the cs data
+ * array.
+ */
+ for_each_available_child_of_node(np, child_np) {
+ ret = of_aemif_parse_abus_config(pdev, child_np);
+ if (ret < 0)
+ goto error;
+ }
+ } else if (pdata && pdata->num_abus_data > 0) {
+ for (i = 0; i < pdata->num_abus_data; i++, aemif->num_cs++) {
+ aemif->cs_data[i].cs = pdata->abus_data[i].cs;
+ aemif_get_hw_params(pdev, i);
+ }
}
for (i = 0; i < aemif->num_cs; i++) {
@@ -394,14 +401,25 @@ static int aemif_probe(struct platform_device *pdev)
}
/*
- * Create a child devices explicitly from here to
- * guarantee that the child will be probed after the AEMIF timing
- * parameters are set.
+ * Create a child devices explicitly from here to guarantee that the
+ * child will be probed after the AEMIF timing parameters are set.
*/
- for_each_available_child_of_node(np, child_np) {
- ret = of_platform_populate(child_np, NULL, dev_lookup, dev);
- if (ret < 0)
- goto error;
+ if (np) {
+ for_each_available_child_of_node(np, child_np) {
+ ret = of_platform_populate(child_np, NULL,
+ dev_lookup, dev);
+ if (ret < 0)
+ goto error;
+ }
+ } else {
+ for (i = 0; i < pdata->num_sub_devices; i++) {
+ pdata->sub_devices[i].dev.parent = dev;
+ ret = platform_device_register(&pdata->sub_devices[i]);
+ if (ret) {
+ dev_warn(dev, "Error register sub device %s\n",
+ pdata->sub_devices[i].name);
+ }
+ }
}
return 0;
@@ -422,7 +440,7 @@ static struct platform_driver aemif_driver = {
.probe = aemif_probe,
.remove = aemif_remove,
.driver = {
- .name = KBUILD_MODNAME,
+ .name = "ti-aemif",
.of_match_table = of_match_ptr(aemif_of_match),
},
};
diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c
index a15181f..716fc8e 100644
--- a/drivers/memstick/core/ms_block.c
+++ b/drivers/memstick/core/ms_block.c
@@ -1201,7 +1201,8 @@ static int msb_read_boot_blocks(struct msb_data *msb)
dbg_verbose("Start of a scan for the boot blocks");
if (!msb->boot_page) {
- page = kmalloc(sizeof(struct ms_boot_page)*2, GFP_KERNEL);
+ page = kmalloc_array(2, sizeof(struct ms_boot_page),
+ GFP_KERNEL);
if (!page)
return -ENOMEM;
@@ -1341,7 +1342,8 @@ static int msb_ftl_initialize(struct msb_data *msb)
msb->used_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL);
msb->erased_blocks_bitmap = kzalloc(msb->block_count / 8, GFP_KERNEL);
msb->lba_to_pba_table =
- kmalloc(msb->logical_block_count * sizeof(u16), GFP_KERNEL);
+ kmalloc_array(msb->logical_block_count, sizeof(u16),
+ GFP_KERNEL);
if (!msb->used_blocks_bitmap || !msb->lba_to_pba_table ||
!msb->erased_blocks_bitmap) {
diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h
index 4e9c0ce..059997f 100644
--- a/drivers/message/fusion/lsi/mpi_cnfg.h
+++ b/drivers/message/fusion/lsi/mpi_cnfg.h
@@ -1802,13 +1802,13 @@ typedef struct _CONFIG_PAGE_FC_PORT_0
#define MPI_FCPORTPAGE0_SUPPORT_CLASS_2 (0x00000002)
#define MPI_FCPORTPAGE0_SUPPORT_CLASS_3 (0x00000004)
-#define MPI_FCPORTPAGE0_SUPPORT_SPEED_UKNOWN (0x00000000) /* (SNIA)HBA_PORTSPEED_UNKNOWN 0 Unknown - transceiver incapable of reporting */
+#define MPI_FCPORTPAGE0_SUPPORT_SPEED_UNKNOWN (0x00000000) /* (SNIA)HBA_PORTSPEED_UNKNOWN 0 Unknown - transceiver incapable of reporting */
#define MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED (0x00000001) /* (SNIA)HBA_PORTSPEED_1GBIT 1 1 GBit/sec */
#define MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED (0x00000002) /* (SNIA)HBA_PORTSPEED_2GBIT 2 2 GBit/sec */
#define MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED (0x00000004) /* (SNIA)HBA_PORTSPEED_10GBIT 4 10 GBit/sec */
#define MPI_FCPORTPAGE0_SUPPORT_4GBIT_SPEED (0x00000008) /* (SNIA)HBA_PORTSPEED_4GBIT 8 4 GBit/sec */
-#define MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN MPI_FCPORTPAGE0_SUPPORT_SPEED_UKNOWN
+#define MPI_FCPORTPAGE0_CURRENT_SPEED_UNKNOWN MPI_FCPORTPAGE0_SUPPORT_SPEED_UNKNOWN
#define MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT MPI_FCPORTPAGE0_SUPPORT_1GBIT_SPEED
#define MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT MPI_FCPORTPAGE0_SUPPORT_2GBIT_SPEED
#define MPI_FCPORTPAGE0_CURRENT_SPEED_10GBIT MPI_FCPORTPAGE0_SUPPORT_10GBIT_SPEED
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
index a746ccd..a625ac4 100644
--- a/drivers/message/fusion/mptbase.c
+++ b/drivers/message/fusion/mptbase.c
@@ -7600,7 +7600,7 @@ mpt_display_event_info(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply)
snprintf(evStr, EVENT_DESCR_STR_SZ,
"SAS Initiator Device Table Overflow: max initiators=%02d "
- "current initators=%02d",
+ "current initiators=%02d",
max_init, current_init);
break;
}
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 6d461ca..06b17542 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -693,7 +693,7 @@ mptfc_display_port_link_speed(MPT_ADAPTER *ioc, int portnum, FCPortPage0_t *pp0d
state = pp0dest->PortState;
if (state != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE &&
- new_speed != MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN) {
+ new_speed != MPI_FCPORTPAGE0_CURRENT_SPEED_UNKNOWN) {
old = old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" :
old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" :
diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index 55dd71b..ebc00d4 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -394,7 +394,8 @@ mpt_lan_open(struct net_device *dev)
"a moment.\n");
}
- priv->mpt_txfidx = kmalloc(priv->tx_max_out * sizeof(int), GFP_KERNEL);
+ priv->mpt_txfidx = kmalloc_array(priv->tx_max_out, sizeof(int),
+ GFP_KERNEL);
if (priv->mpt_txfidx == NULL)
goto out;
priv->mpt_txfidx_tail = -1;
@@ -408,8 +409,8 @@ mpt_lan_open(struct net_device *dev)
dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n"));
- priv->mpt_rxfidx = kmalloc(priv->max_buckets_out * sizeof(int),
- GFP_KERNEL);
+ priv->mpt_rxfidx = kmalloc_array(priv->max_buckets_out, sizeof(int),
+ GFP_KERNEL);
if (priv->mpt_rxfidx == NULL)
goto out_SendCtl;
priv->mpt_rxfidx_tail = -1;
@@ -670,7 +671,7 @@ out:
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int
+static netdev_tx_t
mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev)
{
struct mpt_lan_priv *priv = netdev_priv(dev);
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index 19a5aa7..76a66da 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -4320,7 +4320,7 @@ mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
hot_plug_info->id) {
printk(MYIOC_s_WARN_FMT "firmware bug: unable "
- "to add hidden disk - target_id matchs "
+ "to add hidden disk - target_id matches "
"volume_id\n", ioc->name);
mptsas_free_fw_event(ioc, fw_event);
return;
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d9d2cf0..e9fd20d 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_MFD_ASIC3) += asic3.o tmio_core.o
obj-$(CONFIG_MFD_BCM590XX) += bcm590xx.o
obj-$(CONFIG_MFD_BD9571MWV) += bd9571mwv.o
cros_ec_core-objs := cros_ec.o
-cros_ec_core-$(CONFIG_ACPI) += cros_ec_acpi_gpe.o
obj-$(CONFIG_MFD_CROS_EC) += cros_ec_core.o
obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
index 8ba4107..8d652b2 100644
--- a/drivers/mfd/ab8500-debugfs.c
+++ b/drivers/mfd/ab8500-debugfs.c
@@ -2519,11 +2519,10 @@ static ssize_t ab8500_subscribe_write(struct file *file,
if (!dev_attr[irq_index])
return -ENOMEM;
- event_name[irq_index] = kmalloc(count, GFP_KERNEL);
+ event_name[irq_index] = kasprintf(GFP_KERNEL, "%lu", user_val);
if (!event_name[irq_index])
return -ENOMEM;
- sprintf(event_name[irq_index], "%lu", user_val);
dev_attr[irq_index]->show = show_irq;
dev_attr[irq_index]->store = NULL;
dev_attr[irq_index]->attr.name = event_name[irq_index];
@@ -2660,18 +2659,18 @@ static int ab8500_debug_probe(struct platform_device *plf)
ab8500 = dev_get_drvdata(plf->dev.parent);
num_irqs = ab8500->mask_size;
- irq_count = devm_kzalloc(&plf->dev,
- sizeof(*irq_count)*num_irqs, GFP_KERNEL);
+ irq_count = devm_kcalloc(&plf->dev,
+ num_irqs, sizeof(*irq_count), GFP_KERNEL);
if (!irq_count)
return -ENOMEM;
- dev_attr = devm_kzalloc(&plf->dev,
- sizeof(*dev_attr)*num_irqs, GFP_KERNEL);
+ dev_attr = devm_kcalloc(&plf->dev,
+ num_irqs, sizeof(*dev_attr), GFP_KERNEL);
if (!dev_attr)
return -ENOMEM;
- event_name = devm_kzalloc(&plf->dev,
- sizeof(*event_name)*num_irqs, GFP_KERNEL);
+ event_name = devm_kcalloc(&plf->dev,
+ num_irqs, sizeof(*event_name), GFP_KERNEL);
if (!event_name)
return -ENOMEM;
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c
index 0d3846a..f282d39 100644
--- a/drivers/mfd/abx500-core.c
+++ b/drivers/mfd/abx500-core.c
@@ -37,15 +37,12 @@ int abx500_register_ops(struct device *dev, struct abx500_ops *ops)
{
struct abx500_device_entry *dev_entry;
- dev_entry = devm_kzalloc(dev,
- sizeof(struct abx500_device_entry),
- GFP_KERNEL);
- if (!dev_entry) {
- dev_err(dev, "register_ops kzalloc failed");
+ dev_entry = devm_kzalloc(dev, sizeof(*dev_entry), GFP_KERNEL);
+ if (!dev_entry)
return -ENOMEM;
- }
+
dev_entry->dev = dev;
- memcpy(&dev_entry->ops, ops, sizeof(struct abx500_ops));
+ memcpy(&dev_entry->ops, ops, sizeof(*ops));
list_add_tail(&dev_entry->list, &abx500_list);
return 0;
@@ -68,7 +65,7 @@ int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->set_register != NULL))
+ if (ops && ops->set_register)
return ops->set_register(dev, bank, reg, value);
else
return -ENOTSUPP;
@@ -81,7 +78,7 @@ int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->get_register != NULL))
+ if (ops && ops->get_register)
return ops->get_register(dev, bank, reg, value);
else
return -ENOTSUPP;
@@ -94,7 +91,7 @@ int abx500_get_register_page_interruptible(struct device *dev, u8 bank,
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->get_register_page != NULL))
+ if (ops && ops->get_register_page)
return ops->get_register_page(dev, bank,
first_reg, regvals, numregs);
else
@@ -108,7 +105,7 @@ int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->mask_and_set_register != NULL))
+ if (ops && ops->mask_and_set_register)
return ops->mask_and_set_register(dev, bank,
reg, bitmask, bitvalues);
else
@@ -121,7 +118,7 @@ int abx500_get_chip_id(struct device *dev)
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->get_chip_id != NULL))
+ if (ops && ops->get_chip_id)
return ops->get_chip_id(dev);
else
return -ENOTSUPP;
@@ -133,7 +130,7 @@ int abx500_event_registers_startup_state_get(struct device *dev, u8 *event)
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->event_registers_startup_state_get != NULL))
+ if (ops && ops->event_registers_startup_state_get)
return ops->event_registers_startup_state_get(dev, event);
else
return -ENOTSUPP;
@@ -145,7 +142,7 @@ int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)
struct abx500_ops *ops;
lookup_ops(dev->parent, &ops);
- if ((ops != NULL) && (ops->startup_irq_enabled != NULL))
+ if (ops && ops->startup_irq_enabled)
return ops->startup_irq_enabled(dev, irq);
else
return -ENOTSUPP;
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index 7787525..83f1c5a 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -13,13 +13,12 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/mfd/core.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/of_gpio.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@@ -279,7 +278,7 @@ static int arizona_wait_for_boot(struct arizona *arizona)
static inline void arizona_enable_reset(struct arizona *arizona)
{
if (arizona->pdata.reset)
- gpio_set_value_cansleep(arizona->pdata.reset, 0);
+ gpiod_set_raw_value_cansleep(arizona->pdata.reset, 0);
}
static void arizona_disable_reset(struct arizona *arizona)
@@ -295,7 +294,7 @@ static void arizona_disable_reset(struct arizona *arizona)
break;
}
- gpio_set_value_cansleep(arizona->pdata.reset, 1);
+ gpiod_set_raw_value_cansleep(arizona->pdata.reset, 1);
usleep_range(1000, 5000);
}
}
@@ -799,14 +798,27 @@ static int arizona_of_get_core_pdata(struct arizona *arizona)
struct arizona_pdata *pdata = &arizona->pdata;
int ret, i;
- pdata->reset = of_get_named_gpio(arizona->dev->of_node, "wlf,reset", 0);
- if (pdata->reset == -EPROBE_DEFER) {
- return pdata->reset;
- } else if (pdata->reset < 0) {
- dev_err(arizona->dev, "Reset GPIO missing/malformed: %d\n",
- pdata->reset);
+ /* Handle old non-standard DT binding */
+ pdata->reset = devm_gpiod_get_from_of_node(arizona->dev,
+ arizona->dev->of_node,
+ "wlf,reset", 0,
+ GPIOD_OUT_LOW,
+ "arizona /RESET");
+ if (IS_ERR(pdata->reset)) {
+ ret = PTR_ERR(pdata->reset);
- pdata->reset = 0;
+ /*
+ * Reset missing will be caught when other binding is read
+ * but all other errors imply this binding is in use but has
+ * encountered a problem so should be handled.
+ */
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ else if (ret != -ENOENT && ret != -ENOSYS)
+ dev_err(arizona->dev, "Reset GPIO malformed: %d\n",
+ ret);
+
+ pdata->reset = NULL;
}
ret = of_property_read_u32_array(arizona->dev->of_node,
@@ -1050,14 +1062,19 @@ int arizona_dev_init(struct arizona *arizona)
goto err_early;
}
- if (arizona->pdata.reset) {
+ if (!arizona->pdata.reset) {
/* Start out with /RESET low to put the chip into reset */
- ret = devm_gpio_request_one(arizona->dev, arizona->pdata.reset,
- GPIOF_DIR_OUT | GPIOF_INIT_LOW,
- "arizona /RESET");
- if (ret != 0) {
- dev_err(dev, "Failed to request /RESET: %d\n", ret);
- goto err_dcvdd;
+ arizona->pdata.reset = devm_gpiod_get(arizona->dev, "reset",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(arizona->pdata.reset)) {
+ ret = PTR_ERR(arizona->pdata.reset);
+ if (ret == -EPROBE_DEFER)
+ goto err_dcvdd;
+
+ dev_err(arizona->dev,
+ "Reset GPIO missing/malformed: %d\n", ret);
+
+ arizona->pdata.reset = NULL;
}
}
diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c
index cf2e25a..1531302 100644
--- a/drivers/mfd/asic3.c
+++ b/drivers/mfd/asic3.c
@@ -31,6 +31,8 @@
#include <linux/mfd/ds1wm.h>
#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+
enum {
ASIC3_CLOCK_SPI,
ASIC3_CLOCK_OWM,
@@ -719,6 +721,7 @@ static void asic3_mmc_clk_div(struct platform_device *pdev, int state)
static struct tmio_mmc_data asic3_mmc_data = {
.hclk = 24576000,
+ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
.set_pwr = asic3_mmc_pwr,
.set_clk_div = asic3_mmc_clk_div,
};
diff --git a/drivers/mfd/atmel-smc.c b/drivers/mfd/atmel-smc.c
index 7d77948..0adbd2e 100644
--- a/drivers/mfd/atmel-smc.c
+++ b/drivers/mfd/atmel-smc.c
@@ -12,6 +12,7 @@
*/
#include <linux/mfd/syscon/atmel-smc.h>
+#include <linux/string.h>
/**
* atmel_smc_cs_conf_init - initialize a SMC CS conf
diff --git a/drivers/mfd/axp20x.c b/drivers/mfd/axp20x.c
index e94c72c..9a2ef3d 100644
--- a/drivers/mfd/axp20x.c
+++ b/drivers/mfd/axp20x.c
@@ -169,131 +169,61 @@ static const struct regmap_access_table axp806_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(axp806_volatile_ranges),
};
-static struct resource axp152_pek_resources[] = {
+static const struct resource axp152_pek_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
DEFINE_RES_IRQ_NAMED(AXP152_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
-static struct resource axp20x_ac_power_supply_resources[] = {
+static const struct resource axp20x_ac_power_supply_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_PLUGIN, "ACIN_PLUGIN"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_REMOVAL, "ACIN_REMOVAL"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_ACIN_OVER_V, "ACIN_OVER_V"),
};
-static struct resource axp20x_pek_resources[] = {
- {
- .name = "PEK_DBR",
- .start = AXP20X_IRQ_PEK_RIS_EDGE,
- .end = AXP20X_IRQ_PEK_RIS_EDGE,
- .flags = IORESOURCE_IRQ,
- }, {
- .name = "PEK_DBF",
- .start = AXP20X_IRQ_PEK_FAL_EDGE,
- .end = AXP20X_IRQ_PEK_FAL_EDGE,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp20x_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
-static struct resource axp20x_usb_power_supply_resources[] = {
+static const struct resource axp20x_usb_power_supply_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_VALID, "VBUS_VALID"),
DEFINE_RES_IRQ_NAMED(AXP20X_IRQ_VBUS_NOT_VALID, "VBUS_NOT_VALID"),
};
-static struct resource axp22x_usb_power_supply_resources[] = {
+static const struct resource axp22x_usb_power_supply_resources[] = {
DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_PLUGIN, "VBUS_PLUGIN"),
DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_VBUS_REMOVAL, "VBUS_REMOVAL"),
};
-static struct resource axp22x_pek_resources[] = {
- {
- .name = "PEK_DBR",
- .start = AXP22X_IRQ_PEK_RIS_EDGE,
- .end = AXP22X_IRQ_PEK_RIS_EDGE,
- .flags = IORESOURCE_IRQ,
- }, {
- .name = "PEK_DBF",
- .start = AXP22X_IRQ_PEK_FAL_EDGE,
- .end = AXP22X_IRQ_PEK_FAL_EDGE,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp22x_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP22X_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
-static struct resource axp288_power_button_resources[] = {
- {
- .name = "PEK_DBR",
- .start = AXP288_IRQ_POKP,
- .end = AXP288_IRQ_POKP,
- .flags = IORESOURCE_IRQ,
- },
- {
- .name = "PEK_DBF",
- .start = AXP288_IRQ_POKN,
- .end = AXP288_IRQ_POKN,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp288_power_button_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP288_IRQ_POKP, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP288_IRQ_POKN, "PEK_DBF"),
};
-static struct resource axp288_fuel_gauge_resources[] = {
- {
- .start = AXP288_IRQ_QWBTU,
- .end = AXP288_IRQ_QWBTU,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_WBTU,
- .end = AXP288_IRQ_WBTU,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_QWBTO,
- .end = AXP288_IRQ_QWBTO,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_WBTO,
- .end = AXP288_IRQ_WBTO,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_WL2,
- .end = AXP288_IRQ_WL2,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_WL1,
- .end = AXP288_IRQ_WL1,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp288_fuel_gauge_resources[] = {
+ DEFINE_RES_IRQ(AXP288_IRQ_QWBTU),
+ DEFINE_RES_IRQ(AXP288_IRQ_WBTU),
+ DEFINE_RES_IRQ(AXP288_IRQ_QWBTO),
+ DEFINE_RES_IRQ(AXP288_IRQ_WBTO),
+ DEFINE_RES_IRQ(AXP288_IRQ_WL2),
+ DEFINE_RES_IRQ(AXP288_IRQ_WL1),
};
-static struct resource axp803_pek_resources[] = {
- {
- .name = "PEK_DBR",
- .start = AXP803_IRQ_PEK_RIS_EDGE,
- .end = AXP803_IRQ_PEK_RIS_EDGE,
- .flags = IORESOURCE_IRQ,
- }, {
- .name = "PEK_DBF",
- .start = AXP803_IRQ_PEK_FAL_EDGE,
- .end = AXP803_IRQ_PEK_FAL_EDGE,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp803_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP803_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
-static struct resource axp809_pek_resources[] = {
- {
- .name = "PEK_DBR",
- .start = AXP809_IRQ_PEK_RIS_EDGE,
- .end = AXP809_IRQ_PEK_RIS_EDGE,
- .flags = IORESOURCE_IRQ,
- }, {
- .name = "PEK_DBF",
- .start = AXP809_IRQ_PEK_FAL_EDGE,
- .end = AXP809_IRQ_PEK_FAL_EDGE,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp809_pek_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_RIS_EDGE, "PEK_DBR"),
+ DEFINE_RES_IRQ_NAMED(AXP809_IRQ_PEK_FAL_EDGE, "PEK_DBF"),
};
static const struct regmap_config axp152_regmap_config = {
@@ -520,11 +450,11 @@ static const struct regmap_irq axp806_regmap_irqs[] = {
INIT_REGMAP_IRQ(AXP806, DCDCC_V_LOW, 0, 5),
INIT_REGMAP_IRQ(AXP806, DCDCD_V_LOW, 0, 6),
INIT_REGMAP_IRQ(AXP806, DCDCE_V_LOW, 0, 7),
- INIT_REGMAP_IRQ(AXP806, PWROK_LONG, 1, 0),
- INIT_REGMAP_IRQ(AXP806, PWROK_SHORT, 1, 1),
+ INIT_REGMAP_IRQ(AXP806, POK_LONG, 1, 0),
+ INIT_REGMAP_IRQ(AXP806, POK_SHORT, 1, 1),
INIT_REGMAP_IRQ(AXP806, WAKEUP, 1, 4),
- INIT_REGMAP_IRQ(AXP806, PWROK_FALL, 1, 5),
- INIT_REGMAP_IRQ(AXP806, PWROK_RISE, 1, 6),
+ INIT_REGMAP_IRQ(AXP806, POK_FALL, 1, 5),
+ INIT_REGMAP_IRQ(AXP806, POK_RISE, 1, 6),
};
static const struct regmap_irq axp809_regmap_irqs[] = {
@@ -648,7 +578,7 @@ static const struct regmap_irq_chip axp809_regmap_irq_chip = {
.num_regs = 5,
};
-static struct mfd_cell axp20x_cells[] = {
+static const struct mfd_cell axp20x_cells[] = {
{
.name = "axp20x-gpio",
.of_compatible = "x-powers,axp209-gpio",
@@ -660,6 +590,7 @@ static struct mfd_cell axp20x_cells[] = {
.name = "axp20x-regulator",
}, {
.name = "axp20x-adc",
+ .of_compatible = "x-powers,axp209-adc",
}, {
.name = "axp20x-battery-power-supply",
.of_compatible = "x-powers,axp209-battery-power-supply",
@@ -676,7 +607,7 @@ static struct mfd_cell axp20x_cells[] = {
},
};
-static struct mfd_cell axp221_cells[] = {
+static const struct mfd_cell axp221_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
@@ -684,7 +615,8 @@ static struct mfd_cell axp221_cells[] = {
}, {
.name = "axp20x-regulator",
}, {
- .name = "axp22x-adc"
+ .name = "axp22x-adc",
+ .of_compatible = "x-powers,axp221-adc",
}, {
.name = "axp20x-ac-power-supply",
.of_compatible = "x-powers,axp221-ac-power-supply",
@@ -701,13 +633,14 @@ static struct mfd_cell axp221_cells[] = {
},
};
-static struct mfd_cell axp223_cells[] = {
+static const struct mfd_cell axp223_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp22x_pek_resources),
.resources = axp22x_pek_resources,
}, {
.name = "axp22x-adc",
+ .of_compatible = "x-powers,axp221-adc",
}, {
.name = "axp20x-battery-power-supply",
.of_compatible = "x-powers,axp221-battery-power-supply",
@@ -726,7 +659,7 @@ static struct mfd_cell axp223_cells[] = {
},
};
-static struct mfd_cell axp152_cells[] = {
+static const struct mfd_cell axp152_cells[] = {
{
.name = "axp20x-pek",
.num_resources = ARRAY_SIZE(axp152_pek_resources),
@@ -734,87 +667,30 @@ static struct mfd_cell axp152_cells[] = {
},
};
-static struct resource axp288_adc_resources[] = {
- {
- .name = "GPADC",
- .start = AXP288_IRQ_GPADC,
- .end = AXP288_IRQ_GPADC,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp288_adc_resources[] = {
+ DEFINE_RES_IRQ_NAMED(AXP288_IRQ_GPADC, "GPADC"),
};
-static struct resource axp288_extcon_resources[] = {
- {
- .start = AXP288_IRQ_VBUS_FALL,
- .end = AXP288_IRQ_VBUS_FALL,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_VBUS_RISE,
- .end = AXP288_IRQ_VBUS_RISE,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_MV_CHNG,
- .end = AXP288_IRQ_MV_CHNG,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_BC_USB_CHNG,
- .end = AXP288_IRQ_BC_USB_CHNG,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp288_extcon_resources[] = {
+ DEFINE_RES_IRQ(AXP288_IRQ_VBUS_FALL),
+ DEFINE_RES_IRQ(AXP288_IRQ_VBUS_RISE),
+ DEFINE_RES_IRQ(AXP288_IRQ_MV_CHNG),
+ DEFINE_RES_IRQ(AXP288_IRQ_BC_USB_CHNG),
};
-static struct resource axp288_charger_resources[] = {
- {
- .start = AXP288_IRQ_OV,
- .end = AXP288_IRQ_OV,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_DONE,
- .end = AXP288_IRQ_DONE,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_CHARGING,
- .end = AXP288_IRQ_CHARGING,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_SAFE_QUIT,
- .end = AXP288_IRQ_SAFE_QUIT,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_SAFE_ENTER,
- .end = AXP288_IRQ_SAFE_ENTER,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_QCBTU,
- .end = AXP288_IRQ_QCBTU,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_CBTU,
- .end = AXP288_IRQ_CBTU,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_QCBTO,
- .end = AXP288_IRQ_QCBTO,
- .flags = IORESOURCE_IRQ,
- },
- {
- .start = AXP288_IRQ_CBTO,
- .end = AXP288_IRQ_CBTO,
- .flags = IORESOURCE_IRQ,
- },
+static const struct resource axp288_charger_resources[] = {
+ DEFINE_RES_IRQ(AXP288_IRQ_OV),
+ DEFINE_RES_IRQ(AXP288_IRQ_DONE),
+ DEFINE_RES_IRQ(AXP288_IRQ_CHARGING),
+ DEFINE_RES_IRQ(AXP288_IRQ_SAFE_QUIT),
+ DEFINE_RES_IRQ(AXP288_IRQ_SAFE_ENTER),
+ DEFINE_RES_IRQ(AXP288_IRQ_QCBTU),
+ DEFINE_RES_IRQ(AXP288_IRQ_CBTU),
+ DEFINE_RES_IRQ(AXP288_IRQ_QCBTO),
+ DEFINE_RES_IRQ(AXP288_IRQ_CBTO),
};
-static struct mfd_cell axp288_cells[] = {
+static const struct mfd_cell axp288_cells[] = {
{
.name = "axp288_adc",
.num_resources = ARRAY_SIZE(axp288_adc_resources),
@@ -845,7 +721,7 @@ static struct mfd_cell axp288_cells[] = {
},
};
-static struct mfd_cell axp803_cells[] = {
+static const struct mfd_cell axp803_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp803_pek_resources),
@@ -854,14 +730,14 @@ static struct mfd_cell axp803_cells[] = {
{ .name = "axp20x-regulator" },
};
-static struct mfd_cell axp806_cells[] = {
+static const struct mfd_cell axp806_cells[] = {
{
.id = 2,
.name = "axp20x-regulator",
},
};
-static struct mfd_cell axp809_cells[] = {
+static const struct mfd_cell axp809_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp809_pek_resources),
@@ -872,7 +748,7 @@ static struct mfd_cell axp809_cells[] = {
},
};
-static struct mfd_cell axp813_cells[] = {
+static const struct mfd_cell axp813_cells[] = {
{
.name = "axp221-pek",
.num_resources = ARRAY_SIZE(axp803_pek_resources),
@@ -882,7 +758,13 @@ static struct mfd_cell axp813_cells[] = {
}, {
.name = "axp20x-gpio",
.of_compatible = "x-powers,axp813-gpio",
- }
+ }, {
+ .name = "axp813-adc",
+ .of_compatible = "x-powers,axp813-adc",
+ }, {
+ .name = "axp20x-battery-power-supply",
+ .of_compatible = "x-powers,axp813-battery-power-supply",
+ },
};
static struct axp20x_dev *axp20x_pm_power_off;
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 36156a4..65a9757 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -112,12 +112,16 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
mutex_init(&ec_dev->lock);
- cros_ec_query_all(ec_dev);
+ err = cros_ec_query_all(ec_dev);
+ if (err) {
+ dev_err(dev, "Cannot identify the EC: error %d\n", err);
+ return err;
+ }
if (ec_dev->irq) {
- err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "chromeos-ec", ec_dev);
+ err = devm_request_threaded_irq(dev, ec_dev->irq, NULL,
+ ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "chromeos-ec", ec_dev);
if (err) {
dev_err(dev, "Failed to request IRQ %d: %d",
ec_dev->irq, err);
@@ -131,7 +135,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
dev_err(dev,
"Failed to register Embedded Controller subdevice %d\n",
err);
- goto fail_mfd;
+ return err;
}
if (ec_dev->max_passthru) {
@@ -149,7 +153,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
dev_err(dev,
"Failed to register Power Delivery subdevice %d\n",
err);
- goto fail_mfd;
+ return err;
}
}
@@ -158,7 +162,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
if (err) {
mfd_remove_devices(dev);
dev_err(dev, "Failed to register sub-devices\n");
- goto fail_mfd;
+ return err;
}
}
@@ -173,14 +177,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
dev_info(dev, "Chrome EC device registered\n");
- cros_ec_acpi_install_gpe_handler(dev);
-
return 0;
-
-fail_mfd:
- if (ec_dev->irq)
- free_irq(ec_dev->irq, ec_dev);
- return err;
}
EXPORT_SYMBOL(cros_ec_register);
@@ -188,11 +185,6 @@ int cros_ec_remove(struct cros_ec_device *ec_dev)
{
mfd_remove_devices(ec_dev->dev);
- cros_ec_acpi_remove_gpe_handler();
-
- if (ec_dev->irq)
- free_irq(ec_dev->irq, ec_dev);
-
return 0;
}
EXPORT_SYMBOL(cros_ec_remove);
@@ -204,14 +196,9 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
int ret;
u8 sleep_event;
- if (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) {
- sleep_event = HOST_SLEEP_EVENT_S3_SUSPEND;
- } else {
- sleep_event = HOST_SLEEP_EVENT_S0IX_SUSPEND;
-
- /* Clearing the GPE status for any pending event */
- cros_ec_acpi_clear_gpe();
- }
+ sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
+ HOST_SLEEP_EVENT_S3_SUSPEND :
+ HOST_SLEEP_EVENT_S0IX_SUSPEND;
ret = cros_ec_sleep_event(ec_dev, sleep_event);
if (ret < 0)
diff --git a/drivers/mfd/cros_ec_acpi_gpe.c b/drivers/mfd/cros_ec_acpi_gpe.c
deleted file mode 100644
index 56d305d..0000000
--- a/drivers/mfd/cros_ec_acpi_gpe.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * ChromeOS EC multi-function device
- *
- * Copyright (C) 2017 Google, Inc
- *
- * 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.
- *
- * The ChromeOS EC multi function device is used to mux all the requests
- * to the EC device for its multiple features: keyboard controller,
- * battery charging and regulator control, firmware update.
- */
-#include <linux/acpi.h>
-
-#define ACPI_LID_DEVICE "LID0"
-
-static int ec_wake_gpe = -EINVAL;
-
-/*
- * This handler indicates to ACPI core that this GPE should stay enabled for
- * lid to work in suspend to idle path.
- */
-static u32 cros_ec_gpe_handler(acpi_handle gpe_device, u32 gpe_number,
- void *data)
-{
- return ACPI_INTERRUPT_HANDLED | ACPI_REENABLE_GPE;
-}
-
-/*
- * Get ACPI GPE for LID0 device.
- */
-static int cros_ec_get_ec_wake_gpe(struct device *dev)
-{
- struct acpi_device *cros_acpi_dev;
- struct acpi_device *adev;
- acpi_handle handle;
- acpi_status status;
- int ret;
-
- cros_acpi_dev = ACPI_COMPANION(dev);
-
- if (!cros_acpi_dev || !cros_acpi_dev->parent ||
- !cros_acpi_dev->parent->handle)
- return -EINVAL;
-
- status = acpi_get_handle(cros_acpi_dev->parent->handle, ACPI_LID_DEVICE,
- &handle);
- if (ACPI_FAILURE(status))
- return -EINVAL;
-
- ret = acpi_bus_get_device(handle, &adev);
- if (ret)
- return ret;
-
- return adev->wakeup.gpe_number;
-}
-
-int cros_ec_acpi_install_gpe_handler(struct device *dev)
-{
- acpi_status status;
-
- ec_wake_gpe = cros_ec_get_ec_wake_gpe(dev);
-
- if (ec_wake_gpe < 0)
- return ec_wake_gpe;
-
- status = acpi_install_gpe_handler(NULL, ec_wake_gpe,
- ACPI_GPE_EDGE_TRIGGERED,
- &cros_ec_gpe_handler, NULL);
- if (ACPI_FAILURE(status))
- return -ENODEV;
-
- dev_info(dev, "Initialized, GPE = 0x%x\n", ec_wake_gpe);
-
- return 0;
-}
-
-void cros_ec_acpi_remove_gpe_handler(void)
-{
- acpi_status status;
-
- if (ec_wake_gpe < 0)
- return;
-
- status = acpi_remove_gpe_handler(NULL, ec_wake_gpe,
- &cros_ec_gpe_handler);
- if (ACPI_FAILURE(status))
- pr_err("failed to remove gpe handler\n");
-}
-
-void cros_ec_acpi_clear_gpe(void)
-{
- if (ec_wake_gpe < 0)
- return;
-
- acpi_clear_gpe(NULL, ec_wake_gpe);
-}
diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index eafd06f..306e1fd 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -113,10 +113,10 @@ static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
ret, msg->result);
memset(ec->features, 0, sizeof(ec->features));
+ } else {
+ memcpy(ec->features, msg->data, sizeof(ec->features));
}
- memcpy(ec->features, msg->data, sizeof(ec->features));
-
dev_dbg(ec->dev, "EC features %08x %08x\n",
ec->features[0], ec->features[1]);
@@ -262,13 +262,6 @@ static const struct file_operations fops = {
#endif
};
-static void __remove(struct device *dev)
-{
- struct cros_ec_dev *ec = container_of(dev, struct cros_ec_dev,
- class_dev);
- kfree(ec);
-}
-
static void cros_ec_sensors_register(struct cros_ec_dev *ec)
{
/*
@@ -306,13 +299,14 @@ static void cros_ec_sensors_register(struct cros_ec_dev *ec)
resp = (struct ec_response_motion_sense *)msg->data;
sensor_num = resp->dump.sensor_count;
/* Allocate 1 extra sensors in FIFO are needed */
- sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 1),
+ sensor_cells = kcalloc(sensor_num + 1, sizeof(struct mfd_cell),
GFP_KERNEL);
if (sensor_cells == NULL)
goto error;
- sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) *
- (sensor_num + 1), GFP_KERNEL);
+ sensor_platforms = kcalloc(sensor_num + 1,
+ sizeof(struct cros_ec_sensor_platform),
+ GFP_KERNEL);
if (sensor_platforms == NULL)
goto error_platforms;
@@ -383,12 +377,16 @@ error:
kfree(msg);
}
+static const struct mfd_cell cros_ec_rtc_cells[] = {
+ { .name = "cros-ec-rtc" }
+};
+
static int ec_device_probe(struct platform_device *pdev)
{
int retval = -ENOMEM;
struct device *dev = &pdev->dev;
struct cros_ec_platform *ec_platform = dev_get_platdata(dev);
- struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);
+ struct cros_ec_dev *ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL);
if (!ec)
return retval;
@@ -410,7 +408,6 @@ static int ec_device_probe(struct platform_device *pdev)
ec->class_dev.devt = MKDEV(ec_major, pdev->id);
ec->class_dev.class = &cros_class;
ec->class_dev.parent = dev;
- ec->class_dev.release = __remove;
retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);
if (retval) {
@@ -422,6 +419,18 @@ static int ec_device_probe(struct platform_device *pdev)
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
cros_ec_sensors_register(ec);
+ /* Check whether this EC instance has RTC host command support */
+ if (cros_ec_check_features(ec, EC_FEATURE_RTC)) {
+ retval = mfd_add_devices(ec->dev, PLATFORM_DEVID_AUTO,
+ cros_ec_rtc_cells,
+ ARRAY_SIZE(cros_ec_rtc_cells),
+ NULL, 0, NULL);
+ if (retval)
+ dev_err(ec->dev,
+ "failed to add cros-ec-rtc device: %d\n",
+ retval);
+ }
+
/* Take control of the lightbar from the EC. */
lb_manual_suspend_ctrl(ec, 1);
@@ -456,9 +465,17 @@ static int ec_device_remove(struct platform_device *pdev)
return 0;
}
+static void ec_device_shutdown(struct platform_device *pdev)
+{
+ struct cros_ec_dev *ec = dev_get_drvdata(&pdev->dev);
+
+ /* Be sure to clear up debugfs delayed works */
+ cros_ec_debugfs_remove(ec);
+}
+
static const struct platform_device_id cros_ec_id[] = {
{ DRV_NAME, 0 },
- { /* sentinel */ },
+ { /* sentinel */ }
};
MODULE_DEVICE_TABLE(platform, cros_ec_id);
@@ -466,6 +483,8 @@ static __maybe_unused int ec_device_suspend(struct device *dev)
{
struct cros_ec_dev *ec = dev_get_drvdata(dev);
+ cros_ec_debugfs_suspend(ec);
+
lb_suspend(ec);
return 0;
@@ -475,6 +494,8 @@ static __maybe_unused int ec_device_resume(struct device *dev)
{
struct cros_ec_dev *ec = dev_get_drvdata(dev);
+ cros_ec_debugfs_resume(ec);
+
lb_resume(ec);
return 0;
@@ -494,6 +515,7 @@ static struct platform_driver cros_ec_dev_driver = {
},
.probe = ec_device_probe,
.remove = ec_device_remove,
+ .shutdown = ec_device_shutdown,
};
static int __init cros_ec_dev_init(void)
diff --git a/drivers/mfd/cros_ec_i2c.c b/drivers/mfd/cros_ec_i2c.c
index 9f70de1..ef9b476 100644
--- a/drivers/mfd/cros_ec_i2c.c
+++ b/drivers/mfd/cros_ec_i2c.c
@@ -13,6 +13,7 @@
* GNU General Public License for more details.
*/
+#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -341,14 +342,17 @@ static int cros_ec_i2c_resume(struct device *dev)
}
#endif
-static SIMPLE_DEV_PM_OPS(cros_ec_i2c_pm_ops, cros_ec_i2c_suspend,
- cros_ec_i2c_resume);
+static const struct dev_pm_ops cros_ec_i2c_pm_ops = {
+ SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_i2c_suspend, cros_ec_i2c_resume)
+};
+#ifdef CONFIG_OF
static const struct of_device_id cros_ec_i2c_of_match[] = {
{ .compatible = "google,cros-ec-i2c", },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, cros_ec_i2c_of_match);
+#endif
static const struct i2c_device_id cros_ec_i2c_id[] = {
{ "cros-ec-i2c", 0 },
@@ -356,9 +360,18 @@ static const struct i2c_device_id cros_ec_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, cros_ec_i2c_id);
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id cros_ec_i2c_acpi_id[] = {
+ { "GOOG0008", 0 },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(acpi, cros_ec_i2c_acpi_id);
+#endif
+
static struct i2c_driver cros_ec_driver = {
.driver = {
.name = "cros-ec-i2c",
+ .acpi_match_table = ACPI_PTR(cros_ec_i2c_acpi_id),
.of_match_table = of_match_ptr(cros_ec_i2c_of_match),
.pm = &cros_ec_i2c_pm_ops,
},
diff --git a/drivers/mfd/da9062-core.c b/drivers/mfd/da9062-core.c
index fe18115..9f61059 100644
--- a/drivers/mfd/da9062-core.c
+++ b/drivers/mfd/da9062-core.c
@@ -365,186 +365,69 @@ static int da9062_get_device_type(struct da9062 *chip)
}
static const struct regmap_range da9061_aa_readable_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_STATUS_B,
- }, {
- .range_min = DA9062AA_STATUS_D,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_IRQ_MASK_A,
- .range_max = DA9062AA_IRQ_MASK_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_GPIO_4,
- }, {
- .range_min = DA9062AA_GPIO_WKUP_MODE,
- .range_max = DA9062AA_GPIO_OUT3_4,
- }, {
- .range_min = DA9062AA_BUCK1_CONT,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_ID_4_3,
- }, {
- .range_min = DA9062AA_ID_12_11,
- .range_max = DA9062AA_ID_16_15,
- }, {
- .range_min = DA9062AA_ID_22_21,
- .range_max = DA9062AA_ID_32_31,
- }, {
- .range_min = DA9062AA_SEQ_A,
- .range_max = DA9062AA_WAIT,
- }, {
- .range_min = DA9062AA_RESET,
- .range_max = DA9062AA_BUCK_ILIM_C,
- }, {
- .range_min = DA9062AA_BUCK1_CFG,
- .range_max = DA9062AA_BUCK3_CFG,
- }, {
- .range_min = DA9062AA_VBUCK1_A,
- .range_max = DA9062AA_VBUCK4_A,
- }, {
- .range_min = DA9062AA_VBUCK3_A,
- .range_max = DA9062AA_VBUCK3_A,
- }, {
- .range_min = DA9062AA_VLDO1_A,
- .range_max = DA9062AA_VLDO4_A,
- }, {
- .range_min = DA9062AA_VBUCK1_B,
- .range_max = DA9062AA_VBUCK4_B,
- }, {
- .range_min = DA9062AA_VBUCK3_B,
- .range_max = DA9062AA_VBUCK3_B,
- }, {
- .range_min = DA9062AA_VLDO1_B,
- .range_max = DA9062AA_VLDO4_B,
- }, {
- .range_min = DA9062AA_INTERFACE,
- .range_max = DA9062AA_CONFIG_E,
- }, {
- .range_min = DA9062AA_CONFIG_G,
- .range_max = DA9062AA_CONFIG_K,
- }, {
- .range_min = DA9062AA_CONFIG_M,
- .range_max = DA9062AA_CONFIG_M,
- }, {
- .range_min = DA9062AA_GP_ID_0,
- .range_max = DA9062AA_GP_ID_19,
- }, {
- .range_min = DA9062AA_DEVICE_ID,
- .range_max = DA9062AA_CONFIG_ID,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
+ regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
+ regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),
+ regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
+ regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
+ regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
+ regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),
+ regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),
+ regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),
+ regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),
+ regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
+ regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
+ regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
+ regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
+ regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
+ regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),
+ regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),
+ regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),
+ regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
+ regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),
};
static const struct regmap_range da9061_aa_writeable_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_PAGE_CON,
- }, {
- .range_min = DA9062AA_FAULT_LOG,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_IRQ_MASK_A,
- .range_max = DA9062AA_IRQ_MASK_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_GPIO_4,
- }, {
- .range_min = DA9062AA_GPIO_WKUP_MODE,
- .range_max = DA9062AA_GPIO_OUT3_4,
- }, {
- .range_min = DA9062AA_BUCK1_CONT,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_ID_4_3,
- }, {
- .range_min = DA9062AA_ID_12_11,
- .range_max = DA9062AA_ID_16_15,
- }, {
- .range_min = DA9062AA_ID_22_21,
- .range_max = DA9062AA_ID_32_31,
- }, {
- .range_min = DA9062AA_SEQ_A,
- .range_max = DA9062AA_WAIT,
- }, {
- .range_min = DA9062AA_RESET,
- .range_max = DA9062AA_BUCK_ILIM_C,
- }, {
- .range_min = DA9062AA_BUCK1_CFG,
- .range_max = DA9062AA_BUCK3_CFG,
- }, {
- .range_min = DA9062AA_VBUCK1_A,
- .range_max = DA9062AA_VBUCK4_A,
- }, {
- .range_min = DA9062AA_VBUCK3_A,
- .range_max = DA9062AA_VBUCK3_A,
- }, {
- .range_min = DA9062AA_VLDO1_A,
- .range_max = DA9062AA_VLDO4_A,
- }, {
- .range_min = DA9062AA_VBUCK1_B,
- .range_max = DA9062AA_VBUCK4_B,
- }, {
- .range_min = DA9062AA_VBUCK3_B,
- .range_max = DA9062AA_VBUCK3_B,
- }, {
- .range_min = DA9062AA_VLDO1_B,
- .range_max = DA9062AA_VLDO4_B,
- }, {
- .range_min = DA9062AA_GP_ID_0,
- .range_max = DA9062AA_GP_ID_19,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),
+ regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
+ regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_GPIO_OUT3_4),
+ regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
+ regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
+ regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
+ regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_WAIT),
+ regmap_reg_range(DA9062AA_RESET, DA9062AA_BUCK_ILIM_C),
+ regmap_reg_range(DA9062AA_BUCK1_CFG, DA9062AA_BUCK3_CFG),
+ regmap_reg_range(DA9062AA_VBUCK1_A, DA9062AA_VBUCK4_A),
+ regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
+ regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
+ regmap_reg_range(DA9062AA_VBUCK1_B, DA9062AA_VBUCK4_B),
+ regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
+ regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
+ regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
};
static const struct regmap_range da9061_aa_volatile_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_STATUS_B,
- }, {
- .range_min = DA9062AA_STATUS_D,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_CONTROL_B,
- }, {
- .range_min = DA9062AA_CONTROL_E,
- .range_max = DA9062AA_CONTROL_F,
- }, {
- .range_min = DA9062AA_BUCK1_CONT,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_SEQ,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
+ regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),
+ regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),
+ regmap_reg_range(DA9062AA_BUCK1_CONT, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),
};
static const struct regmap_access_table da9061_aa_readable_table = {
@@ -587,186 +470,69 @@ static struct regmap_config da9061_regmap_config = {
};
static const struct regmap_range da9062_aa_readable_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_STATUS_B,
- }, {
- .range_min = DA9062AA_STATUS_D,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_IRQ_MASK_A,
- .range_max = DA9062AA_IRQ_MASK_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_GPIO_4,
- }, {
- .range_min = DA9062AA_GPIO_WKUP_MODE,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_COUNT_S,
- .range_max = DA9062AA_SECOND_D,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_ID_4_3,
- }, {
- .range_min = DA9062AA_ID_12_11,
- .range_max = DA9062AA_ID_16_15,
- }, {
- .range_min = DA9062AA_ID_22_21,
- .range_max = DA9062AA_ID_32_31,
- }, {
- .range_min = DA9062AA_SEQ_A,
- .range_max = DA9062AA_BUCK3_CFG,
- }, {
- .range_min = DA9062AA_VBUCK2_A,
- .range_max = DA9062AA_VBUCK4_A,
- }, {
- .range_min = DA9062AA_VBUCK3_A,
- .range_max = DA9062AA_VBUCK3_A,
- }, {
- .range_min = DA9062AA_VLDO1_A,
- .range_max = DA9062AA_VLDO4_A,
- }, {
- .range_min = DA9062AA_VBUCK2_B,
- .range_max = DA9062AA_VBUCK4_B,
- }, {
- .range_min = DA9062AA_VBUCK3_B,
- .range_max = DA9062AA_VBUCK3_B,
- }, {
- .range_min = DA9062AA_VLDO1_B,
- .range_max = DA9062AA_VLDO4_B,
- }, {
- .range_min = DA9062AA_BBAT_CONT,
- .range_max = DA9062AA_BBAT_CONT,
- }, {
- .range_min = DA9062AA_INTERFACE,
- .range_max = DA9062AA_CONFIG_E,
- }, {
- .range_min = DA9062AA_CONFIG_G,
- .range_max = DA9062AA_CONFIG_K,
- }, {
- .range_min = DA9062AA_CONFIG_M,
- .range_max = DA9062AA_CONFIG_M,
- }, {
- .range_min = DA9062AA_TRIM_CLDR,
- .range_max = DA9062AA_GP_ID_19,
- }, {
- .range_min = DA9062AA_DEVICE_ID,
- .range_max = DA9062AA_CONFIG_ID,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
+ regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
+ regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
+ regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
+ regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
+ regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),
+ regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),
+ regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
+ regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
+ regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),
+ regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
+ regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
+ regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),
+ regmap_reg_range(DA9062AA_INTERFACE, DA9062AA_CONFIG_E),
+ regmap_reg_range(DA9062AA_CONFIG_G, DA9062AA_CONFIG_K),
+ regmap_reg_range(DA9062AA_CONFIG_M, DA9062AA_CONFIG_M),
+ regmap_reg_range(DA9062AA_TRIM_CLDR, DA9062AA_GP_ID_19),
+ regmap_reg_range(DA9062AA_DEVICE_ID, DA9062AA_CONFIG_ID),
};
static const struct regmap_range da9062_aa_writeable_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_PAGE_CON,
- }, {
- .range_min = DA9062AA_FAULT_LOG,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_IRQ_MASK_A,
- .range_max = DA9062AA_IRQ_MASK_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_GPIO_4,
- }, {
- .range_min = DA9062AA_GPIO_WKUP_MODE,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_COUNT_S,
- .range_max = DA9062AA_ALARM_Y,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_ID_4_3,
- }, {
- .range_min = DA9062AA_ID_12_11,
- .range_max = DA9062AA_ID_16_15,
- }, {
- .range_min = DA9062AA_ID_22_21,
- .range_max = DA9062AA_ID_32_31,
- }, {
- .range_min = DA9062AA_SEQ_A,
- .range_max = DA9062AA_BUCK3_CFG,
- }, {
- .range_min = DA9062AA_VBUCK2_A,
- .range_max = DA9062AA_VBUCK4_A,
- }, {
- .range_min = DA9062AA_VBUCK3_A,
- .range_max = DA9062AA_VBUCK3_A,
- }, {
- .range_min = DA9062AA_VLDO1_A,
- .range_max = DA9062AA_VLDO4_A,
- }, {
- .range_min = DA9062AA_VBUCK2_B,
- .range_max = DA9062AA_VBUCK4_B,
- }, {
- .range_min = DA9062AA_VBUCK3_B,
- .range_max = DA9062AA_VBUCK3_B,
- }, {
- .range_min = DA9062AA_VLDO1_B,
- .range_max = DA9062AA_VLDO4_B,
- }, {
- .range_min = DA9062AA_BBAT_CONT,
- .range_max = DA9062AA_BBAT_CONT,
- }, {
- .range_min = DA9062AA_GP_ID_0,
- .range_max = DA9062AA_GP_ID_19,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_PAGE_CON),
+ regmap_reg_range(DA9062AA_FAULT_LOG, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_IRQ_MASK_A, DA9062AA_IRQ_MASK_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_GPIO_4),
+ regmap_reg_range(DA9062AA_GPIO_WKUP_MODE, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_ALARM_Y),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_ID_4_3),
+ regmap_reg_range(DA9062AA_ID_12_11, DA9062AA_ID_16_15),
+ regmap_reg_range(DA9062AA_ID_22_21, DA9062AA_ID_32_31),
+ regmap_reg_range(DA9062AA_SEQ_A, DA9062AA_BUCK3_CFG),
+ regmap_reg_range(DA9062AA_VBUCK2_A, DA9062AA_VBUCK4_A),
+ regmap_reg_range(DA9062AA_VBUCK3_A, DA9062AA_VBUCK3_A),
+ regmap_reg_range(DA9062AA_VLDO1_A, DA9062AA_VLDO4_A),
+ regmap_reg_range(DA9062AA_VBUCK2_B, DA9062AA_VBUCK4_B),
+ regmap_reg_range(DA9062AA_VBUCK3_B, DA9062AA_VBUCK3_B),
+ regmap_reg_range(DA9062AA_VLDO1_B, DA9062AA_VLDO4_B),
+ regmap_reg_range(DA9062AA_BBAT_CONT, DA9062AA_BBAT_CONT),
+ regmap_reg_range(DA9062AA_GP_ID_0, DA9062AA_GP_ID_19),
};
static const struct regmap_range da9062_aa_volatile_ranges[] = {
- {
- .range_min = DA9062AA_PAGE_CON,
- .range_max = DA9062AA_STATUS_B,
- }, {
- .range_min = DA9062AA_STATUS_D,
- .range_max = DA9062AA_EVENT_C,
- }, {
- .range_min = DA9062AA_CONTROL_A,
- .range_max = DA9062AA_CONTROL_B,
- }, {
- .range_min = DA9062AA_CONTROL_E,
- .range_max = DA9062AA_CONTROL_F,
- }, {
- .range_min = DA9062AA_BUCK2_CONT,
- .range_max = DA9062AA_BUCK4_CONT,
- }, {
- .range_min = DA9062AA_BUCK3_CONT,
- .range_max = DA9062AA_BUCK3_CONT,
- }, {
- .range_min = DA9062AA_LDO1_CONT,
- .range_max = DA9062AA_LDO4_CONT,
- }, {
- .range_min = DA9062AA_DVC_1,
- .range_max = DA9062AA_DVC_1,
- }, {
- .range_min = DA9062AA_COUNT_S,
- .range_max = DA9062AA_SECOND_D,
- }, {
- .range_min = DA9062AA_SEQ,
- .range_max = DA9062AA_SEQ,
- }, {
- .range_min = DA9062AA_EN_32K,
- .range_max = DA9062AA_EN_32K,
- },
+ regmap_reg_range(DA9062AA_PAGE_CON, DA9062AA_STATUS_B),
+ regmap_reg_range(DA9062AA_STATUS_D, DA9062AA_EVENT_C),
+ regmap_reg_range(DA9062AA_CONTROL_A, DA9062AA_CONTROL_B),
+ regmap_reg_range(DA9062AA_CONTROL_E, DA9062AA_CONTROL_F),
+ regmap_reg_range(DA9062AA_BUCK2_CONT, DA9062AA_BUCK4_CONT),
+ regmap_reg_range(DA9062AA_BUCK3_CONT, DA9062AA_BUCK3_CONT),
+ regmap_reg_range(DA9062AA_LDO1_CONT, DA9062AA_LDO4_CONT),
+ regmap_reg_range(DA9062AA_DVC_1, DA9062AA_DVC_1),
+ regmap_reg_range(DA9062AA_COUNT_S, DA9062AA_SECOND_D),
+ regmap_reg_range(DA9062AA_SEQ, DA9062AA_SEQ),
+ regmap_reg_range(DA9062AA_EN_32K, DA9062AA_EN_32K),
};
static const struct regmap_access_table da9062_aa_readable_table = {
diff --git a/drivers/mfd/htc-i2cpld.c b/drivers/mfd/htc-i2cpld.c
index 3f9eee5..01572b5e 100644
--- a/drivers/mfd/htc-i2cpld.c
+++ b/drivers/mfd/htc-i2cpld.c
@@ -477,12 +477,12 @@ static int htcpld_setup_chips(struct platform_device *pdev)
/* Setup each chip's output GPIOs */
htcpld->nchips = pdata->num_chip;
- htcpld->chip = devm_kzalloc(dev, sizeof(struct htcpld_chip) * htcpld->nchips,
+ htcpld->chip = devm_kcalloc(dev,
+ htcpld->nchips,
+ sizeof(struct htcpld_chip),
GFP_KERNEL);
- if (!htcpld->chip) {
- dev_warn(dev, "Unable to allocate memory for chips\n");
+ if (!htcpld->chip)
return -ENOMEM;
- }
/* Add the chips as best we can */
for (i = 0; i < htcpld->nchips; i++) {
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index d1c46de..d9ae983 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -124,6 +124,11 @@ static const struct intel_lpss_platform_info apl_i2c_info = {
.properties = apl_i2c_properties,
};
+static const struct intel_lpss_platform_info cnl_i2c_info = {
+ .clk_rate = 216000000,
+ .properties = spt_i2c_properties,
+};
+
static const struct pci_device_id intel_lpss_pci_ids[] = {
/* BXT A-Step */
{ PCI_VDEVICE(INTEL, 0x0aac), (kernel_ulong_t)&bxt_i2c_info },
@@ -207,13 +212,13 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0x9daa), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x9dab), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x9dfb), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9dc5), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9dc6), (kernel_ulong_t)&cnl_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9dc7), (kernel_ulong_t)&spt_uart_info },
- { PCI_VDEVICE(INTEL, 0x9de8), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9de8), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9de9), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9dea), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9deb), (kernel_ulong_t)&cnl_i2c_info },
/* SPT-H */
{ PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa128), (kernel_ulong_t)&spt_uart_info },
@@ -240,10 +245,10 @@ static const struct pci_device_id intel_lpss_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0xa32b), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0xa37b), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0xa347), (kernel_ulong_t)&spt_uart_info },
- { PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&spt_i2c_info },
- { PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa368), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa369), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa36a), (kernel_ulong_t)&cnl_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa36b), (kernel_ulong_t)&cnl_i2c_info },
{ }
};
MODULE_DEVICE_TABLE(pci, intel_lpss_pci_ids);
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index 9e545eb..50bffc3 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -40,8 +40,8 @@
/* Offsets from lpss->priv */
#define LPSS_PRIV_RESETS 0x04
-#define LPSS_PRIV_RESETS_FUNC BIT(2)
-#define LPSS_PRIV_RESETS_IDMA 0x3
+#define LPSS_PRIV_RESETS_IDMA BIT(2)
+#define LPSS_PRIV_RESETS_FUNC 0x3
#define LPSS_PRIV_ACTIVELTR 0x10
#define LPSS_PRIV_IDLELTR 0x14
@@ -275,11 +275,11 @@ static void intel_lpss_init_dev(const struct intel_lpss *lpss)
intel_lpss_deassert_reset(lpss);
+ intel_lpss_set_remap_addr(lpss);
+
if (!intel_lpss_has_idma(lpss))
return;
- intel_lpss_set_remap_addr(lpss);
-
/* Make sure that SPI multiblock DMA transfers are re-enabled */
if (lpss->type == LPSS_DEV_SPI)
writel(value, lpss->priv + LPSS_PRIV_SSP_REG);
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c
index ec1f46a..317a47a 100644
--- a/drivers/mfd/janz-cmodio.c
+++ b/drivers/mfd/janz-cmodio.c
@@ -183,10 +183,8 @@ static int cmodio_pci_probe(struct pci_dev *dev,
int ret;
priv = devm_kzalloc(&dev->dev, sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(&dev->dev, "unable to allocate private data\n");
+ if (!priv)
return -ENOMEM;
- }
pci_set_drvdata(dev, priv);
priv->pdev = dev;
diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
index 798e443..f4cd142 100644
--- a/drivers/mfd/jz4740-adc.c
+++ b/drivers/mfd/jz4740-adc.c
@@ -212,10 +212,8 @@ static int jz4740_adc_probe(struct platform_device *pdev)
int irq_base;
adc = devm_kzalloc(&pdev->dev, sizeof(*adc), GFP_KERNEL);
- if (!adc) {
- dev_err(&pdev->dev, "Failed to allocate driver structure\n");
+ if (!adc)
return -ENOMEM;
- }
adc->irq = platform_get_irq(pdev, 0);
if (adc->irq < 0) {
diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
index 2d6e2c3..3f554c4 100644
--- a/drivers/mfd/max8997.c
+++ b/drivers/mfd/max8997.c
@@ -148,10 +148,8 @@ static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
struct max8997_platform_data *pd;
pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
- if (!pd) {
- dev_err(dev, "could not allocate memory for pdata\n");
+ if (!pd)
return ERR_PTR(-ENOMEM);
- }
pd->ono = irq_of_parse_and_map(dev->of_node, 1);
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index c57e407..94e3f32 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -158,7 +158,7 @@ static int mfd_add_device(struct device *parent, int id,
if (!pdev)
goto fail_alloc;
- res = kzalloc(sizeof(*res) * cell->num_resources, GFP_KERNEL);
+ res = kcalloc(cell->num_resources, sizeof(*res), GFP_KERNEL);
if (!res)
goto fail_device;
diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c
index d2cc1ea..5276911 100644
--- a/drivers/mfd/motorola-cpcap.c
+++ b/drivers/mfd/motorola-cpcap.c
@@ -173,9 +173,9 @@ static int cpcap_init_irq(struct cpcap_ddata *cpcap)
int ret;
cpcap->irqs = devm_kzalloc(&cpcap->spi->dev,
- sizeof(*cpcap->irqs) *
- CPCAP_NR_IRQ_REG_BANKS *
- cpcap->regmap_conf->val_bits,
+ array3_size(sizeof(*cpcap->irqs),
+ CPCAP_NR_IRQ_REG_BANKS,
+ cpcap->regmap_conf->val_bits),
GFP_KERNEL);
if (!cpcap->irqs)
return -ENOMEM;
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 04a601f..77b64bd 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -43,6 +43,16 @@ static const struct resource mt6397_rtc_resources[] = {
},
};
+static const struct resource mt6323_keys_resources[] = {
+ DEFINE_RES_IRQ(MT6323_IRQ_STATUS_PWRKEY),
+ DEFINE_RES_IRQ(MT6323_IRQ_STATUS_FCHRKEY),
+};
+
+static const struct resource mt6397_keys_resources[] = {
+ DEFINE_RES_IRQ(MT6397_IRQ_PWRKEY),
+ DEFINE_RES_IRQ(MT6397_IRQ_HOMEKEY),
+};
+
static const struct mfd_cell mt6323_devs[] = {
{
.name = "mt6323-regulator",
@@ -50,6 +60,11 @@ static const struct mfd_cell mt6323_devs[] = {
}, {
.name = "mt6323-led",
.of_compatible = "mediatek,mt6323-led"
+ }, {
+ .name = "mtk-pmic-keys",
+ .num_resources = ARRAY_SIZE(mt6323_keys_resources),
+ .resources = mt6323_keys_resources,
+ .of_compatible = "mediatek,mt6323-keys"
},
};
@@ -71,7 +86,12 @@ static const struct mfd_cell mt6397_devs[] = {
}, {
.name = "mt6397-pinctrl",
.of_compatible = "mediatek,mt6397-pinctrl",
- },
+ }, {
+ .name = "mtk-pmic-keys",
+ .num_resources = ARRAY_SIZE(mt6397_keys_resources),
+ .resources = mt6397_keys_resources,
+ .of_compatible = "mediatek,mt6397-keys"
+ }
};
static void mt6397_irq_lock(struct irq_data *data)
@@ -289,7 +309,7 @@ static int mt6397_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6323_devs,
ARRAY_SIZE(mt6323_devs), NULL,
- 0, NULL);
+ 0, pmic->irq_domain);
break;
case MT6397_CID_CODE:
@@ -304,7 +324,7 @@ static int mt6397_probe(struct platform_device *pdev)
ret = devm_mfd_add_devices(&pdev->dev, -1, mt6397_devs,
ARRAY_SIZE(mt6397_devs), NULL,
- 0, NULL);
+ 0, pmic->irq_domain);
break;
default:
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 7aab376..e11ab12 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -153,27 +153,6 @@ static const char * const port_modes[] = {
[OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM] = "ohci-tll-2pin-dpdm",
};
-/**
- * omap_usbhs_get_dt_port_mode - Get the 'enum usbhs_omap_port_mode'
- * from the port mode string.
- * @mode: The port mode string, usually obtained from device tree.
- *
- * The function returns the 'enum usbhs_omap_port_mode' that matches the
- * provided port mode string as per the port_modes table.
- * If no match is found it returns -ENODEV
- */
-static int omap_usbhs_get_dt_port_mode(const char *mode)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(port_modes); i++) {
- if (!strcmp(mode, port_modes[i]))
- return i;
- }
-
- return -ENODEV;
-}
-
static struct platform_device *omap_usbhs_alloc_child(const char *name,
struct resource *res, int num_resources, void *pdata,
size_t pdata_size, struct device *dev)
@@ -529,7 +508,8 @@ static int usbhs_omap_get_dt_pdata(struct device *dev,
if (ret < 0)
continue;
- ret = omap_usbhs_get_dt_port_mode(mode);
+ /* get 'enum usbhs_omap_port_mode' from port mode string */
+ ret = match_string(port_modes, ARRAY_SIZE(port_modes), mode);
if (ret < 0) {
dev_warn(dev, "Invalid port%d-mode \"%s\" in device tree\n",
i, mode);
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index 44a5d66..446713d 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -108,9 +108,9 @@
(x) != OMAP_EHCI_PORT_MODE_PHY)
struct usbtll_omap {
- int nch; /* num. of channels */
- struct clk **ch_clk;
- void __iomem *base;
+ void __iomem *base;
+ int nch; /* num. of channels */
+ struct clk *ch_clk[0]; /* must be the last member */
};
/*-------------------------------------------------------------------------*/
@@ -216,53 +216,49 @@ static int usbtll_omap_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct resource *res;
struct usbtll_omap *tll;
- int ret = 0;
- int i, ver;
+ void __iomem *base;
+ int i, nch, ver;
dev_dbg(dev, "starting TI HSUSB TLL Controller\n");
- tll = devm_kzalloc(dev, sizeof(struct usbtll_omap), GFP_KERNEL);
- if (!tll) {
- dev_err(dev, "Memory allocation failed\n");
- return -ENOMEM;
- }
-
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- tll->base = devm_ioremap_resource(dev, res);
- if (IS_ERR(tll->base))
- return PTR_ERR(tll->base);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
- platform_set_drvdata(pdev, tll);
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
- ver = usbtll_read(tll->base, OMAP_USBTLL_REVISION);
+ ver = usbtll_read(base, OMAP_USBTLL_REVISION);
switch (ver) {
case OMAP_USBTLL_REV1:
case OMAP_USBTLL_REV4:
- tll->nch = OMAP_TLL_CHANNEL_COUNT;
+ nch = OMAP_TLL_CHANNEL_COUNT;
break;
case OMAP_USBTLL_REV2:
case OMAP_USBTLL_REV3:
- tll->nch = OMAP_REV2_TLL_CHANNEL_COUNT;
+ nch = OMAP_REV2_TLL_CHANNEL_COUNT;
break;
default:
- tll->nch = OMAP_TLL_CHANNEL_COUNT;
- dev_dbg(dev,
- "USB TLL Rev : 0x%x not recognized, assuming %d channels\n",
- ver, tll->nch);
+ nch = OMAP_TLL_CHANNEL_COUNT;
+ dev_dbg(dev, "rev 0x%x not recognized, assuming %d channels\n",
+ ver, nch);
break;
}
- tll->ch_clk = devm_kzalloc(dev, sizeof(struct clk *) * tll->nch,
- GFP_KERNEL);
- if (!tll->ch_clk) {
- ret = -ENOMEM;
- dev_err(dev, "Couldn't allocate memory for channel clocks\n");
- goto err_clk_alloc;
+ tll = devm_kzalloc(dev, sizeof(*tll) + sizeof(tll->ch_clk[nch]),
+ GFP_KERNEL);
+ if (!tll) {
+ pm_runtime_put_sync(dev);
+ pm_runtime_disable(dev);
+ return -ENOMEM;
}
- for (i = 0; i < tll->nch; i++) {
+ tll->base = base;
+ tll->nch = nch;
+ platform_set_drvdata(pdev, tll);
+
+ for (i = 0; i < nch; i++) {
char clkname[] = "usb_tll_hs_usb_chx_clk";
snprintf(clkname, sizeof(clkname),
@@ -282,12 +278,6 @@ static int usbtll_omap_probe(struct platform_device *pdev)
spin_unlock(&tll_lock);
return 0;
-
-err_clk_alloc:
- pm_runtime_put_sync(dev);
- pm_runtime_disable(dev);
-
- return ret;
}
/**
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index f952dff..0d2a88d 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -242,8 +242,10 @@ static int pcf50633_probe(struct i2c_client *client,
for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
pdev = platform_device_alloc("pcf50633-regulator", i);
- if (!pdev)
- return -ENOMEM;
+ if (!pdev) {
+ ret = -ENOMEM;
+ goto err2;
+ }
pdev->dev.parent = pcf->dev;
ret = platform_device_add_data(pdev, &pdata->reg_init_data[i],
@@ -269,6 +271,7 @@ static int pcf50633_probe(struct i2c_client *client,
err:
platform_device_put(pdev);
+err2:
for (j = 0; j < i; j++)
platform_device_put(pcf->regulator_pdev[j]);
diff --git a/drivers/mfd/qcom-spmi-pmic.c b/drivers/mfd/qcom-spmi-pmic.c
index 2022bdf..e2e95de 100644
--- a/drivers/mfd/qcom-spmi-pmic.c
+++ b/drivers/mfd/qcom-spmi-pmic.c
@@ -39,6 +39,9 @@
#define PM8916_SUBTYPE 0x0b
#define PM8004_SUBTYPE 0x0c
#define PM8909_SUBTYPE 0x0d
+#define PM8998_SUBTYPE 0x14
+#define PMI8998_SUBTYPE 0x15
+#define PM8005_SUBTYPE 0x18
static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,spmi-pmic", .data = (void *)COMMON_SUBTYPE },
@@ -55,6 +58,9 @@ static const struct of_device_id pmic_spmi_id_table[] = {
{ .compatible = "qcom,pm8916", .data = (void *)PM8916_SUBTYPE },
{ .compatible = "qcom,pm8004", .data = (void *)PM8004_SUBTYPE },
{ .compatible = "qcom,pm8909", .data = (void *)PM8909_SUBTYPE },
+ { .compatible = "qcom,pm8998", .data = (void *)PM8998_SUBTYPE },
+ { .compatible = "qcom,pmi8998", .data = (void *)PMI8998_SUBTYPE },
+ { .compatible = "qcom,pm8005", .data = (void *)PM8005_SUBTYPE },
{ }
};
diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c
index 5c858e7..36dcd98 100644
--- a/drivers/mfd/rave-sp.c
+++ b/drivers/mfd/rave-sp.c
@@ -45,7 +45,9 @@
#define RAVE_SP_DLE 0x10
#define RAVE_SP_MAX_DATA_SIZE 64
-#define RAVE_SP_CHECKSUM_SIZE 2 /* Worst case scenario on RDU2 */
+#define RAVE_SP_CHECKSUM_8B2C 1
+#define RAVE_SP_CHECKSUM_CCITT 2
+#define RAVE_SP_CHECKSUM_SIZE RAVE_SP_CHECKSUM_CCITT
/*
* We don't store STX, ETX and unescaped bytes, so Rx is only
* DATA + CSUM
@@ -160,6 +162,8 @@ struct rave_sp_variant {
* @variant: Device variant specific information
* @event_notifier_list: Input event notification chain
*
+ * @part_number_firmware: Firmware version
+ * @part_number_bootloader: Bootloader version
*/
struct rave_sp {
struct serdev_device *serdev;
@@ -171,8 +175,40 @@ struct rave_sp {
const struct rave_sp_variant *variant;
struct blocking_notifier_head event_notifier_list;
+
+ const char *part_number_firmware;
+ const char *part_number_bootloader;
};
+struct rave_sp_version {
+ u8 hardware;
+ __le16 major;
+ u8 minor;
+ u8 letter[2];
+} __packed;
+
+struct rave_sp_status {
+ struct rave_sp_version bootloader_version;
+ struct rave_sp_version firmware_version;
+ u16 rdu_eeprom_flag;
+ u16 dds_eeprom_flag;
+ u8 pic_flag;
+ u8 orientation;
+ u32 etc;
+ s16 temp[2];
+ u8 backlight_current[3];
+ u8 dip_switch;
+ u8 host_interrupt;
+ u16 voltage_28;
+ u8 i2c_device_status;
+ u8 power_status;
+ u8 general_status;
+ u8 deprecated1;
+ u8 power_led_status;
+ u8 deprecated2;
+ u8 periph_power_shutoff;
+} __packed;
+
static bool rave_sp_id_is_event(u8 code)
{
return (code & 0xF0) == RAVE_SP_EVNT_BASE;
@@ -275,8 +311,8 @@ static int rave_sp_write(struct rave_sp *sp, const u8 *data, u8 data_size)
length = dest - frame;
- print_hex_dump(KERN_DEBUG, "rave-sp tx: ", DUMP_PREFIX_NONE,
- 16, 1, frame, length, false);
+ print_hex_dump_debug("rave-sp tx: ", DUMP_PREFIX_NONE,
+ 16, 1, frame, length, false);
return serdev_device_write(sp->serdev, frame, length, HZ);
}
@@ -415,10 +451,15 @@ static void rave_sp_receive_frame(struct rave_sp *sp,
const size_t payload_length = length - checksum_length;
const u8 *crc_reported = &data[payload_length];
struct device *dev = &sp->serdev->dev;
- u8 crc_calculated[checksum_length];
+ u8 crc_calculated[RAVE_SP_CHECKSUM_SIZE];
+
+ if (unlikely(checksum_length > sizeof(crc_calculated))) {
+ dev_warn(dev, "Checksum too long, dropping\n");
+ return;
+ }
- print_hex_dump(KERN_DEBUG, "rave-sp rx: ", DUMP_PREFIX_NONE,
- 16, 1, data, length, false);
+ print_hex_dump_debug("rave-sp rx: ", DUMP_PREFIX_NONE,
+ 16, 1, data, length, false);
if (unlikely(length <= checksum_length)) {
dev_warn(dev, "Dropping short frame\n");
@@ -512,8 +553,6 @@ static int rave_sp_receive_buf(struct serdev_device *serdev,
/* FALLTHROUGH */
case RAVE_SP_EXPECT_ESCAPED_DATA:
- deframer->data[deframer->length++] = byte;
-
if (deframer->length == sizeof(deframer->data)) {
dev_warn(dev, "Bad frame: Too long\n");
/*
@@ -528,6 +567,8 @@ static int rave_sp_receive_buf(struct serdev_device *serdev,
goto reset_framer;
}
+ deframer->data[deframer->length++] = byte;
+
/*
* We've extracted out special byte, now we
* can go back to regular data collecting
@@ -609,6 +650,52 @@ static int rave_sp_default_cmd_translate(enum rave_sp_command command)
}
}
+static const char *devm_rave_sp_version(struct device *dev,
+ struct rave_sp_version *version)
+{
+ /*
+ * NOTE: The format string below uses %02d to display u16
+ * intentionally for the sake of backwards compatibility with
+ * legacy software.
+ */
+ return devm_kasprintf(dev, GFP_KERNEL, "%02d%02d%02d.%c%c\n",
+ version->hardware,
+ le16_to_cpu(version->major),
+ version->minor,
+ version->letter[0],
+ version->letter[1]);
+}
+
+static int rave_sp_get_status(struct rave_sp *sp)
+{
+ struct device *dev = &sp->serdev->dev;
+ u8 cmd[] = {
+ [0] = RAVE_SP_CMD_STATUS,
+ [1] = 0
+ };
+ struct rave_sp_status status;
+ const char *version;
+ int ret;
+
+ ret = rave_sp_exec(sp, cmd, sizeof(cmd), &status, sizeof(status));
+ if (ret)
+ return ret;
+
+ version = devm_rave_sp_version(dev, &status.firmware_version);
+ if (!version)
+ return -ENOMEM;
+
+ sp->part_number_firmware = version;
+
+ version = devm_rave_sp_version(dev, &status.bootloader_version);
+ if (!version)
+ return -ENOMEM;
+
+ sp->part_number_bootloader = version;
+
+ return 0;
+}
+
static const struct rave_sp_checksum rave_sp_checksum_8b2c = {
.length = 1,
.subroutine = csum_8b2c,
@@ -657,6 +744,7 @@ static const struct serdev_device_ops rave_sp_serdev_device_ops = {
static int rave_sp_probe(struct serdev_device *serdev)
{
struct device *dev = &serdev->dev;
+ const char *unknown = "unknown\n";
struct rave_sp *sp;
u32 baud;
int ret;
@@ -689,6 +777,20 @@ static int rave_sp_probe(struct serdev_device *serdev)
serdev_device_set_baudrate(serdev, baud);
+ ret = rave_sp_get_status(sp);
+ if (ret) {
+ dev_warn(dev, "Failed to get firmware status: %d\n", ret);
+ sp->part_number_firmware = unknown;
+ sp->part_number_bootloader = unknown;
+ }
+
+ /*
+ * Those strings already have a \n embedded, so there's no
+ * need to have one in format string.
+ */
+ dev_info(dev, "Firmware version: %s", sp->part_number_firmware);
+ dev_info(dev, "Bootloader version: %s", sp->part_number_bootloader);
+
return devm_of_platform_populate(dev);
}
diff --git a/drivers/mfd/rc5t583.c b/drivers/mfd/rc5t583.c
index d12243d..fd46de0 100644
--- a/drivers/mfd/rc5t583.c
+++ b/drivers/mfd/rc5t583.c
@@ -258,11 +258,9 @@ static int rc5t583_i2c_probe(struct i2c_client *i2c,
return -EINVAL;
}
- rc5t583 = devm_kzalloc(&i2c->dev, sizeof(struct rc5t583), GFP_KERNEL);
- if (!rc5t583) {
- dev_err(&i2c->dev, "Memory allocation failed\n");
+ rc5t583 = devm_kzalloc(&i2c->dev, sizeof(*rc5t583), GFP_KERNEL);
+ if (!rc5t583)
return -ENOMEM;
- }
rc5t583->dev = &i2c->dev;
i2c_set_clientdata(i2c, rc5t583);
diff --git a/drivers/mfd/si476x-i2c.c b/drivers/mfd/si476x-i2c.c
index e6a3d99..2c5ec93 100644
--- a/drivers/mfd/si476x-i2c.c
+++ b/drivers/mfd/si476x-i2c.c
@@ -697,11 +697,9 @@ static int si476x_core_probe(struct i2c_client *client,
int cell_num;
core = devm_kzalloc(&client->dev, sizeof(*core), GFP_KERNEL);
- if (!core) {
- dev_err(&client->dev,
- "failed to allocate 'struct si476x_core'\n");
+ if (!core)
return -ENOMEM;
- }
+
core->client = client;
core->regmap = devm_regmap_init_si476x(core);
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index ad77416..2a87b0d 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -19,7 +19,7 @@
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/pci.h>
-#include <linux/i2c-gpio.h>
+#include <linux/platform_data/i2c-gpio.h>
#include <linux/gpio/machine.h>
#include <linux/slab.h>
@@ -1050,13 +1050,13 @@ static int sm501_register_gpio(struct sm501_devdata *sm)
spin_lock_init(&gpio->lock);
gpio->regs_res = request_mem_region(iobase, 0x20, "sm501-gpio");
- if (gpio->regs_res == NULL) {
+ if (!gpio->regs_res) {
dev_err(sm->dev, "gpio: failed to request region\n");
return -ENXIO;
}
gpio->regs = ioremap(iobase, 0x20);
- if (gpio->regs == NULL) {
+ if (!gpio->regs) {
dev_err(sm->dev, "gpio: failed to remap registers\n");
ret = -ENXIO;
goto err_claimed;
@@ -1358,7 +1358,7 @@ static int sm501_init_dev(struct sm501_devdata *sm)
sm501_register_gpio(sm);
}
- if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+ if (pdata && pdata->gpio_i2c && pdata->gpio_i2c_nr > 0) {
if (!sm501_gpio_isregistered(sm))
dev_err(sm->dev, "no gpio available for i2c gpio.\n");
else
@@ -1383,9 +1383,8 @@ static int sm501_plat_probe(struct platform_device *dev)
struct sm501_devdata *sm;
int ret;
- sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
- if (sm == NULL) {
- dev_err(&dev->dev, "no memory for device data\n");
+ sm = kzalloc(sizeof(*sm), GFP_KERNEL);
+ if (!sm) {
ret = -ENOMEM;
goto err1;
}
@@ -1403,8 +1402,7 @@ static int sm501_plat_probe(struct platform_device *dev)
sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
-
- if (sm->io_res == NULL || sm->mem_res == NULL) {
+ if (!sm->io_res || !sm->mem_res) {
dev_err(&dev->dev, "failed to get IO resource\n");
ret = -ENOENT;
goto err_res;
@@ -1412,8 +1410,7 @@ static int sm501_plat_probe(struct platform_device *dev)
sm->regs_claim = request_mem_region(sm->io_res->start,
0x100, "sm501");
-
- if (sm->regs_claim == NULL) {
+ if (!sm->regs_claim) {
dev_err(&dev->dev, "cannot claim registers\n");
ret = -EBUSY;
goto err_res;
@@ -1422,8 +1419,7 @@ static int sm501_plat_probe(struct platform_device *dev)
platform_set_drvdata(dev, sm);
sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res));
-
- if (sm->regs == NULL) {
+ if (!sm->regs) {
dev_err(&dev->dev, "cannot remap registers\n");
ret = -EIO;
goto err_claim;
@@ -1449,7 +1445,7 @@ static void sm501_set_power(struct sm501_devdata *sm, int on)
{
struct sm501_platdata *pd = sm->platdata;
- if (pd == NULL)
+ if (!pd)
return;
if (pd->get_power) {
@@ -1573,9 +1569,8 @@ static int sm501_pci_probe(struct pci_dev *dev,
struct sm501_devdata *sm;
int err;
- sm = kzalloc(sizeof(struct sm501_devdata), GFP_KERNEL);
- if (sm == NULL) {
- dev_err(&dev->dev, "no memory for device data\n");
+ sm = kzalloc(sizeof(*sm), GFP_KERNEL);
+ if (!sm) {
err = -ENOMEM;
goto err1;
}
@@ -1626,15 +1621,14 @@ static int sm501_pci_probe(struct pci_dev *dev,
sm->regs_claim = request_mem_region(sm->io_res->start,
0x100, "sm501");
- if (sm->regs_claim == NULL) {
+ if (!sm->regs_claim) {
dev_err(&dev->dev, "cannot claim registers\n");
err= -EBUSY;
goto err3;
}
sm->regs = pci_ioremap_bar(dev, 1);
-
- if (sm->regs == NULL) {
+ if (!sm->regs) {
dev_err(&dev->dev, "cannot remap registers\n");
err = -EIO;
goto err4;
diff --git a/drivers/mfd/smsc-ece1099.c b/drivers/mfd/smsc-ece1099.c
index 93a8297..57b792eb 100644
--- a/drivers/mfd/smsc-ece1099.c
+++ b/drivers/mfd/smsc-ece1099.c
@@ -37,12 +37,9 @@ static int smsc_i2c_probe(struct i2c_client *i2c,
int devid, rev, venid_l, venid_h;
int ret;
- smsc = devm_kzalloc(&i2c->dev, sizeof(struct smsc),
- GFP_KERNEL);
- if (!smsc) {
- dev_err(&i2c->dev, "smsc mfd driver memory allocation failed\n");
+ smsc = devm_kzalloc(&i2c->dev, sizeof(*smsc), GFP_KERNEL);
+ if (!smsc)
return -ENOMEM;
- }
smsc->regmap = devm_regmap_init_i2c(i2c, &smsc_regmap_config);
if (IS_ERR(smsc->regmap))
diff --git a/drivers/mfd/sprd-sc27xx-spi.c b/drivers/mfd/sprd-sc27xx-spi.c
index 56a4782..69df277 100644
--- a/drivers/mfd/sprd-sc27xx-spi.c
+++ b/drivers/mfd/sprd-sc27xx-spi.c
@@ -111,6 +111,9 @@ static const struct mfd_cell sprd_pmic_devs[] = {
}, {
.name = "sc27xx-poweroff",
.of_compatible = "sprd,sc27xx-poweroff",
+ }, {
+ .name = "sc27xx-syscon",
+ .of_compatible = "sprd,sc27xx-syscon",
},
};
@@ -196,8 +199,9 @@ static int sprd_pmic_probe(struct spi_device *spi)
ddata->irq_chip.num_irqs = pdata->num_irqs;
ddata->irq_chip.mask_invert = true;
- ddata->irqs = devm_kzalloc(&spi->dev, sizeof(struct regmap_irq) *
- pdata->num_irqs, GFP_KERNEL);
+ ddata->irqs = devm_kcalloc(&spi->dev,
+ pdata->num_irqs, sizeof(struct regmap_irq),
+ GFP_KERNEL);
if (!ddata->irqs)
return -ENOMEM;
diff --git a/drivers/mfd/stm32-timers.c b/drivers/mfd/stm32-timers.c
index 1d347e5..efcd4b9 100644
--- a/drivers/mfd/stm32-timers.c
+++ b/drivers/mfd/stm32-timers.c
@@ -4,16 +4,156 @@
* Author: Benjamin Gaignard <benjamin.gaignard@st.com>
*/
+#include <linux/bitfield.h>
#include <linux/mfd/stm32-timers.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/reset.h>
+#define STM32_TIMERS_MAX_REGISTERS 0x3fc
+
+/* DIER register DMA enable bits */
+static const u32 stm32_timers_dier_dmaen[STM32_TIMERS_MAX_DMAS] = {
+ TIM_DIER_CC1DE,
+ TIM_DIER_CC2DE,
+ TIM_DIER_CC3DE,
+ TIM_DIER_CC4DE,
+ TIM_DIER_UIE,
+ TIM_DIER_TDE,
+ TIM_DIER_COMDE
+};
+
+static void stm32_timers_dma_done(void *p)
+{
+ struct stm32_timers_dma *dma = p;
+ struct dma_tx_state state;
+ enum dma_status status;
+
+ status = dmaengine_tx_status(dma->chan, dma->chan->cookie, &state);
+ if (status == DMA_COMPLETE)
+ complete(&dma->completion);
+}
+
+/**
+ * stm32_timers_dma_burst_read - Read from timers registers using DMA.
+ *
+ * Read from STM32 timers registers using DMA on a single event.
+ * @dev: reference to stm32_timers MFD device
+ * @buf: DMA'able destination buffer
+ * @id: stm32_timers_dmas event identifier (ch[1..4], up, trig or com)
+ * @reg: registers start offset for DMA to read from (like CCRx for capture)
+ * @num_reg: number of registers to read upon each DMA request, starting @reg.
+ * @bursts: number of bursts to read (e.g. like two for pwm period capture)
+ * @tmo_ms: timeout (milliseconds)
+ */
+int stm32_timers_dma_burst_read(struct device *dev, u32 *buf,
+ enum stm32_timers_dmas id, u32 reg,
+ unsigned int num_reg, unsigned int bursts,
+ unsigned long tmo_ms)
+{
+ struct stm32_timers *ddata = dev_get_drvdata(dev);
+ unsigned long timeout = msecs_to_jiffies(tmo_ms);
+ struct regmap *regmap = ddata->regmap;
+ struct stm32_timers_dma *dma = &ddata->dma;
+ size_t len = num_reg * bursts * sizeof(u32);
+ struct dma_async_tx_descriptor *desc;
+ struct dma_slave_config config;
+ dma_cookie_t cookie;
+ dma_addr_t dma_buf;
+ u32 dbl, dba;
+ long err;
+ int ret;
+
+ /* Sanity check */
+ if (id < STM32_TIMERS_DMA_CH1 || id >= STM32_TIMERS_MAX_DMAS)
+ return -EINVAL;
+
+ if (!num_reg || !bursts || reg > STM32_TIMERS_MAX_REGISTERS ||
+ (reg + num_reg * sizeof(u32)) > STM32_TIMERS_MAX_REGISTERS)
+ return -EINVAL;
+
+ if (!dma->chans[id])
+ return -ENODEV;
+ mutex_lock(&dma->lock);
+
+ /* Select DMA channel in use */
+ dma->chan = dma->chans[id];
+ dma_buf = dma_map_single(dev, buf, len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(dev, dma_buf)) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ /* Prepare DMA read from timer registers, using DMA burst mode */
+ memset(&config, 0, sizeof(config));
+ config.src_addr = (dma_addr_t)dma->phys_base + TIM_DMAR;
+ config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ ret = dmaengine_slave_config(dma->chan, &config);
+ if (ret)
+ goto unmap;
+
+ desc = dmaengine_prep_slave_single(dma->chan, dma_buf, len,
+ DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
+ if (!desc) {
+ ret = -EBUSY;
+ goto unmap;
+ }
+
+ desc->callback = stm32_timers_dma_done;
+ desc->callback_param = dma;
+ cookie = dmaengine_submit(desc);
+ ret = dma_submit_error(cookie);
+ if (ret)
+ goto dma_term;
+
+ reinit_completion(&dma->completion);
+ dma_async_issue_pending(dma->chan);
+
+ /* Setup and enable timer DMA burst mode */
+ dbl = FIELD_PREP(TIM_DCR_DBL, bursts - 1);
+ dba = FIELD_PREP(TIM_DCR_DBA, reg >> 2);
+ ret = regmap_write(regmap, TIM_DCR, dbl | dba);
+ if (ret)
+ goto dma_term;
+
+ /* Clear pending flags before enabling DMA request */
+ ret = regmap_write(regmap, TIM_SR, 0);
+ if (ret)
+ goto dcr_clr;
+
+ ret = regmap_update_bits(regmap, TIM_DIER, stm32_timers_dier_dmaen[id],
+ stm32_timers_dier_dmaen[id]);
+ if (ret)
+ goto dcr_clr;
+
+ err = wait_for_completion_interruptible_timeout(&dma->completion,
+ timeout);
+ if (err == 0)
+ ret = -ETIMEDOUT;
+ else if (err < 0)
+ ret = err;
+
+ regmap_update_bits(regmap, TIM_DIER, stm32_timers_dier_dmaen[id], 0);
+ regmap_write(regmap, TIM_SR, 0);
+dcr_clr:
+ regmap_write(regmap, TIM_DCR, 0);
+dma_term:
+ dmaengine_terminate_all(dma->chan);
+unmap:
+ dma_unmap_single(dev, dma_buf, len, DMA_FROM_DEVICE);
+unlock:
+ dma->chan = NULL;
+ mutex_unlock(&dma->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(stm32_timers_dma_burst_read);
+
static const struct regmap_config stm32_timers_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = sizeof(u32),
- .max_register = 0x3fc,
+ .max_register = STM32_TIMERS_MAX_REGISTERS,
};
static void stm32_timers_get_arr_size(struct stm32_timers *ddata)
@@ -27,12 +167,45 @@ static void stm32_timers_get_arr_size(struct stm32_timers *ddata)
regmap_write(ddata->regmap, TIM_ARR, 0x0);
}
+static void stm32_timers_dma_probe(struct device *dev,
+ struct stm32_timers *ddata)
+{
+ int i;
+ char name[4];
+
+ init_completion(&ddata->dma.completion);
+ mutex_init(&ddata->dma.lock);
+
+ /* Optional DMA support: get valid DMA channel(s) or NULL */
+ for (i = STM32_TIMERS_DMA_CH1; i <= STM32_TIMERS_DMA_CH4; i++) {
+ snprintf(name, ARRAY_SIZE(name), "ch%1d", i + 1);
+ ddata->dma.chans[i] = dma_request_slave_channel(dev, name);
+ }
+ ddata->dma.chans[STM32_TIMERS_DMA_UP] =
+ dma_request_slave_channel(dev, "up");
+ ddata->dma.chans[STM32_TIMERS_DMA_TRIG] =
+ dma_request_slave_channel(dev, "trig");
+ ddata->dma.chans[STM32_TIMERS_DMA_COM] =
+ dma_request_slave_channel(dev, "com");
+}
+
+static void stm32_timers_dma_remove(struct device *dev,
+ struct stm32_timers *ddata)
+{
+ int i;
+
+ for (i = STM32_TIMERS_DMA_CH1; i < STM32_TIMERS_MAX_DMAS; i++)
+ if (ddata->dma.chans[i])
+ dma_release_channel(ddata->dma.chans[i]);
+}
+
static int stm32_timers_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct stm32_timers *ddata;
struct resource *res;
void __iomem *mmio;
+ int ret;
ddata = devm_kzalloc(dev, sizeof(*ddata), GFP_KERNEL);
if (!ddata)
@@ -43,6 +216,9 @@ static int stm32_timers_probe(struct platform_device *pdev)
if (IS_ERR(mmio))
return PTR_ERR(mmio);
+ /* Timer physical addr for DMA */
+ ddata->dma.phys_base = res->start;
+
ddata->regmap = devm_regmap_init_mmio_clk(dev, "int", mmio,
&stm32_timers_regmap_cfg);
if (IS_ERR(ddata->regmap))
@@ -54,9 +230,29 @@ static int stm32_timers_probe(struct platform_device *pdev)
stm32_timers_get_arr_size(ddata);
+ stm32_timers_dma_probe(dev, ddata);
+
platform_set_drvdata(pdev, ddata);
- return devm_of_platform_populate(&pdev->dev);
+ ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+ if (ret)
+ stm32_timers_dma_remove(dev, ddata);
+
+ return ret;
+}
+
+static int stm32_timers_remove(struct platform_device *pdev)
+{
+ struct stm32_timers *ddata = platform_get_drvdata(pdev);
+
+ /*
+ * Don't use devm_ here: enfore of_platform_depopulate() happens before
+ * DMA are released, to avoid race on DMA.
+ */
+ of_platform_depopulate(&pdev->dev);
+ stm32_timers_dma_remove(&pdev->dev, ddata);
+
+ return 0;
}
static const struct of_device_id stm32_timers_of_match[] = {
@@ -67,6 +263,7 @@ MODULE_DEVICE_TABLE(of, stm32_timers_of_match);
static struct platform_driver stm32_timers_driver = {
.probe = stm32_timers_probe,
+ .remove = stm32_timers_remove,
.driver = {
.name = "stm32-timers",
.of_match_table = stm32_timers_of_match,
diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c
index 7eaa40b..b6d05cd 100644
--- a/drivers/mfd/syscon.c
+++ b/drivers/mfd/syscon.c
@@ -106,9 +106,11 @@ static struct syscon *of_syscon_register(struct device_node *np)
}
}
+ syscon_config.name = of_node_full_name(np);
syscon_config.reg_stride = reg_io_width;
syscon_config.val_bits = reg_io_width * 8;
syscon_config.max_register = resource_size(&res) - reg_io_width;
+ syscon_config.name = of_node_full_name(np);
regmap = regmap_init_mmio(NULL, base, &syscon_config);
if (IS_ERR(regmap)) {
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index 3cd958a..47012c0 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -169,10 +169,9 @@ static int ti_tscadc_probe(struct platform_device *pdev)
/* Allocate memory for device */
tscadc = devm_kzalloc(&pdev->dev, sizeof(*tscadc), GFP_KERNEL);
- if (!tscadc) {
- dev_err(&pdev->dev, "failed to allocate memory.\n");
+ if (!tscadc)
return -ENOMEM;
- }
+
tscadc->dev = &pdev->dev;
err = platform_get_irq(pdev, 0);
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c
index cd4a6d7..436e347 100644
--- a/drivers/mfd/timberdale.c
+++ b/drivers/mfd/timberdale.c
@@ -30,8 +30,8 @@
#include <linux/timb_gpio.h>
#include <linux/i2c.h>
-#include <linux/i2c-ocores.h>
-#include <linux/i2c-xiic.h>
+#include <linux/platform_data/i2c-ocores.h>
+#include <linux/platform_data/i2c-xiic.h>
#include <linux/spi/spi.h>
#include <linux/spi/xilinx_spi.h>
@@ -707,8 +707,8 @@ static int timb_probe(struct pci_dev *dev,
goto err_config;
}
- msix_entries = kzalloc(TIMBERDALE_NR_IRQS * sizeof(*msix_entries),
- GFP_KERNEL);
+ msix_entries = kcalloc(TIMBERDALE_NR_IRQS, sizeof(*msix_entries),
+ GFP_KERNEL);
if (!msix_entries)
goto err_config;
@@ -777,7 +777,7 @@ static int timb_probe(struct pci_dev *dev,
&dev->resource[0], msix_entries[0].vector, NULL);
break;
default:
- dev_err(&dev->dev, "Uknown IP setup: %d.%d.%d\n",
+ dev_err(&dev->dev, "Unknown IP setup: %d.%d.%d\n",
priv->fw.major, priv->fw.minor, ip_setup);
err = -ENODEV;
goto err_mfd;
diff --git a/drivers/mfd/tps65090.c b/drivers/mfd/tps65090.c
index d7ec318..f13e4cd 100644
--- a/drivers/mfd/tps65090.c
+++ b/drivers/mfd/tps65090.c
@@ -192,10 +192,8 @@ static int tps65090_i2c_probe(struct i2c_client *client,
irq_base = pdata->irq_base;
tps65090 = devm_kzalloc(&client->dev, sizeof(*tps65090), GFP_KERNEL);
- if (!tps65090) {
- dev_err(&client->dev, "mem alloc for tps65090 failed\n");
+ if (!tps65090)
return -ENOMEM;
- }
tps65090->dev = &client->dev;
i2c_set_clientdata(client, tps65090);
diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c
index 5628a6b..b893797 100644
--- a/drivers/mfd/tps6586x.c
+++ b/drivers/mfd/tps6586x.c
@@ -423,10 +423,8 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien
struct tps6586x_platform_data *pdata;
pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
- dev_err(&client->dev, "Memory allocation failed\n");
+ if (!pdata)
return NULL;
- }
pdata->num_subdevs = 0;
pdata->subdevs = NULL;
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 8263605..bf16cbe 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -229,7 +229,7 @@ static struct regmap_irq_chip tps65910_irq_chip = {
static int tps65910_irq_init(struct tps65910 *tps65910, int irq,
struct tps65910_platform_data *pdata)
{
- int ret = 0;
+ int ret;
static struct regmap_irq_chip *tps6591x_irqs_chip;
if (!irq) {
@@ -312,14 +312,14 @@ static int tps65910_ck32k_init(struct tps65910 *tps65910,
static int tps65910_sleepinit(struct tps65910 *tps65910,
struct tps65910_board *pmic_pdata)
{
- struct device *dev = NULL;
- int ret = 0;
-
- dev = tps65910->dev;
+ struct device *dev;
+ int ret;
if (!pmic_pdata->en_dev_slp)
return 0;
+ dev = tps65910->dev;
+
/* enabling SLEEP device state */
ret = tps65910_reg_set_bits(tps65910, TPS65910_DEVCTRL,
DEVCTRL_DEV_SLP_MASK);
@@ -383,7 +383,7 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
struct tps65910_board *board_info;
unsigned int prop;
const struct of_device_id *match;
- int ret = 0;
+ int ret;
match = of_match_device(tps65910_of_match, &client->dev);
if (!match) {
@@ -395,10 +395,8 @@ static struct tps65910_board *tps65910_parse_dt(struct i2c_client *client,
board_info = devm_kzalloc(&client->dev, sizeof(*board_info),
GFP_KERNEL);
- if (!board_info) {
- dev_err(&client->dev, "Failed to allocate pdata\n");
+ if (!board_info)
return NULL;
- }
ret = of_property_read_u32(np, "ti,vmbch-threshold", &prop);
if (!ret)
@@ -462,7 +460,7 @@ static int tps65910_i2c_probe(struct i2c_client *i2c,
struct tps65910_board *of_pmic_plat_data = NULL;
struct tps65910_platform_data *init_data;
unsigned long chip_id = id->driver_data;
- int ret = 0;
+ int ret;
pmic_plat_data = dev_get_platdata(&i2c->dev);
diff --git a/drivers/mfd/tps65911-comparator.c b/drivers/mfd/tps65911-comparator.c
index c0789f8..3359176 100644
--- a/drivers/mfd/tps65911-comparator.c
+++ b/drivers/mfd/tps65911-comparator.c
@@ -22,9 +22,8 @@
#include <linux/gpio.h>
#include <linux/mfd/tps65910.h>
-#define COMP 0
-#define COMP1 1
-#define COMP2 2
+#define COMP1 0
+#define COMP2 1
/* Comparator 1 voltage selection table in millivolts */
static const u16 COMP_VSEL_TABLE[] = {
@@ -63,9 +62,6 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
int ret;
u8 index = 0, val;
- if (id == COMP)
- return 0;
-
while (curr_voltage < tps_comp.uV_max) {
curr_voltage = tps_comp.vsel_table[index];
if (curr_voltage >= voltage)
@@ -78,7 +74,7 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
return -EINVAL;
val = index << 1;
- ret = tps65910->write(tps65910, tps_comp.reg, 1, &val);
+ ret = tps65910_reg_write(tps65910, tps_comp.reg, val);
return ret;
}
@@ -86,13 +82,10 @@ static int comp_threshold_set(struct tps65910 *tps65910, int id, int voltage)
static int comp_threshold_get(struct tps65910 *tps65910, int id)
{
struct comparator tps_comp = tps_comparators[id];
+ unsigned int val;
int ret;
- u8 val;
-
- if (id == COMP)
- return 0;
- ret = tps65910->read(tps65910, tps_comp.reg, 1, &val);
+ ret = tps65910_reg_read(tps65910, tps_comp.reg, &val);
if (ret < 0)
return ret;
diff --git a/drivers/mfd/tps68470.c b/drivers/mfd/tps68470.c
index 189efae..a5981a7 100644
--- a/drivers/mfd/tps68470.c
+++ b/drivers/mfd/tps68470.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* TPS68470 chip Parent driver
*
@@ -8,15 +9,6 @@
* Tianshu Qiu <tian.shu.qiu@intel.com>
* Jian Xu Zheng <jian.xu.zheng@intel.com>
* Yuning Pu <yuning.pu@intel.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.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#include <linux/acpi.h>
diff --git a/drivers/mfd/tps80031.c b/drivers/mfd/tps80031.c
index 0812df3..608c7f7 100644
--- a/drivers/mfd/tps80031.c
+++ b/drivers/mfd/tps80031.c
@@ -431,10 +431,8 @@ static int tps80031_probe(struct i2c_client *client,
}
tps80031 = devm_kzalloc(&client->dev, sizeof(*tps80031), GFP_KERNEL);
- if (!tps80031) {
- dev_err(&client->dev, "Malloc failed for tps80031\n");
+ if (!tps80031)
return -ENOMEM;
- }
for (i = 0; i < TPS80031_NUM_SLAVES; i++) {
if (tps80031_slave_address[i] == client->addr)
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index d3133a3..4be3d23 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -1139,8 +1139,9 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
}
num_slaves = twl_get_num_slaves();
- twl_priv->twl_modules = devm_kzalloc(&client->dev,
- sizeof(struct twl_client) * num_slaves,
+ twl_priv->twl_modules = devm_kcalloc(&client->dev,
+ num_slaves,
+ sizeof(struct twl_client),
GFP_KERNEL);
if (!twl_priv->twl_modules) {
status = -ENOMEM;
@@ -1177,7 +1178,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
twl_priv->ready = true;
/* setup clock framework */
- clocks_init(&pdev->dev, pdata ? pdata->clock : NULL);
+ clocks_init(&client->dev, pdata ? pdata->clock : NULL);
/* read TWL IDCODE Register */
if (twl_class_is_4030()) {
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index e3ec8df..e939431 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -392,10 +392,8 @@ int twl6030_init_irq(struct device *dev, int irq_num)
nr_irqs = TWL6030_NR_IRQS;
twl6030_irq = devm_kzalloc(dev, sizeof(*twl6030_irq), GFP_KERNEL);
- if (!twl6030_irq) {
- dev_err(dev, "twl6030_irq: Memory allocation failed\n");
+ if (!twl6030_irq)
return -ENOMEM;
- }
mask[0] = 0xFF;
mask[1] = 0xFF;
diff --git a/drivers/mfd/viperboard.c b/drivers/mfd/viperboard.c
index e6b3c70..e9f6126 100644
--- a/drivers/mfd/viperboard.c
+++ b/drivers/mfd/viperboard.c
@@ -59,10 +59,8 @@ static int vprbrd_probe(struct usb_interface *interface,
/* allocate memory for our device state and initialize it */
vb = kzalloc(sizeof(*vb), GFP_KERNEL);
- if (vb == NULL) {
- dev_err(&interface->dev, "Out of memory\n");
+ if (!vb)
return -ENOMEM;
- }
mutex_init(&vb->lock);
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 953d079..5d5888e 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -368,9 +368,10 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
goto err;
}
- wm8994->supplies = devm_kzalloc(wm8994->dev,
- sizeof(struct regulator_bulk_data) *
- wm8994->num_supplies, GFP_KERNEL);
+ wm8994->supplies = devm_kcalloc(wm8994->dev,
+ wm8994->num_supplies,
+ sizeof(struct regulator_bulk_data),
+ GFP_KERNEL);
if (!wm8994->supplies) {
ret = -ENOMEM;
goto err;
diff --git a/drivers/mfd/wm97xx-core.c b/drivers/mfd/wm97xx-core.c
index 4141ee5..f5a8347 100644
--- a/drivers/mfd/wm97xx-core.c
+++ b/drivers/mfd/wm97xx-core.c
@@ -278,7 +278,7 @@ static int wm97xx_ac97_probe(struct ac97_codec_device *adev)
codec_pdata = &wm97xx->codec_pdata;
codec_pdata->ac97 = wm97xx->ac97;
- codec_pdata->batt_pdata = pdata->batt_pdata;
+ codec_pdata->batt_pdata = pdata ? pdata->batt_pdata : NULL;
switch (adev->vendor_id) {
case WM9705_VENDOR_ID:
diff --git a/drivers/misc/altera-stapl/altera.c b/drivers/misc/altera-stapl/altera.c
index f53e217..ef83a90 100644
--- a/drivers/misc/altera-stapl/altera.c
+++ b/drivers/misc/altera-stapl/altera.c
@@ -304,13 +304,13 @@ static int altera_execute(struct altera_state *astate,
if (sym_count <= 0)
goto exit_done;
- vars = kzalloc(sym_count * sizeof(long), GFP_KERNEL);
+ vars = kcalloc(sym_count, sizeof(long), GFP_KERNEL);
if (vars == NULL)
status = -ENOMEM;
if (status == 0) {
- var_size = kzalloc(sym_count * sizeof(s32), GFP_KERNEL);
+ var_size = kcalloc(sym_count, sizeof(s32), GFP_KERNEL);
if (var_size == NULL)
status = -ENOMEM;
@@ -1136,7 +1136,7 @@ exit_done:
/* Allocate a writable buffer for this array */
count = var_size[variable_id];
long_tmp = vars[variable_id];
- longptr_tmp = kzalloc(count * sizeof(long),
+ longptr_tmp = kcalloc(count, sizeof(long),
GFP_KERNEL);
vars[variable_id] = (long)longptr_tmp;
diff --git a/drivers/misc/cxl/guest.c b/drivers/misc/cxl/guest.c
index f58b4b6c..4644f16 100644
--- a/drivers/misc/cxl/guest.c
+++ b/drivers/misc/cxl/guest.c
@@ -89,7 +89,7 @@ static ssize_t guest_collect_vpd(struct cxl *adapter, struct cxl_afu *afu,
mod = 0;
}
- vpd_buf = kzalloc(entries * sizeof(unsigned long *), GFP_KERNEL);
+ vpd_buf = kcalloc(entries, sizeof(unsigned long *), GFP_KERNEL);
if (!vpd_buf)
return -ENOMEM;
diff --git a/drivers/misc/cxl/of.c b/drivers/misc/cxl/of.c
index ec175ea..aff181c 100644
--- a/drivers/misc/cxl/of.c
+++ b/drivers/misc/cxl/of.c
@@ -302,7 +302,7 @@ static int read_adapter_irq_config(struct cxl *adapter, struct device_node *np)
if (nranges == 0 || (nranges * 2 * sizeof(int)) != len)
return -EINVAL;
- adapter->guest->irq_avail = kzalloc(nranges * sizeof(struct irq_avail),
+ adapter->guest->irq_avail = kcalloc(nranges, sizeof(struct irq_avail),
GFP_KERNEL);
if (adapter->guest->irq_avail == NULL)
return -ENOMEM;
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 33053b0..f5cc517 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -532,6 +532,45 @@ static int at24_get_pdata(struct device *dev, struct at24_platform_data *pdata)
return 0;
}
+static void at24_remove_dummy_clients(struct at24_data *at24)
+{
+ int i;
+
+ for (i = 1; i < at24->num_addresses; i++)
+ i2c_unregister_device(at24->client[i].client);
+}
+
+static int at24_make_dummy_client(struct at24_data *at24, unsigned int index,
+ struct regmap_config *regmap_config)
+{
+ struct i2c_client *base_client, *dummy_client;
+ unsigned short int addr;
+ struct regmap *regmap;
+ struct device *dev;
+
+ base_client = at24->client[0].client;
+ dev = &base_client->dev;
+ addr = base_client->addr + index;
+
+ dummy_client = i2c_new_dummy(base_client->adapter,
+ base_client->addr + index);
+ if (!dummy_client) {
+ dev_err(dev, "address 0x%02x unavailable\n", addr);
+ return -EADDRINUSE;
+ }
+
+ regmap = devm_regmap_init_i2c(dummy_client, regmap_config);
+ if (IS_ERR(regmap)) {
+ i2c_unregister_device(dummy_client);
+ return PTR_ERR(regmap);
+ }
+
+ at24->client[index].client = dummy_client;
+ at24->client[index].regmap = regmap;
+
+ return 0;
+}
+
static unsigned int at24_get_offset_adj(u8 flags, unsigned int byte_len)
{
if (flags & AT24_FLAG_MAC) {
@@ -637,20 +676,10 @@ static int at24_probe(struct i2c_client *client)
/* use dummy devices for multiple-address chips */
for (i = 1; i < num_addresses; i++) {
- at24->client[i].client = i2c_new_dummy(client->adapter,
- client->addr + i);
- if (!at24->client[i].client) {
- dev_err(dev, "address 0x%02x unavailable\n",
- client->addr + i);
- err = -EADDRINUSE;
- goto err_clients;
- }
- at24->client[i].regmap = devm_regmap_init_i2c(
- at24->client[i].client,
- &regmap_config);
- if (IS_ERR(at24->client[i].regmap)) {
- err = PTR_ERR(at24->client[i].regmap);
- goto err_clients;
+ err = at24_make_dummy_client(at24, i, &regmap_config);
+ if (err) {
+ at24_remove_dummy_clients(at24);
+ return err;
}
}
@@ -685,7 +714,7 @@ static int at24_probe(struct i2c_client *client)
nvmem_config.word_size = 1;
nvmem_config.size = pdata.byte_len;
- at24->nvmem = nvmem_register(&nvmem_config);
+ at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
if (IS_ERR(at24->nvmem)) {
err = PTR_ERR(at24->nvmem);
goto err_clients;
@@ -702,10 +731,7 @@ static int at24_probe(struct i2c_client *client)
return 0;
err_clients:
- for (i = 1; i < num_addresses; i++)
- if (at24->client[i].client)
- i2c_unregister_device(at24->client[i].client);
-
+ at24_remove_dummy_clients(at24);
pm_runtime_disable(dev);
return err;
@@ -714,15 +740,10 @@ err_clients:
static int at24_remove(struct i2c_client *client)
{
struct at24_data *at24;
- int i;
at24 = i2c_get_clientdata(client);
- nvmem_unregister(at24->nvmem);
-
- for (i = 1; i < at24->num_addresses; i++)
- i2c_unregister_device(at24->client[i].client);
-
+ at24_remove_dummy_clients(at24);
pm_runtime_disable(&client->dev);
pm_runtime_set_suspended(&client->dev);
diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c
index 34a5a41..59dc24bb 100644
--- a/drivers/misc/eeprom/idt_89hpesx.c
+++ b/drivers/misc/eeprom/idt_89hpesx.c
@@ -964,7 +964,7 @@ static ssize_t idt_dbgfs_csr_write(struct file *filep, const char __user *ubuf,
if (colon_ch != NULL) {
csraddr_len = colon_ch - buf;
csraddr_str =
- kmalloc(sizeof(char)*(csraddr_len + 1), GFP_KERNEL);
+ kmalloc(csraddr_len + 1, GFP_KERNEL);
if (csraddr_str == NULL) {
ret = -ENOMEM;
goto free_buf;
diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c
index b7f8d35..656449c 100644
--- a/drivers/misc/genwqe/card_ddcb.c
+++ b/drivers/misc/genwqe/card_ddcb.c
@@ -1048,15 +1048,16 @@ static int setup_ddcb_queue(struct genwqe_dev *cd, struct ddcb_queue *queue)
"[%s] **err: could not allocate DDCB **\n", __func__);
return -ENOMEM;
}
- queue->ddcb_req = kzalloc(sizeof(struct ddcb_requ *) *
- queue->ddcb_max, GFP_KERNEL);
+ queue->ddcb_req = kcalloc(queue->ddcb_max, sizeof(struct ddcb_requ *),
+ GFP_KERNEL);
if (!queue->ddcb_req) {
rc = -ENOMEM;
goto free_ddcbs;
}
- queue->ddcb_waitqs = kzalloc(sizeof(wait_queue_head_t) *
- queue->ddcb_max, GFP_KERNEL);
+ queue->ddcb_waitqs = kcalloc(queue->ddcb_max,
+ sizeof(wait_queue_head_t),
+ GFP_KERNEL);
if (!queue->ddcb_waitqs) {
rc = -ENOMEM;
goto free_requs;
diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c
index 0c775d6..83fc748 100644
--- a/drivers/misc/sgi-xp/xpc_main.c
+++ b/drivers/misc/sgi-xp/xpc_main.c
@@ -416,7 +416,8 @@ xpc_setup_ch_structures(struct xpc_partition *part)
* memory.
*/
DBUG_ON(part->channels != NULL);
- part->channels = kzalloc(sizeof(struct xpc_channel) * XPC_MAX_NCHANNELS,
+ part->channels = kcalloc(XPC_MAX_NCHANNELS,
+ sizeof(struct xpc_channel),
GFP_KERNEL);
if (part->channels == NULL) {
dev_err(xpc_chan, "can't get memory for channels\n");
@@ -905,8 +906,9 @@ xpc_setup_partitions(void)
short partid;
struct xpc_partition *part;
- xpc_partitions = kzalloc(sizeof(struct xpc_partition) *
- xp_max_npartitions, GFP_KERNEL);
+ xpc_partitions = kcalloc(xp_max_npartitions,
+ sizeof(struct xpc_partition),
+ GFP_KERNEL);
if (xpc_partitions == NULL) {
dev_err(xpc_part, "can't get memory for partition structure\n");
return -ENOMEM;
diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c
index 6956f7e..7284413 100644
--- a/drivers/misc/sgi-xp/xpc_partition.c
+++ b/drivers/misc/sgi-xp/xpc_partition.c
@@ -425,7 +425,7 @@ xpc_discovery(void)
if (remote_rp == NULL)
return;
- discovered_nasids = kzalloc(sizeof(long) * xpc_nasid_mask_nlongs,
+ discovered_nasids = kcalloc(xpc_nasid_mask_nlongs, sizeof(long),
GFP_KERNEL);
if (discovered_nasids == NULL) {
kfree(remote_rp_base);
diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c
index 216d5c7..44d750d 100644
--- a/drivers/misc/sgi-xp/xpnet.c
+++ b/drivers/misc/sgi-xp/xpnet.c
@@ -520,8 +520,9 @@ xpnet_init(void)
dev_info(xpnet, "registering network device %s\n", XPNET_DEVICE_NAME);
- xpnet_broadcast_partitions = kzalloc(BITS_TO_LONGS(xp_max_npartitions) *
- sizeof(long), GFP_KERNEL);
+ xpnet_broadcast_partitions = kcalloc(BITS_TO_LONGS(xp_max_npartitions),
+ sizeof(long),
+ GFP_KERNEL);
if (xpnet_broadcast_partitions == NULL)
return -ENOMEM;
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index fc04157..c5dc609 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -185,7 +185,7 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
* after the reserved blocks from the dt are processed.
*/
nblocks = (np) ? of_get_available_child_count(np) + 1 : 1;
- rblocks = kzalloc((nblocks) * sizeof(*rblocks), GFP_KERNEL);
+ rblocks = kcalloc(nblocks, sizeof(*rblocks), GFP_KERNEL);
if (!rblocks)
return -ENOMEM;
@@ -264,8 +264,8 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
list_sort(NULL, &reserve_list, sram_reserve_cmp);
if (exports) {
- sram->partition = devm_kzalloc(sram->dev,
- exports * sizeof(*sram->partition),
+ sram->partition = devm_kcalloc(sram->dev,
+ exports, sizeof(*sram->partition),
GFP_KERNEL);
if (!sram->partition) {
ret = -ENOMEM;
diff --git a/drivers/misc/vmw_vmci/vmci_queue_pair.c b/drivers/misc/vmw_vmci/vmci_queue_pair.c
index 0339538..b4d7774 100644
--- a/drivers/misc/vmw_vmci/vmci_queue_pair.c
+++ b/drivers/misc/vmw_vmci/vmci_queue_pair.c
@@ -449,12 +449,14 @@ static int qp_alloc_ppn_set(void *prod_q,
return VMCI_ERROR_ALREADY_EXISTS;
produce_ppns =
- kmalloc(num_produce_pages * sizeof(*produce_ppns), GFP_KERNEL);
+ kmalloc_array(num_produce_pages, sizeof(*produce_ppns),
+ GFP_KERNEL);
if (!produce_ppns)
return VMCI_ERROR_NO_MEM;
consume_ppns =
- kmalloc(num_consume_pages * sizeof(*consume_ppns), GFP_KERNEL);
+ kmalloc_array(num_consume_pages, sizeof(*consume_ppns),
+ GFP_KERNEL);
if (!consume_ppns) {
kfree(produce_ppns);
return VMCI_ERROR_NO_MEM;
diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c
index f3a7c8e..88347ce 100644
--- a/drivers/mmc/host/sdhci-omap.c
+++ b/drivers/mmc/host/sdhci-omap.c
@@ -797,8 +797,10 @@ static int sdhci_omap_config_iodelay_pinctrl_state(struct sdhci_omap_host
if (!(omap_host->flags & SDHCI_OMAP_REQUIRE_IODELAY))
return 0;
- pinctrl_state = devm_kzalloc(dev, sizeof(*pinctrl_state) *
- (MMC_TIMING_MMC_HS200 + 1), GFP_KERNEL);
+ pinctrl_state = devm_kcalloc(dev,
+ MMC_TIMING_MMC_HS200 + 1,
+ sizeof(*pinctrl_state),
+ GFP_KERNEL);
if (!pinctrl_state)
return -ENOMEM;
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c
index 90575de..fc15ec5 100644
--- a/drivers/mtd/ar7part.c
+++ b/drivers/mtd/ar7part.c
@@ -55,7 +55,7 @@ static int create_mtd_partitions(struct mtd_info *master,
int retries = 10;
struct mtd_partition *ar7_parts;
- ar7_parts = kzalloc(sizeof(*ar7_parts) * AR7_PARTS, GFP_KERNEL);
+ ar7_parts = kcalloc(AR7_PARTS, sizeof(*ar7_parts), GFP_KERNEL);
if (!ar7_parts)
return -ENOMEM;
ar7_parts[0].name = "loader";
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c
index 0f93d22..fc424b1 100644
--- a/drivers/mtd/bcm47xxpart.c
+++ b/drivers/mtd/bcm47xxpart.c
@@ -110,7 +110,7 @@ static int bcm47xxpart_parse(struct mtd_info *master,
blocksize = 0x1000;
/* Alloc */
- parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS,
+ parts = kcalloc(BCM47XXPART_MAX_PARTS, sizeof(struct mtd_partition),
GFP_KERNEL);
if (!parts)
return -ENOMEM;
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index f5695be..6e8e7b1 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -608,8 +608,9 @@ static struct mtd_info *cfi_intelext_setup(struct mtd_info *mtd)
mtd->size = devsize * cfi->numchips;
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
- mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info)
- * mtd->numeraseregions, GFP_KERNEL);
+ mtd->eraseregions = kcalloc(mtd->numeraseregions,
+ sizeof(struct mtd_erase_region_info),
+ GFP_KERNEL);
if (!mtd->eraseregions)
goto setup_err;
@@ -758,7 +759,9 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd,
newcfi = kmalloc(sizeof(struct cfi_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL);
if (!newcfi)
return -ENOMEM;
- shared = kmalloc(sizeof(struct flchip_shared) * cfi->numchips, GFP_KERNEL);
+ shared = kmalloc_array(cfi->numchips,
+ sizeof(struct flchip_shared),
+ GFP_KERNEL);
if (!shared) {
kfree(newcfi);
return -ENOMEM;
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c
index 7c889ec..a0c6556 100644
--- a/drivers/mtd/chips/cfi_cmdset_0002.c
+++ b/drivers/mtd/chips/cfi_cmdset_0002.c
@@ -692,8 +692,9 @@ static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd)
mtd->size = devsize * cfi->numchips;
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
- mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
- * mtd->numeraseregions, GFP_KERNEL);
+ mtd->eraseregions = kmalloc_array(mtd->numeraseregions,
+ sizeof(struct mtd_erase_region_info),
+ GFP_KERNEL);
if (!mtd->eraseregions)
goto setup_err;
@@ -2635,7 +2636,7 @@ static int __maybe_unused cfi_ppb_unlock(struct mtd_info *mtd, loff_t ofs,
* first check the locking status of all sectors and save
* it for future use.
*/
- sect = kzalloc(MAX_SECTORS * sizeof(struct ppb_lock), GFP_KERNEL);
+ sect = kcalloc(MAX_SECTORS, sizeof(struct ppb_lock), GFP_KERNEL);
if (!sect)
return -ENOMEM;
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
index 7b7658a..35aa72b 100644
--- a/drivers/mtd/chips/cfi_cmdset_0020.c
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c
@@ -184,8 +184,9 @@ static struct mtd_info *cfi_staa_setup(struct map_info *map)
mtd->size = devsize * cfi->numchips;
mtd->numeraseregions = cfi->cfiq->NumEraseRegions * cfi->numchips;
- mtd->eraseregions = kmalloc(sizeof(struct mtd_erase_region_info)
- * mtd->numeraseregions, GFP_KERNEL);
+ mtd->eraseregions = kmalloc_array(mtd->numeraseregions,
+ sizeof(struct mtd_erase_region_info),
+ GFP_KERNEL);
if (!mtd->eraseregions) {
kfree(cfi->cmdset_priv);
kfree(mtd);
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
index 802d8f1..512bd4c 100644
--- a/drivers/mtd/devices/docg3.c
+++ b/drivers/mtd/devices/docg3.c
@@ -1827,7 +1827,7 @@ doc_probe_device(struct docg3_cascade *cascade, int floor, struct device *dev)
mtd->dev.parent = dev;
bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1,
8 * DOC_LAYOUT_PAGE_SIZE);
- docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL);
+ docg3->bbt = kcalloc(DOC_LAYOUT_PAGE_SIZE, bbt_nbpages, GFP_KERNEL);
if (!docg3->bbt)
goto nomem3;
@@ -1993,7 +1993,7 @@ static int __init docg3_probe(struct platform_device *pdev)
base = devm_ioremap(dev, ress->start, DOC_IOSPACE_SIZE);
ret = -ENOMEM;
- cascade = devm_kzalloc(dev, sizeof(*cascade) * DOC_MAX_NBFLOORS,
+ cascade = devm_kcalloc(dev, DOC_MAX_NBFLOORS, sizeof(*cascade),
GFP_KERNEL);
if (!cascade)
return ret;
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c
index ef6ad25..2578f27 100644
--- a/drivers/mtd/ftl.c
+++ b/drivers/mtd/ftl.c
@@ -201,15 +201,16 @@ static int build_maps(partition_t *part)
/* Set up erase unit maps */
part->DataUnits = le16_to_cpu(part->header.NumEraseUnits) -
part->header.NumTransferUnits;
- part->EUNInfo = kmalloc(part->DataUnits * sizeof(struct eun_info_t),
- GFP_KERNEL);
+ part->EUNInfo = kmalloc_array(part->DataUnits, sizeof(struct eun_info_t),
+ GFP_KERNEL);
if (!part->EUNInfo)
goto out;
for (i = 0; i < part->DataUnits; i++)
part->EUNInfo[i].Offset = 0xffffffff;
part->XferInfo =
- kmalloc(part->header.NumTransferUnits * sizeof(struct xfer_info_t),
- GFP_KERNEL);
+ kmalloc_array(part->header.NumTransferUnits,
+ sizeof(struct xfer_info_t),
+ GFP_KERNEL);
if (!part->XferInfo)
goto out_EUNInfo;
@@ -262,15 +263,15 @@ static int build_maps(partition_t *part)
/* Set up virtual page map */
blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize;
- part->VirtualBlockMap = vmalloc(blocks * sizeof(uint32_t));
+ part->VirtualBlockMap = vmalloc(array_size(blocks, sizeof(uint32_t)));
if (!part->VirtualBlockMap)
goto out_XferInfo;
memset(part->VirtualBlockMap, 0xff, blocks * sizeof(uint32_t));
part->BlocksPerUnit = (1 << header.EraseUnitSize) >> header.BlockSize;
- part->bam_cache = kmalloc(part->BlocksPerUnit * sizeof(uint32_t),
- GFP_KERNEL);
+ part->bam_cache = kmalloc_array(part->BlocksPerUnit, sizeof(uint32_t),
+ GFP_KERNEL);
if (!part->bam_cache)
goto out_VirtualBlockMap;
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c
index 2d59841..10d977e 100644
--- a/drivers/mtd/inftlmount.c
+++ b/drivers/mtd/inftlmount.c
@@ -270,7 +270,8 @@ static int find_boot_record(struct INFTLrecord *inftl)
inftl->nb_blocks = ip->lastUnit + 1;
/* Memory alloc */
- inftl->PUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL);
+ inftl->PUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16),
+ GFP_KERNEL);
if (!inftl->PUtable) {
printk(KERN_WARNING "INFTL: allocation of PUtable "
"failed (%zd bytes)\n",
@@ -278,7 +279,8 @@ static int find_boot_record(struct INFTLrecord *inftl)
return -ENOMEM;
}
- inftl->VUtable = kmalloc(inftl->nb_blocks * sizeof(u16), GFP_KERNEL);
+ inftl->VUtable = kmalloc_array(inftl->nb_blocks, sizeof(u16),
+ GFP_KERNEL);
if (!inftl->VUtable) {
kfree(inftl->PUtable);
printk(KERN_WARNING "INFTL: allocation of VUtable "
diff --git a/drivers/mtd/lpddr/lpddr_cmds.c b/drivers/mtd/lpddr/lpddr_cmds.c
index 5c5ba3c..b13557f 100644
--- a/drivers/mtd/lpddr/lpddr_cmds.c
+++ b/drivers/mtd/lpddr/lpddr_cmds.c
@@ -78,7 +78,7 @@ struct mtd_info *lpddr_cmdset(struct map_info *map)
mtd->erasesize = 1 << lpddr->qinfo->UniformBlockSizeShift;
mtd->writesize = 1 << lpddr->qinfo->BufSizeShift;
- shared = kmalloc(sizeof(struct flchip_shared) * lpddr->numchips,
+ shared = kmalloc_array(lpddr->numchips, sizeof(struct flchip_shared),
GFP_KERNEL);
if (!shared) {
kfree(lpddr);
diff --git a/drivers/mtd/maps/physmap_of_core.c b/drivers/mtd/maps/physmap_of_core.c
index 527b168..4129535 100644
--- a/drivers/mtd/maps/physmap_of_core.c
+++ b/drivers/mtd/maps/physmap_of_core.c
@@ -124,7 +124,7 @@ static const char * const *of_get_probes(struct device_node *dp)
if (count < 0)
return part_probe_types_def;
- res = kzalloc((count + 1) * sizeof(*res), GFP_KERNEL);
+ res = kcalloc(count + 1, sizeof(*res), GFP_KERNEL);
if (!res)
return NULL;
@@ -197,7 +197,7 @@ static int of_flash_probe(struct platform_device *dev)
dev_set_drvdata(&dev->dev, info);
- mtd_list = kzalloc(sizeof(*mtd_list) * count, GFP_KERNEL);
+ mtd_list = kcalloc(count, sizeof(*mtd_list), GFP_KERNEL);
if (!mtd_list)
goto err_flash_remove;
diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c
index 6b223cf..c5d4b65 100644
--- a/drivers/mtd/maps/vmu-flash.c
+++ b/drivers/mtd/maps/vmu-flash.c
@@ -629,15 +629,15 @@ static int vmu_connect(struct maple_device *mdev)
* Not sure there are actually any multi-partition devices in the
* real world, but the hardware supports them, so, so will we
*/
- card->parts = kmalloc(sizeof(struct vmupart) * card->partitions,
- GFP_KERNEL);
+ card->parts = kmalloc_array(card->partitions, sizeof(struct vmupart),
+ GFP_KERNEL);
if (!card->parts) {
error = -ENOMEM;
goto fail_partitions;
}
- card->mtd = kmalloc(sizeof(struct mtd_info) * card->partitions,
- GFP_KERNEL);
+ card->mtd = kmalloc_array(card->partitions, sizeof(struct mtd_info),
+ GFP_KERNEL);
if (!card->mtd) {
error = -ENOMEM;
goto fail_mtd_info;
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 6b86d1a..cbc5925 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -778,8 +778,9 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.erasesize = max_erasesize;
concat->mtd.numeraseregions = num_erase_region;
concat->mtd.eraseregions = erase_region_p =
- kmalloc(num_erase_region *
- sizeof (struct mtd_erase_region_info), GFP_KERNEL);
+ kmalloc_array(num_erase_region,
+ sizeof(struct mtd_erase_region_info),
+ GFP_KERNEL);
if (!erase_region_p) {
kfree(concat);
printk
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
index 9f25111..e078fc4 100644
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -330,8 +330,10 @@ static void mtdoops_notify_add(struct mtd_info *mtd)
}
/* oops_page_used is a bit field */
- cxt->oops_page_used = vmalloc(DIV_ROUND_UP(mtdoops_pages,
- BITS_PER_LONG) * sizeof(unsigned long));
+ cxt->oops_page_used =
+ vmalloc(array_size(sizeof(unsigned long),
+ DIV_ROUND_UP(mtdoops_pages,
+ BITS_PER_LONG)));
if (!cxt->oops_page_used) {
printk(KERN_ERR "mtdoops: could not allocate page array\n");
return;
diff --git a/drivers/mtd/mtdswap.c b/drivers/mtd/mtdswap.c
index 7161f8a..d9dcb2d 100644
--- a/drivers/mtd/mtdswap.c
+++ b/drivers/mtd/mtdswap.c
@@ -1317,11 +1317,11 @@ static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks,
for (i = 0; i < MTDSWAP_TREE_CNT; i++)
d->trees[i].root = RB_ROOT;
- d->page_data = vmalloc(sizeof(int)*pages);
+ d->page_data = vmalloc(array_size(pages, sizeof(int)));
if (!d->page_data)
goto page_data_fail;
- d->revmap = vmalloc(sizeof(int)*blocks);
+ d->revmap = vmalloc(array_size(blocks, sizeof(int)));
if (!d->revmap)
goto revmap_fail;
@@ -1340,7 +1340,7 @@ static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks,
if (!d->page_buf)
goto page_buf_fail;
- d->oob_buf = kmalloc(2 * mtd->oobavail, GFP_KERNEL);
+ d->oob_buf = kmalloc_array(2, mtd->oobavail, GFP_KERNEL);
if (!d->oob_buf)
goto oob_buf_fail;
diff --git a/drivers/mtd/nand/onenand/onenand_base.c b/drivers/mtd/nand/onenand/onenand_base.c
index b710519..4ca4b19 100644
--- a/drivers/mtd/nand/onenand/onenand_base.c
+++ b/drivers/mtd/nand/onenand/onenand_base.c
@@ -3721,8 +3721,10 @@ static int onenand_probe(struct mtd_info *mtd)
this->dies = ONENAND_IS_DDP(this) ? 2 : 1;
/* Maximum possible erase regions */
mtd->numeraseregions = this->dies << 1;
- mtd->eraseregions = kzalloc(sizeof(struct mtd_erase_region_info)
- * (this->dies << 1), GFP_KERNEL);
+ mtd->eraseregions =
+ kcalloc(this->dies << 1,
+ sizeof(struct mtd_erase_region_info),
+ GFP_KERNEL);
if (!mtd->eraseregions)
return -ENOMEM;
}
diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c
index 7255a0d..cd12e5a 100644
--- a/drivers/mtd/nand/raw/davinci_nand.c
+++ b/drivers/mtd/nand/raw/davinci_nand.c
@@ -545,7 +545,7 @@ static struct davinci_nand_pdata
return ERR_PTR(-ENOMEM);
if (!of_property_read_u32(pdev->dev.of_node,
"ti,davinci-chipselect", &prop))
- pdev->id = prop;
+ pdata->core_chipsel = prop;
else
return ERR_PTR(-EINVAL);
@@ -627,7 +627,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
return -ENODEV;
/* which external chipselect will we be managing? */
- if (pdev->id < 0 || pdev->id > 3)
+ if (pdata->core_chipsel < 0 || pdata->core_chipsel > 3)
return -ENODEV;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
@@ -683,7 +683,7 @@ static int nand_davinci_probe(struct platform_device *pdev)
info->ioaddr = (uint32_t __force) vaddr;
info->current_cs = info->ioaddr;
- info->core_chipsel = pdev->id;
+ info->core_chipsel = pdata->core_chipsel;
info->mask_chipsel = pdata->mask_chipsel;
/* use nandboot-capable ALE/CLE masks by default */
diff --git a/drivers/mtd/nand/raw/nand_bch.c b/drivers/mtd/nand/raw/nand_bch.c
index 7f11b68..b7387ac 100644
--- a/drivers/mtd/nand/raw/nand_bch.c
+++ b/drivers/mtd/nand/raw/nand_bch.c
@@ -186,7 +186,7 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
}
nbc->eccmask = kmalloc(eccbytes, GFP_KERNEL);
- nbc->errloc = kmalloc(t*sizeof(*nbc->errloc), GFP_KERNEL);
+ nbc->errloc = kmalloc_array(t, sizeof(*nbc->errloc), GFP_KERNEL);
if (!nbc->eccmask || !nbc->errloc)
goto fail;
/*
diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
index e027c6f..f8edacde 100644
--- a/drivers/mtd/nand/raw/nandsim.c
+++ b/drivers/mtd/nand/raw/nandsim.c
@@ -565,8 +565,9 @@ static int __init alloc_device(struct nandsim *ns)
err = -EINVAL;
goto err_close;
}
- ns->pages_written = vzalloc(BITS_TO_LONGS(ns->geom.pgnum) *
- sizeof(unsigned long));
+ ns->pages_written =
+ vzalloc(array_size(sizeof(unsigned long),
+ BITS_TO_LONGS(ns->geom.pgnum)));
if (!ns->pages_written) {
NS_ERR("alloc_device: unable to allocate pages written array\n");
err = -ENOMEM;
@@ -582,7 +583,7 @@ static int __init alloc_device(struct nandsim *ns)
return 0;
}
- ns->pages = vmalloc(ns->geom.pgnum * sizeof(union ns_mem));
+ ns->pages = vmalloc(array_size(sizeof(union ns_mem), ns->geom.pgnum));
if (!ns->pages) {
NS_ERR("alloc_device: unable to allocate page array\n");
return -ENOMEM;
diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
index b554fb6..6a5519f 100644
--- a/drivers/mtd/nand/raw/qcom_nandc.c
+++ b/drivers/mtd/nand/raw/qcom_nandc.c
@@ -2510,8 +2510,8 @@ static int qcom_nandc_alloc(struct qcom_nand_controller *nandc)
if (!nandc->regs)
return -ENOMEM;
- nandc->reg_read_buf = devm_kzalloc(nandc->dev,
- MAX_REG_RD * sizeof(*nandc->reg_read_buf),
+ nandc->reg_read_buf = devm_kcalloc(nandc->dev,
+ MAX_REG_RD, sizeof(*nandc->reg_read_buf),
GFP_KERNEL);
if (!nandc->reg_read_buf)
return -ENOMEM;
diff --git a/drivers/mtd/nand/raw/s3c2410.c b/drivers/mtd/nand/raw/s3c2410.c
index 1bc0458..19661c5 100644
--- a/drivers/mtd/nand/raw/s3c2410.c
+++ b/drivers/mtd/nand/raw/s3c2410.c
@@ -1038,7 +1038,7 @@ static int s3c24xx_nand_probe_dt(struct platform_device *pdev)
if (!pdata->nr_sets)
return 0;
- sets = devm_kzalloc(&pdev->dev, sizeof(*sets) * pdata->nr_sets,
+ sets = devm_kcalloc(&pdev->dev, pdata->nr_sets, sizeof(*sets),
GFP_KERNEL);
if (!sets)
return -ENOMEM;
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c
index 6281da3..27184e3 100644
--- a/drivers/mtd/nftlmount.c
+++ b/drivers/mtd/nftlmount.c
@@ -199,13 +199,16 @@ device is already correct.
nftl->lastEUN = nftl->nb_blocks - 1;
/* memory alloc */
- nftl->EUNtable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL);
+ nftl->EUNtable = kmalloc_array(nftl->nb_blocks, sizeof(u16),
+ GFP_KERNEL);
if (!nftl->EUNtable) {
printk(KERN_NOTICE "NFTL: allocation of EUNtable failed\n");
return -ENOMEM;
}
- nftl->ReplUnitTable = kmalloc(nftl->nb_blocks * sizeof(u16), GFP_KERNEL);
+ nftl->ReplUnitTable = kmalloc_array(nftl->nb_blocks,
+ sizeof(u16),
+ GFP_KERNEL);
if (!nftl->ReplUnitTable) {
kfree(nftl->EUNtable);
printk(KERN_NOTICE "NFTL: allocation of ReplUnitTable failed\n");
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 615f8c1..6b21a92 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -71,7 +71,7 @@ static int parse_fixed_partitions(struct mtd_info *master,
if (nr_parts == 0)
return 0;
- parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL);
+ parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL);
if (!parts)
return -ENOMEM;
@@ -177,7 +177,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
nr_parts = plen / sizeof(part[0]);
- parts = kzalloc(nr_parts * sizeof(*parts), GFP_KERNEL);
+ parts = kcalloc(nr_parts, sizeof(*parts), GFP_KERNEL);
if (!parts)
return -ENOMEM;
diff --git a/drivers/mtd/parsers/parser_trx.c b/drivers/mtd/parsers/parser_trx.c
index df360a7..17ac335 100644
--- a/drivers/mtd/parsers/parser_trx.c
+++ b/drivers/mtd/parsers/parser_trx.c
@@ -62,7 +62,7 @@ static int parser_trx_parse(struct mtd_info *mtd,
uint8_t curr_part = 0, i = 0;
int err;
- parts = kzalloc(sizeof(struct mtd_partition) * TRX_PARSER_MAX_PARTS,
+ parts = kcalloc(TRX_PARSER_MAX_PARTS, sizeof(struct mtd_partition),
GFP_KERNEL);
if (!parts)
return -ENOMEM;
diff --git a/drivers/mtd/parsers/sharpslpart.c b/drivers/mtd/parsers/sharpslpart.c
index 8893dc8..e5ea612 100644
--- a/drivers/mtd/parsers/sharpslpart.c
+++ b/drivers/mtd/parsers/sharpslpart.c
@@ -362,8 +362,9 @@ static int sharpsl_parse_mtd_partitions(struct mtd_info *master,
return err;
}
- sharpsl_nand_parts = kzalloc(sizeof(*sharpsl_nand_parts) *
- SHARPSL_NAND_PARTS, GFP_KERNEL);
+ sharpsl_nand_parts = kcalloc(SHARPSL_NAND_PARTS,
+ sizeof(*sharpsl_nand_parts),
+ GFP_KERNEL);
if (!sharpsl_nand_parts)
return -ENOMEM;
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c
index df27f24..94720f2 100644
--- a/drivers/mtd/rfd_ftl.c
+++ b/drivers/mtd/rfd_ftl.c
@@ -189,7 +189,8 @@ static int scan_header(struct partition *part)
if (!part->blocks)
goto err;
- part->sector_map = vmalloc(part->sector_count * sizeof(u_long));
+ part->sector_map = vmalloc(array_size(sizeof(u_long),
+ part->sector_count));
if (!part->sector_map) {
printk(KERN_ERR PREFIX "'%s': unable to allocate memory for "
"sector map", part->mbd.mtd->name);
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index 7963634..f3bd86e 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -82,7 +82,7 @@ static struct attribute_group *sm_create_sysfs_attributes(struct sm_ftl *ftl)
/* Create array of pointers to the attributes */
- attributes = kzalloc(sizeof(struct attribute *) * (NUM_ATTRIBUTES + 1),
+ attributes = kcalloc(NUM_ATTRIBUTES + 1, sizeof(struct attribute *),
GFP_KERNEL);
if (!attributes)
goto error3;
@@ -750,7 +750,7 @@ static int sm_init_zone(struct sm_ftl *ftl, int zone_num)
dbg("initializing zone %d", zone_num);
/* Allocate memory for FTL table */
- zone->lba_to_phys_table = kmalloc(ftl->max_lba * 2, GFP_KERNEL);
+ zone->lba_to_phys_table = kmalloc_array(ftl->max_lba, 2, GFP_KERNEL);
if (!zone->lba_to_phys_table)
return -ENOMEM;
@@ -1137,7 +1137,7 @@ static void sm_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
goto error2;
/* Allocate zone array, it will be initialized on demand */
- ftl->zones = kzalloc(sizeof(struct ftl_zone) * ftl->zone_count,
+ ftl->zones = kcalloc(ftl->zone_count, sizeof(struct ftl_zone),
GFP_KERNEL);
if (!ftl->zones)
goto error3;
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index 95f0bf9..7a1e545 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -332,8 +332,9 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
(long)ssfdc->sectors;
/* Allocate logical block map */
- ssfdc->logic_block_map = kmalloc(sizeof(ssfdc->logic_block_map[0]) *
- ssfdc->map_len, GFP_KERNEL);
+ ssfdc->logic_block_map =
+ kmalloc_array(ssfdc->map_len,
+ sizeof(ssfdc->logic_block_map[0]), GFP_KERNEL);
if (!ssfdc->logic_block_map)
goto out_err;
memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) *
diff --git a/drivers/mtd/tests/pagetest.c b/drivers/mtd/tests/pagetest.c
index bc303ca..7568736 100644
--- a/drivers/mtd/tests/pagetest.c
+++ b/drivers/mtd/tests/pagetest.c
@@ -127,7 +127,7 @@ static int crosstest(void)
unsigned char *pp1, *pp2, *pp3, *pp4;
pr_info("crosstest\n");
- pp1 = kzalloc(pgsize * 4, GFP_KERNEL);
+ pp1 = kcalloc(pgsize, 4, GFP_KERNEL);
if (!pp1)
return -ENOMEM;
pp2 = pp1 + pgsize;
diff --git a/drivers/mtd/tests/stresstest.c b/drivers/mtd/tests/stresstest.c
index e509f8a..0fe1217 100644
--- a/drivers/mtd/tests/stresstest.c
+++ b/drivers/mtd/tests/stresstest.c
@@ -199,7 +199,7 @@ static int __init mtd_stresstest_init(void)
err = -ENOMEM;
readbuf = vmalloc(bufsize);
writebuf = vmalloc(bufsize);
- offsets = kmalloc(ebcnt * sizeof(int), GFP_KERNEL);
+ offsets = kmalloc_array(ebcnt, sizeof(int), GFP_KERNEL);
if (!readbuf || !writebuf || !offsets)
goto out;
for (i = 0; i < ebcnt; i++)
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 753494e..d2a7266 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -526,6 +526,7 @@ void ubi_free_internal_volumes(struct ubi_device *ubi)
for (i = ubi->vtbl_slots;
i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
ubi_eba_replace_table(ubi->volumes[i], NULL);
+ ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
kfree(ubi->volumes[i]);
}
}
@@ -1091,6 +1092,9 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
if (ubi->bgt_thread)
kthread_stop(ubi->bgt_thread);
+#ifdef CONFIG_MTD_UBI_FASTMAP
+ cancel_work_sync(&ubi->fm_work);
+#endif
ubi_debugfs_exit_dev(ubi);
uif_close(ubi);
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 250e30f..b98481b 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -490,6 +490,103 @@ out_unlock:
return err;
}
+#ifdef CONFIG_MTD_UBI_FASTMAP
+/**
+ * check_mapping - check and fixup a mapping
+ * @ubi: UBI device description object
+ * @vol: volume description object
+ * @lnum: logical eraseblock number
+ * @pnum: physical eraseblock number
+ *
+ * Checks whether a given mapping is valid. Fastmap cannot track LEB unmap
+ * operations, if such an operation is interrupted the mapping still looks
+ * good, but upon first read an ECC is reported to the upper layer.
+ * Normaly during the full-scan at attach time this is fixed, for Fastmap
+ * we have to deal with it while reading.
+ * If the PEB behind a LEB shows this symthom we change the mapping to
+ * %UBI_LEB_UNMAPPED and schedule the PEB for erasure.
+ *
+ * Returns 0 on success, negative error code in case of failure.
+ */
+static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
+ int *pnum)
+{
+ int err;
+ struct ubi_vid_io_buf *vidb;
+ struct ubi_vid_hdr *vid_hdr;
+
+ if (!ubi->fast_attach)
+ return 0;
+
+ if (!vol->checkmap || test_bit(lnum, vol->checkmap))
+ return 0;
+
+ vidb = ubi_alloc_vid_buf(ubi, GFP_NOFS);
+ if (!vidb)
+ return -ENOMEM;
+
+ err = ubi_io_read_vid_hdr(ubi, *pnum, vidb, 0);
+ if (err > 0 && err != UBI_IO_BITFLIPS) {
+ int torture = 0;
+
+ switch (err) {
+ case UBI_IO_FF:
+ case UBI_IO_FF_BITFLIPS:
+ case UBI_IO_BAD_HDR:
+ case UBI_IO_BAD_HDR_EBADMSG:
+ break;
+ default:
+ ubi_assert(0);
+ }
+
+ if (err == UBI_IO_BAD_HDR_EBADMSG || err == UBI_IO_FF_BITFLIPS)
+ torture = 1;
+
+ down_read(&ubi->fm_eba_sem);
+ vol->eba_tbl->entries[lnum].pnum = UBI_LEB_UNMAPPED;
+ up_read(&ubi->fm_eba_sem);
+ ubi_wl_put_peb(ubi, vol->vol_id, lnum, *pnum, torture);
+
+ *pnum = UBI_LEB_UNMAPPED;
+ } else if (err < 0) {
+ ubi_err(ubi, "unable to read VID header back from PEB %i: %i",
+ *pnum, err);
+
+ goto out_free;
+ } else {
+ int found_vol_id, found_lnum;
+
+ ubi_assert(err == 0 || err == UBI_IO_BITFLIPS);
+
+ vid_hdr = ubi_get_vid_hdr(vidb);
+ found_vol_id = be32_to_cpu(vid_hdr->vol_id);
+ found_lnum = be32_to_cpu(vid_hdr->lnum);
+
+ if (found_lnum != lnum || found_vol_id != vol->vol_id) {
+ ubi_err(ubi, "EBA mismatch! PEB %i is LEB %i:%i instead of LEB %i:%i",
+ *pnum, found_vol_id, found_lnum, vol->vol_id, lnum);
+ ubi_ro_mode(ubi);
+ err = -EINVAL;
+ goto out_free;
+ }
+ }
+
+ set_bit(lnum, vol->checkmap);
+ err = 0;
+
+out_free:
+ ubi_free_vid_buf(vidb);
+
+ return err;
+}
+#else
+static int check_mapping(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
+ int *pnum)
+{
+ return 0;
+}
+#endif
+
/**
* ubi_eba_read_leb - read data.
* @ubi: UBI device description object
@@ -522,7 +619,13 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
return err;
pnum = vol->eba_tbl->entries[lnum].pnum;
- if (pnum < 0) {
+ if (pnum >= 0) {
+ err = check_mapping(ubi, vol, lnum, &pnum);
+ if (err < 0)
+ goto out_unlock;
+ }
+
+ if (pnum == UBI_LEB_UNMAPPED) {
/*
* The logical eraseblock is not mapped, fill the whole buffer
* with 0xFF bytes. The exception is static volumes for which
@@ -931,6 +1034,12 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
pnum = vol->eba_tbl->entries[lnum].pnum;
if (pnum >= 0) {
+ err = check_mapping(ubi, vol, lnum, &pnum);
+ if (err < 0)
+ goto out;
+ }
+
+ if (pnum >= 0) {
dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d",
len, offset, vol_id, lnum, pnum);
@@ -1427,11 +1536,11 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
- scan_eba = kmalloc(sizeof(*scan_eba) * num_volumes, GFP_KERNEL);
+ scan_eba = kmalloc_array(num_volumes, sizeof(*scan_eba), GFP_KERNEL);
if (!scan_eba)
return -ENOMEM;
- fm_eba = kmalloc(sizeof(*fm_eba) * num_volumes, GFP_KERNEL);
+ fm_eba = kmalloc_array(num_volumes, sizeof(*fm_eba), GFP_KERNEL);
if (!fm_eba) {
kfree(scan_eba);
return -ENOMEM;
@@ -1442,15 +1551,17 @@ int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
if (!vol)
continue;
- scan_eba[i] = kmalloc(vol->reserved_pebs * sizeof(**scan_eba),
- GFP_KERNEL);
+ scan_eba[i] = kmalloc_array(vol->reserved_pebs,
+ sizeof(**scan_eba),
+ GFP_KERNEL);
if (!scan_eba[i]) {
ret = -ENOMEM;
goto out_free;
}
- fm_eba[i] = kmalloc(vol->reserved_pebs * sizeof(**fm_eba),
- GFP_KERNEL);
+ fm_eba[i] = kmalloc_array(vol->reserved_pebs,
+ sizeof(**fm_eba),
+ GFP_KERNEL);
if (!fm_eba[i]) {
ret = -ENOMEM;
goto out_free;
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 9170596..462526a 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1100,6 +1100,26 @@ free_fm_sb:
goto out;
}
+int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count)
+{
+ struct ubi_device *ubi = vol->ubi;
+
+ if (!ubi->fast_attach)
+ return 0;
+
+ vol->checkmap = kcalloc(BITS_TO_LONGS(leb_count), sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!vol->checkmap)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol)
+{
+ kfree(vol->checkmap);
+}
+
/**
* ubi_write_fastmap - writes a fastmap.
* @ubi: UBI device object
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index bfceae5..195ff8c 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -1,28 +1,12 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
+ * Copyright (C) International Business Machines Corp., 2006
* Authors: Artem Bityutskiy (Битюцкий Артём)
* Thomas Gleixner
* Frank Haverkamp
* Oliver Lohmann
* Andreas Arnez
- */
-
-/*
+ *
* This file defines the layout of UBI headers and all the other UBI on-flash
* data structures.
*/
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 5fe6265..f5ba97c 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -334,6 +334,9 @@ struct ubi_eba_leb_desc {
* @changing_leb: %1 if the atomic LEB change ioctl command is in progress
* @direct_writes: %1 if direct writes are enabled for this volume
*
+ * @checkmap: bitmap to remember which PEB->LEB mappings got checked,
+ * protected by UBI LEB lock tree.
+ *
* The @corrupted field indicates that the volume's contents is corrupted.
* Since UBI protects only static volumes, this field is not relevant to
* dynamic volumes - it is user's responsibility to assure their data
@@ -377,6 +380,10 @@ struct ubi_volume {
unsigned int updating:1;
unsigned int changing_leb:1;
unsigned int direct_writes:1;
+
+#ifdef CONFIG_MTD_UBI_FASTMAP
+ unsigned long *checkmap;
+#endif
};
/**
@@ -965,8 +972,12 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi);
int ubi_update_fastmap(struct ubi_device *ubi);
int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
struct ubi_attach_info *scan_ai);
+int ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count);
+void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol);
#else
static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; }
+int static inline ubi_fastmap_init_checkmap(struct ubi_volume *vol, int leb_count) { return 0; }
+static inline void ubi_fastmap_destroy_checkmap(struct ubi_volume *vol) {}
#endif
/* block.c */
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 3fd8d7f..0be5167 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -139,6 +139,7 @@ static void vol_release(struct device *dev)
struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);
ubi_eba_replace_table(vol, NULL);
+ ubi_fastmap_destroy_checkmap(vol);
kfree(vol);
}
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 263743e..94d7a865 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -534,7 +534,7 @@ static int init_volumes(struct ubi_device *ubi,
const struct ubi_attach_info *ai,
const struct ubi_vtbl_record *vtbl)
{
- int i, reserved_pebs = 0;
+ int i, err, reserved_pebs = 0;
struct ubi_ainf_volume *av;
struct ubi_volume *vol;
@@ -620,6 +620,16 @@ static int init_volumes(struct ubi_device *ubi,
(long long)(vol->used_ebs - 1) * vol->usable_leb_size;
vol->used_bytes += av->last_data_size;
vol->last_eb_bytes = av->last_data_size;
+
+ /*
+ * We use ubi->peb_count and not vol->reserved_pebs because
+ * we want to keep the code simple. Otherwise we'd have to
+ * resize/check the bitmap upon volume resize too.
+ * Allocating a few bytes more does not hurt.
+ */
+ err = ubi_fastmap_init_checkmap(vol, ubi->peb_count);
+ if (err)
+ return err;
}
/* And add the layout volume */
@@ -645,6 +655,9 @@ static int init_volumes(struct ubi_device *ubi,
reserved_pebs += vol->reserved_pebs;
ubi->vol_count += 1;
vol->ubi = ubi;
+ err = ubi_fastmap_init_checkmap(vol, UBI_LAYOUT_VOLUME_EBS);
+ if (err)
+ return err;
if (reserved_pebs > ubi->avail_pebs) {
ubi_err(ubi, "not enough PEBs, required %d, available %d",
@@ -849,6 +862,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai)
out_free:
vfree(ubi->vtbl);
for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
+ ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
kfree(ubi->volumes[i]);
ubi->volumes[i] = NULL;
}
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 2052a64..6f2ac86 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1505,6 +1505,7 @@ int ubi_thread(void *u)
}
dbg_wl("background thread \"%s\" is killed", ubi->bgt_name);
+ ubi->thread_enabled = 0;
return 0;
}
@@ -1514,9 +1515,6 @@ int ubi_thread(void *u)
*/
static void shutdown_work(struct ubi_device *ubi)
{
-#ifdef CONFIG_MTD_UBI_FASTMAP
- flush_work(&ubi->fm_work);
-#endif
while (!list_empty(&ubi->works)) {
struct ubi_work *wrk;
@@ -1594,7 +1592,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num);
err = -ENOMEM;
- ubi->lookuptbl = kzalloc(ubi->peb_count * sizeof(void *), GFP_KERNEL);
+ ubi->lookuptbl = kcalloc(ubi->peb_count, sizeof(void *), GFP_KERNEL);
if (!ubi->lookuptbl)
return err;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index bd53a71..63e3844 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2418,7 +2418,7 @@ struct bond_vlan_tag *bond_verify_device_path(struct net_device *start_dev,
struct list_head *iter;
if (start_dev == end_dev) {
- tags = kzalloc(sizeof(*tags) * (level + 1), GFP_ATOMIC);
+ tags = kcalloc(level + 1, sizeof(*tags), GFP_ATOMIC);
if (!tags)
return ERR_PTR(-ENOMEM);
tags[level].vlan_proto = VLAN_N_VID;
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 8a945c9..98663c5 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -1142,6 +1142,7 @@ static int bond_option_primary_set(struct bonding *bond,
slave->dev->name);
rcu_assign_pointer(bond->primary_slave, slave);
strcpy(bond->params.primary, slave->dev->name);
+ bond->force_primary = true;
bond_select_active_slave(bond);
goto out;
}
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index 2d3046a..7eec1d9 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -1057,7 +1057,7 @@ static int grcan_open(struct net_device *dev)
return err;
}
- priv->echo_skb = kzalloc(dma->tx.size * sizeof(*priv->echo_skb),
+ priv->echo_skb = kcalloc(dma->tx.size, sizeof(*priv->echo_skb),
GFP_KERNEL);
if (!priv->echo_skb) {
err = -ENOMEM;
@@ -1066,7 +1066,7 @@ static int grcan_open(struct net_device *dev)
priv->can.echo_skb_max = dma->tx.size;
priv->can.echo_skb = priv->echo_skb;
- priv->txdlc = kzalloc(dma->tx.size * sizeof(*priv->txdlc), GFP_KERNEL);
+ priv->txdlc = kcalloc(dma->tx.size, sizeof(*priv->txdlc), GFP_KERNEL);
if (!priv->txdlc) {
err = -ENOMEM;
goto exit_free_echo_skb;
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 89d60d8..aa97dbc 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -703,7 +703,7 @@ static int __init slcan_init(void)
pr_info("slcan: serial line CAN interface driver\n");
pr_info("slcan: %d dynamic interface channels.\n", maxdev);
- slcan_devs = kzalloc(sizeof(struct net_device *)*maxdev, GFP_KERNEL);
+ slcan_devs = kcalloc(maxdev, sizeof(struct net_device *), GFP_KERNEL);
if (!slcan_devs)
return -ENOMEM;
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 5e010b1..d93c790 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -2044,14 +2044,14 @@ static int b53_switch_init(struct b53_device *dev)
}
}
- dev->ports = devm_kzalloc(dev->dev,
- sizeof(struct b53_port) * dev->num_ports,
+ dev->ports = devm_kcalloc(dev->dev,
+ dev->num_ports, sizeof(struct b53_port),
GFP_KERNEL);
if (!dev->ports)
return -ENOMEM;
- dev->vlans = devm_kzalloc(dev->dev,
- sizeof(struct b53_vlan) * dev->num_vlans,
+ dev->vlans = devm_kcalloc(dev->dev,
+ dev->num_vlans, sizeof(struct b53_vlan),
GFP_KERNEL);
if (!dev->vlans)
return -ENOMEM;
diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c
index 060cb18..521607b 100644
--- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c
+++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c
@@ -838,8 +838,8 @@ static void ena_dump_stats_ex(struct ena_adapter *adapter, u8 *buf)
return;
}
- strings_buf = devm_kzalloc(&adapter->pdev->dev,
- strings_num * ETH_GSTRING_LEN,
+ strings_buf = devm_kcalloc(&adapter->pdev->dev,
+ ETH_GSTRING_LEN, strings_num,
GFP_ATOMIC);
if (!strings_buf) {
netif_err(adapter, drv, netdev,
@@ -847,8 +847,8 @@ static void ena_dump_stats_ex(struct ena_adapter *adapter, u8 *buf)
return;
}
- data_buf = devm_kzalloc(&adapter->pdev->dev,
- strings_num * sizeof(u64),
+ data_buf = devm_kcalloc(&adapter->pdev->dev,
+ strings_num, sizeof(u64),
GFP_ATOMIC);
if (!data_buf) {
netif_err(adapter, drv, netdev,
diff --git a/drivers/net/ethernet/amd/lance.c b/drivers/net/ethernet/amd/lance.c
index 12a6a93..b56d84c 100644
--- a/drivers/net/ethernet/amd/lance.c
+++ b/drivers/net/ethernet/amd/lance.c
@@ -551,13 +551,13 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int
if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp);
dev->ml_priv = lp;
lp->name = chipname;
- lp->rx_buffs = (unsigned long)kmalloc(PKT_BUF_SZ*RX_RING_SIZE,
- GFP_DMA | GFP_KERNEL);
+ lp->rx_buffs = (unsigned long)kmalloc_array(RX_RING_SIZE, PKT_BUF_SZ,
+ GFP_DMA | GFP_KERNEL);
if (!lp->rx_buffs)
goto out_lp;
if (lance_need_isa_bounce_buffers) {
- lp->tx_bounce_buffs = kmalloc(PKT_BUF_SZ*TX_RING_SIZE,
- GFP_DMA | GFP_KERNEL);
+ lp->tx_bounce_buffs = kmalloc_array(TX_RING_SIZE, PKT_BUF_SZ,
+ GFP_DMA | GFP_KERNEL);
if (!lp->tx_bounce_buffs)
goto out_rx;
} else
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
index a50e08b..7500075 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
@@ -267,14 +267,13 @@ static int aq_pci_probe(struct pci_dev *pdev,
numvecs = min(numvecs, num_online_cpus());
/*enable interrupts */
#if !AQ_CFG_FORCE_LEGACY_INT
- numvecs = pci_alloc_irq_vectors(self->pdev, 1, numvecs,
- PCI_IRQ_MSIX | PCI_IRQ_MSI |
- PCI_IRQ_LEGACY);
+ err = pci_alloc_irq_vectors(self->pdev, 1, numvecs,
+ PCI_IRQ_MSIX | PCI_IRQ_MSI |
+ PCI_IRQ_LEGACY);
- if (numvecs < 0) {
- err = numvecs;
+ if (err < 0)
goto err_hwinit;
- }
+ numvecs = err;
#endif
self->irqvecs = numvecs;
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
index cfe86a2..28e9ae1 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
@@ -209,8 +209,8 @@ static int atl1c_get_eeprom(struct net_device *netdev,
first_dword = eeprom->offset >> 2;
last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
- eeprom_buff = kmalloc(sizeof(u32) *
- (last_dword - first_dword + 1), GFP_KERNEL);
+ eeprom_buff = kmalloc_array(last_dword - first_dword + 1, sizeof(u32),
+ GFP_KERNEL);
if (eeprom_buff == NULL)
return -ENOMEM;
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
index cb489e7..282ebdd 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
@@ -236,8 +236,8 @@ static int atl1e_get_eeprom(struct net_device *netdev,
first_dword = eeprom->offset >> 2;
last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
- eeprom_buff = kmalloc(sizeof(u32) *
- (last_dword - first_dword + 1), GFP_KERNEL);
+ eeprom_buff = kmalloc_array(last_dword - first_dword + 1, sizeof(u32),
+ GFP_KERNEL);
if (eeprom_buff == NULL)
return -ENOMEM;
diff --git a/drivers/net/ethernet/atheros/atlx/atl2.c b/drivers/net/ethernet/atheros/atlx/atl2.c
index db4bcc5..bb41bec 100644
--- a/drivers/net/ethernet/atheros/atlx/atl2.c
+++ b/drivers/net/ethernet/atheros/atlx/atl2.c
@@ -1941,8 +1941,8 @@ static int atl2_get_eeprom(struct net_device *netdev,
first_dword = eeprom->offset >> 2;
last_dword = (eeprom->offset + eeprom->len - 1) >> 2;
- eeprom_buff = kmalloc(sizeof(u32) * (last_dword - first_dword + 1),
- GFP_KERNEL);
+ eeprom_buff = kmalloc_array(last_dword - first_dword + 1, sizeof(u32),
+ GFP_KERNEL);
if (!eeprom_buff)
return -ENOMEM;
diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index 14a59e5..897302a 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -2150,7 +2150,7 @@ static int bcm_enetsw_open(struct net_device *dev)
priv->tx_desc_alloc_size = size;
priv->tx_desc_cpu = p;
- priv->tx_skb = kzalloc(sizeof(struct sk_buff *) * priv->tx_ring_size,
+ priv->tx_skb = kcalloc(priv->tx_ring_size, sizeof(struct sk_buff *),
GFP_KERNEL);
if (!priv->tx_skb) {
dev_err(kdev, "cannot allocate rx skb queue\n");
@@ -2164,7 +2164,7 @@ static int bcm_enetsw_open(struct net_device *dev)
spin_lock_init(&priv->tx_lock);
/* init & fill rx ring with skbs */
- priv->rx_skb = kzalloc(sizeof(struct sk_buff *) * priv->rx_ring_size,
+ priv->rx_skb = kcalloc(priv->rx_ring_size, sizeof(struct sk_buff *),
GFP_KERNEL);
if (!priv->rx_skb) {
dev_err(kdev, "cannot allocate rx skb queue\n");
diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c
index 3853296..122fdb8 100644
--- a/drivers/net/ethernet/broadcom/bnx2.c
+++ b/drivers/net/ethernet/broadcom/bnx2.c
@@ -778,7 +778,7 @@ bnx2_alloc_rx_mem(struct bnx2 *bp)
int j;
rxr->rx_buf_ring =
- vzalloc(SW_RXBD_RING_SIZE * bp->rx_max_ring);
+ vzalloc(array_size(SW_RXBD_RING_SIZE, bp->rx_max_ring));
if (!rxr->rx_buf_ring)
return -ENOMEM;
@@ -794,8 +794,9 @@ bnx2_alloc_rx_mem(struct bnx2 *bp)
}
if (bp->rx_pg_ring_size) {
- rxr->rx_pg_ring = vzalloc(SW_RXPG_RING_SIZE *
- bp->rx_max_pg_ring);
+ rxr->rx_pg_ring =
+ vzalloc(array_size(SW_RXPG_RING_SIZE,
+ bp->rx_max_pg_ring));
if (!rxr->rx_pg_ring)
return -ENOMEM;
@@ -2666,7 +2667,7 @@ bnx2_alloc_bad_rbuf(struct bnx2 *bp)
u32 good_mbuf_cnt;
u32 val;
- good_mbuf = kmalloc(512 * sizeof(u16), GFP_KERNEL);
+ good_mbuf = kmalloc_array(512, sizeof(u16), GFP_KERNEL);
if (!good_mbuf)
return -ENOMEM;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
index ffa7959..dc77bfd 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
@@ -571,7 +571,7 @@ int bnx2x_vf_mcast(struct bnx2x *bp, struct bnx2x_virtf *vf,
else
set_bit(RAMROD_COMP_WAIT, &mcast.ramrod_flags);
if (mc_num) {
- mc = kzalloc(mc_num * sizeof(struct bnx2x_mcast_list_elem),
+ mc = kcalloc(mc_num, sizeof(struct bnx2x_mcast_list_elem),
GFP_KERNEL);
if (!mc) {
BNX2X_ERR("Cannot Configure multicasts due to lack of memory\n");
@@ -1253,8 +1253,9 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
num_vfs_param, iov->nr_virtfn);
/* allocate the vf array */
- bp->vfdb->vfs = kzalloc(sizeof(struct bnx2x_virtf) *
- BNX2X_NR_VIRTFN(bp), GFP_KERNEL);
+ bp->vfdb->vfs = kcalloc(BNX2X_NR_VIRTFN(bp),
+ sizeof(struct bnx2x_virtf),
+ GFP_KERNEL);
if (!bp->vfdb->vfs) {
BNX2X_ERR("failed to allocate vf array\n");
err = -ENOMEM;
@@ -1278,9 +1279,9 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
}
/* allocate the queue arrays for all VFs */
- bp->vfdb->vfqs = kzalloc(
- BNX2X_MAX_NUM_VF_QUEUES * sizeof(struct bnx2x_vf_queue),
- GFP_KERNEL);
+ bp->vfdb->vfqs = kcalloc(BNX2X_MAX_NUM_VF_QUEUES,
+ sizeof(struct bnx2x_vf_queue),
+ GFP_KERNEL);
if (!bp->vfdb->vfqs) {
BNX2X_ERR("failed to allocate vf queue array\n");
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
index 38f635c..05d4059 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
@@ -444,8 +444,8 @@ static int bnxt_vf_reps_create(struct bnxt *bp)
return -ENOMEM;
/* storage for cfa_code to vf-idx mapping */
- cfa_code_map = kmalloc(sizeof(*bp->cfa_code_map) * MAX_CFA_CODE,
- GFP_KERNEL);
+ cfa_code_map = kmalloc_array(MAX_CFA_CODE, sizeof(*bp->cfa_code_map),
+ GFP_KERNEL);
if (!cfa_code_map) {
rc = -ENOMEM;
goto err;
diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c
index 8bc126a..30273a7 100644
--- a/drivers/net/ethernet/broadcom/cnic.c
+++ b/drivers/net/ethernet/broadcom/cnic.c
@@ -660,7 +660,7 @@ static int cnic_init_id_tbl(struct cnic_id_tbl *id_tbl, u32 size, u32 start_id,
id_tbl->max = size;
id_tbl->next = next;
spin_lock_init(&id_tbl->lock);
- id_tbl->table = kzalloc(DIV_ROUND_UP(size, 32) * 4, GFP_KERNEL);
+ id_tbl->table = kcalloc(DIV_ROUND_UP(size, 32), 4, GFP_KERNEL);
if (!id_tbl->table)
return -ENOMEM;
@@ -1255,13 +1255,13 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev)
cp->fcoe_init_cid = 0x10;
}
- cp->iscsi_tbl = kzalloc(sizeof(struct cnic_iscsi) * MAX_ISCSI_TBL_SZ,
+ cp->iscsi_tbl = kcalloc(MAX_ISCSI_TBL_SZ, sizeof(struct cnic_iscsi),
GFP_KERNEL);
if (!cp->iscsi_tbl)
goto error;
- cp->ctx_tbl = kzalloc(sizeof(struct cnic_context) *
- cp->max_cid_space, GFP_KERNEL);
+ cp->ctx_tbl = kcalloc(cp->max_cid_space, sizeof(struct cnic_context),
+ GFP_KERNEL);
if (!cp->ctx_tbl)
goto error;
@@ -4100,7 +4100,7 @@ static int cnic_cm_alloc_mem(struct cnic_dev *dev)
struct cnic_local *cp = dev->cnic_priv;
u32 port_id;
- cp->csk_tbl = kzalloc(sizeof(struct cnic_sock) * MAX_CM_SK_TBL_SZ,
+ cp->csk_tbl = kcalloc(MAX_CM_SK_TBL_SZ, sizeof(struct cnic_sock),
GFP_KERNEL);
if (!cp->csk_tbl)
return -ENOMEM;
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 9f59b12..3be87ef 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -8631,8 +8631,9 @@ static int tg3_mem_tx_acquire(struct tg3 *tp)
tnapi++;
for (i = 0; i < tp->txq_cnt; i++, tnapi++) {
- tnapi->tx_buffers = kzalloc(sizeof(struct tg3_tx_ring_info) *
- TG3_TX_RING_SIZE, GFP_KERNEL);
+ tnapi->tx_buffers = kcalloc(TG3_TX_RING_SIZE,
+ sizeof(struct tg3_tx_ring_info),
+ GFP_KERNEL);
if (!tnapi->tx_buffers)
goto err_out;
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 69cc3e0..ea5f32e 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -3141,7 +3141,7 @@ bnad_set_rx_ucast_fltr(struct bnad *bnad)
if (uc_count > bna_attr(&bnad->bna)->num_ucmac)
goto mode_default;
- mac_list = kzalloc(uc_count * ETH_ALEN, GFP_ATOMIC);
+ mac_list = kcalloc(ETH_ALEN, uc_count, GFP_ATOMIC);
if (mac_list == NULL)
goto mode_default;
@@ -3182,7 +3182,7 @@ bnad_set_rx_mcast_fltr(struct bnad *bnad)
if (mc_count > bna_attr(&bnad->bna)->num_mcmac)
goto mode_allmulti;
- mac_list = kzalloc((mc_count + 1) * ETH_ALEN, GFP_ATOMIC);
+ mac_list = kcalloc(mc_count + 1, ETH_ALEN, GFP_ATOMIC);
if (mac_list == NULL)
goto mode_allmulti;
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index 2bd7c63..2c63aff 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -739,7 +739,7 @@ static int xgmac_dma_desc_rings_init(struct net_device *dev)
netdev_dbg(priv->dev, "mtu [%d] bfsize [%d]\n", dev->mtu, bfsize);
- priv->rx_skbuff = kzalloc(sizeof(struct sk_buff *) * DMA_RX_RING_SZ,
+ priv->rx_skbuff = kcalloc(DMA_RX_RING_SZ, sizeof(struct sk_buff *),
GFP_KERNEL);
if (!priv->rx_skbuff)
return -ENOMEM;
@@ -752,7 +752,7 @@ static int xgmac_dma_desc_rings_init(struct net_device *dev)
if (!priv->dma_rx)
goto err_dma_rx;
- priv->tx_skbuff = kzalloc(sizeof(struct sk_buff *) * DMA_TX_RING_SZ,
+ priv->tx_skbuff = kcalloc(DMA_TX_RING_SZ, sizeof(struct sk_buff *),
GFP_KERNEL);
if (!priv->tx_skbuff)
goto err_tx_skb;
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
index f044718..a71dbb7 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c
@@ -281,13 +281,12 @@ int octeon_init_droq(struct octeon_device *oct,
droq->max_count);
droq->recv_buf_list = (struct octeon_recv_buffer *)
- vzalloc_node(droq->max_count *
- OCT_DROQ_RECVBUF_SIZE,
- numa_node);
+ vzalloc_node(array_size(droq->max_count, OCT_DROQ_RECVBUF_SIZE),
+ numa_node);
if (!droq->recv_buf_list)
droq->recv_buf_list = (struct octeon_recv_buffer *)
- vzalloc(droq->max_count *
- OCT_DROQ_RECVBUF_SIZE);
+ vzalloc(array_size(droq->max_count,
+ OCT_DROQ_RECVBUF_SIZE));
if (!droq->recv_buf_list) {
dev_err(&oct->pci_dev->dev, "Output queue recv buf list alloc failed\n");
goto init_droq_fail;
diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c
index b127035..1f2e75d 100644
--- a/drivers/net/ethernet/cavium/liquidio/request_manager.c
+++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c
@@ -98,8 +98,9 @@ int octeon_init_instr_queue(struct octeon_device *oct,
iq->request_list = vmalloc_node((sizeof(*iq->request_list) * num_descs),
numa_node);
if (!iq->request_list)
- iq->request_list = vmalloc(sizeof(*iq->request_list) *
- num_descs);
+ iq->request_list =
+ vmalloc(array_size(num_descs,
+ sizeof(*iq->request_list)));
if (!iq->request_list) {
lio_dma_free(oct, q_size, iq->base_addr, iq->base_addr_dma);
dev_err(&oct->pci_dev->dev, "Alloc failed for IQ[%d] nr free list\n",
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 448d1fa..f4d8176 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -325,6 +325,8 @@ struct nicvf {
struct tasklet_struct qs_err_task;
struct work_struct reset_task;
struct nicvf_work rx_mode_work;
+ /* spinlock to protect workqueue arguments from concurrent access */
+ spinlock_t rx_mode_wq_lock;
/* PTP timestamp */
struct cavium_ptp *ptp_clock;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 7135db4..135766c 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1923,17 +1923,12 @@ static int nicvf_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
}
}
-static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
+static void __nicvf_set_rx_mode_task(u8 mode, struct xcast_addr_list *mc_addrs,
+ struct nicvf *nic)
{
- struct nicvf_work *vf_work = container_of(work_arg, struct nicvf_work,
- work.work);
- struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work);
union nic_mbx mbx = {};
int idx;
- if (!vf_work)
- return;
-
/* From the inside of VM code flow we have only 128 bits memory
* available to send message to host's PF, so send all mc addrs
* one by one, starting from flush command in case if kernel
@@ -1944,7 +1939,7 @@ static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
mbx.xcast.msg = NIC_MBOX_MSG_RESET_XCAST;
nicvf_send_msg_to_pf(nic, &mbx);
- if (vf_work->mode & BGX_XCAST_MCAST_FILTER) {
+ if (mode & BGX_XCAST_MCAST_FILTER) {
/* once enabling filtering, we need to signal to PF to add
* its' own LMAC to the filter to accept packets for it.
*/
@@ -1954,23 +1949,46 @@ static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
}
/* check if we have any specific MACs to be added to PF DMAC filter */
- if (vf_work->mc) {
+ if (mc_addrs) {
/* now go through kernel list of MACs and add them one by one */
- for (idx = 0; idx < vf_work->mc->count; idx++) {
+ for (idx = 0; idx < mc_addrs->count; idx++) {
mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST;
- mbx.xcast.data.mac = vf_work->mc->mc[idx];
+ mbx.xcast.data.mac = mc_addrs->mc[idx];
nicvf_send_msg_to_pf(nic, &mbx);
}
- kfree(vf_work->mc);
+ kfree(mc_addrs);
}
/* and finally set rx mode for PF accordingly */
mbx.xcast.msg = NIC_MBOX_MSG_SET_XCAST;
- mbx.xcast.data.mode = vf_work->mode;
+ mbx.xcast.data.mode = mode;
nicvf_send_msg_to_pf(nic, &mbx);
}
+static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
+{
+ struct nicvf_work *vf_work = container_of(work_arg, struct nicvf_work,
+ work.work);
+ struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work);
+ u8 mode;
+ struct xcast_addr_list *mc;
+
+ if (!vf_work)
+ return;
+
+ /* Save message data locally to prevent them from
+ * being overwritten by next ndo_set_rx_mode call().
+ */
+ spin_lock(&nic->rx_mode_wq_lock);
+ mode = vf_work->mode;
+ mc = vf_work->mc;
+ vf_work->mc = NULL;
+ spin_unlock(&nic->rx_mode_wq_lock);
+
+ __nicvf_set_rx_mode_task(mode, mc, nic);
+}
+
static void nicvf_set_rx_mode(struct net_device *netdev)
{
struct nicvf *nic = netdev_priv(netdev);
@@ -2004,9 +2022,12 @@ static void nicvf_set_rx_mode(struct net_device *netdev)
}
}
}
+ spin_lock(&nic->rx_mode_wq_lock);
+ kfree(nic->rx_mode_work.mc);
nic->rx_mode_work.mc = mc_list;
nic->rx_mode_work.mode = mode;
- queue_delayed_work(nicvf_rx_mode_wq, &nic->rx_mode_work.work, 2 * HZ);
+ queue_delayed_work(nicvf_rx_mode_wq, &nic->rx_mode_work.work, 0);
+ spin_unlock(&nic->rx_mode_wq_lock);
}
static const struct net_device_ops nicvf_netdev_ops = {
@@ -2163,6 +2184,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&nic->reset_task, nicvf_reset_task);
INIT_DELAYED_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task);
+ spin_lock_init(&nic->rx_mode_wq_lock);
err = register_netdev(netdev);
if (err) {
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index d42704d..187a249 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -292,8 +292,8 @@ static int nicvf_init_rbdr(struct nicvf *nic, struct rbdr *rbdr,
rbdr->is_xdp = true;
}
rbdr->pgcnt = roundup_pow_of_two(rbdr->pgcnt);
- rbdr->pgcache = kzalloc(sizeof(*rbdr->pgcache) *
- rbdr->pgcnt, GFP_KERNEL);
+ rbdr->pgcache = kcalloc(rbdr->pgcnt, sizeof(*rbdr->pgcache),
+ GFP_KERNEL);
if (!rbdr->pgcache)
return -ENOMEM;
rbdr->pgidx = 0;
diff --git a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
index 2edfdbd..7b795ed 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
@@ -3362,10 +3362,17 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
err = sysfs_create_group(&adapter->port[0]->dev.kobj,
&cxgb3_attr_group);
+ if (err) {
+ dev_err(&pdev->dev, "cannot create sysfs group\n");
+ goto out_close_led;
+ }
print_port_info(adapter, ai);
return 0;
+out_close_led:
+ t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, 0);
+
out_free_dev:
iounmap(adapter->regs);
for (i = ai->nports0 + ai->nports1 - 1; i >= 0; --i)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
index 2900390..5701272 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
@@ -304,7 +304,7 @@ 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 = kvzalloc(clipt_size*sizeof(struct clip_entry), GFP_KERNEL);
+ cl_list = kvcalloc(clipt_size, sizeof(struct clip_entry), GFP_KERNEL);
if (!cl_list) {
kvfree(ctbl);
return NULL;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index 251d5bd..c301aaf 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -873,7 +873,7 @@ static int cctrl_tbl_show(struct seq_file *seq, void *v)
u16 (*incr)[NCCTRL_WIN];
struct adapter *adap = seq->private;
- incr = kmalloc(sizeof(*incr) * NMTUS, GFP_KERNEL);
+ incr = kmalloc_array(NMTUS, sizeof(*incr), GFP_KERNEL);
if (!incr)
return -ENOMEM;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 35cb3ae..dd04a2f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -713,7 +713,7 @@ int cxgb4_write_rss(const struct port_info *pi, const u16 *queues)
const struct sge_eth_rxq *rxq;
rxq = &adapter->sge.ethrxq[pi->first_qset];
- rss = kmalloc(pi->rss_size * sizeof(u16), GFP_KERNEL);
+ rss = kmalloc_array(pi->rss_size, sizeof(u16), GFP_KERNEL);
if (!rss)
return -ENOMEM;
@@ -4972,8 +4972,8 @@ static int enable_msix(struct adapter *adap)
max_ingq += (MAX_OFLD_QSETS * adap->num_uld);
if (is_offload(adap))
max_ingq += (MAX_OFLD_QSETS * adap->num_ofld_uld);
- entries = kmalloc(sizeof(*entries) * (max_ingq + 1),
- GFP_KERNEL);
+ entries = kmalloc_array(max_ingq + 1, sizeof(*entries),
+ GFP_KERNEL);
if (!entries)
return -ENOMEM;
@@ -5646,8 +5646,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->params.offload = 0;
}
- adapter->mps_encap = kvzalloc(sizeof(struct mps_encap_entry) *
- adapter->params.arch.mps_tcam_size,
+ adapter->mps_encap = kvcalloc(adapter->params.arch.mps_tcam_size,
+ sizeof(struct mps_encap_entry),
GFP_KERNEL);
if (!adapter->mps_encap)
dev_warn(&pdev->dev, "could not allocate MPS Encap entries, continuing\n");
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
index ab174bc..18eb2ae 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
@@ -457,7 +457,8 @@ 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 = kvzalloc(sizeof(unsigned long) * bmap_size, GFP_KERNEL);
+ link->tid_map = kvcalloc(bmap_size, sizeof(unsigned long),
+ GFP_KERNEL);
if (!link->tid_map)
goto out_no_mem;
bitmap_zero(link->tid_map, max_tids);
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
index a95cde0..4bc2110 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
@@ -561,13 +561,13 @@ int t4_uld_mem_alloc(struct adapter *adap)
if (!adap->uld)
return -ENOMEM;
- s->uld_rxq_info = kzalloc(CXGB4_ULD_MAX *
+ s->uld_rxq_info = kcalloc(CXGB4_ULD_MAX,
sizeof(struct sge_uld_rxq_info *),
GFP_KERNEL);
if (!s->uld_rxq_info)
goto err_uld;
- s->uld_txq_info = kzalloc(CXGB4_TX_MAX *
+ s->uld_txq_info = kcalloc(CXGB4_TX_MAX,
sizeof(struct sge_uld_txq_info *),
GFP_KERNEL);
if (!s->uld_txq_info)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c
index 7a271fe..395e2a0 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c
@@ -699,7 +699,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size,
if (!p)
return NULL;
if (sw_size) {
- s = kzalloc_node(nelem * sw_size, GFP_KERNEL, node);
+ s = kcalloc_node(sw_size, nelem, GFP_KERNEL, node);
if (!s) {
dma_free_coherent(dev, len, p, *phys);
diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.c b/drivers/net/ethernet/cisco/enic/enic_clsf.c
index 973c1fb..99038df 100644
--- a/drivers/net/ethernet/cisco/enic/enic_clsf.c
+++ b/drivers/net/ethernet/cisco/enic/enic_clsf.c
@@ -79,7 +79,6 @@ void enic_rfs_flw_tbl_init(struct enic *enic)
enic->rfs_h.max = enic->config.num_arfs;
enic->rfs_h.free = enic->rfs_h.max;
enic->rfs_h.toclean = 0;
- enic_rfs_timer_start(enic);
}
void enic_rfs_flw_tbl_free(struct enic *enic)
@@ -88,7 +87,6 @@ void enic_rfs_flw_tbl_free(struct enic *enic)
enic_rfs_timer_stop(enic);
spin_lock_bh(&enic->rfs_h.lock);
- enic->rfs_h.free = 0;
for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) {
struct hlist_head *hhead;
struct hlist_node *tmp;
@@ -99,6 +97,7 @@ void enic_rfs_flw_tbl_free(struct enic *enic)
enic_delfltr(enic, n->fltr_id);
hlist_del(&n->node);
kfree(n);
+ enic->rfs_h.free++;
}
}
spin_unlock_bh(&enic->rfs_h.lock);
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 30d2eaa..90c645b 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -1920,7 +1920,7 @@ static int enic_open(struct net_device *netdev)
{
struct enic *enic = netdev_priv(netdev);
unsigned int i;
- int err;
+ int err, ret;
err = enic_request_intr(enic);
if (err) {
@@ -1971,16 +1971,15 @@ static int enic_open(struct net_device *netdev)
vnic_intr_unmask(&enic->intr[i]);
enic_notify_timer_start(enic);
- enic_rfs_flw_tbl_init(enic);
+ enic_rfs_timer_start(enic);
return 0;
err_out_free_rq:
for (i = 0; i < enic->rq_count; i++) {
- err = vnic_rq_disable(&enic->rq[i]);
- if (err)
- return err;
- vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
+ ret = vnic_rq_disable(&enic->rq[i]);
+ if (!ret)
+ vnic_rq_clean(&enic->rq[i], enic_free_rq_buf);
}
enic_dev_notify_unset(enic);
err_out_free_intr:
@@ -2904,6 +2903,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
timer_setup(&enic->notify_timer, enic_notify_timer, 0);
+ enic_rfs_flw_tbl_init(enic);
enic_set_rx_coal_setting(enic);
INIT_WORK(&enic->reset, enic_reset);
INIT_WORK(&enic->tx_hang_reset, enic_tx_hang_reset);
diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c
index ff9eb45..6d7404f 100644
--- a/drivers/net/ethernet/cortina/gemini.c
+++ b/drivers/net/ethernet/cortina/gemini.c
@@ -910,8 +910,8 @@ static int geth_setup_freeq(struct gemini_ethernet *geth)
}
/* Allocate a mapping to page look-up index */
- geth->freeq_pages = kzalloc(pages * sizeof(*geth->freeq_pages),
- GFP_KERNEL);
+ geth->freeq_pages = kcalloc(pages, sizeof(*geth->freeq_pages),
+ GFP_KERNEL);
if (!geth->freeq_pages)
goto err_freeq;
geth->num_freeq_pages = pages;
diff --git a/drivers/net/ethernet/ethoc.c b/drivers/net/ethernet/ethoc.c
index 00a5727..60da049 100644
--- a/drivers/net/ethernet/ethoc.c
+++ b/drivers/net/ethernet/ethoc.c
@@ -1141,7 +1141,8 @@ static int ethoc_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "ethoc: num_tx: %d num_rx: %d\n",
priv->num_tx, priv->num_rx);
- priv->vma = devm_kzalloc(&pdev->dev, num_bd*sizeof(void *), GFP_KERNEL);
+ priv->vma = devm_kcalloc(&pdev->dev, num_bd, sizeof(void *),
+ GFP_KERNEL);
if (!priv->vma) {
ret = -ENOMEM;
goto free;
diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c
index 78db8e6..ed6c76d 100644
--- a/drivers/net/ethernet/faraday/ftgmac100.c
+++ b/drivers/net/ethernet/faraday/ftgmac100.c
@@ -1735,8 +1735,8 @@ static void ftgmac100_ncsi_handler(struct ncsi_dev *nd)
if (unlikely(nd->state != ncsi_dev_state_functional))
return;
- netdev_info(nd->dev, "NCSI interface %s\n",
- nd->link_up ? "up" : "down");
+ netdev_dbg(nd->dev, "NCSI interface %s\n",
+ nd->link_up ? "up" : "down");
}
static void ftgmac100_setup_clk(struct ftgmac100 *priv)
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index fd43f98..5f4e1ff 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -664,7 +664,7 @@ static struct dpaa_fq *dpaa_fq_alloc(struct device *dev,
struct dpaa_fq *dpaa_fq;
int i;
- dpaa_fq = devm_kzalloc(dev, sizeof(*dpaa_fq) * count,
+ dpaa_fq = devm_kcalloc(dev, count, sizeof(*dpaa_fq),
GFP_KERNEL);
if (!dpaa_fq)
return NULL;
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index a96b838..42fca32 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -2253,9 +2253,9 @@ static int ucc_geth_alloc_tx(struct ucc_geth_private *ugeth)
/* Init Tx bds */
for (j = 0; j < ug_info->numQueuesTx; j++) {
/* Setup the skbuff rings */
- ugeth->tx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) *
- ugeth->ug_info->bdRingLenTx[j],
- GFP_KERNEL);
+ ugeth->tx_skbuff[j] =
+ kmalloc_array(ugeth->ug_info->bdRingLenTx[j],
+ sizeof(struct sk_buff *), GFP_KERNEL);
if (ugeth->tx_skbuff[j] == NULL) {
if (netif_msg_ifup(ugeth))
@@ -2326,9 +2326,9 @@ static int ucc_geth_alloc_rx(struct ucc_geth_private *ugeth)
/* Init Rx bds */
for (j = 0; j < ug_info->numQueuesRx; j++) {
/* Setup the skbuff rings */
- ugeth->rx_skbuff[j] = kmalloc(sizeof(struct sk_buff *) *
- ugeth->ug_info->bdRingLenRx[j],
- GFP_KERNEL);
+ ugeth->rx_skbuff[j] =
+ kmalloc_array(ugeth->ug_info->bdRingLenRx[j],
+ sizeof(struct sk_buff *), GFP_KERNEL);
if (ugeth->rx_skbuff[j] == NULL) {
if (netif_msg_ifup(ugeth))
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 85e1d14..0ce07f6 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -1406,8 +1406,8 @@ static int hns_dsaf_init(struct dsaf_device *dsaf_dev)
return ret;
/* malloc mem for tcam mac key(vlan+mac) */
- priv->soft_mac_tbl = vzalloc(sizeof(*priv->soft_mac_tbl)
- * DSAF_TCAM_SUM);
+ priv->soft_mac_tbl = vzalloc(array_size(DSAF_TCAM_SUM,
+ sizeof(*priv->soft_mac_tbl)));
if (!priv->soft_mac_tbl) {
ret = -ENOMEM;
goto remove_hw;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
index 1ccb644..ef9ef70 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c
@@ -2197,7 +2197,8 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv)
return -EINVAL;
}
- priv->ring_data = kzalloc(h->q_num * sizeof(*priv->ring_data) * 2,
+ priv->ring_data = kzalloc(array3_size(h->q_num,
+ sizeof(*priv->ring_data), 2),
GFP_KERNEL);
if (!priv->ring_data)
return -ENOMEM;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index f2b31d2..25a73bb 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2846,8 +2846,10 @@ static int hns3_get_ring_config(struct hns3_nic_priv *priv)
struct pci_dev *pdev = h->pdev;
int i, ret;
- priv->ring_data = devm_kzalloc(&pdev->dev, h->kinfo.num_tqps *
- sizeof(*priv->ring_data) * 2,
+ priv->ring_data = devm_kzalloc(&pdev->dev,
+ array3_size(h->kinfo.num_tqps,
+ sizeof(*priv->ring_data),
+ 2),
GFP_KERNEL);
if (!priv->ring_data)
return -ENOMEM;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c
index 28a81ac..4d09ea7 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_cmdq.c
@@ -753,11 +753,12 @@ static int init_cmdq(struct hinic_cmdq *cmdq, struct hinic_wq *wq,
spin_lock_init(&cmdq->cmdq_lock);
- cmdq->done = vzalloc(wq->q_depth * sizeof(*cmdq->done));
+ cmdq->done = vzalloc(array_size(sizeof(*cmdq->done), wq->q_depth));
if (!cmdq->done)
return -ENOMEM;
- cmdq->errcode = vzalloc(wq->q_depth * sizeof(*cmdq->errcode));
+ cmdq->errcode = vzalloc(array_size(sizeof(*cmdq->errcode),
+ wq->q_depth));
if (!cmdq->errcode) {
err = -ENOMEM;
goto err_errcode;
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index c1b51ed..525d8b8 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -171,7 +171,7 @@ static int ibmveth_alloc_buffer_pool(struct ibmveth_buff_pool *pool)
{
int i;
- pool->free_map = kmalloc(sizeof(u16) * pool->size, GFP_KERNEL);
+ pool->free_map = kmalloc_array(pool->size, sizeof(u16), GFP_KERNEL);
if (!pool->free_map)
return -1;
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 14d287b..1ab613e 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -33,7 +33,7 @@ config E100
to identify the adapter.
More specific information on configuring the driver is in
- <file:Documentation/networking/e100.txt>.
+ <file:Documentation/networking/e100.rst>.
To compile this driver as a module, choose M here. The module
will be called e100.
@@ -49,7 +49,7 @@ config E1000
<http://support.intel.com>
More specific information on configuring the driver is in
- <file:Documentation/networking/e1000.txt>.
+ <file:Documentation/networking/e1000.rst>.
To compile this driver as a module, choose M here. The module
will be called e1000.
@@ -94,7 +94,7 @@ config IGB
<http://support.intel.com>
More specific information on configuring the driver is in
- <file:Documentation/networking/e1000.txt>.
+ <file:Documentation/networking/e1000.rst>.
To compile this driver as a module, choose M here. The module
will be called igb.
@@ -130,7 +130,7 @@ config IGBVF
<http://support.intel.com>
More specific information on configuring the driver is in
- <file:Documentation/networking/e1000.txt>.
+ <file:Documentation/networking/e1000.rst>.
To compile this driver as a module, choose M here. The module
will be called igbvf.
diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
index 5d365a9..bdb3f8e 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c
@@ -435,8 +435,8 @@ static int e1000_get_eeprom(struct net_device *netdev,
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
- eeprom_buff = kmalloc(sizeof(u16) *
- (last_word - first_word + 1), GFP_KERNEL);
+ eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16),
+ GFP_KERNEL);
if (!eeprom_buff)
return -ENOMEM;
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index e084cb7..02ebf20 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -509,8 +509,8 @@ static int e1000_get_eeprom(struct net_device *netdev,
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
- eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
- GFP_KERNEL);
+ eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16),
+ GFP_KERNEL);
if (!eeprom_buff)
return -ENOMEM;
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c
index acf1e8b..3ba0c90 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -3312,7 +3312,7 @@ static int e1000e_write_mc_addr_list(struct net_device *netdev)
return 0;
}
- mta_list = kzalloc(netdev_mc_count(netdev) * ETH_ALEN, GFP_ATOMIC);
+ mta_list = kcalloc(netdev_mc_count(netdev), ETH_ALEN, GFP_ATOMIC);
if (!mta_list)
return -ENOMEM;
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
index 7657daa..4895dd8 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
@@ -558,7 +558,7 @@ static int fm10k_set_ringparam(struct net_device *netdev,
/* allocate temporary buffer to store rings in */
i = max_t(int, interface->num_tx_queues, interface->num_rx_queues);
- temp_ring = vmalloc(i * sizeof(struct fm10k_ring));
+ temp_ring = vmalloc(array_size(i, sizeof(struct fm10k_ring)));
if (!temp_ring) {
err = -ENOMEM;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
index 8ffb745..ed6dbcf 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
@@ -2103,9 +2103,8 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
unsigned int truesize = i40e_rx_pg_size(rx_ring) / 2;
#else
unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) +
- SKB_DATA_ALIGN(I40E_SKB_PAD +
- (xdp->data_end -
- xdp->data_hard_start));
+ SKB_DATA_ALIGN(xdp->data_end -
+ xdp->data_hard_start);
#endif
struct sk_buff *skb;
@@ -2124,7 +2123,7 @@ static struct sk_buff *i40e_build_skb(struct i40e_ring *rx_ring,
return NULL;
/* update pointers within the skb to store the data */
- skb_reserve(skb, I40E_SKB_PAD + (xdp->data - xdp->data_hard_start));
+ skb_reserve(skb, xdp->data - xdp->data_hard_start);
__skb_put(skb, xdp->data_end - xdp->data);
if (metasize)
skb_metadata_set(skb, metasize);
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 2d798499d..f92f791 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -736,8 +736,8 @@ static int igb_get_eeprom(struct net_device *netdev,
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
- eeprom_buff = kmalloc(sizeof(u16) *
- (last_word - first_word + 1), GFP_KERNEL);
+ eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16),
+ GFP_KERNEL);
if (!eeprom_buff)
return -ENOMEM;
@@ -902,11 +902,11 @@ static int igb_set_ringparam(struct net_device *netdev,
}
if (adapter->num_tx_queues > adapter->num_rx_queues)
- temp_ring = vmalloc(adapter->num_tx_queues *
- sizeof(struct igb_ring));
+ temp_ring = vmalloc(array_size(sizeof(struct igb_ring),
+ adapter->num_tx_queues));
else
- temp_ring = vmalloc(adapter->num_rx_queues *
- sizeof(struct igb_ring));
+ temp_ring = vmalloc(array_size(sizeof(struct igb_ring),
+ adapter->num_rx_queues));
if (!temp_ring) {
err = -ENOMEM;
@@ -3245,8 +3245,8 @@ static int igb_get_module_eeprom(struct net_device *netdev,
first_word = ee->offset >> 1;
last_word = (ee->offset + ee->len - 1) >> 1;
- dataword = kmalloc(sizeof(u16) * (last_word - first_word + 1),
- GFP_KERNEL);
+ dataword = kmalloc_array(last_word - first_word + 1, sizeof(u16),
+ GFP_KERNEL);
if (!dataword)
return -ENOMEM;
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index c33821d..f707709 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -3763,8 +3763,9 @@ static int igb_sw_init(struct igb_adapter *adapter)
/* Assume MSI-X interrupts, will be checked during IRQ allocation */
adapter->flags |= IGB_FLAG_HAS_MSIX;
- adapter->mac_table = kzalloc(sizeof(struct igb_mac_addr) *
- hw->mac.rar_entry_count, GFP_ATOMIC);
+ adapter->mac_table = kcalloc(hw->mac.rar_entry_count,
+ sizeof(struct igb_mac_addr),
+ GFP_ATOMIC);
if (!adapter->mac_table)
return -ENOMEM;
@@ -4752,7 +4753,7 @@ static int igb_write_mc_addr_list(struct net_device *netdev)
return 0;
}
- mta_list = kzalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC);
+ mta_list = kcalloc(netdev_mc_count(netdev), 6, GFP_ATOMIC);
if (!mta_list)
return -ENOMEM;
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
index 43744bf..c8c93ac 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
@@ -375,8 +375,9 @@ ixgb_get_eeprom(struct net_device *netdev,
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
- eeprom_buff = kmalloc(sizeof(__le16) *
- (last_word - first_word + 1), GFP_KERNEL);
+ eeprom_buff = kmalloc_array(last_word - first_word + 1,
+ sizeof(__le16),
+ GFP_KERNEL);
if (!eeprom_buff)
return -ENOMEM;
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index 62f2173..43664ad 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -1093,8 +1093,9 @@ ixgb_set_multi(struct net_device *netdev)
rctl |= IXGB_RCTL_MPE;
IXGB_WRITE_REG(hw, RCTL, rctl);
} else {
- u8 *mta = kmalloc(IXGB_MAX_NUM_MULTICAST_ADDRESSES *
- ETH_ALEN, GFP_ATOMIC);
+ u8 *mta = kmalloc_array(ETH_ALEN,
+ IXGB_MAX_NUM_MULTICAST_ADDRESSES,
+ GFP_ATOMIC);
u8 *addr;
if (!mta)
goto alloc_failed;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index fc534e9..144d5fe 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -760,9 +760,9 @@ struct ixgbe_adapter {
#define IXGBE_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */
u32 *rss_key;
-#ifdef CONFIG_XFRM
+#ifdef CONFIG_XFRM_OFFLOAD
struct ixgbe_ipsec *ipsec;
-#endif /* CONFIG_XFRM */
+#endif /* CONFIG_XFRM_OFFLOAD */
};
static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index bdd179c..bd1ba88 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -901,7 +901,7 @@ static int ixgbe_get_eeprom(struct net_device *netdev,
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
eeprom_len = last_word - first_word + 1;
- eeprom_buff = kmalloc(sizeof(u16) * eeprom_len, GFP_KERNEL);
+ eeprom_buff = kmalloc_array(eeprom_len, sizeof(u16), GFP_KERNEL);
if (!eeprom_buff)
return -ENOMEM;
@@ -1063,7 +1063,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
/* allocate temporary buffer to store rings in */
i = max_t(int, adapter->num_tx_queues + adapter->num_xdp_queues,
adapter->num_rx_queues);
- temp_ring = vmalloc(i * sizeof(struct ixgbe_ring));
+ temp_ring = vmalloc(array_size(i, sizeof(struct ixgbe_ring)));
if (!temp_ring) {
err = -ENOMEM;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
index 344a1f2..c116f45 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c
@@ -158,7 +158,16 @@ static void ixgbe_ipsec_stop_data(struct ixgbe_adapter *adapter)
reg |= IXGBE_SECRXCTRL_RX_DIS;
IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, reg);
- IXGBE_WRITE_FLUSH(hw);
+ /* If both Tx and Rx are ready there are no packets
+ * that we need to flush so the loopback configuration
+ * below is not necessary.
+ */
+ t_rdy = IXGBE_READ_REG(hw, IXGBE_SECTXSTAT) &
+ IXGBE_SECTXSTAT_SECTX_RDY;
+ r_rdy = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT) &
+ IXGBE_SECRXSTAT_SECRX_RDY;
+ if (t_rdy && r_rdy)
+ return;
/* If the tx fifo doesn't have link, but still has data,
* we can't clear the tx sec block. Set the MAC loopback
@@ -185,7 +194,7 @@ static void ixgbe_ipsec_stop_data(struct ixgbe_adapter *adapter)
IXGBE_SECTXSTAT_SECTX_RDY;
r_rdy = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT) &
IXGBE_SECRXSTAT_SECRX_RDY;
- } while (!t_rdy && !r_rdy && limit--);
+ } while (!(t_rdy && r_rdy) && limit--);
/* undo loopback if we played with it earlier */
if (!link) {
@@ -966,10 +975,22 @@ void ixgbe_ipsec_rx(struct ixgbe_ring *rx_ring,
**/
void ixgbe_init_ipsec_offload(struct ixgbe_adapter *adapter)
{
+ struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_ipsec *ipsec;
+ u32 t_dis, r_dis;
size_t size;
- if (adapter->hw.mac.type == ixgbe_mac_82598EB)
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ return;
+
+ /* If there is no support for either Tx or Rx offload
+ * we should not be advertising support for IPsec.
+ */
+ t_dis = IXGBE_READ_REG(hw, IXGBE_SECTXSTAT) &
+ IXGBE_SECTXSTAT_SECTX_OFF_DIS;
+ r_dis = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT) &
+ IXGBE_SECRXSTAT_SECRX_OFF_DIS;
+ if (t_dis || r_dis)
return;
ipsec = kzalloc(sizeof(*ipsec), GFP_KERNEL);
@@ -1001,13 +1022,6 @@ void ixgbe_init_ipsec_offload(struct ixgbe_adapter *adapter)
adapter->netdev->xfrmdev_ops = &ixgbe_xfrmdev_ops;
-#define IXGBE_ESP_FEATURES (NETIF_F_HW_ESP | \
- NETIF_F_HW_ESP_TX_CSUM | \
- NETIF_F_GSO_ESP)
-
- adapter->netdev->features |= IXGBE_ESP_FEATURES;
- adapter->netdev->hw_enc_features |= IXGBE_ESP_FEATURES;
-
return;
err2:
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 893a920..d361f57 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -593,6 +593,14 @@ static bool ixgbe_set_sriov_queues(struct ixgbe_adapter *adapter)
}
#endif
+ /* To support macvlan offload we have to use num_tc to
+ * restrict the queues that can be used by the device.
+ * By doing this we can avoid reporting a false number of
+ * queues.
+ */
+ if (vmdq_i > 1)
+ netdev_set_num_tc(adapter->netdev, 1);
+
/* populate TC0 for use by pool 0 */
netdev_set_tc_queue(adapter->netdev, 0,
adapter->num_rx_queues_per_pool, 0);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 4929f72..3e87dbb 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -6034,8 +6034,8 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
for (i = 1; i < IXGBE_MAX_LINK_HANDLE; i++)
adapter->jump_tables[i] = NULL;
- adapter->mac_table = kzalloc(sizeof(struct ixgbe_mac_addr) *
- hw->mac.num_rar_entries,
+ adapter->mac_table = kcalloc(hw->mac.num_rar_entries,
+ sizeof(struct ixgbe_mac_addr),
GFP_ATOMIC);
if (!adapter->mac_table)
return -ENOMEM;
@@ -6117,6 +6117,7 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
#ifdef CONFIG_IXGBE_DCB
ixgbe_init_dcb(adapter);
#endif
+ ixgbe_init_ipsec_offload(adapter);
/* default flow control settings */
hw->fc.requested_mode = ixgbe_fc_full;
@@ -8822,14 +8823,6 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
} else {
netdev_reset_tc(dev);
- /* To support macvlan offload we have to use num_tc to
- * restrict the queues that can be used by the device.
- * By doing this we can avoid reporting a false number of
- * queues.
- */
- if (!tc && adapter->num_rx_pools > 1)
- netdev_set_num_tc(dev, 1);
-
if (adapter->hw.mac.type == ixgbe_mac_82598EB)
adapter->hw.fc.requested_mode = adapter->last_lfc_mode;
@@ -9904,7 +9897,7 @@ ixgbe_features_check(struct sk_buff *skb, struct net_device *dev,
* the TSO, so it's the exception.
*/
if (skb->encapsulation && !(features & NETIF_F_TSO_MANGLEID)) {
-#ifdef CONFIG_XFRM
+#ifdef CONFIG_XFRM_OFFLOAD
if (!skb->sp)
#endif
features &= ~NETIF_F_TSO;
@@ -10437,6 +10430,14 @@ skip_sriov:
if (hw->mac.type >= ixgbe_mac_82599EB)
netdev->features |= NETIF_F_SCTP_CRC;
+#ifdef CONFIG_XFRM_OFFLOAD
+#define IXGBE_ESP_FEATURES (NETIF_F_HW_ESP | \
+ NETIF_F_HW_ESP_TX_CSUM | \
+ NETIF_F_GSO_ESP)
+
+ if (adapter->ipsec)
+ netdev->features |= IXGBE_ESP_FEATURES;
+#endif
/* copy netdev features into list of user selectable features */
netdev->hw_features |= netdev->features |
NETIF_F_HW_VLAN_CTAG_FILTER |
@@ -10499,8 +10500,6 @@ skip_sriov:
NETIF_F_FCOE_MTU;
}
#endif /* IXGBE_FCOE */
- ixgbe_init_ipsec_offload(adapter);
-
if (adapter->flags2 & IXGBE_FLAG2_RSC_CAPABLE)
netdev->hw_features |= NETIF_F_LRO;
if (adapter->flags2 & IXGBE_FLAG2_RSC_ENABLED)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index e8ed377..44cfb20 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -599,13 +599,15 @@ struct ixgbe_nvm_version {
#define IXGBE_SECTXCTRL_STORE_FORWARD 0x00000004
#define IXGBE_SECTXSTAT_SECTX_RDY 0x00000001
-#define IXGBE_SECTXSTAT_ECC_TXERR 0x00000002
+#define IXGBE_SECTXSTAT_SECTX_OFF_DIS 0x00000002
+#define IXGBE_SECTXSTAT_ECC_TXERR 0x00000004
#define IXGBE_SECRXCTRL_SECRX_DIS 0x00000001
#define IXGBE_SECRXCTRL_RX_DIS 0x00000002
#define IXGBE_SECRXSTAT_SECRX_RDY 0x00000001
-#define IXGBE_SECRXSTAT_ECC_RXERR 0x00000002
+#define IXGBE_SECRXSTAT_SECRX_OFF_DIS 0x00000002
+#define IXGBE_SECRXSTAT_ECC_RXERR 0x00000004
/* LinkSec (MacSec) Registers */
#define IXGBE_LSECTXCAP 0x08A00
diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
index e7813d7..631c910 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c
@@ -282,8 +282,9 @@ static int ixgbevf_set_ringparam(struct net_device *netdev,
}
if (new_tx_count != adapter->tx_ring_count) {
- tx_ring = vmalloc((adapter->num_tx_queues +
- adapter->num_xdp_queues) * sizeof(*tx_ring));
+ tx_ring = vmalloc(array_size(sizeof(*tx_ring),
+ adapter->num_tx_queues +
+ adapter->num_xdp_queues));
if (!tx_ring) {
err = -ENOMEM;
goto clear_reset;
@@ -327,7 +328,8 @@ static int ixgbevf_set_ringparam(struct net_device *netdev,
}
if (new_rx_count != adapter->rx_ring_count) {
- rx_ring = vmalloc(adapter->num_rx_queues * sizeof(*rx_ring));
+ rx_ring = vmalloc(array_size(sizeof(*rx_ring),
+ adapter->num_rx_queues));
if (!rx_ring) {
err = -ENOMEM;
goto clear_reset;
diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index 8a16584..06ff185 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -589,8 +589,9 @@ jme_setup_tx_resources(struct jme_adapter *jme)
atomic_set(&txring->next_to_clean, 0);
atomic_set(&txring->nr_free, jme->tx_ring_size);
- txring->bufinf = kzalloc(sizeof(struct jme_buffer_info) *
- jme->tx_ring_size, GFP_ATOMIC);
+ txring->bufinf = kcalloc(jme->tx_ring_size,
+ sizeof(struct jme_buffer_info),
+ GFP_ATOMIC);
if (unlikely(!(txring->bufinf)))
goto err_free_txring;
@@ -838,8 +839,9 @@ jme_setup_rx_resources(struct jme_adapter *jme)
rxring->next_to_use = 0;
atomic_set(&rxring->next_to_clean, 0);
- rxring->bufinf = kzalloc(sizeof(struct jme_buffer_info) *
- jme->rx_ring_size, GFP_ATOMIC);
+ rxring->bufinf = kcalloc(jme->rx_ring_size,
+ sizeof(struct jme_buffer_info),
+ GFP_ATOMIC);
if (unlikely(!(rxring->bufinf)))
goto err_free_rxring;
diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c
index 6dabd98..4bdf250 100644
--- a/drivers/net/ethernet/mellanox/mlx4/alloc.c
+++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c
@@ -185,8 +185,8 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
bitmap->avail = num - reserved_top - reserved_bot;
bitmap->effective_len = bitmap->avail;
spin_lock_init(&bitmap->lock);
- bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) *
- sizeof(long), GFP_KERNEL);
+ bitmap->table = kcalloc(BITS_TO_LONGS(bitmap->max), sizeof(long),
+ GFP_KERNEL);
if (!bitmap->table)
return -ENOMEM;
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 6a9086d..e65bc3c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -2377,20 +2377,23 @@ int mlx4_multi_func_init(struct mlx4_dev *dev)
struct mlx4_vf_admin_state *vf_admin;
priv->mfunc.master.slave_state =
- kzalloc(dev->num_slaves *
- sizeof(struct mlx4_slave_state), GFP_KERNEL);
+ kcalloc(dev->num_slaves,
+ sizeof(struct mlx4_slave_state),
+ GFP_KERNEL);
if (!priv->mfunc.master.slave_state)
goto err_comm;
priv->mfunc.master.vf_admin =
- kzalloc(dev->num_slaves *
- sizeof(struct mlx4_vf_admin_state), GFP_KERNEL);
+ kcalloc(dev->num_slaves,
+ sizeof(struct mlx4_vf_admin_state),
+ GFP_KERNEL);
if (!priv->mfunc.master.vf_admin)
goto err_comm_admin;
priv->mfunc.master.vf_oper =
- kzalloc(dev->num_slaves *
- sizeof(struct mlx4_vf_oper_state), GFP_KERNEL);
+ kcalloc(dev->num_slaves,
+ sizeof(struct mlx4_vf_oper_state),
+ GFP_KERNEL);
if (!priv->mfunc.master.vf_oper)
goto err_comm_oper;
@@ -2636,9 +2639,9 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev)
int i;
int err = 0;
- priv->cmd.context = kmalloc(priv->cmd.max_cmds *
- sizeof(struct mlx4_cmd_context),
- GFP_KERNEL);
+ priv->cmd.context = kmalloc_array(priv->cmd.max_cmds,
+ sizeof(struct mlx4_cmd_context),
+ GFP_KERNEL);
if (!priv->cmd.context)
return -ENOMEM;
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 9670b33..65eb06e 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -2229,13 +2229,15 @@ static int mlx4_en_copy_priv(struct mlx4_en_priv *dst,
if (!dst->tx_ring_num[t])
continue;
- dst->tx_ring[t] = kzalloc(sizeof(struct mlx4_en_tx_ring *) *
- MAX_TX_RINGS, GFP_KERNEL);
+ dst->tx_ring[t] = kcalloc(MAX_TX_RINGS,
+ sizeof(struct mlx4_en_tx_ring *),
+ GFP_KERNEL);
if (!dst->tx_ring[t])
goto err_free_tx;
- dst->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) *
- MAX_TX_RINGS, GFP_KERNEL);
+ dst->tx_cq[t] = kcalloc(MAX_TX_RINGS,
+ sizeof(struct mlx4_en_cq *),
+ GFP_KERNEL);
if (!dst->tx_cq[t]) {
kfree(dst->tx_ring[t]);
goto err_free_tx;
@@ -3320,14 +3322,16 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
if (!priv->tx_ring_num[t])
continue;
- priv->tx_ring[t] = kzalloc(sizeof(struct mlx4_en_tx_ring *) *
- MAX_TX_RINGS, GFP_KERNEL);
+ priv->tx_ring[t] = kcalloc(MAX_TX_RINGS,
+ sizeof(struct mlx4_en_tx_ring *),
+ GFP_KERNEL);
if (!priv->tx_ring[t]) {
err = -ENOMEM;
goto out;
}
- priv->tx_cq[t] = kzalloc(sizeof(struct mlx4_en_cq *) *
- MAX_TX_RINGS, GFP_KERNEL);
+ priv->tx_cq[t] = kcalloc(MAX_TX_RINGS,
+ sizeof(struct mlx4_en_cq *),
+ GFP_KERNEL);
if (!priv->tx_cq[t]) {
err = -ENOMEM;
goto out;
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 6f57c05..1f3372c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -1211,8 +1211,9 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
}
priv->eq_table.irq_names =
- kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1),
- GFP_KERNEL);
+ kmalloc_array(MLX4_IRQNAME_SIZE,
+ (dev->caps.num_comp_vectors + 1),
+ GFP_KERNEL);
if (!priv->eq_table.irq_names) {
err = -ENOMEM;
goto err_out_clr_int;
diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c
index 5342bd8..7262c63 100644
--- a/drivers/net/ethernet/mellanox/mlx4/icm.c
+++ b/drivers/net/ethernet/mellanox/mlx4/icm.c
@@ -408,7 +408,7 @@ int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
return -EINVAL;
num_icm = (nobj + obj_per_chunk - 1) / obj_per_chunk;
- table->icm = kvzalloc(num_icm * sizeof(*table->icm), GFP_KERNEL);
+ table->icm = kvcalloc(num_icm, sizeof(*table->icm), GFP_KERNEL);
if (!table->icm)
return -ENOMEM;
table->virt = virt;
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 0a30d81..8720147 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -2982,7 +2982,8 @@ static int mlx4_init_steering(struct mlx4_dev *dev)
int num_entries = dev->caps.num_ports;
int i, j;
- priv->steer = kzalloc(sizeof(struct mlx4_steer) * num_entries, GFP_KERNEL);
+ priv->steer = kcalloc(num_entries, sizeof(struct mlx4_steer),
+ GFP_KERNEL);
if (!priv->steer)
return -ENOMEM;
@@ -3103,7 +3104,7 @@ static u64 mlx4_enable_sriov(struct mlx4_dev *dev, struct pci_dev *pdev,
}
}
- dev->dev_vfs = kzalloc(total_vfs * sizeof(*dev->dev_vfs), GFP_KERNEL);
+ dev->dev_vfs = kcalloc(total_vfs, sizeof(*dev->dev_vfs), GFP_KERNEL);
if (NULL == dev->dev_vfs) {
mlx4_err(dev, "Failed to allocate memory for VFs\n");
goto disable_sriov;
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
index 29e50f7..7b1b5ac 100644
--- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
+++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
@@ -487,7 +487,7 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev)
int max_vfs_guarantee_counter = get_max_gauranteed_vfs_counter(dev);
priv->mfunc.master.res_tracker.slave_list =
- kzalloc(dev->num_slaves * sizeof(struct slave_list),
+ kcalloc(dev->num_slaves, sizeof(struct slave_list),
GFP_KERNEL);
if (!priv->mfunc.master.res_tracker.slave_list)
return -ENOMEM;
@@ -507,19 +507,21 @@ int mlx4_init_resource_tracker(struct mlx4_dev *dev)
for (i = 0; i < MLX4_NUM_OF_RESOURCE_TYPE; i++) {
struct resource_allocator *res_alloc =
&priv->mfunc.master.res_tracker.res_alloc[i];
- res_alloc->quota = kmalloc((dev->persist->num_vfs + 1) *
- sizeof(int), GFP_KERNEL);
- res_alloc->guaranteed = kmalloc((dev->persist->num_vfs + 1) *
- sizeof(int), GFP_KERNEL);
+ res_alloc->quota = kmalloc_array(dev->persist->num_vfs + 1,
+ sizeof(int),
+ GFP_KERNEL);
+ res_alloc->guaranteed = kmalloc_array(dev->persist->num_vfs + 1,
+ sizeof(int),
+ GFP_KERNEL);
if (i == RES_MAC || i == RES_VLAN)
- res_alloc->allocated = kzalloc(MLX4_MAX_PORTS *
- (dev->persist->num_vfs
- + 1) *
- sizeof(int), GFP_KERNEL);
+ res_alloc->allocated =
+ kcalloc(MLX4_MAX_PORTS *
+ (dev->persist->num_vfs + 1),
+ sizeof(int), GFP_KERNEL);
else
- res_alloc->allocated = kzalloc((dev->persist->
- num_vfs + 1) *
- sizeof(int), GFP_KERNEL);
+ res_alloc->allocated =
+ kcalloc(dev->persist->num_vfs + 1,
+ sizeof(int), GFP_KERNEL);
/* Reduce the sink counter */
if (i == RES_COUNTER)
res_alloc->res_free = dev->caps.max_counters - 1;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 89c96a0..56c1b6f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -352,7 +352,7 @@ static int mlx5e_rq_alloc_mpwqe_info(struct mlx5e_rq *rq,
{
int wq_sz = mlx5_wq_ll_get_size(&rq->mpwqe.wq);
- rq->mpwqe.info = kzalloc_node(wq_sz * sizeof(*rq->mpwqe.info),
+ rq->mpwqe.info = kcalloc_node(wq_sz, sizeof(*rq->mpwqe.info),
GFP_KERNEL, cpu_to_node(c->cpu));
if (!rq->mpwqe.info)
return -ENOMEM;
@@ -448,7 +448,7 @@ static int mlx5e_init_di_list(struct mlx5e_rq *rq,
{
int len = wq_sz << rq->wqe.info.log_num_frags;
- rq->wqe.di = kvzalloc_node(len * sizeof(*rq->wqe.di),
+ rq->wqe.di = kvzalloc_node(array_size(len, sizeof(*rq->wqe.di)),
GFP_KERNEL, cpu_to_node(cpu));
if (!rq->wqe.di)
return -ENOMEM;
@@ -563,8 +563,8 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,
rq->wqe.info = rqp->frags_info;
rq->wqe.frags =
- kvzalloc_node((wq_sz << rq->wqe.info.log_num_frags) *
- sizeof(*rq->wqe.frags),
+ kvzalloc_node(array_size(sizeof(*rq->wqe.frags),
+ (wq_sz << rq->wqe.info.log_num_frags)),
GFP_KERNEL, cpu_to_node(c->cpu));
if (!rq->wqe.frags) {
err = -ENOMEM;
@@ -972,7 +972,7 @@ static int mlx5e_alloc_xdpsq_db(struct mlx5e_xdpsq *sq, int numa)
{
int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
- sq->db.di = kzalloc_node(sizeof(*sq->db.di) * wq_sz,
+ sq->db.di = kcalloc_node(wq_sz, sizeof(*sq->db.di),
GFP_KERNEL, numa);
if (!sq->db.di) {
mlx5e_free_xdpsq_db(sq);
@@ -1031,7 +1031,7 @@ static int mlx5e_alloc_icosq_db(struct mlx5e_icosq *sq, int numa)
{
u8 wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
- sq->db.ico_wqe = kzalloc_node(sizeof(*sq->db.ico_wqe) * wq_sz,
+ sq->db.ico_wqe = kcalloc_node(wq_sz, sizeof(*sq->db.ico_wqe),
GFP_KERNEL, numa);
if (!sq->db.ico_wqe)
return -ENOMEM;
@@ -1086,9 +1086,9 @@ static int mlx5e_alloc_txqsq_db(struct mlx5e_txqsq *sq, int numa)
int wq_sz = mlx5_wq_cyc_get_size(&sq->wq);
int df_sz = wq_sz * MLX5_SEND_WQEBB_NUM_DS;
- sq->db.dma_fifo = kzalloc_node(df_sz * sizeof(*sq->db.dma_fifo),
+ sq->db.dma_fifo = kcalloc_node(df_sz, sizeof(*sq->db.dma_fifo),
GFP_KERNEL, numa);
- sq->db.wqe_info = kzalloc_node(wq_sz * sizeof(*sq->db.wqe_info),
+ sq->db.wqe_info = kcalloc_node(wq_sz, sizeof(*sq->db.wqe_info),
GFP_KERNEL, numa);
if (!sq->db.dma_fifo || !sq->db.wqe_info) {
mlx5e_free_txqsq_db(sq);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c
index 4138a77..8ca1d19 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c
@@ -549,15 +549,17 @@ static int mlx5_fpga_conn_create_qp(struct mlx5_fpga_conn *conn,
if (err)
goto out;
- conn->qp.rq.bufs = kvzalloc(sizeof(conn->qp.rq.bufs[0]) *
- conn->qp.rq.size, GFP_KERNEL);
+ conn->qp.rq.bufs = kvcalloc(conn->qp.rq.size,
+ sizeof(conn->qp.rq.bufs[0]),
+ GFP_KERNEL);
if (!conn->qp.rq.bufs) {
err = -ENOMEM;
goto err_wq;
}
- conn->qp.sq.bufs = kvzalloc(sizeof(conn->qp.sq.bufs[0]) *
- conn->qp.sq.size, GFP_KERNEL);
+ conn->qp.sq.bufs = kvcalloc(conn->qp.sq.size,
+ sizeof(conn->qp.sq.bufs[0]),
+ GFP_KERNEL);
if (!conn->qp.sq.bufs) {
err = -ENOMEM;
goto err_rq_bufs;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
index a0433b4..5645a4f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
@@ -381,7 +381,7 @@ int mlx5_fpga_ipsec_counters_read(struct mlx5_core_dev *mdev, u64 *counters,
count = mlx5_fpga_ipsec_counters_count(mdev);
- data = kzalloc(sizeof(*data) * count * 2, GFP_KERNEL);
+ data = kzalloc(array3_size(sizeof(*data), count, 2), GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
index 8570355..1e062e6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -394,8 +394,9 @@ static int mlx5_init_pin_config(struct mlx5_clock *clock)
int i;
clock->ptp_info.pin_config =
- kzalloc(sizeof(*clock->ptp_info.pin_config) *
- clock->ptp_info.n_pins, GFP_KERNEL);
+ kcalloc(clock->ptp_info.n_pins,
+ sizeof(*clock->ptp_info.pin_config),
+ GFP_KERNEL);
if (!clock->ptp_info.pin_config)
return -ENOMEM;
clock->ptp_info.enable = mlx5_ptp_enable;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
index 91262b0..cad603c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
@@ -740,7 +740,8 @@ int mlxsw_sp_tc_qdisc_init(struct mlxsw_sp_port *mlxsw_sp_port)
mlxsw_sp_port->root_qdisc->prio_bitmap = 0xff;
mlxsw_sp_port->root_qdisc->tclass_num = MLXSW_SP_PORT_DEFAULT_TCLASS;
- mlxsw_sp_qdisc = kzalloc(sizeof(*mlxsw_sp_qdisc) * IEEE_8021QAZ_MAX_TCS,
+ mlxsw_sp_qdisc = kcalloc(IEEE_8021QAZ_MAX_TCS,
+ sizeof(*mlxsw_sp_qdisc),
GFP_KERNEL);
if (!mlxsw_sp_qdisc)
goto err_tclass_qdiscs_init;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 77b2adb..6aaaf3d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -4756,12 +4756,6 @@ static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
kfree(mlxsw_sp_rt6);
}
-static bool mlxsw_sp_fib6_rt_can_mp(const struct fib6_info *rt)
-{
- /* RTF_CACHE routes are ignored */
- return (rt->fib6_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
-}
-
static struct fib6_info *
mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
{
@@ -4771,11 +4765,11 @@ mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
static struct mlxsw_sp_fib6_entry *
mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
- const struct fib6_info *nrt, bool replace)
+ const struct fib6_info *nrt, bool append)
{
struct mlxsw_sp_fib6_entry *fib6_entry;
- if (!mlxsw_sp_fib6_rt_can_mp(nrt) || replace)
+ if (!append)
return NULL;
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
@@ -4790,8 +4784,7 @@ mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
break;
if (rt->fib6_metric < nrt->fib6_metric)
continue;
- if (rt->fib6_metric == nrt->fib6_metric &&
- mlxsw_sp_fib6_rt_can_mp(rt))
+ if (rt->fib6_metric == nrt->fib6_metric)
return fib6_entry;
if (rt->fib6_metric > nrt->fib6_metric)
break;
@@ -5170,7 +5163,7 @@ static struct mlxsw_sp_fib6_entry *
mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
const struct fib6_info *nrt, bool replace)
{
- struct mlxsw_sp_fib6_entry *fib6_entry, *fallback = NULL;
+ struct mlxsw_sp_fib6_entry *fib6_entry;
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
@@ -5179,18 +5172,13 @@ mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
continue;
if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
break;
- if (replace && rt->fib6_metric == nrt->fib6_metric) {
- if (mlxsw_sp_fib6_rt_can_mp(rt) ==
- mlxsw_sp_fib6_rt_can_mp(nrt))
- return fib6_entry;
- if (mlxsw_sp_fib6_rt_can_mp(nrt))
- fallback = fallback ?: fib6_entry;
- }
+ if (replace && rt->fib6_metric == nrt->fib6_metric)
+ return fib6_entry;
if (rt->fib6_metric > nrt->fib6_metric)
- return fallback ?: fib6_entry;
+ return fib6_entry;
}
- return fallback;
+ return NULL;
}
static int
@@ -5316,7 +5304,8 @@ static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp *mlxsw_sp,
}
static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
- struct fib6_info *rt, bool replace)
+ struct fib6_info *rt, bool replace,
+ bool append)
{
struct mlxsw_sp_fib6_entry *fib6_entry;
struct mlxsw_sp_fib_node *fib_node;
@@ -5342,7 +5331,7 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
/* Before creating a new entry, try to append route to an existing
* multipath entry.
*/
- fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, replace);
+ fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, append);
if (fib6_entry) {
err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt);
if (err)
@@ -5350,6 +5339,14 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
return 0;
}
+ /* We received an append event, yet did not find any route to
+ * append to.
+ */
+ if (WARN_ON(append)) {
+ err = -EINVAL;
+ goto err_fib6_entry_append;
+ }
+
fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt);
if (IS_ERR(fib6_entry)) {
err = PTR_ERR(fib6_entry);
@@ -5367,6 +5364,7 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
err_fib6_node_entry_link:
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
err_fib6_entry_create:
+err_fib6_entry_append:
err_fib6_entry_nexthop_add:
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
return err;
@@ -5717,7 +5715,7 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
struct mlxsw_sp_fib_event_work *fib_work =
container_of(work, struct mlxsw_sp_fib_event_work, work);
struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
- bool replace;
+ bool replace, append;
int err;
rtnl_lock();
@@ -5728,8 +5726,10 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
case FIB_EVENT_ENTRY_APPEND: /* fall through */
case FIB_EVENT_ENTRY_ADD:
replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
+ append = fib_work->event == FIB_EVENT_ENTRY_APPEND;
err = mlxsw_sp_router_fib6_add(mlxsw_sp,
- fib_work->fen6_info.rt, replace);
+ fib_work->fen6_info.rt, replace,
+ append);
if (err)
mlxsw_sp_router_fib_abort(mlxsw_sp);
mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index e97652c..eea5666 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1018,8 +1018,10 @@ mlxsw_sp_port_vlan_bridge_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
int err;
/* No need to continue if only VLAN flags were changed */
- if (mlxsw_sp_port_vlan->bridge_port)
+ if (mlxsw_sp_port_vlan->bridge_port) {
+ mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
return 0;
+ }
err = mlxsw_sp_port_vlan_fid_join(mlxsw_sp_port_vlan, bridge_port);
if (err)
diff --git a/drivers/net/ethernet/micrel/ksz884x.c b/drivers/net/ethernet/micrel/ksz884x.c
index 5220750..b72d1bd 100644
--- a/drivers/net/ethernet/micrel/ksz884x.c
+++ b/drivers/net/ethernet/micrel/ksz884x.c
@@ -4372,7 +4372,7 @@ static void ksz_update_timer(struct ksz_timer_info *info)
*/
static int ksz_alloc_soft_desc(struct ksz_desc_info *desc_info, int transmit)
{
- desc_info->ring = kzalloc(sizeof(struct ksz_desc) * desc_info->alloc,
+ desc_info->ring = kcalloc(desc_info->alloc, sizeof(struct ksz_desc),
GFP_KERNEL);
if (!desc_info->ring)
return 1;
diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
index 2e4effa..b34055a 100644
--- a/drivers/net/ethernet/moxa/moxart_ether.c
+++ b/drivers/net/ethernet/moxa/moxart_ether.c
@@ -507,15 +507,15 @@ static int moxart_mac_probe(struct platform_device *pdev)
goto init_fail;
}
- priv->tx_buf_base = kmalloc(priv->tx_buf_size * TX_DESC_NUM,
- GFP_ATOMIC);
+ priv->tx_buf_base = kmalloc_array(priv->tx_buf_size, TX_DESC_NUM,
+ GFP_ATOMIC);
if (!priv->tx_buf_base) {
ret = -ENOMEM;
goto init_fail;
}
- priv->rx_buf_base = kmalloc(priv->rx_buf_size * RX_DESC_NUM,
- GFP_ATOMIC);
+ priv->rx_buf_base = kmalloc_array(priv->rx_buf_size, RX_DESC_NUM,
+ GFP_ATOMIC);
if (!priv->rx_buf_base) {
ret = -ENOMEM;
goto init_fail;
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index c8c74aa..fb2c8f8 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1126,7 +1126,7 @@ static int ocelot_netdevice_event(struct notifier_block *unused,
{
struct netdev_notifier_changeupper_info *info = ptr;
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
- int ret;
+ int ret = 0;
if (netif_is_lag_master(dev)) {
struct net_device *slave;
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-config.c b/drivers/net/ethernet/neterion/vxge/vxge-config.c
index c60da9e..358ed61 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-config.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-config.c
@@ -2220,22 +2220,22 @@ __vxge_hw_channel_allocate(struct __vxge_hw_vpath_handle *vph,
channel->length = length;
channel->vp_id = vp_id;
- channel->work_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
+ channel->work_arr = kcalloc(length, sizeof(void *), GFP_KERNEL);
if (channel->work_arr == NULL)
goto exit1;
- channel->free_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
+ channel->free_arr = kcalloc(length, sizeof(void *), GFP_KERNEL);
if (channel->free_arr == NULL)
goto exit1;
channel->free_ptr = length;
- channel->reserve_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
+ channel->reserve_arr = kcalloc(length, sizeof(void *), GFP_KERNEL);
if (channel->reserve_arr == NULL)
goto exit1;
channel->reserve_ptr = length;
channel->reserve_top = 0;
- channel->orig_arr = kzalloc(sizeof(void *)*length, GFP_KERNEL);
+ channel->orig_arr = kcalloc(length, sizeof(void *), GFP_KERNEL);
if (channel->orig_arr == NULL)
goto exit1;
@@ -2565,7 +2565,7 @@ __vxge_hw_mempool_grow(struct vxge_hw_mempool *mempool, u32 num_allocate,
* allocate new memblock and its private part at once.
* This helps to minimize memory usage a lot. */
mempool->memblocks_priv_arr[i] =
- vzalloc(mempool->items_priv_size * n_items);
+ vzalloc(array_size(mempool->items_priv_size, n_items));
if (mempool->memblocks_priv_arr[i] == NULL) {
status = VXGE_HW_ERR_OUT_OF_MEMORY;
goto exit;
@@ -2665,7 +2665,7 @@ __vxge_hw_mempool_create(struct __vxge_hw_device *devh,
/* allocate array of memblocks */
mempool->memblocks_arr =
- vzalloc(sizeof(void *) * mempool->memblocks_max);
+ vzalloc(array_size(sizeof(void *), mempool->memblocks_max));
if (mempool->memblocks_arr == NULL) {
__vxge_hw_mempool_destroy(mempool);
status = VXGE_HW_ERR_OUT_OF_MEMORY;
@@ -2675,7 +2675,7 @@ __vxge_hw_mempool_create(struct __vxge_hw_device *devh,
/* allocate array of private parts of items per memblocks */
mempool->memblocks_priv_arr =
- vzalloc(sizeof(void *) * mempool->memblocks_max);
+ vzalloc(array_size(sizeof(void *), mempool->memblocks_max));
if (mempool->memblocks_priv_arr == NULL) {
__vxge_hw_mempool_destroy(mempool);
status = VXGE_HW_ERR_OUT_OF_MEMORY;
@@ -2685,8 +2685,8 @@ __vxge_hw_mempool_create(struct __vxge_hw_device *devh,
/* allocate array of memblocks DMA objects */
mempool->memblocks_dma_arr =
- vzalloc(sizeof(struct vxge_hw_mempool_dma) *
- mempool->memblocks_max);
+ vzalloc(array_size(sizeof(struct vxge_hw_mempool_dma),
+ mempool->memblocks_max));
if (mempool->memblocks_dma_arr == NULL) {
__vxge_hw_mempool_destroy(mempool);
status = VXGE_HW_ERR_OUT_OF_MEMORY;
@@ -2695,7 +2695,8 @@ __vxge_hw_mempool_create(struct __vxge_hw_device *devh,
}
/* allocate hash array of items */
- mempool->items_arr = vzalloc(sizeof(void *) * mempool->items_max);
+ mempool->items_arr = vzalloc(array_size(sizeof(void *),
+ mempool->items_max));
if (mempool->items_arr == NULL) {
__vxge_hw_mempool_destroy(mempool);
status = VXGE_HW_ERR_OUT_OF_MEMORY;
diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c
index a8918bb..5ae3fa8 100644
--- a/drivers/net/ethernet/neterion/vxge/vxge-main.c
+++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c
@@ -3429,8 +3429,8 @@ static int vxge_device_register(struct __vxge_hw_device *hldev,
vxge_initialize_ethtool_ops(ndev);
/* Allocate memory for vpath */
- vdev->vpaths = kzalloc((sizeof(struct vxge_vpath)) *
- no_of_vpath, GFP_KERNEL);
+ vdev->vpaths = kcalloc(no_of_vpath, sizeof(struct vxge_vpath),
+ GFP_KERNEL);
if (!vdev->vpaths) {
vxge_debug_init(VXGE_ERR,
"%s: vpath memory allocation failed",
diff --git a/drivers/net/ethernet/netronome/nfp/abm/main.c b/drivers/net/ethernet/netronome/nfp/abm/main.c
index 1561c27..b84a6c2 100644
--- a/drivers/net/ethernet/netronome/nfp/abm/main.c
+++ b/drivers/net/ethernet/netronome/nfp/abm/main.c
@@ -590,7 +590,7 @@ nfp_abm_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, unsigned int id)
alink->id = id;
alink->parent = TC_H_ROOT;
alink->total_queues = alink->vnic->max_rx_rings;
- alink->qdiscs = kvzalloc(sizeof(*alink->qdiscs) * alink->total_queues,
+ alink->qdiscs = kvcalloc(alink->total_queues, sizeof(*alink->qdiscs),
GFP_KERNEL);
if (!alink->qdiscs) {
err = -ENOMEM;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.c b/drivers/net/ethernet/netronome/nfp/flower/main.c
index 19cfa16..1decf3a 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/main.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/main.c
@@ -455,6 +455,7 @@ static int nfp_flower_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
eth_hw_addr_random(nn->dp.netdev);
netif_keep_dst(nn->dp.netdev);
+ nn->vnic_no_name = true;
return 0;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/metadata.c b/drivers/net/ethernet/netronome/nfp/flower/metadata.c
index 21668aa..93fb809 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/metadata.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/metadata.c
@@ -417,7 +417,8 @@ int nfp_flower_metadata_init(struct nfp_app *app)
/* Init ring buffer and unallocated stats_ids. */
priv->stats_ids.free_list.buf =
- vmalloc(NFP_FL_STATS_ENTRY_RS * NFP_FL_STATS_ELEM_RS);
+ vmalloc(array_size(NFP_FL_STATS_ELEM_RS,
+ NFP_FL_STATS_ENTRY_RS));
if (!priv->stats_ids.free_list.buf)
goto err_free_last_used;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
index ec524d9..78afe75 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/tunnel_conf.c
@@ -381,6 +381,8 @@ nfp_tun_neigh_event_handler(struct notifier_block *nb, unsigned long event,
err = PTR_ERR_OR_ZERO(rt);
if (err)
return NOTIFY_DONE;
+
+ ip_rt_put(rt);
#else
return NOTIFY_DONE;
#endif
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 57cb035d..2a71a9f 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -590,6 +590,8 @@ struct nfp_net_dp {
* @vnic_list: Entry on device vNIC list
* @pdev: Backpointer to PCI device
* @app: APP handle if available
+ * @vnic_no_name: For non-port PF vNIC make ndo_get_phys_port_name return
+ * -EOPNOTSUPP to keep backwards compatibility (set by app)
* @port: Pointer to nfp_port structure if vNIC is a port
* @app_priv: APP private data for this vNIC
*/
@@ -663,6 +665,8 @@ struct nfp_net {
struct pci_dev *pdev;
struct nfp_app *app;
+ bool vnic_no_name;
+
struct nfp_port *port;
void *app_priv;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 75110c8..d4c27f8 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3121,7 +3121,7 @@ static void nfp_net_stat64(struct net_device *netdev,
struct nfp_net *nn = netdev_priv(netdev);
int r;
- for (r = 0; r < nn->dp.num_r_vecs; r++) {
+ for (r = 0; r < nn->max_r_vecs; r++) {
struct nfp_net_r_vector *r_vec = &nn->r_vecs[r];
u64 data[3];
unsigned int start;
@@ -3286,7 +3286,7 @@ nfp_net_get_phys_port_name(struct net_device *netdev, char *name, size_t len)
if (nn->port)
return nfp_port_get_phys_port_name(netdev, name, len);
- if (nn->dp.is_vf)
+ if (nn->dp.is_vf || nn->vnic_no_name)
return -EOPNOTSUPP;
n = snprintf(name, len, "n%d", nn->id);
diff --git a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c
index 2dd89db..d32af59 100644
--- a/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c
+++ b/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c
@@ -98,21 +98,18 @@ struct nfp_resource {
static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res)
{
- char name_pad[NFP_RESOURCE_ENTRY_NAME_SZ] = {};
struct nfp_resource_entry entry;
u32 cpp_id, key;
int ret, i;
cpp_id = NFP_CPP_ID(NFP_RESOURCE_TBL_TARGET, 3, 0); /* Atomic read */
- strncpy(name_pad, res->name, sizeof(name_pad));
-
/* Search for a matching entry */
- if (!memcmp(name_pad, NFP_RESOURCE_TBL_NAME "\0\0\0\0\0\0\0\0", 8)) {
+ if (!strcmp(res->name, NFP_RESOURCE_TBL_NAME)) {
nfp_err(cpp, "Grabbing device lock not supported\n");
return -EOPNOTSUPP;
}
- key = crc32_posix(name_pad, sizeof(name_pad));
+ key = crc32_posix(res->name, NFP_RESOURCE_ENTRY_NAME_SZ);
for (i = 0; i < NFP_RESOURCE_TBL_ENTRIES; i++) {
u64 addr = NFP_RESOURCE_TBL_BASE +
diff --git a/drivers/net/ethernet/ni/nixge.c b/drivers/net/ethernet/ni/nixge.c
index b092894..09f674e 100644
--- a/drivers/net/ethernet/ni/nixge.c
+++ b/drivers/net/ethernet/ni/nixge.c
@@ -247,9 +247,8 @@ static int nixge_hw_dma_bd_init(struct net_device *ndev)
if (!priv->tx_bd_v)
goto out;
- priv->tx_skb = devm_kzalloc(ndev->dev.parent,
- sizeof(*priv->tx_skb) *
- TX_BD_NUM,
+ priv->tx_skb = devm_kcalloc(ndev->dev.parent,
+ TX_BD_NUM, sizeof(*priv->tx_skb),
GFP_KERNEL);
if (!priv->tx_skb)
goto out;
diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c
index 66c665d..7cbd017 100644
--- a/drivers/net/ethernet/nvidia/forcedeth.c
+++ b/drivers/net/ethernet/nvidia/forcedeth.c
@@ -4630,8 +4630,10 @@ static int nv_set_ringparam(struct net_device *dev, struct ethtool_ringparam* ri
ring->tx_pending),
&ring_addr, GFP_ATOMIC);
}
- rx_skbuff = kmalloc(sizeof(struct nv_skb_map) * ring->rx_pending, GFP_KERNEL);
- tx_skbuff = kmalloc(sizeof(struct nv_skb_map) * ring->tx_pending, GFP_KERNEL);
+ rx_skbuff = kmalloc_array(ring->rx_pending, sizeof(struct nv_skb_map),
+ GFP_KERNEL);
+ tx_skbuff = kmalloc_array(ring->tx_pending, sizeof(struct nv_skb_map),
+ GFP_KERNEL);
if (!rxtx_ring || !rx_skbuff || !tx_skbuff) {
/* fall back to old rings */
if (!nv_optimized(np)) {
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
index 7cd4946..34a1581 100644
--- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
+++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
@@ -2178,7 +2178,7 @@ static void pch_gbe_set_multi(struct net_device *netdev)
if (mc_count >= PCH_GBE_MAR_ENTRIES)
return;
- mta_list = kmalloc(mc_count * ETH_ALEN, GFP_ATOMIC);
+ mta_list = kmalloc_array(ETH_ALEN, mc_count, GFP_ATOMIC);
if (!mta_list)
return;
diff --git a/drivers/net/ethernet/pasemi/pasemi_mac.c b/drivers/net/ethernet/pasemi/pasemi_mac.c
index 07a2eb3..8a31a02 100644
--- a/drivers/net/ethernet/pasemi/pasemi_mac.c
+++ b/drivers/net/ethernet/pasemi/pasemi_mac.c
@@ -390,8 +390,9 @@ static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
spin_lock_init(&ring->lock);
ring->size = RX_RING_SIZE;
- ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
- RX_RING_SIZE, GFP_KERNEL);
+ ring->ring_info = kcalloc(RX_RING_SIZE,
+ sizeof(struct pasemi_mac_buffer),
+ GFP_KERNEL);
if (!ring->ring_info)
goto out_ring_info;
@@ -473,8 +474,9 @@ pasemi_mac_setup_tx_resources(const struct net_device *dev)
spin_lock_init(&ring->lock);
ring->size = TX_RING_SIZE;
- ring->ring_info = kzalloc(sizeof(struct pasemi_mac_buffer) *
- TX_RING_SIZE, GFP_KERNEL);
+ ring->ring_info = kcalloc(TX_RING_SIZE,
+ sizeof(struct pasemi_mac_buffer),
+ GFP_KERNEL);
if (!ring->ring_info)
goto out_ring_info;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
index 8f31406..f0b0138 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
@@ -255,9 +255,8 @@ qed_dcbx_get_app_protocol_type(struct qed_hwfn *p_hwfn,
*type = DCBX_PROTOCOL_ROCE_V2;
} else {
*type = DCBX_MAX_PROTOCOL_TYPE;
- DP_ERR(p_hwfn,
- "No action required, App TLV id = 0x%x app_prio_bitmap = 0x%x\n",
- id, app_prio_bitmap);
+ DP_ERR(p_hwfn, "No action required, App TLV entry = 0x%x\n",
+ app_prio_bitmap);
return false;
}
@@ -1479,8 +1478,8 @@ static u8 qed_dcbnl_getcap(struct qed_dev *cdev, int capid, u8 *cap)
*cap = 0x80;
break;
case DCB_CAP_ATTR_DCBX:
- *cap = (DCB_CAP_DCBX_LLD_MANAGED | DCB_CAP_DCBX_VER_CEE |
- DCB_CAP_DCBX_VER_IEEE | DCB_CAP_DCBX_STATIC);
+ *cap = (DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_VER_IEEE |
+ DCB_CAP_DCBX_STATIC);
break;
default:
*cap = false;
@@ -1548,8 +1547,6 @@ static u8 qed_dcbnl_getdcbx(struct qed_dev *cdev)
if (!dcbx_info)
return 0;
- if (dcbx_info->operational.enabled)
- mode |= DCB_CAP_DCBX_LLD_MANAGED;
if (dcbx_info->operational.ieee)
mode |= DCB_CAP_DCBX_VER_IEEE;
if (dcbx_info->operational.cee)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c
index b9ec460..a14e484 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_debug.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c
@@ -6617,7 +6617,8 @@ static enum dbg_status qed_mcp_trace_alloc_meta(struct qed_hwfn *p_hwfn,
/* Read no. of modules and allocate memory for their pointers */
meta->modules_num = qed_read_byte_from_buf(meta_buf_bytes, &offset);
- meta->modules = kzalloc(meta->modules_num * sizeof(char *), GFP_KERNEL);
+ meta->modules = kcalloc(meta->modules_num, sizeof(char *),
+ GFP_KERNEL);
if (!meta->modules)
return DBG_STATUS_VIRT_MEM_ALLOC_FAILED;
@@ -6645,7 +6646,7 @@ static enum dbg_status qed_mcp_trace_alloc_meta(struct qed_hwfn *p_hwfn,
/* Read number of formats and allocate memory for all formats */
meta->formats_num = qed_read_dword_from_buf(meta_buf_bytes, &offset);
- meta->formats = kzalloc(meta->formats_num *
+ meta->formats = kcalloc(meta->formats_num,
sizeof(struct mcp_trace_format),
GFP_KERNEL);
if (!meta->formats)
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index b285edc..329781c 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -814,26 +814,26 @@ static int qed_alloc_qm_data(struct qed_hwfn *p_hwfn)
if (rc)
goto alloc_err;
- qm_info->qm_pq_params = kzalloc(sizeof(*qm_info->qm_pq_params) *
- qed_init_qm_get_num_pqs(p_hwfn),
+ qm_info->qm_pq_params = kcalloc(qed_init_qm_get_num_pqs(p_hwfn),
+ sizeof(*qm_info->qm_pq_params),
GFP_KERNEL);
if (!qm_info->qm_pq_params)
goto alloc_err;
- qm_info->qm_vport_params = kzalloc(sizeof(*qm_info->qm_vport_params) *
- qed_init_qm_get_num_vports(p_hwfn),
+ qm_info->qm_vport_params = kcalloc(qed_init_qm_get_num_vports(p_hwfn),
+ sizeof(*qm_info->qm_vport_params),
GFP_KERNEL);
if (!qm_info->qm_vport_params)
goto alloc_err;
- qm_info->qm_port_params = kzalloc(sizeof(*qm_info->qm_port_params) *
- p_hwfn->cdev->num_ports_in_engine,
+ qm_info->qm_port_params = kcalloc(p_hwfn->cdev->num_ports_in_engine,
+ sizeof(*qm_info->qm_port_params),
GFP_KERNEL);
if (!qm_info->qm_port_params)
goto alloc_err;
- qm_info->wfq_data = kzalloc(sizeof(*qm_info->wfq_data) *
- qed_init_qm_get_num_vports(p_hwfn),
+ qm_info->wfq_data = kcalloc(qed_init_qm_get_num_vports(p_hwfn),
+ sizeof(*qm_info->wfq_data),
GFP_KERNEL);
if (!qm_info->wfq_data)
goto alloc_err;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_init_ops.c b/drivers/net/ethernet/qlogic/qed/qed_init_ops.c
index 3bb76da..d9ab5add 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_init_ops.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_init_ops.c
@@ -149,12 +149,12 @@ int qed_init_alloc(struct qed_hwfn *p_hwfn)
if (IS_VF(p_hwfn->cdev))
return 0;
- rt_data->b_valid = kzalloc(sizeof(bool) * RUNTIME_ARRAY_SIZE,
+ rt_data->b_valid = kcalloc(RUNTIME_ARRAY_SIZE, sizeof(bool),
GFP_KERNEL);
if (!rt_data->b_valid)
return -ENOMEM;
- rt_data->init_val = kzalloc(sizeof(u32) * RUNTIME_ARRAY_SIZE,
+ rt_data->init_val = kcalloc(RUNTIME_ARRAY_SIZE, sizeof(u32),
GFP_KERNEL);
if (!rt_data->init_val) {
kfree(rt_data->b_valid);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index 1f6ac848..99973e1 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -98,7 +98,7 @@ int qed_l2_alloc(struct qed_hwfn *p_hwfn)
p_l2_info->queues = max_t(u8, rx, tx);
}
- pp_qids = kzalloc(sizeof(unsigned long *) * p_l2_info->queues,
+ pp_qids = kcalloc(p_l2_info->queues, sizeof(unsigned long *),
GFP_KERNEL);
if (!pp_qids)
return -ENOMEM;
@@ -2435,7 +2435,7 @@ static int qed_update_vport(struct qed_dev *cdev,
if (!cdev)
return -ENODEV;
- rss = vzalloc(sizeof(*rss) * cdev->num_hwfns);
+ rss = vzalloc(array_size(sizeof(*rss), cdev->num_hwfns));
if (!rss)
return -ENOMEM;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
index c97ebd6..012973d 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
@@ -201,8 +201,9 @@ void qed_ll2b_complete_rx_packet(void *cxt, struct qed_ll2_comp_rx_data *data)
skb = build_skb(buffer->data, 0);
if (!skb) {
- rc = -ENOMEM;
- goto out_post;
+ DP_INFO(cdev, "Failed to build SKB\n");
+ kfree(buffer->data);
+ goto out_post1;
}
data->u.placement_offset += NET_SKB_PAD;
@@ -224,8 +225,14 @@ void qed_ll2b_complete_rx_packet(void *cxt, struct qed_ll2_comp_rx_data *data)
cdev->ll2->cbs->rx_cb(cdev->ll2->cb_cookie, skb,
data->opaque_data_0,
data->opaque_data_1);
+ } else {
+ DP_VERBOSE(p_hwfn, (NETIF_MSG_RX_STATUS | NETIF_MSG_PKTDATA |
+ QED_MSG_LL2 | QED_MSG_STORAGE),
+ "Dropping the packet\n");
+ kfree(buffer->data);
}
+out_post1:
/* Update Buffer information and update FW producer */
buffer->data = new_data;
buffer->phys_addr = new_phys_addr;
diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
index b04d57c..5c10fd7 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_main.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
@@ -567,8 +567,16 @@ static irqreturn_t qed_single_int(int irq, void *dev_instance)
/* Fastpath interrupts */
for (j = 0; j < 64; j++) {
if ((0x2ULL << j) & status) {
- hwfn->simd_proto_handler[j].func(
- hwfn->simd_proto_handler[j].token);
+ struct qed_simd_fp_handler *p_handler =
+ &hwfn->simd_proto_handler[j];
+
+ if (p_handler->func)
+ p_handler->func(p_handler->token);
+ else
+ DP_NOTICE(hwfn,
+ "Not calling fastpath handler as it is NULL [handler #%d, status 0x%llx]\n",
+ j, status);
+
status &= ~(0x2ULL << j);
rc = IRQ_HANDLED;
}
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 6f9927d..4e0b443 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -2578,9 +2578,9 @@ int qed_mcp_nvm_info_populate(struct qed_hwfn *p_hwfn)
goto err0;
}
- nvm_info->image_att = kmalloc(nvm_info->num_images *
- sizeof(struct bist_nvm_image_att),
- GFP_KERNEL);
+ nvm_info->image_att = kmalloc_array(nvm_info->num_images,
+ sizeof(struct bist_nvm_image_att),
+ GFP_KERNEL);
if (!nvm_info->image_att) {
rc = -ENOMEM;
goto err0;
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index e9e088d..b823bfe 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -342,8 +342,9 @@ int qede_alloc_arfs(struct qede_dev *edev)
for (i = 0; i <= QEDE_RFS_FLW_MASK; i++)
INIT_HLIST_HEAD(QEDE_ARFS_BUCKET_HEAD(edev, i));
- edev->arfs->arfs_fltr_bmap = vzalloc(BITS_TO_LONGS(QEDE_RFS_MAX_FLTR) *
- sizeof(long));
+ edev->arfs->arfs_fltr_bmap =
+ vzalloc(array_size(sizeof(long),
+ BITS_TO_LONGS(QEDE_RFS_MAX_FLTR)));
if (!edev->arfs->arfs_fltr_bmap) {
vfree(edev->arfs);
edev->arfs = NULL;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
index 97c146e7..569d54e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
@@ -386,8 +386,9 @@ int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter)
}
/* setup interrupt mapping table for fw */
- ahw->intr_tbl = vzalloc(num_msix *
- sizeof(struct qlcnic_intrpt_config));
+ ahw->intr_tbl =
+ vzalloc(array_size(num_msix,
+ sizeof(struct qlcnic_intrpt_config)));
if (!ahw->intr_tbl)
return -ENOMEM;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
index 1b5f7d5..2d38d1a 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c
@@ -916,8 +916,9 @@ int qlcnic_82xx_mq_intrpt(struct qlcnic_adapter *adapter, int op_type)
if (qlcnic_check_multi_tx(adapter) &&
!ahw->diag_test &&
(adapter->flags & QLCNIC_MSIX_ENABLED)) {
- ahw->intr_tbl = vzalloc(ahw->num_msix *
- sizeof(struct qlcnic_intrpt_config));
+ ahw->intr_tbl =
+ vzalloc(array_size(sizeof(struct qlcnic_intrpt_config),
+ ahw->num_msix));
if (!ahw->intr_tbl)
return -ENOMEM;
@@ -1025,15 +1026,17 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter)
act_pci_func = ahw->total_nic_func;
- adapter->npars = kzalloc(sizeof(struct qlcnic_npar_info) *
- act_pci_func, GFP_KERNEL);
+ adapter->npars = kcalloc(act_pci_func,
+ sizeof(struct qlcnic_npar_info),
+ GFP_KERNEL);
if (!adapter->npars) {
ret = -ENOMEM;
goto err_pci_info;
}
- adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) *
- QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL);
+ adapter->eswitch = kcalloc(QLCNIC_NIU_MAX_XG_PORTS,
+ sizeof(struct qlcnic_eswitch),
+ GFP_KERNEL);
if (!adapter->eswitch) {
ret = -ENOMEM;
goto err_npars;
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
index c58180f..0c744b9 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c
@@ -157,8 +157,8 @@ int qlcnic_sriov_init(struct qlcnic_adapter *adapter, int num_vfs)
adapter->ahw->sriov = sriov;
sriov->num_vfs = num_vfs;
bc = &sriov->bc;
- sriov->vf_info = kzalloc(sizeof(struct qlcnic_vf_info) *
- num_vfs, GFP_KERNEL);
+ sriov->vf_info = kcalloc(num_vfs, sizeof(struct qlcnic_vf_info),
+ GFP_KERNEL);
if (!sriov->vf_info) {
err = -ENOMEM;
goto qlcnic_free_sriov;
@@ -450,7 +450,7 @@ static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter,
return 0;
num_vlans = sriov->num_allowed_vlans;
- sriov->allowed_vlans = kzalloc(sizeof(u16) * num_vlans, GFP_KERNEL);
+ sriov->allowed_vlans = kcalloc(num_vlans, sizeof(u16), GFP_KERNEL);
if (!sriov->allowed_vlans)
return -ENOMEM;
@@ -706,7 +706,7 @@ static inline int qlcnic_sriov_alloc_bc_trans(struct qlcnic_bc_trans **trans)
static inline int qlcnic_sriov_alloc_bc_msg(struct qlcnic_bc_hdr **hdr,
u32 size)
{
- *hdr = kzalloc(sizeof(struct qlcnic_bc_hdr) * size, GFP_ATOMIC);
+ *hdr = kcalloc(size, sizeof(struct qlcnic_bc_hdr), GFP_ATOMIC);
if (!*hdr)
return -ENOMEM;
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index 70de062..353f1c1 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -2810,7 +2810,8 @@ static int ql_alloc_tx_resources(struct ql_adapter *qdev,
goto pci_alloc_err;
tx_ring->q =
- kmalloc(tx_ring->wq_len * sizeof(struct tx_ring_desc), GFP_KERNEL);
+ kmalloc_array(tx_ring->wq_len, sizeof(struct tx_ring_desc),
+ GFP_KERNEL);
if (tx_ring->q == NULL)
goto err;
diff --git a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
index e78e5db..c694e34 100644
--- a/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
+++ b/drivers/net/ethernet/qualcomm/emac/emac-sgmii.c
@@ -384,6 +384,7 @@ int emac_sgmii_config(struct platform_device *pdev, struct emac_adapter *adpt)
}
sgmii_pdev = of_find_device_by_node(np);
+ of_node_put(np);
if (!sgmii_pdev) {
dev_err(&pdev->dev, "invalid internal-phy property\n");
return -ENODEV;
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index d90a7b1..23f0785 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -4984,7 +4984,8 @@ static int efx_ef10_filter_table_probe(struct efx_nic *efx)
net_dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_FILTER;
}
- table->entry = vzalloc(HUNT_FILTER_TBL_ROWS * sizeof(*table->entry));
+ table->entry = vzalloc(array_size(HUNT_FILTER_TBL_ROWS,
+ sizeof(*table->entry)));
if (!table->entry) {
rc = -ENOMEM;
goto fail;
diff --git a/drivers/net/ethernet/sfc/falcon/farch.c b/drivers/net/ethernet/sfc/falcon/farch.c
index 494884f..411a2f4 100644
--- a/drivers/net/ethernet/sfc/falcon/farch.c
+++ b/drivers/net/ethernet/sfc/falcon/farch.c
@@ -2755,7 +2755,8 @@ int ef4_farch_filter_table_probe(struct ef4_nic *efx)
GFP_KERNEL);
if (!table->used_bitmap)
goto fail;
- table->spec = vzalloc(table->size * sizeof(*table->spec));
+ table->spec = vzalloc(array_size(sizeof(*table->spec),
+ table->size));
if (!table->spec)
goto fail;
}
diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c
index c72adf8..8edf209 100644
--- a/drivers/net/ethernet/sfc/farch.c
+++ b/drivers/net/ethernet/sfc/farch.c
@@ -2826,7 +2826,8 @@ int efx_farch_filter_table_probe(struct efx_nic *efx)
GFP_KERNEL);
if (!table->used_bitmap)
goto fail;
- table->spec = vzalloc(table->size * sizeof(*table->spec));
+ table->spec = vzalloc(array_size(sizeof(*table->spec),
+ table->size));
if (!table->spec)
goto fail;
}
diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index ce8071f..e080d3e 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -973,7 +973,7 @@ static int netsec_alloc_dring(struct netsec_priv *priv, enum ring_id id)
goto err;
}
- dring->desc = kzalloc(DESC_NUM * sizeof(*dring->desc), GFP_KERNEL);
+ dring->desc = kcalloc(DESC_NUM, sizeof(*dring->desc), GFP_KERNEL);
if (!dring->desc) {
ret = -ENOMEM;
goto err;
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index e28c0d2..edf2036 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -33,7 +33,7 @@ config DWMAC_DWC_QOS_ETH
select PHYLIB
select CRC32
select MII
- depends on OF && HAS_DMA
+ depends on OF && COMMON_CLK && HAS_DMA
help
Support for chips using the snps,dwc-qos-ethernet.txt DT binding.
@@ -57,7 +57,7 @@ config DWMAC_ANARION
config DWMAC_IPQ806X
tristate "QCA IPQ806x DWMAC support"
default ARCH_QCOM
- depends on OF && (ARCH_QCOM || COMPILE_TEST)
+ depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST)
select MFD_SYSCON
help
Support for QCA IPQ806X DWMAC Ethernet.
@@ -100,7 +100,7 @@ config DWMAC_OXNAS
config DWMAC_ROCKCHIP
tristate "Rockchip dwmac support"
default ARCH_ROCKCHIP
- depends on OF && (ARCH_ROCKCHIP || COMPILE_TEST)
+ depends on OF && COMMON_CLK && (ARCH_ROCKCHIP || COMPILE_TEST)
select MFD_SYSCON
help
Support for Ethernet controller on Rockchip RK3288 SoC.
@@ -111,7 +111,7 @@ config DWMAC_ROCKCHIP
config DWMAC_SOCFPGA
tristate "SOCFPGA dwmac support"
default ARCH_SOCFPGA
- depends on OF && (ARCH_SOCFPGA || COMPILE_TEST)
+ depends on OF && (ARCH_SOCFPGA || ARCH_STRATIX10 || COMPILE_TEST)
select MFD_SYSCON
help
Support for ethernet controller on Altera SOCFPGA
@@ -123,7 +123,7 @@ config DWMAC_SOCFPGA
config DWMAC_STI
tristate "STi GMAC support"
default ARCH_STI
- depends on OF && (ARCH_STI || COMPILE_TEST)
+ depends on OF && COMMON_CLK && (ARCH_STI || COMPILE_TEST)
select MFD_SYSCON
---help---
Support for ethernet controller on STi SOCs.
@@ -147,7 +147,7 @@ config DWMAC_STM32
config DWMAC_SUNXI
tristate "Allwinner GMAC support"
default ARCH_SUNXI
- depends on OF && (ARCH_SUNXI || COMPILE_TEST)
+ depends on OF && COMMON_CLK && (ARCH_SUNXI || COMPILE_TEST)
---help---
Support for Allwinner A20/A31 GMAC ethernet controllers.
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
index 4ff231d..c597956 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -334,9 +334,10 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
dwmac->data = (const struct meson8b_dwmac_data *)
of_device_get_match_data(&pdev->dev);
- if (!dwmac->data)
- return -EINVAL;
-
+ if (!dwmac->data) {
+ ret = -EINVAL;
+ goto err_remove_config_dt;
+ }
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
dwmac->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(dwmac->regs)) {
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index 6e35957..5b3b06a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -55,6 +55,7 @@ struct socfpga_dwmac {
struct device *dev;
struct regmap *sys_mgr_base_addr;
struct reset_control *stmmac_rst;
+ struct reset_control *stmmac_ocp_rst;
void __iomem *splitter_base;
bool f2h_ptp_ref_clk;
struct tse_pcs pcs;
@@ -262,8 +263,8 @@ static int socfpga_dwmac_set_phy_mode(struct socfpga_dwmac *dwmac)
val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
/* Assert reset to the enet controller before changing the phy mode */
- if (dwmac->stmmac_rst)
- reset_control_assert(dwmac->stmmac_rst);
+ reset_control_assert(dwmac->stmmac_ocp_rst);
+ reset_control_assert(dwmac->stmmac_rst);
regmap_read(sys_mgr_base_addr, reg_offset, &ctrl);
ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
@@ -288,8 +289,8 @@ static int socfpga_dwmac_set_phy_mode(struct socfpga_dwmac *dwmac)
/* Deassert reset for the phy configuration to be sampled by
* the enet controller, and operation to start in requested mode
*/
- if (dwmac->stmmac_rst)
- reset_control_deassert(dwmac->stmmac_rst);
+ reset_control_deassert(dwmac->stmmac_ocp_rst);
+ reset_control_deassert(dwmac->stmmac_rst);
if (phymode == PHY_INTERFACE_MODE_SGMII) {
if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) {
dev_err(dwmac->dev, "Unable to initialize TSE PCS");
@@ -324,6 +325,15 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
goto err_remove_config_dt;
}
+ dwmac->stmmac_ocp_rst = devm_reset_control_get_optional(dev, "stmmaceth-ocp");
+ if (IS_ERR(dwmac->stmmac_ocp_rst)) {
+ ret = PTR_ERR(dwmac->stmmac_ocp_rst);
+ dev_err(dev, "error getting reset control of ocp %d\n", ret);
+ goto err_remove_config_dt;
+ }
+
+ reset_control_deassert(dwmac->stmmac_ocp_rst);
+
ret = socfpga_dwmac_parse_data(dwmac, dev);
if (ret) {
dev_err(dev, "Unable to parse OF data\n");
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index 14770fc..1f50e83 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -252,13 +252,8 @@ int stmmac_hwif_init(struct stmmac_priv *priv)
return ret;
}
- /* Run quirks, if needed */
- if (entry->quirks) {
- ret = entry->quirks(priv);
- if (ret)
- return ret;
- }
-
+ /* Save quirks, if needed for posterior use */
+ priv->hwif_quirks = entry->quirks;
return 0;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 025efbf..76649ad 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -129,6 +129,7 @@ struct stmmac_priv {
struct net_device *dev;
struct device *device;
struct mac_device_info *hw;
+ int (*hwif_quirks)(struct stmmac_priv *priv);
struct mutex lock;
/* RX Queue */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 11fb7c7..cba46b6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -928,6 +928,7 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
static int stmmac_init_phy(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
+ u32 tx_cnt = priv->plat->tx_queues_to_use;
struct phy_device *phydev;
char phy_id_fmt[MII_BUS_ID_SIZE + 3];
char bus_id[MII_BUS_ID_SIZE];
@@ -969,6 +970,15 @@ static int stmmac_init_phy(struct net_device *dev)
SUPPORTED_1000baseT_Full);
/*
+ * Half-duplex mode not supported with multiqueue
+ * half-duplex can only works with single queue
+ */
+ if (tx_cnt > 1)
+ phydev->supported &= ~(SUPPORTED_1000baseT_Half |
+ SUPPORTED_100baseT_Half |
+ SUPPORTED_10baseT_Half);
+
+ /*
* Broken HW is sometimes missing the pull-up resistor on the
* MDIO line, which results in reads to non-existent devices returning
* 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
@@ -3182,17 +3192,22 @@ dma_map_err:
static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
{
- struct ethhdr *ehdr;
+ struct vlan_ethhdr *veth;
+ __be16 vlan_proto;
u16 vlanid;
- if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
- NETIF_F_HW_VLAN_CTAG_RX &&
- !__vlan_get_tag(skb, &vlanid)) {
+ veth = (struct vlan_ethhdr *)skb->data;
+ vlan_proto = veth->h_vlan_proto;
+
+ if ((vlan_proto == htons(ETH_P_8021Q) &&
+ dev->features & NETIF_F_HW_VLAN_CTAG_RX) ||
+ (vlan_proto == htons(ETH_P_8021AD) &&
+ dev->features & NETIF_F_HW_VLAN_STAG_RX)) {
/* pop the vlan tag */
- ehdr = (struct ethhdr *)skb->data;
- memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
+ vlanid = ntohs(veth->h_vlan_TCI);
+ memmove(skb->data + VLAN_HLEN, veth, ETH_ALEN * 2);
skb_pull(skb, VLAN_HLEN);
- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
+ __vlan_hwaccel_put_tag(skb, vlan_proto, vlanid);
}
}
@@ -4130,6 +4145,13 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
if (priv->dma_cap.tsoen)
dev_info(priv->device, "TSO supported\n");
+ /* Run HW quirks, if any */
+ if (priv->hwif_quirks) {
+ ret = priv->hwif_quirks(priv);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
@@ -4235,7 +4257,7 @@ int stmmac_dvr_probe(struct device *device,
ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
#ifdef STMMAC_VLAN_TAG_USED
/* Both mac100 and gmac support receive VLAN tag detection */
- ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
+ ndev->features |= NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX;
#endif
priv->msg_enable = netif_msg_init(debug, default_msg_level);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 881c94b..2258cd8 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -277,8 +277,8 @@ static int tc_init(struct stmmac_priv *priv)
/* Reserve one last filter which lets all pass */
priv->tc_entries_max = count;
- priv->tc_entries = devm_kzalloc(priv->device,
- sizeof(*priv->tc_entries) * count, GFP_KERNEL);
+ priv->tc_entries = devm_kcalloc(priv->device,
+ count, sizeof(*priv->tc_entries), GFP_KERNEL);
if (!priv->tc_entries)
return -ENOMEM;
diff --git a/drivers/net/ethernet/sun/sungem.c b/drivers/net/ethernet/sun/sungem.c
index 7a16d40..b9221fc 100644
--- a/drivers/net/ethernet/sun/sungem.c
+++ b/drivers/net/ethernet/sun/sungem.c
@@ -60,8 +60,7 @@
#include <linux/sungem_phy.h>
#include "sungem.h"
-/* Stripping FCS is causing problems, disabled for now */
-#undef STRIP_FCS
+#define STRIP_FCS
#define DEFAULT_MSG (NETIF_MSG_DRV | \
NETIF_MSG_PROBE | \
@@ -435,7 +434,7 @@ static int gem_rxmac_reset(struct gem *gp)
writel(desc_dma & 0xffffffff, gp->regs + RXDMA_DBLOW);
writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK);
val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) |
- ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_128);
+ (ETH_HLEN << 13) | RXDMA_CFG_FTHRESH_128);
writel(val, gp->regs + RXDMA_CFG);
if (readl(gp->regs + GREG_BIFCFG) & GREG_BIFCFG_M66EN)
writel(((5 & RXDMA_BLANK_IPKTS) |
@@ -760,7 +759,6 @@ static int gem_rx(struct gem *gp, int work_to_do)
struct net_device *dev = gp->dev;
int entry, drops, work_done = 0;
u32 done;
- __sum16 csum;
if (netif_msg_rx_status(gp))
printk(KERN_DEBUG "%s: rx interrupt, done: %d, rx_new: %d\n",
@@ -855,9 +853,13 @@ static int gem_rx(struct gem *gp, int work_to_do)
skb = copy_skb;
}
- csum = (__force __sum16)htons((status & RXDCTRL_TCPCSUM) ^ 0xffff);
- skb->csum = csum_unfold(csum);
- skb->ip_summed = CHECKSUM_COMPLETE;
+ if (likely(dev->features & NETIF_F_RXCSUM)) {
+ __sum16 csum;
+
+ csum = (__force __sum16)htons((status & RXDCTRL_TCPCSUM) ^ 0xffff);
+ skb->csum = csum_unfold(csum);
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ }
skb->protocol = eth_type_trans(skb, gp->dev);
napi_gro_receive(&gp->napi, skb);
@@ -1761,7 +1763,7 @@ static void gem_init_dma(struct gem *gp)
writel(0, gp->regs + TXDMA_KICK);
val = (RXDMA_CFG_BASE | (RX_OFFSET << 10) |
- ((14 / 2) << 13) | RXDMA_CFG_FTHRESH_128);
+ (ETH_HLEN << 13) | RXDMA_CFG_FTHRESH_128);
writel(val, gp->regs + RXDMA_CFG);
writel(desc_dma >> 32, gp->regs + RXDMA_DBHI);
@@ -2985,8 +2987,8 @@ static int gem_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev);
/* We can do scatter/gather and HW checksum */
- dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM;
- dev->features |= dev->hw_features | NETIF_F_RXCSUM;
+ dev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
+ dev->features = dev->hw_features;
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 534596c..358edab 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -2740,8 +2740,9 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
}
data->active_slave = prop;
- data->slave_data = devm_kzalloc(&pdev->dev, data->slaves
- * sizeof(struct cpsw_slave_data),
+ data->slave_data = devm_kcalloc(&pdev->dev,
+ data->slaves,
+ sizeof(struct cpsw_slave_data),
GFP_KERNEL);
if (!data->slave_data)
return -ENOMEM;
@@ -3045,8 +3046,8 @@ static int cpsw_probe(struct platform_device *pdev)
memcpy(ndev->dev_addr, priv->mac_addr, ETH_ALEN);
- cpsw->slaves = devm_kzalloc(&pdev->dev,
- sizeof(struct cpsw_slave) * data->slaves,
+ cpsw->slaves = devm_kcalloc(&pdev->dev,
+ data->slaves, sizeof(struct cpsw_slave),
GFP_KERNEL);
if (!cpsw->slaves) {
ret = -ENOMEM;
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 06d7c9e..a1a6445 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -1385,6 +1385,11 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd)
return -EOPNOTSUPP;
}
+static int match_first_device(struct device *dev, void *data)
+{
+ return !strncmp(dev_name(dev), "davinci_mdio", 12);
+}
+
/**
* emac_dev_open - EMAC device open
* @ndev: The DaVinci EMAC network adapter
@@ -1484,8 +1489,14 @@ static int emac_dev_open(struct net_device *ndev)
/* use the first phy on the bus if pdata did not give us a phy id */
if (!phydev && !priv->phy_id) {
- phy = bus_find_device_by_name(&mdio_bus_type, NULL,
- "davinci_mdio");
+ /* NOTE: we can't use bus_find_device_by_name() here because
+ * the device name is not guaranteed to be 'davinci_mdio'. On
+ * some systems it can be 'davinci_mdio.0' so we need to use
+ * strncmp() against the first part of the string to correctly
+ * match it.
+ */
+ phy = bus_find_device(&mdio_bus_type, NULL, NULL,
+ match_first_device);
if (phy) {
priv->phy_id = dev_name(phy);
if (!priv->phy_id || !*priv->phy_id)
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c
index 6e455a2..72b98e2 100644
--- a/drivers/net/ethernet/ti/netcp_ethss.c
+++ b/drivers/net/ethernet/ti/netcp_ethss.c
@@ -3285,8 +3285,8 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev,
gbe_dev->et_stats = xgbe10_et_stats;
gbe_dev->num_et_stats = ARRAY_SIZE(xgbe10_et_stats);
- gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev,
- gbe_dev->num_et_stats * sizeof(u64),
+ gbe_dev->hw_stats = devm_kcalloc(gbe_dev->dev,
+ gbe_dev->num_et_stats, sizeof(u64),
GFP_KERNEL);
if (!gbe_dev->hw_stats) {
dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n");
@@ -3294,8 +3294,8 @@ static int set_xgbe_ethss10_priv(struct gbe_priv *gbe_dev,
}
gbe_dev->hw_stats_prev =
- devm_kzalloc(gbe_dev->dev,
- gbe_dev->num_et_stats * sizeof(u32),
+ devm_kcalloc(gbe_dev->dev,
+ gbe_dev->num_et_stats, sizeof(u32),
GFP_KERNEL);
if (!gbe_dev->hw_stats_prev) {
dev_err(gbe_dev->dev,
@@ -3405,8 +3405,8 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev,
gbe_dev->et_stats = gbe13_et_stats;
gbe_dev->num_et_stats = ARRAY_SIZE(gbe13_et_stats);
- gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev,
- gbe_dev->num_et_stats * sizeof(u64),
+ gbe_dev->hw_stats = devm_kcalloc(gbe_dev->dev,
+ gbe_dev->num_et_stats, sizeof(u64),
GFP_KERNEL);
if (!gbe_dev->hw_stats) {
dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n");
@@ -3414,8 +3414,8 @@ static int set_gbe_ethss14_priv(struct gbe_priv *gbe_dev,
}
gbe_dev->hw_stats_prev =
- devm_kzalloc(gbe_dev->dev,
- gbe_dev->num_et_stats * sizeof(u32),
+ devm_kcalloc(gbe_dev->dev,
+ gbe_dev->num_et_stats, sizeof(u32),
GFP_KERNEL);
if (!gbe_dev->hw_stats_prev) {
dev_err(gbe_dev->dev,
@@ -3477,8 +3477,8 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev,
gbe_dev->num_et_stats = GBENU_ET_STATS_HOST_SIZE +
GBENU_ET_STATS_PORT_SIZE;
- gbe_dev->hw_stats = devm_kzalloc(gbe_dev->dev,
- gbe_dev->num_et_stats * sizeof(u64),
+ gbe_dev->hw_stats = devm_kcalloc(gbe_dev->dev,
+ gbe_dev->num_et_stats, sizeof(u64),
GFP_KERNEL);
if (!gbe_dev->hw_stats) {
dev_err(gbe_dev->dev, "hw_stats memory allocation failed\n");
@@ -3486,8 +3486,8 @@ static int set_gbenu_ethss_priv(struct gbe_priv *gbe_dev,
}
gbe_dev->hw_stats_prev =
- devm_kzalloc(gbe_dev->dev,
- gbe_dev->num_et_stats * sizeof(u32),
+ devm_kcalloc(gbe_dev->dev,
+ gbe_dev->num_et_stats, sizeof(u32),
GFP_KERNEL);
if (!gbe_dev->hw_stats_prev) {
dev_err(gbe_dev->dev,
diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
index eed18f8..302079e 100644
--- a/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
+++ b/drivers/net/ethernet/toshiba/ps3_gelic_wireless.c
@@ -2320,8 +2320,9 @@ static struct net_device *gelic_wl_alloc(struct gelic_card *card)
pr_debug("%s: wl=%p port=%p\n", __func__, wl, port);
/* allocate scan list */
- wl->networks = kzalloc(sizeof(struct gelic_wl_scan_info) *
- GELIC_WL_BSS_MAX_ENT, GFP_KERNEL);
+ wl->networks = kcalloc(GELIC_WL_BSS_MAX_ENT,
+ sizeof(struct gelic_wl_scan_info),
+ GFP_KERNEL);
if (!wl->networks)
goto fail_bss;
diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
index 69e31ce..2a0c06e 100644
--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c
+++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c
@@ -123,7 +123,6 @@
* @phy_node: pointer to the PHY device node
* @mii_bus: pointer to the MII bus
* @last_link: last link status
- * @has_mdio: indicates whether MDIO is included in the HW
*/
struct net_local {
@@ -144,7 +143,6 @@ struct net_local {
struct mii_bus *mii_bus;
int last_link;
- bool has_mdio;
};
@@ -863,14 +861,14 @@ static int xemaclite_mdio_setup(struct net_local *lp, struct device *dev)
bus->write = xemaclite_mdio_write;
bus->parent = dev;
- lp->mii_bus = bus;
-
rc = of_mdiobus_register(bus, np);
if (rc) {
dev_err(dev, "Failed to register mdio bus.\n");
goto err_register;
}
+ lp->mii_bus = bus;
+
return 0;
err_register:
@@ -1145,9 +1143,7 @@ static int xemaclite_of_probe(struct platform_device *ofdev)
xemaclite_update_address(lp, ndev->dev_addr);
lp->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0);
- rc = xemaclite_mdio_setup(lp, &ofdev->dev);
- if (rc)
- dev_warn(&ofdev->dev, "error registering MDIO bus\n");
+ xemaclite_mdio_setup(lp, &ofdev->dev);
dev_info(dev, "MAC address is now %pM\n", ndev->dev_addr);
@@ -1191,7 +1187,7 @@ static int xemaclite_of_remove(struct platform_device *of_dev)
struct net_local *lp = netdev_priv(ndev);
/* Un-register the mii_bus, if configured */
- if (lp->has_mdio) {
+ if (lp->mii_bus) {
mdiobus_unregister(lp->mii_bus);
mdiobus_free(lp->mii_bus);
lp->mii_bus = NULL;
diff --git a/drivers/net/fddi/skfp/skfddi.c b/drivers/net/fddi/skfp/skfddi.c
index 2414f1d..72433f3e 100644
--- a/drivers/net/fddi/skfp/skfddi.c
+++ b/drivers/net/fddi/skfp/skfddi.c
@@ -297,11 +297,11 @@ static int skfp_init_one(struct pci_dev *pdev,
return 0;
err_out5:
if (smc->os.SharedMemAddr)
- pci_free_consistent(pdev, smc->os.SharedMemSize,
- smc->os.SharedMemAddr,
- smc->os.SharedMemDMA);
- pci_free_consistent(pdev, MAX_FRAME_SIZE,
- smc->os.LocalRxBuffer, smc->os.LocalRxBufferDMA);
+ dma_free_coherent(&pdev->dev, smc->os.SharedMemSize,
+ smc->os.SharedMemAddr,
+ smc->os.SharedMemDMA);
+ dma_free_coherent(&pdev->dev, MAX_FRAME_SIZE,
+ smc->os.LocalRxBuffer, smc->os.LocalRxBufferDMA);
err_out4:
free_netdev(dev);
err_out3:
@@ -328,17 +328,17 @@ static void skfp_remove_one(struct pci_dev *pdev)
unregister_netdev(p);
if (lp->os.SharedMemAddr) {
- pci_free_consistent(&lp->os.pdev,
- lp->os.SharedMemSize,
- lp->os.SharedMemAddr,
- lp->os.SharedMemDMA);
+ dma_free_coherent(&pdev->dev,
+ lp->os.SharedMemSize,
+ lp->os.SharedMemAddr,
+ lp->os.SharedMemDMA);
lp->os.SharedMemAddr = NULL;
}
if (lp->os.LocalRxBuffer) {
- pci_free_consistent(&lp->os.pdev,
- MAX_FRAME_SIZE,
- lp->os.LocalRxBuffer,
- lp->os.LocalRxBufferDMA);
+ dma_free_coherent(&pdev->dev,
+ MAX_FRAME_SIZE,
+ lp->os.LocalRxBuffer,
+ lp->os.LocalRxBufferDMA);
lp->os.LocalRxBuffer = NULL;
}
#ifdef MEM_MAPPED_IO
@@ -394,7 +394,9 @@ static int skfp_driver_init(struct net_device *dev)
spin_lock_init(&bp->DriverLock);
// Allocate invalid frame
- bp->LocalRxBuffer = pci_alloc_consistent(&bp->pdev, MAX_FRAME_SIZE, &bp->LocalRxBufferDMA);
+ bp->LocalRxBuffer = dma_alloc_coherent(&bp->pdev.dev, MAX_FRAME_SIZE,
+ &bp->LocalRxBufferDMA,
+ GFP_ATOMIC);
if (!bp->LocalRxBuffer) {
printk("could not allocate mem for ");
printk("LocalRxBuffer: %d byte\n", MAX_FRAME_SIZE);
@@ -407,23 +409,22 @@ static int skfp_driver_init(struct net_device *dev)
if (bp->SharedMemSize > 0) {
bp->SharedMemSize += 16; // for descriptor alignment
- bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
- bp->SharedMemSize,
- &bp->SharedMemDMA);
+ bp->SharedMemAddr = dma_zalloc_coherent(&bp->pdev.dev,
+ bp->SharedMemSize,
+ &bp->SharedMemDMA,
+ GFP_ATOMIC);
if (!bp->SharedMemAddr) {
printk("could not allocate mem for ");
printk("hardware module: %ld byte\n",
bp->SharedMemSize);
goto fail;
}
- bp->SharedMemHeap = 0; // Nothing used yet.
} else {
bp->SharedMemAddr = NULL;
- bp->SharedMemHeap = 0;
- } // SharedMemSize > 0
+ }
- memset(bp->SharedMemAddr, 0, bp->SharedMemSize);
+ bp->SharedMemHeap = 0;
card_stop(smc); // Reset adapter.
@@ -442,15 +443,15 @@ static int skfp_driver_init(struct net_device *dev)
fail:
if (bp->SharedMemAddr) {
- pci_free_consistent(&bp->pdev,
- bp->SharedMemSize,
- bp->SharedMemAddr,
- bp->SharedMemDMA);
+ dma_free_coherent(&bp->pdev.dev,
+ bp->SharedMemSize,
+ bp->SharedMemAddr,
+ bp->SharedMemDMA);
bp->SharedMemAddr = NULL;
}
if (bp->LocalRxBuffer) {
- pci_free_consistent(&bp->pdev, MAX_FRAME_SIZE,
- bp->LocalRxBuffer, bp->LocalRxBufferDMA);
+ dma_free_coherent(&bp->pdev.dev, MAX_FRAME_SIZE,
+ bp->LocalRxBuffer, bp->LocalRxBufferDMA);
bp->LocalRxBuffer = NULL;
}
return err;
diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
index f38e32a..ec629a7 100644
--- a/drivers/net/gtp.c
+++ b/drivers/net/gtp.c
@@ -742,11 +742,13 @@ static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize)
{
int i;
- gtp->addr_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL);
+ gtp->addr_hash = kmalloc_array(hsize, sizeof(struct hlist_head),
+ GFP_KERNEL);
if (gtp->addr_hash == NULL)
return -ENOMEM;
- gtp->tid_hash = kmalloc(sizeof(struct hlist_head) * hsize, GFP_KERNEL);
+ gtp->tid_hash = kmalloc_array(hsize, sizeof(struct hlist_head),
+ GFP_KERNEL);
if (gtp->tid_hash == NULL)
goto err1;
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index f347fd9..777fa59 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -89,10 +89,6 @@
static const char banner[] __initconst = KERN_INFO \
"AX.25: bpqether driver version 004\n";
-static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
-
-static char bpq_eth_addr[6];
-
static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *);
static int bpq_device_event(struct notifier_block *, unsigned long, void *);
@@ -501,8 +497,8 @@ static int bpq_new_device(struct net_device *edev)
bpq->ethdev = edev;
bpq->axdev = ndev;
- memcpy(bpq->dest_addr, bcast_addr, sizeof(bpq_eth_addr));
- memcpy(bpq->acpt_addr, bcast_addr, sizeof(bpq_eth_addr));
+ eth_broadcast_addr(bpq->dest_addr);
+ eth_broadcast_addr(bpq->acpt_addr);
err = register_netdevice(ndev);
if (err)
diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c
index f411164..029206e4 100644
--- a/drivers/net/hippi/rrunner.c
+++ b/drivers/net/hippi/rrunner.c
@@ -1583,7 +1583,7 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return -EPERM;
}
- image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
+ image = kmalloc_array(EEPROM_WORDS, sizeof(u32), GFP_KERNEL);
if (!image)
return -ENOMEM;
diff --git a/drivers/net/hyperv/Kconfig b/drivers/net/hyperv/Kconfig
index 23a2d14..0765d5f 100644
--- a/drivers/net/hyperv/Kconfig
+++ b/drivers/net/hyperv/Kconfig
@@ -2,6 +2,5 @@ config HYPERV_NET
tristate "Microsoft Hyper-V virtual network driver"
depends on HYPERV
select UCS2_STRING
- select FAILOVER
help
Select this option to enable the Hyper-V virtual network driver.
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 99d8e73..1a924b8 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -189,7 +189,6 @@ struct netvsc_device;
struct net_device_context;
extern u32 netvsc_ring_bytes;
-extern struct reciprocal_value netvsc_ring_reciprocal;
struct netvsc_device *netvsc_device_add(struct hv_device *device,
const struct netvsc_device_info *info);
@@ -902,6 +901,8 @@ struct net_device_context {
struct hv_device *device_ctx;
/* netvsc_device */
struct netvsc_device __rcu *nvdev;
+ /* list of netvsc net_devices */
+ struct list_head list;
/* reconfigure work */
struct delayed_work dwork;
/* last reconfig time */
@@ -932,8 +933,6 @@ struct net_device_context {
u32 vf_alloc;
/* Serial number of the VF to team with */
u32 vf_serial;
-
- struct failover *failover;
};
/* Per channel data */
@@ -1278,17 +1277,17 @@ struct ndis_lsov2_offload {
struct ndis_ipsecv2_offload {
u32 encap;
- u16 ip6;
- u16 ip4opt;
- u16 ip6ext;
- u16 ah;
- u16 esp;
- u16 ah_esp;
- u16 xport;
- u16 tun;
- u16 xport_tun;
- u16 lso;
- u16 extseq;
+ u8 ip6;
+ u8 ip4opt;
+ u8 ip6ext;
+ u8 ah;
+ u8 esp;
+ u8 ah_esp;
+ u8 xport;
+ u8 tun;
+ u8 xport_tun;
+ u8 lso;
+ u8 extseq;
u32 udp_esp;
u32 auth;
u32 crypto;
@@ -1296,8 +1295,8 @@ struct ndis_ipsecv2_offload {
};
struct ndis_rsc_offload {
- u16 ip4;
- u16 ip6;
+ u8 ip4;
+ u8 ip6;
};
struct ndis_encap_offload {
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index d2ee66c2..5d5bd51 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -31,7 +31,6 @@
#include <linux/vmalloc.h>
#include <linux/rtnetlink.h>
#include <linux/prefetch.h>
-#include <linux/reciprocal_div.h>
#include <asm/sync_bitops.h>
@@ -635,17 +634,6 @@ void netvsc_device_remove(struct hv_device *device)
#define RING_AVAIL_PERCENT_HIWATER 20
#define RING_AVAIL_PERCENT_LOWATER 10
-/*
- * Get the percentage of available bytes to write in the ring.
- * The return value is in range from 0 to 100.
- */
-static u32 hv_ringbuf_avail_percent(const struct hv_ring_buffer_info *ring_info)
-{
- u32 avail_write = hv_get_bytes_to_write(ring_info);
-
- return reciprocal_divide(avail_write * 100, netvsc_ring_reciprocal);
-}
-
static inline void netvsc_free_send_slot(struct netvsc_device *net_device,
u32 index)
{
@@ -694,8 +682,8 @@ static void netvsc_send_tx_complete(struct net_device *ndev,
struct netdev_queue *txq = netdev_get_tx_queue(ndev, q_idx);
if (netif_tx_queue_stopped(txq) &&
- (hv_ringbuf_avail_percent(&channel->outbound) > RING_AVAIL_PERCENT_HIWATER ||
- queue_sends < 1)) {
+ (hv_get_avail_to_write_percent(&channel->outbound) >
+ RING_AVAIL_PERCENT_HIWATER || queue_sends < 1)) {
netif_tx_wake_queue(txq);
ndev_ctx->eth_stats.wake_queue++;
}
@@ -802,7 +790,7 @@ static inline int netvsc_send_pkt(
struct netdev_queue *txq = netdev_get_tx_queue(ndev, packet->q_idx);
u64 req_id;
int ret;
- u32 ring_avail = hv_ringbuf_avail_percent(&out_channel->outbound);
+ u32 ring_avail = hv_get_avail_to_write_percent(&out_channel->outbound);
nvmsg.hdr.msg_type = NVSP_MSG1_TYPE_SEND_RNDIS_PKT;
if (skb)
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index bef4d55..fe2256b 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -35,7 +35,6 @@
#include <linux/slab.h>
#include <linux/rtnetlink.h>
#include <linux/netpoll.h>
-#include <linux/reciprocal_div.h>
#include <net/arp.h>
#include <net/route.h>
@@ -43,7 +42,6 @@
#include <net/pkt_sched.h>
#include <net/checksum.h>
#include <net/ip6_checksum.h>
-#include <net/failover.h>
#include "hyperv_net.h"
@@ -59,7 +57,6 @@ static unsigned int ring_size __ro_after_init = 128;
module_param(ring_size, uint, 0444);
MODULE_PARM_DESC(ring_size, "Ring buffer size (# of pages)");
unsigned int netvsc_ring_bytes __ro_after_init;
-struct reciprocal_value netvsc_ring_reciprocal __ro_after_init;
static const u32 default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE |
NETIF_MSG_LINK | NETIF_MSG_IFUP |
@@ -70,6 +67,8 @@ static int debug = -1;
module_param(debug, int, 0444);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+static LIST_HEAD(netvsc_dev_list);
+
static void netvsc_change_rx_flags(struct net_device *net, int change)
{
struct net_device_context *ndev_ctx = netdev_priv(net);
@@ -127,8 +126,10 @@ static int netvsc_open(struct net_device *net)
}
rdev = nvdev->extension;
- if (!rdev->link_state)
+ if (!rdev->link_state) {
netif_carrier_on(net);
+ netif_tx_wake_all_queues(net);
+ }
if (vf_netdev) {
/* Setting synthetic device up transparently sets
@@ -1780,6 +1781,36 @@ out_unlock:
rtnl_unlock();
}
+static struct net_device *get_netvsc_bymac(const u8 *mac)
+{
+ struct net_device_context *ndev_ctx;
+
+ list_for_each_entry(ndev_ctx, &netvsc_dev_list, list) {
+ struct net_device *dev = hv_get_drvdata(ndev_ctx->device_ctx);
+
+ if (ether_addr_equal(mac, dev->perm_addr))
+ return dev;
+ }
+
+ return NULL;
+}
+
+static struct net_device *get_netvsc_byref(struct net_device *vf_netdev)
+{
+ struct net_device_context *net_device_ctx;
+ struct net_device *dev;
+
+ dev = netdev_master_upper_dev_get(vf_netdev);
+ if (!dev || dev->netdev_ops != &device_ops)
+ return NULL; /* not a netvsc device */
+
+ net_device_ctx = netdev_priv(dev);
+ if (!rtnl_dereference(net_device_ctx->nvdev))
+ return NULL; /* device is removed */
+
+ return dev;
+}
+
/* Called when VF is injecting data into network stack.
* Change the associated network device from VF to netvsc.
* note: already called with rcu_read_lock
@@ -1802,6 +1833,46 @@ static rx_handler_result_t netvsc_vf_handle_frame(struct sk_buff **pskb)
return RX_HANDLER_ANOTHER;
}
+static int netvsc_vf_join(struct net_device *vf_netdev,
+ struct net_device *ndev)
+{
+ struct net_device_context *ndev_ctx = netdev_priv(ndev);
+ int ret;
+
+ ret = netdev_rx_handler_register(vf_netdev,
+ netvsc_vf_handle_frame, ndev);
+ if (ret != 0) {
+ netdev_err(vf_netdev,
+ "can not register netvsc VF receive handler (err = %d)\n",
+ ret);
+ goto rx_handler_failed;
+ }
+
+ ret = netdev_master_upper_dev_link(vf_netdev, ndev,
+ NULL, NULL, NULL);
+ if (ret != 0) {
+ netdev_err(vf_netdev,
+ "can not set master device %s (err = %d)\n",
+ ndev->name, ret);
+ goto upper_link_failed;
+ }
+
+ /* set slave flag before open to prevent IPv6 addrconf */
+ vf_netdev->flags |= IFF_SLAVE;
+
+ schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
+
+ call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
+
+ netdev_info(vf_netdev, "joined to %s\n", ndev->name);
+ return 0;
+
+upper_link_failed:
+ netdev_rx_handler_unregister(vf_netdev);
+rx_handler_failed:
+ return ret;
+}
+
static void __netvsc_vf_setup(struct net_device *ndev,
struct net_device *vf_netdev)
{
@@ -1852,95 +1923,104 @@ static void netvsc_vf_setup(struct work_struct *w)
rtnl_unlock();
}
-static int netvsc_pre_register_vf(struct net_device *vf_netdev,
- struct net_device *ndev)
+static int netvsc_register_vf(struct net_device *vf_netdev)
{
+ struct net_device *ndev;
struct net_device_context *net_device_ctx;
struct netvsc_device *netvsc_dev;
+ int ret;
+
+ if (vf_netdev->addr_len != ETH_ALEN)
+ return NOTIFY_DONE;
+
+ /*
+ * We will use the MAC address to locate the synthetic interface to
+ * associate with the VF interface. If we don't find a matching
+ * synthetic interface, move on.
+ */
+ ndev = get_netvsc_bymac(vf_netdev->perm_addr);
+ if (!ndev)
+ return NOTIFY_DONE;
net_device_ctx = netdev_priv(ndev);
netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
- return -ENODEV;
-
- return 0;
-}
+ return NOTIFY_DONE;
-static int netvsc_register_vf(struct net_device *vf_netdev,
- struct net_device *ndev)
-{
- struct net_device_context *ndev_ctx = netdev_priv(ndev);
-
- /* set slave flag before open to prevent IPv6 addrconf */
- vf_netdev->flags |= IFF_SLAVE;
-
- schedule_delayed_work(&ndev_ctx->vf_takeover, VF_TAKEOVER_INT);
+ /* if syntihetic interface is a different namespace,
+ * then move the VF to that namespace; join will be
+ * done again in that context.
+ */
+ if (!net_eq(dev_net(ndev), dev_net(vf_netdev))) {
+ ret = dev_change_net_namespace(vf_netdev,
+ dev_net(ndev), "eth%d");
+ if (ret)
+ netdev_err(vf_netdev,
+ "could not move to same namespace as %s: %d\n",
+ ndev->name, ret);
+ else
+ netdev_info(vf_netdev,
+ "VF moved to namespace with: %s\n",
+ ndev->name);
+ return NOTIFY_DONE;
+ }
- call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
+ netdev_info(ndev, "VF registering: %s\n", vf_netdev->name);
- netdev_info(vf_netdev, "joined to %s\n", ndev->name);
+ if (netvsc_vf_join(vf_netdev, ndev) != 0)
+ return NOTIFY_DONE;
dev_hold(vf_netdev);
- rcu_assign_pointer(ndev_ctx->vf_netdev, vf_netdev);
-
- return 0;
+ rcu_assign_pointer(net_device_ctx->vf_netdev, vf_netdev);
+ return NOTIFY_OK;
}
/* VF up/down change detected, schedule to change data path */
-static int netvsc_vf_changed(struct net_device *vf_netdev,
- struct net_device *ndev)
+static int netvsc_vf_changed(struct net_device *vf_netdev)
{
struct net_device_context *net_device_ctx;
struct netvsc_device *netvsc_dev;
+ struct net_device *ndev;
bool vf_is_up = netif_running(vf_netdev);
+ ndev = get_netvsc_byref(vf_netdev);
+ if (!ndev)
+ return NOTIFY_DONE;
+
net_device_ctx = netdev_priv(ndev);
netvsc_dev = rtnl_dereference(net_device_ctx->nvdev);
if (!netvsc_dev)
- return -ENODEV;
+ return NOTIFY_DONE;
netvsc_switch_datapath(ndev, vf_is_up);
netdev_info(ndev, "Data path switched %s VF: %s\n",
vf_is_up ? "to" : "from", vf_netdev->name);
- return 0;
+ return NOTIFY_OK;
}
-static int netvsc_pre_unregister_vf(struct net_device *vf_netdev,
- struct net_device *ndev)
+static int netvsc_unregister_vf(struct net_device *vf_netdev)
{
+ struct net_device *ndev;
struct net_device_context *net_device_ctx;
- net_device_ctx = netdev_priv(ndev);
- cancel_delayed_work_sync(&net_device_ctx->vf_takeover);
-
- return 0;
-}
-
-static int netvsc_unregister_vf(struct net_device *vf_netdev,
- struct net_device *ndev)
-{
- struct net_device_context *net_device_ctx;
+ ndev = get_netvsc_byref(vf_netdev);
+ if (!ndev)
+ return NOTIFY_DONE;
net_device_ctx = netdev_priv(ndev);
+ cancel_delayed_work_sync(&net_device_ctx->vf_takeover);
netdev_info(ndev, "VF unregistering: %s\n", vf_netdev->name);
+ netdev_rx_handler_unregister(vf_netdev);
+ netdev_upper_dev_unlink(vf_netdev, ndev);
RCU_INIT_POINTER(net_device_ctx->vf_netdev, NULL);
dev_put(vf_netdev);
- return 0;
+ return NOTIFY_OK;
}
-static struct failover_ops netvsc_failover_ops = {
- .slave_pre_register = netvsc_pre_register_vf,
- .slave_register = netvsc_register_vf,
- .slave_pre_unregister = netvsc_pre_unregister_vf,
- .slave_unregister = netvsc_unregister_vf,
- .slave_link_change = netvsc_vf_changed,
- .slave_handle_frame = netvsc_vf_handle_frame,
-};
-
static int netvsc_probe(struct hv_device *dev,
const struct hv_vmbus_device_id *dev_id)
{
@@ -2024,23 +2104,19 @@ static int netvsc_probe(struct hv_device *dev,
else
net->max_mtu = ETH_DATA_LEN;
- ret = register_netdev(net);
+ rtnl_lock();
+ ret = register_netdevice(net);
if (ret != 0) {
pr_err("Unable to register netdev.\n");
goto register_failed;
}
- net_device_ctx->failover = failover_register(net, &netvsc_failover_ops);
- if (IS_ERR(net_device_ctx->failover)) {
- ret = PTR_ERR(net_device_ctx->failover);
- goto err_failover;
- }
-
- return ret;
+ list_add(&net_device_ctx->list, &netvsc_dev_list);
+ rtnl_unlock();
+ return 0;
-err_failover:
- unregister_netdev(net);
register_failed:
+ rtnl_unlock();
rndis_filter_device_remove(dev, nvdev);
rndis_failed:
free_percpu(net_device_ctx->vf_stats);
@@ -2080,14 +2156,13 @@ static int netvsc_remove(struct hv_device *dev)
rtnl_lock();
vf_netdev = rtnl_dereference(ndev_ctx->vf_netdev);
if (vf_netdev)
- failover_slave_unregister(vf_netdev);
+ netvsc_unregister_vf(vf_netdev);
if (nvdev)
rndis_filter_device_remove(dev, nvdev);
unregister_netdevice(net);
-
- failover_unregister(ndev_ctx->failover);
+ list_del(&ndev_ctx->list);
rtnl_unlock();
rcu_read_unlock();
@@ -2115,8 +2190,54 @@ static struct hv_driver netvsc_drv = {
.remove = netvsc_remove,
};
+/*
+ * On Hyper-V, every VF interface is matched with a corresponding
+ * synthetic interface. The synthetic interface is presented first
+ * to the guest. When the corresponding VF instance is registered,
+ * we will take care of switching the data path.
+ */
+static int netvsc_netdev_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
+
+ /* Skip our own events */
+ if (event_dev->netdev_ops == &device_ops)
+ return NOTIFY_DONE;
+
+ /* Avoid non-Ethernet type devices */
+ if (event_dev->type != ARPHRD_ETHER)
+ return NOTIFY_DONE;
+
+ /* Avoid Vlan dev with same MAC registering as VF */
+ if (is_vlan_dev(event_dev))
+ return NOTIFY_DONE;
+
+ /* Avoid Bonding master dev with same MAC registering as VF */
+ if ((event_dev->priv_flags & IFF_BONDING) &&
+ (event_dev->flags & IFF_MASTER))
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ return netvsc_register_vf(event_dev);
+ case NETDEV_UNREGISTER:
+ return netvsc_unregister_vf(event_dev);
+ case NETDEV_UP:
+ case NETDEV_DOWN:
+ return netvsc_vf_changed(event_dev);
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct notifier_block netvsc_netdev_notifier = {
+ .notifier_call = netvsc_netdev_event,
+};
+
static void __exit netvsc_drv_exit(void)
{
+ unregister_netdevice_notifier(&netvsc_netdev_notifier);
vmbus_driver_unregister(&netvsc_drv);
}
@@ -2130,12 +2251,12 @@ static int __init netvsc_drv_init(void)
ring_size);
}
netvsc_ring_bytes = ring_size * PAGE_SIZE;
- netvsc_ring_reciprocal = reciprocal_value(netvsc_ring_bytes);
ret = vmbus_driver_register(&netvsc_drv);
if (ret)
return ret;
+ register_netdevice_notifier(&netvsc_netdev_notifier);
return 0;
}
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 4377c26..d02f0a7 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -693,6 +693,7 @@ void ipvlan_link_setup(struct net_device *dev)
{
ether_setup(dev);
+ dev->max_mtu = ETH_MAX_MTU;
dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE;
dev->netdev_ops = &ipvlan_netdev_ops;
diff --git a/drivers/net/net_failover.c b/drivers/net/net_failover.c
index 83f7420..4f390fa 100644
--- a/drivers/net/net_failover.c
+++ b/drivers/net/net_failover.c
@@ -527,7 +527,7 @@ static int net_failover_slave_register(struct net_device *slave_dev,
netif_addr_lock_bh(failover_dev);
dev_uc_sync_multiple(slave_dev, failover_dev);
- dev_uc_sync_multiple(slave_dev, failover_dev);
+ dev_mc_sync_multiple(slave_dev, failover_dev);
netif_addr_unlock_bh(failover_dev);
err = vlan_vids_add_by_dev(slave_dev, failover_dev);
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index a6c8779..79e9b10 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -1097,8 +1097,9 @@ static struct dp83640_clock *dp83640_clock_get_bus(struct mii_bus *bus)
if (!clock)
goto out;
- clock->caps.pin_config = kzalloc(sizeof(struct ptp_pin_desc) *
- DP83640_N_PINS, GFP_KERNEL);
+ clock->caps.pin_config = kcalloc(DP83640_N_PINS,
+ sizeof(struct ptp_pin_desc),
+ GFP_KERNEL);
if (!clock->caps.pin_config) {
kfree(clock);
clock = NULL;
diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c
index cd09c3a..6e8e423 100644
--- a/drivers/net/phy/dp83848.c
+++ b/drivers/net/phy/dp83848.c
@@ -74,6 +74,25 @@ static int dp83848_config_intr(struct phy_device *phydev)
return phy_write(phydev, DP83848_MICR, control);
}
+static int dp83848_config_init(struct phy_device *phydev)
+{
+ int err;
+ int val;
+
+ err = genphy_config_init(phydev);
+ if (err < 0)
+ return err;
+
+ /* DP83620 always reports Auto Negotiation Ability on BMSR. Instead,
+ * we check initial value of BMCR Auto negotiation enable bit
+ */
+ val = phy_read(phydev, MII_BMCR);
+ if (!(val & BMCR_ANENABLE))
+ phydev->autoneg = AUTONEG_DISABLE;
+
+ return 0;
+}
+
static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
{ TI_DP83848C_PHY_ID, 0xfffffff0 },
{ NS_DP83848C_PHY_ID, 0xfffffff0 },
@@ -83,7 +102,7 @@ static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
};
MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
-#define DP83848_PHY_DRIVER(_id, _name) \
+#define DP83848_PHY_DRIVER(_id, _name, _config_init) \
{ \
.phy_id = _id, \
.phy_id_mask = 0xfffffff0, \
@@ -92,7 +111,7 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
.flags = PHY_HAS_INTERRUPT, \
\
.soft_reset = genphy_soft_reset, \
- .config_init = genphy_config_init, \
+ .config_init = _config_init, \
.suspend = genphy_suspend, \
.resume = genphy_resume, \
\
@@ -102,10 +121,14 @@ MODULE_DEVICE_TABLE(mdio, dp83848_tbl);
}
static struct phy_driver dp83848_driver[] = {
- DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"),
- DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY"),
- DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY"),
- DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY"),
+ DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY",
+ genphy_config_init),
+ DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY",
+ genphy_config_init),
+ DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY",
+ dp83848_config_init),
+ DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY",
+ genphy_config_init),
};
module_phy_driver(dp83848_driver);
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
index 4e4c8da..3326574 100644
--- a/drivers/net/phy/mdio-gpio.c
+++ b/drivers/net/phy/mdio-gpio.c
@@ -26,10 +26,7 @@
#include <linux/platform_device.h>
#include <linux/mdio-bitbang.h>
#include <linux/mdio-gpio.h>
-#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
-
-#include <linux/of_gpio.h>
#include <linux/of_mdio.h>
struct mdio_gpio_info {
diff --git a/drivers/net/phy/phy_led_triggers.c b/drivers/net/phy/phy_led_triggers.c
index 39ecad2..491efc1 100644
--- a/drivers/net/phy/phy_led_triggers.c
+++ b/drivers/net/phy/phy_led_triggers.c
@@ -128,9 +128,9 @@ int phy_led_triggers_register(struct phy_device *phy)
if (err)
goto out_free_link;
- phy->phy_led_triggers = devm_kzalloc(&phy->mdio.dev,
- sizeof(struct phy_led_trigger) *
- phy->phy_num_led_triggers,
+ phy->phy_led_triggers = devm_kcalloc(&phy->mdio.dev,
+ phy->phy_num_led_triggers,
+ sizeof(struct phy_led_trigger),
GFP_KERNEL);
if (!phy->phy_led_triggers) {
err = -ENOMEM;
diff --git a/drivers/net/ppp/bsd_comp.c b/drivers/net/ppp/bsd_comp.c
index a9b759a..61fedb23 100644
--- a/drivers/net/ppp/bsd_comp.c
+++ b/drivers/net/ppp/bsd_comp.c
@@ -406,7 +406,7 @@ static void *bsd_alloc (unsigned char *options, int opt_len, int decomp)
* Allocate space for the dictionary. This may be more than one page in
* length.
*/
- db->dict = vmalloc(hsize * sizeof(struct bsd_dict));
+ db->dict = vmalloc(array_size(hsize, sizeof(struct bsd_dict)));
if (!db->dict)
{
bsd_free (db);
@@ -425,7 +425,7 @@ static void *bsd_alloc (unsigned char *options, int opt_len, int decomp)
*/
else
{
- db->lens = vmalloc((maxmaxcode + 1) * sizeof(db->lens[0]));
+ db->lens = vmalloc(array_size(sizeof(db->lens[0]), (maxmaxcode + 1)));
if (!db->lens)
{
bsd_free (db);
diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c
index 157b67c..67ffe74 100644
--- a/drivers/net/ppp/pptp.c
+++ b/drivers/net/ppp/pptp.c
@@ -648,7 +648,7 @@ static int __init pptp_init_module(void)
int err = 0;
pr_info("PPTP driver version " PPTP_DRIVER_VERSION "\n");
- callid_sock = vzalloc((MAX_CALLID + 1) * sizeof(void *));
+ callid_sock = vzalloc(array_size(sizeof(void *), (MAX_CALLID + 1)));
if (!callid_sock)
return -ENOMEM;
diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c
index 8940417..b008266 100644
--- a/drivers/net/slip/slip.c
+++ b/drivers/net/slip/slip.c
@@ -1307,7 +1307,7 @@ static int __init slip_init(void)
printk(KERN_INFO "SLIP linefill/keepalive option.\n");
#endif
- slip_devs = kzalloc(sizeof(struct net_device *)*slip_maxdev,
+ slip_devs = kcalloc(slip_maxdev, sizeof(struct net_device *),
GFP_KERNEL);
if (!slip_devs)
return -ENOMEM;
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 9b6cb78..f0f7cd9 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -774,13 +774,16 @@ static ssize_t tap_put_user(struct tap_queue *q,
int total;
if (q->flags & IFF_VNET_HDR) {
+ int vlan_hlen = skb_vlan_tag_present(skb) ? VLAN_HLEN : 0;
struct virtio_net_hdr vnet_hdr;
+
vnet_hdr_len = READ_ONCE(q->vnet_hdr_sz);
if (iov_iter_count(iter) < vnet_hdr_len)
return -EINVAL;
if (virtio_net_hdr_from_skb(skb, &vnet_hdr,
- tap_is_little_endian(q), true))
+ tap_is_little_endian(q), true,
+ vlan_hlen))
BUG();
if (copy_to_iter(&vnet_hdr, sizeof(vnet_hdr), iter) !=
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 8863fa0..b070959 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -280,7 +280,7 @@ static int __team_options_register(struct team *team,
struct team_option **dst_opts;
int err;
- dst_opts = kzalloc(sizeof(struct team_option *) * option_count,
+ dst_opts = kcalloc(option_count, sizeof(struct team_option *),
GFP_KERNEL);
if (!dst_opts)
return -ENOMEM;
@@ -791,7 +791,8 @@ static int team_queue_override_init(struct team *team)
if (!queue_cnt)
return 0;
- listarr = kmalloc(sizeof(struct list_head) * queue_cnt, GFP_KERNEL);
+ listarr = kmalloc_array(queue_cnt, sizeof(struct list_head),
+ GFP_KERNEL);
if (!listarr)
return -ENOMEM;
team->qom_lists = listarr;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 85e14ad..a192a01 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -2089,7 +2089,8 @@ static ssize_t tun_put_user(struct tun_struct *tun,
return -EINVAL;
if (virtio_net_hdr_from_skb(skb, &gso,
- tun_is_little_endian(tun), true)) {
+ tun_is_little_endian(tun), true,
+ vlan_hlen)) {
struct skb_shared_info *sinfo = skb_shinfo(skb);
pr_err("unexpected GSO type: "
"0x%x, gso_size %d, hdr_len %d\n",
diff --git a/drivers/net/usb/asix_common.c b/drivers/net/usb/asix_common.c
index f4d7362..e95dd12 100644
--- a/drivers/net/usb/asix_common.c
+++ b/drivers/net/usb/asix_common.c
@@ -640,8 +640,8 @@ int asix_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
- eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
- GFP_KERNEL);
+ eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16),
+ GFP_KERNEL);
if (!eeprom_buff)
return -ENOMEM;
@@ -680,8 +680,8 @@ int asix_set_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
- eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
- GFP_KERNEL);
+ eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16),
+ GFP_KERNEL);
if (!eeprom_buff)
return -ENOMEM;
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index a6ef759..9e8ad37 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -599,8 +599,8 @@ ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom,
first_word = eeprom->offset >> 1;
last_word = (eeprom->offset + eeprom->len - 1) >> 1;
- eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1),
- GFP_KERNEL);
+ eeprom_buff = kmalloc_array(last_word - first_word + 1, sizeof(u16),
+ GFP_KERNEL);
if (!eeprom_buff)
return -ENOMEM;
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 90d07ed..1eaec64 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -967,8 +967,7 @@ void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
atomic_set(&ctx->stop, 1);
- if (hrtimer_active(&ctx->tx_timer))
- hrtimer_cancel(&ctx->tx_timer);
+ hrtimer_cancel(&ctx->tx_timer);
tasklet_kill(&ctx->bh);
@@ -1124,7 +1123,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
* accordingly. Otherwise, we should check here.
*/
if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END)
- delayed_ndp_size = ctx->max_ndp_size;
+ delayed_ndp_size = ALIGN(ctx->max_ndp_size, ctx->tx_ndp_modulus);
else
delayed_ndp_size = 0;
@@ -1285,7 +1284,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
/* If requested, put NDP at end of frame. */
if (ctx->drvflags & CDC_NCM_FLAG_NDP_TO_END) {
nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
- cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size);
+ cdc_ncm_align_tail(skb_out, ctx->tx_ndp_modulus, 0, ctx->tx_curr_size - ctx->max_ndp_size);
nth16->wNdpIndex = cpu_to_le16(skb_out->len);
skb_put_data(skb_out, ctx->delayed_ndp16, ctx->max_ndp_size);
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 309b88a..06b4d29 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -1661,7 +1661,7 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)
}
if (pdata->wolopts & (WAKE_BCAST | WAKE_MCAST | WAKE_ARP | WAKE_UCAST)) {
- u32 *filter_mask = kzalloc(sizeof(u32) * 32, GFP_KERNEL);
+ u32 *filter_mask = kcalloc(32, sizeof(u32), GFP_KERNEL);
u32 command[2];
u32 offset[2];
u32 crc[4];
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index d9eea8c..770aa62 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1323,8 +1323,8 @@ static int build_dma_sg(const struct sk_buff *skb, struct urb *urb)
return 0;
/* reserve one for zero packet */
- urb->sg = kmalloc((num_sgs + 1) * sizeof(struct scatterlist),
- GFP_ATOMIC);
+ urb->sg = kmalloc_array(num_sgs + 1, sizeof(struct scatterlist),
+ GFP_ATOMIC);
if (!urb->sg)
return -ENOMEM;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 2aaa18e..b6c9a2a 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1411,7 +1411,8 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
hdr = skb_vnet_hdr(skb);
if (virtio_net_hdr_from_skb(skb, &hdr->hdr,
- virtio_is_little_endian(vi->vdev), false))
+ virtio_is_little_endian(vi->vdev), false,
+ 0))
BUG();
if (vi->mergeable_rx_bufs)
@@ -2551,17 +2552,17 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ);
/* Allocate space for find_vqs parameters */
- vqs = kzalloc(total_vqs * sizeof(*vqs), GFP_KERNEL);
+ vqs = kcalloc(total_vqs, sizeof(*vqs), GFP_KERNEL);
if (!vqs)
goto err_vq;
- callbacks = kmalloc(total_vqs * sizeof(*callbacks), GFP_KERNEL);
+ callbacks = kmalloc_array(total_vqs, sizeof(*callbacks), GFP_KERNEL);
if (!callbacks)
goto err_callback;
- names = kmalloc(total_vqs * sizeof(*names), GFP_KERNEL);
+ names = kmalloc_array(total_vqs, sizeof(*names), GFP_KERNEL);
if (!names)
goto err_names;
if (!vi->big_packets || vi->mergeable_rx_bufs) {
- ctx = kzalloc(total_vqs * sizeof(*ctx), GFP_KERNEL);
+ ctx = kcalloc(total_vqs, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
goto err_ctx;
} else {
@@ -2625,10 +2626,10 @@ static int virtnet_alloc_queues(struct virtnet_info *vi)
vi->ctrl = kzalloc(sizeof(*vi->ctrl), GFP_KERNEL);
if (!vi->ctrl)
goto err_ctrl;
- vi->sq = kzalloc(sizeof(*vi->sq) * vi->max_queue_pairs, GFP_KERNEL);
+ vi->sq = kcalloc(vi->max_queue_pairs, sizeof(*vi->sq), GFP_KERNEL);
if (!vi->sq)
goto err_sq;
- vi->rq = kzalloc(sizeof(*vi->rq) * vi->max_queue_pairs, GFP_KERNEL);
+ vi->rq = kcalloc(vi->max_queue_pairs, sizeof(*vi->rq), GFP_KERNEL);
if (!vi->rq)
goto err_rq;
diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c
index 4205dfd..9b09c9d 100644
--- a/drivers/net/wan/fsl_ucc_hdlc.c
+++ b/drivers/net/wan/fsl_ucc_hdlc.c
@@ -198,12 +198,14 @@ static int uhdlc_init(struct ucc_hdlc_private *priv)
goto free_tx_bd;
}
- priv->rx_skbuff = kzalloc(priv->rx_ring_size * sizeof(*priv->rx_skbuff),
+ priv->rx_skbuff = kcalloc(priv->rx_ring_size,
+ sizeof(*priv->rx_skbuff),
GFP_KERNEL);
if (!priv->rx_skbuff)
goto free_ucc_pram;
- priv->tx_skbuff = kzalloc(priv->tx_ring_size * sizeof(*priv->tx_skbuff),
+ priv->tx_skbuff = kcalloc(priv->tx_ring_size,
+ sizeof(*priv->tx_skbuff),
GFP_KERNEL);
if (!priv->tx_skbuff)
goto free_rx_skbuff;
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index bd23f69..c72d8af 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -582,7 +582,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
}
htt->rx_ring.netbufs_ring =
- kzalloc(htt->rx_ring.size * sizeof(struct sk_buff *),
+ kcalloc(htt->rx_ring.size, sizeof(struct sk_buff *),
GFP_KERNEL);
if (!htt->rx_ring.netbufs_ring)
goto err_netbuf;
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 2e34a1f..8c49a26 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -155,7 +155,7 @@ ath10k_wmi_tlv_parse_alloc(struct ath10k *ar, const void *ptr,
const void **tb;
int ret;
- tb = kzalloc(sizeof(*tb) * WMI_TLV_TAG_MAX, gfp);
+ tb = kcalloc(WMI_TLV_TAG_MAX, sizeof(*tb), gfp);
if (!tb)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index 3513bbe..e01faf6 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -931,7 +931,7 @@ static int open_file_eeprom(struct inode *inode, struct file *file)
/* Create buffer and read in eeprom */
- buf = vmalloc(eesize * 2);
+ buf = vmalloc(array_size(eesize, 2));
if (!buf) {
ret = -ENOMEM;
goto err;
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 641b13a..b1b8bc3 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -890,7 +890,8 @@ ath5k_hw_rfregs_init(struct ath5k_hw *ah,
* ah->ah_rf_banks based on ah->ah_rf_banks_size
* we set above */
if (ah->ah_rf_banks == NULL) {
- ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size,
+ ah->ah_rf_banks = kmalloc_array(ah->ah_rf_banks_size,
+ sizeof(u32),
GFP_KERNEL);
if (ah->ah_rf_banks == NULL) {
ATH5K_ERR(ah, "out of memory\n");
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 2ba8cf3..0687697 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1041,7 +1041,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
n_channels = request->n_channels;
- channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL);
+ channels = kcalloc(n_channels, sizeof(u16), GFP_KERNEL);
if (channels == NULL) {
ath6kl_warn("failed to set scan channels, scan all channels");
n_channels = 0;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index 6343cc9..34e1009 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -925,7 +925,7 @@ int ar9003_paprd_create_curve(struct ath_hw *ah,
memset(caldata->pa_table[chain], 0, sizeof(caldata->pa_table[chain]));
- buf = kmalloc(2 * 48 * sizeof(u32), GFP_KERNEL);
+ buf = kmalloc_array(2 * 48, sizeof(u32), GFP_KERNEL);
if (!buf)
return -ENOMEM;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 6b37036..e60bea4 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -127,13 +127,13 @@ void ath9k_hw_read_array(struct ath_hw *ah, u32 array[][2], int size)
u32 *tmp_reg_list, *tmp_data;
int i;
- tmp_reg_list = kmalloc(size * sizeof(u32), GFP_KERNEL);
+ tmp_reg_list = kmalloc_array(size, sizeof(u32), GFP_KERNEL);
if (!tmp_reg_list) {
dev_err(ah->dev, "%s: tmp_reg_list: alloc filed\n", __func__);
return;
}
- tmp_data = kmalloc(size * sizeof(u32), GFP_KERNEL);
+ tmp_data = kmalloc_array(size, sizeof(u32), GFP_KERNEL);
if (!tmp_data) {
dev_err(ah->dev, "%s tmp_data: alloc filed\n", __func__);
goto error_tmp_data;
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 29e93c9..7f1bdea 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1958,7 +1958,7 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
if (!bands)
return -EINVAL;
- ar->survey = kzalloc(sizeof(struct survey_info) * chans, GFP_KERNEL);
+ ar->survey = kcalloc(chans, sizeof(struct survey_info), GFP_KERNEL);
if (!ar->survey)
return -ENOMEM;
ar->num_channels = chans;
@@ -1988,8 +1988,9 @@ int carl9170_register(struct ar9170 *ar)
if (WARN_ON(ar->mem_bitmap))
return -EINVAL;
- ar->mem_bitmap = kzalloc(roundup(ar->fw.mem_blocks, BITS_PER_LONG) *
- sizeof(unsigned long), GFP_KERNEL);
+ ar->mem_bitmap = kcalloc(roundup(ar->fw.mem_blocks, BITS_PER_LONG),
+ sizeof(unsigned long),
+ GFP_KERNEL);
if (!ar->mem_bitmap)
return -ENOMEM;
diff --git a/drivers/net/wireless/broadcom/b43/phy_n.c b/drivers/net/wireless/broadcom/b43/phy_n.c
index f2a2f41..44ab080 100644
--- a/drivers/net/wireless/broadcom/b43/phy_n.c
+++ b/drivers/net/wireless/broadcom/b43/phy_n.c
@@ -1518,7 +1518,7 @@ static int b43_nphy_load_samples(struct b43_wldev *dev,
u16 i;
u32 *data;
- data = kzalloc(len * sizeof(u32), GFP_KERNEL);
+ data = kcalloc(len, sizeof(u32), GFP_KERNEL);
if (!data) {
b43err(dev->wl, "allocation for samples loading failed\n");
return -ENOMEM;
diff --git a/drivers/net/wireless/broadcom/b43legacy/main.c b/drivers/net/wireless/broadcom/b43legacy/main.c
index f1e3dad..55f4119 100644
--- a/drivers/net/wireless/broadcom/b43legacy/main.c
+++ b/drivers/net/wireless/broadcom/b43legacy/main.c
@@ -3300,8 +3300,8 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
if ((phy->type == B43legacy_PHYTYPE_B) ||
(phy->type == B43legacy_PHYTYPE_G)) {
- phy->_lo_pairs = kzalloc(sizeof(struct b43legacy_lopair)
- * B43legacy_LO_COUNT,
+ phy->_lo_pairs = kcalloc(B43legacy_LO_COUNT,
+ sizeof(struct b43legacy_lopair),
GFP_KERNEL);
if (!phy->_lo_pairs)
return -ENOMEM;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index 49d37ad..c40ba88 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -1486,8 +1486,9 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
(struct brcmf_commonring **)if_msgbuf->commonrings;
msgbuf->flowrings = (struct brcmf_commonring **)if_msgbuf->flowrings;
msgbuf->max_flowrings = if_msgbuf->max_flowrings;
- msgbuf->flowring_dma_handle = kzalloc(msgbuf->max_flowrings *
- sizeof(*msgbuf->flowring_dma_handle), GFP_KERNEL);
+ msgbuf->flowring_dma_handle =
+ kcalloc(msgbuf->max_flowrings,
+ sizeof(*msgbuf->flowring_dma_handle), GFP_KERNEL);
if (!msgbuf->flowring_dma_handle)
goto fail;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index 4b2149b..3e9c4f2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -1058,7 +1058,7 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
channel_cnt = AF_PEER_SEARCH_CNT;
else
channel_cnt = SOCIAL_CHAN_CNT;
- default_chan_list = kzalloc(channel_cnt * sizeof(*default_chan_list),
+ default_chan_list = kcalloc(channel_cnt, sizeof(*default_chan_list),
GFP_KERNEL);
if (default_chan_list == NULL) {
brcmf_err("channel list allocation failed\n");
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c
index 0a14942..7d4e8f5 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/main.c
@@ -507,7 +507,7 @@ brcms_c_attach_malloc(uint unit, uint *err, uint devid)
wlc->hw->wlc = wlc;
wlc->hw->bandstate[0] =
- kzalloc(sizeof(struct brcms_hw_band) * MAXBANDS, GFP_ATOMIC);
+ kcalloc(MAXBANDS, sizeof(struct brcms_hw_band), GFP_ATOMIC);
if (wlc->hw->bandstate[0] == NULL) {
*err = 1006;
goto fail;
@@ -521,7 +521,8 @@ brcms_c_attach_malloc(uint unit, uint *err, uint devid)
}
wlc->modulecb =
- kzalloc(sizeof(struct modulecb) * BRCMS_MAXMODULES, GFP_ATOMIC);
+ kcalloc(BRCMS_MAXMODULES, sizeof(struct modulecb),
+ GFP_ATOMIC);
if (wlc->modulecb == NULL) {
*err = 1009;
goto fail;
@@ -553,7 +554,7 @@ brcms_c_attach_malloc(uint unit, uint *err, uint devid)
}
wlc->bandstate[0] =
- kzalloc(sizeof(struct brcms_band)*MAXBANDS, GFP_ATOMIC);
+ kcalloc(MAXBANDS, sizeof(struct brcms_band), GFP_ATOMIC);
if (wlc->bandstate[0] == NULL) {
*err = 1025;
goto fail;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
index 9d830d2..9fb0d9f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c
@@ -1387,7 +1387,7 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
s16 *ptr;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+ ptr = kmalloc_array(131, sizeof(s16), GFP_ATOMIC);
if (NULL == ptr)
return false;
if (module == 2) {
@@ -2670,7 +2670,7 @@ wlc_lcnphy_tx_iqlo_cal(struct brcms_phy *pi,
u16 *values_to_save;
struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy;
- values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
+ values_to_save = kmalloc_array(20, sizeof(u16), GFP_ATOMIC);
if (NULL == values_to_save)
return;
@@ -3678,11 +3678,11 @@ wlc_lcnphy_a1(struct brcms_phy *pi, int cal_type, int num_levels,
u16 *phy_c32;
phy_c21 = 0;
phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
- ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+ ptr = kmalloc_array(131, sizeof(s16), GFP_ATOMIC);
if (NULL == ptr)
return;
- phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
+ phy_c32 = kmalloc_array(20, sizeof(u16), GFP_ATOMIC);
if (NULL == phy_c32) {
kfree(ptr);
return;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c
index 7e01981b..1a18755 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c
@@ -23032,7 +23032,7 @@ wlc_phy_loadsampletable_nphy(struct brcms_phy *pi, struct cordic_iq *tone_buf,
u16 t;
u32 *data_buf = NULL;
- data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC);
+ data_buf = kmalloc_array(num_samps, sizeof(u32), GFP_ATOMIC);
if (data_buf == NULL)
return;
@@ -23074,7 +23074,8 @@ wlc_phy_gen_load_samples_nphy(struct brcms_phy *pi, u32 f_kHz, u16 max_val,
tbl_len = (phy_bw << 1);
}
- tone_buf = kmalloc(sizeof(struct cordic_iq) * tbl_len, GFP_ATOMIC);
+ tone_buf = kmalloc_array(tbl_len, sizeof(struct cordic_iq),
+ GFP_ATOMIC);
if (tone_buf == NULL)
return 0;
diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
index ce0fbf8..72046e18 100644
--- a/drivers/net/wireless/cisco/airo.c
+++ b/drivers/net/wireless/cisco/airo.c
@@ -7127,7 +7127,7 @@ static int airo_get_aplist(struct net_device *dev,
int i;
int loseSync = capable(CAP_NET_ADMIN) ? 1: -1;
- qual = kmalloc(IW_MAX_AP * sizeof(*qual), GFP_KERNEL);
+ qual = kmalloc_array(IW_MAX_AP, sizeof(*qual), GFP_KERNEL);
if (!qual)
return -ENOMEM;
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index 7c4f550..b8fd3cc 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -3445,8 +3445,9 @@ static int ipw2100_msg_allocate(struct ipw2100_priv *priv)
dma_addr_t p;
priv->msg_buffers =
- kmalloc(IPW_COMMAND_POOL_SIZE * sizeof(struct ipw2100_tx_packet),
- GFP_KERNEL);
+ kmalloc_array(IPW_COMMAND_POOL_SIZE,
+ sizeof(struct ipw2100_tx_packet),
+ GFP_KERNEL);
if (!priv->msg_buffers)
return -ENOMEM;
@@ -4587,9 +4588,9 @@ static int ipw2100_rx_allocate(struct ipw2100_priv *priv)
/*
* allocate packets
*/
- priv->rx_buffers = kmalloc(RX_QUEUE_LENGTH *
- sizeof(struct ipw2100_rx_packet),
- GFP_KERNEL);
+ priv->rx_buffers = kmalloc_array(RX_QUEUE_LENGTH,
+ sizeof(struct ipw2100_rx_packet),
+ GFP_KERNEL);
if (!priv->rx_buffers) {
IPW_DEBUG_INFO("can't allocate rx packet buffer table\n");
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2200.c b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
index f26beeb..8a858f7 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2200.c
@@ -3208,13 +3208,13 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len)
IPW_DEBUG_TRACE("<< :\n");
- virts = kmalloc(sizeof(void *) * CB_NUMBER_OF_ELEMENTS_SMALL,
- GFP_KERNEL);
+ virts = kmalloc_array(CB_NUMBER_OF_ELEMENTS_SMALL, sizeof(void *),
+ GFP_KERNEL);
if (!virts)
return -ENOMEM;
- phys = kmalloc(sizeof(dma_addr_t) * CB_NUMBER_OF_ELEMENTS_SMALL,
- GFP_KERNEL);
+ phys = kmalloc_array(CB_NUMBER_OF_ELEMENTS_SMALL, sizeof(dma_addr_t),
+ GFP_KERNEL);
if (!phys) {
kfree(virts);
return -ENOMEM;
@@ -3782,7 +3782,7 @@ static int ipw_queue_tx_init(struct ipw_priv *priv,
{
struct pci_dev *dev = priv->pci_dev;
- q->txb = kmalloc(sizeof(q->txb[0]) * count, GFP_KERNEL);
+ q->txb = kmalloc_array(count, sizeof(q->txb[0]), GFP_KERNEL);
if (!q->txb) {
IPW_ERROR("vmalloc for auxiliary BD structures failed\n");
return -ENOMEM;
diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c
index 063e19c..6514baf 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.c
+++ b/drivers/net/wireless/intel/iwlegacy/common.c
@@ -922,7 +922,7 @@ il_init_channel_map(struct il_priv *il)
D_EEPROM("Parsing data for %d channels.\n", il->channel_count);
il->channel_info =
- kzalloc(sizeof(struct il_channel_info) * il->channel_count,
+ kcalloc(il->channel_count, sizeof(struct il_channel_info),
GFP_KERNEL);
if (!il->channel_info) {
IL_ERR("Could not allocate channel_info\n");
@@ -3041,9 +3041,9 @@ il_tx_queue_init(struct il_priv *il, u32 txq_id)
}
txq->meta =
- kzalloc(sizeof(struct il_cmd_meta) * actual_slots, GFP_KERNEL);
+ kcalloc(actual_slots, sizeof(struct il_cmd_meta), GFP_KERNEL);
txq->cmd =
- kzalloc(sizeof(struct il_device_cmd *) * actual_slots, GFP_KERNEL);
+ kcalloc(actual_slots, sizeof(struct il_device_cmd *), GFP_KERNEL);
if (!txq->meta || !txq->cmd)
goto out_free_arrays;
@@ -3455,7 +3455,7 @@ il_init_geos(struct il_priv *il)
}
channels =
- kzalloc(sizeof(struct ieee80211_channel) * il->channel_count,
+ kcalloc(il->channel_count, sizeof(struct ieee80211_channel),
GFP_KERNEL);
if (!channels)
return -ENOMEM;
@@ -4654,8 +4654,9 @@ il_alloc_txq_mem(struct il_priv *il)
{
if (!il->txq)
il->txq =
- kzalloc(sizeof(struct il_tx_queue) *
- il->cfg->num_of_queues, GFP_KERNEL);
+ kcalloc(il->cfg->num_of_queues,
+ sizeof(struct il_tx_queue),
+ GFP_KERNEL);
if (!il->txq) {
IL_ERR("Not enough memory for txq\n");
return -ENOMEM;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
index 4b3753d7..11ecdf6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c
@@ -564,7 +564,7 @@ iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
else
blacklist_len = IWL_SCAN_MAX_BLACKLIST_LEN;
- blacklist = kzalloc(sizeof(*blacklist) * blacklist_len, GFP_KERNEL);
+ blacklist = kcalloc(blacklist_len, sizeof(*blacklist), GFP_KERNEL);
if (!blacklist)
return -ENOMEM;
diff --git a/drivers/net/wireless/intersil/hostap/hostap_info.c b/drivers/net/wireless/intersil/hostap/hostap_info.c
index de8a099..da8c30f 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_info.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_info.c
@@ -271,8 +271,9 @@ static void prism2_info_scanresults(local_info_t *local, unsigned char *buf,
left -= 4;
new_count = left / sizeof(struct hfa384x_scan_result);
- results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result),
- GFP_ATOMIC);
+ results = kmalloc_array(new_count,
+ sizeof(struct hfa384x_hostscan_result),
+ GFP_ATOMIC);
if (results == NULL)
return;
diff --git a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
index c1bc0a6..1ca9731 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_ioctl.c
@@ -513,8 +513,8 @@ static int prism2_ioctl_giwaplist(struct net_device *dev,
return -EOPNOTSUPP;
}
- addr = kmalloc(sizeof(struct sockaddr) * IW_MAX_AP, GFP_KERNEL);
- qual = kmalloc(sizeof(struct iw_quality) * IW_MAX_AP, GFP_KERNEL);
+ addr = kmalloc_array(IW_MAX_AP, sizeof(struct sockaddr), GFP_KERNEL);
+ qual = kmalloc_array(IW_MAX_AP, sizeof(struct iw_quality), GFP_KERNEL);
if (addr == NULL || qual == NULL) {
kfree(addr);
kfree(qual);
diff --git a/drivers/net/wireless/intersil/p54/eeprom.c b/drivers/net/wireless/intersil/p54/eeprom.c
index d4c73d3..de2ef95 100644
--- a/drivers/net/wireless/intersil/p54/eeprom.c
+++ b/drivers/net/wireless/intersil/p54/eeprom.c
@@ -161,8 +161,9 @@ static int p54_generate_band(struct ieee80211_hw *dev,
if (!tmp)
goto err_out;
- tmp->channels = kzalloc(sizeof(struct ieee80211_channel) *
- list->band_channel_num[band], GFP_KERNEL);
+ tmp->channels = kcalloc(list->band_channel_num[band],
+ sizeof(struct ieee80211_channel),
+ GFP_KERNEL);
if (!tmp->channels)
goto err_out;
@@ -344,7 +345,7 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
goto free;
}
priv->chan_num = max_channel_num;
- priv->survey = kzalloc(sizeof(struct survey_info) * max_channel_num,
+ priv->survey = kcalloc(max_channel_num, sizeof(struct survey_info),
GFP_KERNEL);
if (!priv->survey) {
ret = -ENOMEM;
@@ -352,8 +353,9 @@ static int p54_generate_channel_lists(struct ieee80211_hw *dev)
}
list->max_entries = max_channel_num;
- list->channels = kzalloc(sizeof(struct p54_channel_entry) *
- max_channel_num, GFP_KERNEL);
+ list->channels = kcalloc(max_channel_num,
+ sizeof(struct p54_channel_entry),
+ GFP_KERNEL);
if (!list->channels) {
ret = -ENOMEM;
goto free;
diff --git a/drivers/net/wireless/intersil/prism54/oid_mgt.c b/drivers/net/wireless/intersil/prism54/oid_mgt.c
index 6528ed5..6d57e1c 100644
--- a/drivers/net/wireless/intersil/prism54/oid_mgt.c
+++ b/drivers/net/wireless/intersil/prism54/oid_mgt.c
@@ -244,7 +244,7 @@ mgt_init(islpci_private *priv)
/* Alloc the cache */
for (i = 0; i < OID_NUM_LAST; i++) {
if (isl_oid[i].flags & OID_FLAG_CACHED) {
- priv->mib[i] = kzalloc(isl_oid[i].size *
+ priv->mib[i] = kcalloc(isl_oid[i].size,
(isl_oid[i].range + 1),
GFP_KERNEL);
if (!priv->mib[i])
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 9825bfd..18e819d 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -3572,11 +3572,14 @@ static int __init init_mac80211_hwsim(void)
hwsim_wq = alloc_workqueue("hwsim_wq", 0, 0);
if (!hwsim_wq)
return -ENOMEM;
- rhashtable_init(&hwsim_radios_rht, &hwsim_rht_params);
+
+ err = rhashtable_init(&hwsim_radios_rht, &hwsim_rht_params);
+ if (err)
+ goto out_free_wq;
err = register_pernet_device(&hwsim_net_ops);
if (err)
- return err;
+ goto out_free_rht;
err = platform_driver_register(&mac80211_hwsim_driver);
if (err)
@@ -3701,6 +3704,10 @@ out_unregister_driver:
platform_driver_unregister(&mac80211_hwsim_driver);
out_unregister_pernet:
unregister_pernet_device(&hwsim_net_ops);
+out_free_rht:
+ rhashtable_destroy(&hwsim_radios_rht);
+out_free_wq:
+ destroy_workqueue(hwsim_wq);
return err;
}
module_init(init_mac80211_hwsim);
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
index 1edcdda..7ab44cd 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -399,8 +399,8 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
new_node->win_size = win_size;
- new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size,
- GFP_KERNEL);
+ new_node->rx_reorder_ptr = kcalloc(win_size, sizeof(void *),
+ GFP_KERNEL);
if (!new_node->rx_reorder_ptr) {
kfree((u8 *) new_node);
mwifiex_dbg(priv->adapter, ERROR,
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index a67e2d6..4b5ae90 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -4242,8 +4242,8 @@ int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
* additional active scan request for hidden SSIDs on passive channels.
*/
adapter->num_in_chan_stats = 2 * (n_channels_bg + n_channels_a);
- adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) *
- adapter->num_in_chan_stats);
+ adapter->chan_stats = vmalloc(array_size(sizeof(*adapter->chan_stats),
+ adapter->num_in_chan_stats));
if (!adapter->chan_stats)
return -ENOMEM;
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 47d2dcc..dfdcbc4 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -2106,15 +2106,16 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
return -ENOMEM;
/* Allocate skb pointer buffers */
- card->mpa_rx.skb_arr = kzalloc((sizeof(void *)) *
- card->mp_agg_pkt_limit, GFP_KERNEL);
+ card->mpa_rx.skb_arr = kcalloc(card->mp_agg_pkt_limit, sizeof(void *),
+ GFP_KERNEL);
if (!card->mpa_rx.skb_arr) {
kfree(card->mp_regs);
return -ENOMEM;
}
- card->mpa_rx.len_arr = kzalloc(sizeof(*card->mpa_rx.len_arr) *
- card->mp_agg_pkt_limit, GFP_KERNEL);
+ card->mpa_rx.len_arr = kcalloc(card->mp_agg_pkt_limit,
+ sizeof(*card->mpa_rx.len_arr),
+ GFP_KERNEL);
if (!card->mpa_rx.len_arr) {
kfree(card->mp_regs);
kfree(card->mpa_rx.skb_arr);
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index fcd079a..d62e34e 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -181,7 +181,7 @@ mt76_init_sband(struct mt76_dev *dev, struct mt76_sband *msband,
if (!chanlist)
return -ENOMEM;
- msband->chan = devm_kzalloc(dev->dev, n_chan * sizeof(*msband->chan),
+ msband->chan = devm_kcalloc(dev->dev, n_chan, sizeof(*msband->chan),
GFP_KERNEL);
if (!msband->chan)
return -ENOMEM;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/commands.c b/drivers/net/wireless/quantenna/qtnfmac/commands.c
index 5eb1436..c5d94a9 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/commands.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/commands.c
@@ -1216,7 +1216,7 @@ static int qtnf_parse_variable_mac_info(struct qtnf_wmac *mac,
return -EINVAL;
}
- limits = kzalloc(sizeof(*limits) * rec->n_limits,
+ limits = kcalloc(rec->n_limits, sizeof(*limits),
GFP_KERNEL);
if (!limits)
return -ENOMEM;
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
index 0eee479..acc399b 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00debug.c
@@ -397,7 +397,7 @@ static ssize_t rt2x00debug_read_crypto_stats(struct file *file,
if (*offset)
return 0;
- data = kzalloc((1 + CIPHER_MAX) * MAX_LINE_LENGTH, GFP_KERNEL);
+ data = kcalloc(1 + CIPHER_MAX, MAX_LINE_LENGTH, GFP_KERNEL);
if (!data)
return -ENOMEM;
diff --git a/drivers/net/wireless/realtek/rtlwifi/efuse.c b/drivers/net/wireless/realtek/rtlwifi/efuse.c
index fd13d4e..9729e51f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/efuse.c
+++ b/drivers/net/wireless/realtek/rtlwifi/efuse.c
@@ -258,8 +258,8 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf)
}
/* allocate memory for efuse_tbl and efuse_word */
- efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE] *
- sizeof(u8), GFP_ATOMIC);
+ efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE],
+ GFP_ATOMIC);
if (!efuse_tbl)
return;
efuse_word = kcalloc(EFUSE_MAX_WORD_UNIT, sizeof(u16 *), GFP_ATOMIC);
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index ce3103b..f9faffc 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -1048,7 +1048,7 @@ int rtl_usb_probe(struct usb_interface *intf,
}
rtlpriv = hw->priv;
rtlpriv->hw = hw;
- rtlpriv->usb_data = kzalloc(RTL_USB_MAX_RX_COUNT * sizeof(u32),
+ rtlpriv->usb_data = kcalloc(RTL_USB_MAX_RX_COUNT, sizeof(u32),
GFP_KERNEL);
if (!rtlpriv->usb_data)
return -ENOMEM;
diff --git a/drivers/net/wireless/st/cw1200/queue.c b/drivers/net/wireless/st/cw1200/queue.c
index 5153d2c..7c31b63 100644
--- a/drivers/net/wireless/st/cw1200/queue.c
+++ b/drivers/net/wireless/st/cw1200/queue.c
@@ -154,7 +154,7 @@ int cw1200_queue_stats_init(struct cw1200_queue_stats *stats,
spin_lock_init(&stats->lock);
init_waitqueue_head(&stats->wait_link_id_empty);
- stats->link_map_cache = kzalloc(sizeof(int) * map_capacity,
+ stats->link_map_cache = kcalloc(map_capacity, sizeof(int),
GFP_KERNEL);
if (!stats->link_map_cache)
return -ENOMEM;
@@ -181,13 +181,13 @@ int cw1200_queue_init(struct cw1200_queue *queue,
spin_lock_init(&queue->lock);
timer_setup(&queue->gc, cw1200_queue_gc, 0);
- queue->pool = kzalloc(sizeof(struct cw1200_queue_item) * capacity,
- GFP_KERNEL);
+ queue->pool = kcalloc(capacity, sizeof(struct cw1200_queue_item),
+ GFP_KERNEL);
if (!queue->pool)
return -ENOMEM;
- queue->link_map_cache = kzalloc(sizeof(int) * stats->map_capacity,
- GFP_KERNEL);
+ queue->link_map_cache = kcalloc(stats->map_capacity, sizeof(int),
+ GFP_KERNEL);
if (!queue->link_map_cache) {
kfree(queue->pool);
queue->pool = NULL;
diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c
index cc2ce60..67213f1 100644
--- a/drivers/net/wireless/st/cw1200/scan.c
+++ b/drivers/net/wireless/st/cw1200/scan.c
@@ -230,9 +230,9 @@ void cw1200_scan_work(struct work_struct *work)
scan.type = WSM_SCAN_TYPE_BACKGROUND;
scan.flags = WSM_SCAN_FLAG_FORCE_BACKGROUND;
}
- scan.ch = kzalloc(
- sizeof(struct wsm_scan_ch) * (it - priv->scan.curr),
- GFP_KERNEL);
+ scan.ch = kcalloc(it - priv->scan.curr,
+ sizeof(struct wsm_scan_ch),
+ GFP_KERNEL);
if (!scan.ch) {
priv->scan.status = -ENOMEM;
goto fail;
diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
index b01b44a..1f6d9f3 100644
--- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c
@@ -732,7 +732,8 @@ static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon,
/* Alloc memory for full beacon write at once. */
num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
- ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
+ ioreqs = kmalloc_array(num_cmds, sizeof(struct zd_ioreq32),
+ GFP_KERNEL);
if (!ioreqs) {
r = -ENOMEM;
goto out_nofree;
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index e1aef25..cd51492 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -977,8 +977,8 @@ static void connect(struct backend_info *be)
}
/* Use the number of queues requested by the frontend */
- be->vif->queues = vzalloc(requested_num_queues *
- sizeof(struct xenvif_queue));
+ be->vif->queues = vzalloc(array_size(requested_num_queues,
+ sizeof(struct xenvif_queue)));
if (!be->vif->queues) {
xenbus_dev_fatal(dev, -ENOMEM,
"allocating queues");
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 679da1a..922ce0a 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -239,7 +239,7 @@ static void rx_refill_timeout(struct timer_list *t)
static int netfront_tx_slot_available(struct netfront_queue *queue)
{
return (queue->tx.req_prod_pvt - queue->tx.rsp_cons) <
- (NET_TX_RING_SIZE - MAX_SKB_FRAGS - 2);
+ (NET_TX_RING_SIZE - XEN_NETIF_NR_SLOTS_MIN - 1);
}
static void xennet_maybe_wake_tx(struct netfront_queue *queue)
@@ -790,7 +790,7 @@ static int xennet_get_responses(struct netfront_queue *queue,
RING_IDX cons = queue->rx.rsp_cons;
struct sk_buff *skb = xennet_get_rx_skb(queue, cons);
grant_ref_t ref = xennet_get_rx_ref(queue, cons);
- int max = MAX_SKB_FRAGS + (rx->status <= RX_COPY_THRESHOLD);
+ int max = XEN_NETIF_NR_SLOTS_MIN + (rx->status <= RX_COPY_THRESHOLD);
int slots = 1;
int err = 0;
unsigned long ret;
diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c
index c4da50e..d8d70dd 100644
--- a/drivers/nfc/fdp/i2c.c
+++ b/drivers/nfc/fdp/i2c.c
@@ -259,8 +259,8 @@ static void fdp_nci_i2c_read_device_properties(struct device *dev,
/* Add 1 to the length to inclue the length byte itself */
len++;
- *fw_vsc_cfg = devm_kmalloc(dev,
- len * sizeof(**fw_vsc_cfg),
+ *fw_vsc_cfg = devm_kmalloc_array(dev,
+ len, sizeof(**fw_vsc_cfg),
GFP_KERNEL);
r = device_property_read_u8_array(dev, FDP_DP_FW_VSC_CFG_NAME,
diff --git a/drivers/ntb/hw/amd/ntb_hw_amd.c b/drivers/ntb/hw/amd/ntb_hw_amd.c
index 3cfa468..efb214f 100644
--- a/drivers/ntb/hw/amd/ntb_hw_amd.c
+++ b/drivers/ntb/hw/amd/ntb_hw_amd.c
@@ -592,12 +592,12 @@ static int ndev_init_isr(struct amd_ntb_dev *ndev,
ndev->db_mask = ndev->db_valid_mask;
/* Try to set up msix irq */
- ndev->vec = kzalloc_node(msix_max * sizeof(*ndev->vec),
+ ndev->vec = kcalloc_node(msix_max, sizeof(*ndev->vec),
GFP_KERNEL, node);
if (!ndev->vec)
goto err_msix_vec_alloc;
- ndev->msix = kzalloc_node(msix_max * sizeof(*ndev->msix),
+ ndev->msix = kcalloc_node(msix_max, sizeof(*ndev->msix),
GFP_KERNEL, node);
if (!ndev->msix)
goto err_msix_alloc;
diff --git a/drivers/ntb/hw/idt/ntb_hw_idt.c b/drivers/ntb/hw/idt/ntb_hw_idt.c
index 8d98872..dbe72f1 100644
--- a/drivers/ntb/hw/idt/ntb_hw_idt.c
+++ b/drivers/ntb/hw/idt/ntb_hw_idt.c
@@ -1401,7 +1401,7 @@ static int idt_ntb_peer_mw_clear_trans(struct ntb_dev *ntb, int pidx,
* 5. Doorbell operations
*
* Doorbell functionality of IDT PCIe-switches is pretty unusual. First of
- * all there is global doorbell register which state can by changed by any
+ * all there is global doorbell register which state can be changed by any
* NT-function of the IDT device in accordance with global permissions. These
* permissions configs are not supported by NTB API, so it must be done by
* either BIOS or EEPROM settings. In the same way the state of the global
diff --git a/drivers/ntb/hw/intel/Makefile b/drivers/ntb/hw/intel/Makefile
index 1b43456..4ff22af 100644
--- a/drivers/ntb/hw/intel/Makefile
+++ b/drivers/ntb/hw/intel/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_NTB_INTEL) += ntb_hw_intel.o
+ntb_hw_intel-y := ntb_hw_gen1.o ntb_hw_gen3.o
diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.c b/drivers/ntb/hw/intel/ntb_hw_gen1.c
index 156b45c..6aa5732 100644
--- a/drivers/ntb/hw/intel/ntb_hw_intel.c
+++ b/drivers/ntb/hw/intel/ntb_hw_gen1.c
@@ -45,9 +45,6 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Intel PCIe NTB Linux driver
- *
- * Contact Information:
- * Jon Mason <jon.mason@intel.com>
*/
#include <linux/debugfs.h>
@@ -61,6 +58,8 @@
#include <linux/ntb.h>
#include "ntb_hw_intel.h"
+#include "ntb_hw_gen1.h"
+#include "ntb_hw_gen3.h"
#define NTB_NAME "ntb_hw_intel"
#define NTB_DESC "Intel(R) PCI-E Non-Transparent Bridge Driver"
@@ -80,14 +79,7 @@ static const struct intel_ntb_alt_reg xeon_sec_reg;
static const struct intel_ntb_alt_reg xeon_b2b_reg;
static const struct intel_ntb_xlat_reg xeon_pri_xlat;
static const struct intel_ntb_xlat_reg xeon_sec_xlat;
-static struct intel_b2b_addr xeon_b2b_usd_addr;
-static struct intel_b2b_addr xeon_b2b_dsd_addr;
-static const struct intel_ntb_reg skx_reg;
-static const struct intel_ntb_alt_reg skx_pri_reg;
-static const struct intel_ntb_alt_reg skx_b2b_reg;
-static const struct intel_ntb_xlat_reg skx_sec_xlat;
static const struct ntb_dev_ops intel_ntb_ops;
-static const struct ntb_dev_ops intel_ntb3_ops;
static const struct file_operations intel_ntb_debugfs_info;
static struct dentry *debugfs_dir;
@@ -146,68 +138,8 @@ module_param_named(xeon_b2b_dsd_bar5_addr32,
MODULE_PARM_DESC(xeon_b2b_dsd_bar5_addr32,
"XEON B2B DSD split-BAR 5 32-bit address");
-static inline enum ntb_topo xeon_ppd_topo(struct intel_ntb_dev *ndev, u8 ppd);
-static int xeon_init_isr(struct intel_ntb_dev *ndev);
-
-#ifndef ioread64
-#ifdef readq
-#define ioread64 readq
-#else
-#define ioread64 _ioread64
-static inline u64 _ioread64(void __iomem *mmio)
-{
- u64 low, high;
-
- low = ioread32(mmio);
- high = ioread32(mmio + sizeof(u32));
- return low | (high << 32);
-}
-#endif
-#endif
-
-#ifndef iowrite64
-#ifdef writeq
-#define iowrite64 writeq
-#else
-#define iowrite64 _iowrite64
-static inline void _iowrite64(u64 val, void __iomem *mmio)
-{
- iowrite32(val, mmio);
- iowrite32(val >> 32, mmio + sizeof(u32));
-}
-#endif
-#endif
-
-static inline int pdev_is_xeon(struct pci_dev *pdev)
-{
- switch (pdev->device) {
- case PCI_DEVICE_ID_INTEL_NTB_SS_JSF:
- case PCI_DEVICE_ID_INTEL_NTB_SS_SNB:
- case PCI_DEVICE_ID_INTEL_NTB_SS_IVT:
- case PCI_DEVICE_ID_INTEL_NTB_SS_HSX:
- case PCI_DEVICE_ID_INTEL_NTB_SS_BDX:
- case PCI_DEVICE_ID_INTEL_NTB_PS_JSF:
- case PCI_DEVICE_ID_INTEL_NTB_PS_SNB:
- case PCI_DEVICE_ID_INTEL_NTB_PS_IVT:
- case PCI_DEVICE_ID_INTEL_NTB_PS_HSX:
- case PCI_DEVICE_ID_INTEL_NTB_PS_BDX:
- case PCI_DEVICE_ID_INTEL_NTB_B2B_JSF:
- case PCI_DEVICE_ID_INTEL_NTB_B2B_SNB:
- case PCI_DEVICE_ID_INTEL_NTB_B2B_IVT:
- case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX:
- case PCI_DEVICE_ID_INTEL_NTB_B2B_BDX:
- return 1;
- }
- return 0;
-}
-
-static inline int pdev_is_skx_xeon(struct pci_dev *pdev)
-{
- if (pdev->device == PCI_DEVICE_ID_INTEL_NTB_B2B_SKX)
- return 1;
- return 0;
-}
+static int xeon_init_isr(struct intel_ntb_dev *ndev);
static inline void ndev_reset_unsafe_flags(struct intel_ntb_dev *ndev)
{
@@ -241,7 +173,7 @@ static inline int ndev_ignore_unsafe(struct intel_ntb_dev *ndev,
return !!flag;
}
-static int ndev_mw_to_bar(struct intel_ntb_dev *ndev, int idx)
+int ndev_mw_to_bar(struct intel_ntb_dev *ndev, int idx)
{
if (idx < 0 || idx >= ndev->mw_count)
return -EINVAL;
@@ -268,7 +200,7 @@ static inline int ndev_db_addr(struct intel_ntb_dev *ndev,
return 0;
}
-static inline u64 ndev_db_read(struct intel_ntb_dev *ndev,
+u64 ndev_db_read(struct intel_ntb_dev *ndev,
void __iomem *mmio)
{
if (ndev_is_unsafe(ndev, NTB_UNSAFE_DB))
@@ -277,7 +209,7 @@ static inline u64 ndev_db_read(struct intel_ntb_dev *ndev,
return ndev->reg->db_ioread(mmio);
}
-static inline int ndev_db_write(struct intel_ntb_dev *ndev, u64 db_bits,
+int ndev_db_write(struct intel_ntb_dev *ndev, u64 db_bits,
void __iomem *mmio)
{
if (ndev_is_unsafe(ndev, NTB_UNSAFE_DB))
@@ -429,7 +361,7 @@ static irqreturn_t ndev_irq_isr(int irq, void *dev)
return ndev_interrupt(ndev, irq - ndev->ntb.pdev->irq);
}
-static int ndev_init_isr(struct intel_ntb_dev *ndev,
+int ndev_init_isr(struct intel_ntb_dev *ndev,
int msix_min, int msix_max,
int msix_shift, int total_shift)
{
@@ -448,12 +380,12 @@ static int ndev_init_isr(struct intel_ntb_dev *ndev,
/* Try to set up msix irq */
- ndev->vec = kzalloc_node(msix_max * sizeof(*ndev->vec),
+ ndev->vec = kcalloc_node(msix_max, sizeof(*ndev->vec),
GFP_KERNEL, node);
if (!ndev->vec)
goto err_msix_vec_alloc;
- ndev->msix = kzalloc_node(msix_max * sizeof(*ndev->msix),
+ ndev->msix = kcalloc_node(msix_max, sizeof(*ndev->msix),
GFP_KERNEL, node);
if (!ndev->msix)
goto err_msix_alloc;
@@ -557,169 +489,6 @@ static void ndev_deinit_isr(struct intel_ntb_dev *ndev)
}
}
-static ssize_t ndev_ntb3_debugfs_read(struct file *filp, char __user *ubuf,
- size_t count, loff_t *offp)
-{
- struct intel_ntb_dev *ndev;
- void __iomem *mmio;
- char *buf;
- size_t buf_size;
- ssize_t ret, off;
- union { u64 v64; u32 v32; u16 v16; } u;
-
- ndev = filp->private_data;
- mmio = ndev->self_mmio;
-
- buf_size = min(count, 0x800ul);
-
- buf = kmalloc(buf_size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- off = 0;
-
- off += scnprintf(buf + off, buf_size - off,
- "NTB Device Information:\n");
-
- off += scnprintf(buf + off, buf_size - off,
- "Connection Topology -\t%s\n",
- ntb_topo_string(ndev->ntb.topo));
-
- off += scnprintf(buf + off, buf_size - off,
- "NTB CTL -\t\t%#06x\n", ndev->ntb_ctl);
- off += scnprintf(buf + off, buf_size - off,
- "LNK STA -\t\t%#06x\n", ndev->lnk_sta);
-
- if (!ndev->reg->link_is_up(ndev))
- off += scnprintf(buf + off, buf_size - off,
- "Link Status -\t\tDown\n");
- else {
- off += scnprintf(buf + off, buf_size - off,
- "Link Status -\t\tUp\n");
- off += scnprintf(buf + off, buf_size - off,
- "Link Speed -\t\tPCI-E Gen %u\n",
- NTB_LNK_STA_SPEED(ndev->lnk_sta));
- off += scnprintf(buf + off, buf_size - off,
- "Link Width -\t\tx%u\n",
- NTB_LNK_STA_WIDTH(ndev->lnk_sta));
- }
-
- off += scnprintf(buf + off, buf_size - off,
- "Memory Window Count -\t%u\n", ndev->mw_count);
- off += scnprintf(buf + off, buf_size - off,
- "Scratchpad Count -\t%u\n", ndev->spad_count);
- off += scnprintf(buf + off, buf_size - off,
- "Doorbell Count -\t%u\n", ndev->db_count);
- off += scnprintf(buf + off, buf_size - off,
- "Doorbell Vector Count -\t%u\n", ndev->db_vec_count);
- off += scnprintf(buf + off, buf_size - off,
- "Doorbell Vector Shift -\t%u\n", ndev->db_vec_shift);
-
- off += scnprintf(buf + off, buf_size - off,
- "Doorbell Valid Mask -\t%#llx\n", ndev->db_valid_mask);
- off += scnprintf(buf + off, buf_size - off,
- "Doorbell Link Mask -\t%#llx\n", ndev->db_link_mask);
- off += scnprintf(buf + off, buf_size - off,
- "Doorbell Mask Cached -\t%#llx\n", ndev->db_mask);
-
- u.v64 = ndev_db_read(ndev, mmio + ndev->self_reg->db_mask);
- off += scnprintf(buf + off, buf_size - off,
- "Doorbell Mask -\t\t%#llx\n", u.v64);
-
- u.v64 = ndev_db_read(ndev, mmio + ndev->self_reg->db_bell);
- off += scnprintf(buf + off, buf_size - off,
- "Doorbell Bell -\t\t%#llx\n", u.v64);
-
- off += scnprintf(buf + off, buf_size - off,
- "\nNTB Incoming XLAT:\n");
-
- u.v64 = ioread64(mmio + SKX_IMBAR1XBASE_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "IMBAR1XBASE -\t\t%#018llx\n", u.v64);
-
- u.v64 = ioread64(mmio + SKX_IMBAR2XBASE_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "IMBAR2XBASE -\t\t%#018llx\n", u.v64);
-
- u.v64 = ioread64(mmio + SKX_IMBAR1XLMT_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "IMBAR1XLMT -\t\t\t%#018llx\n", u.v64);
-
- u.v64 = ioread64(mmio + SKX_IMBAR2XLMT_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "IMBAR2XLMT -\t\t\t%#018llx\n", u.v64);
-
- if (ntb_topo_is_b2b(ndev->ntb.topo)) {
- off += scnprintf(buf + off, buf_size - off,
- "\nNTB Outgoing B2B XLAT:\n");
-
- u.v64 = ioread64(mmio + SKX_EMBAR1XBASE_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "EMBAR1XBASE -\t\t%#018llx\n", u.v64);
-
- u.v64 = ioread64(mmio + SKX_EMBAR2XBASE_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "EMBAR2XBASE -\t\t%#018llx\n", u.v64);
-
- u.v64 = ioread64(mmio + SKX_EMBAR1XLMT_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "EMBAR1XLMT -\t\t%#018llx\n", u.v64);
-
- u.v64 = ioread64(mmio + SKX_EMBAR2XLMT_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "EMBAR2XLMT -\t\t%#018llx\n", u.v64);
-
- off += scnprintf(buf + off, buf_size - off,
- "\nNTB Secondary BAR:\n");
-
- u.v64 = ioread64(mmio + SKX_EMBAR0_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "EMBAR0 -\t\t%#018llx\n", u.v64);
-
- u.v64 = ioread64(mmio + SKX_EMBAR1_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "EMBAR1 -\t\t%#018llx\n", u.v64);
-
- u.v64 = ioread64(mmio + SKX_EMBAR2_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "EMBAR2 -\t\t%#018llx\n", u.v64);
- }
-
- off += scnprintf(buf + off, buf_size - off,
- "\nNTB Statistics:\n");
-
- u.v16 = ioread16(mmio + SKX_USMEMMISS_OFFSET);
- off += scnprintf(buf + off, buf_size - off,
- "Upstream Memory Miss -\t%u\n", u.v16);
-
- off += scnprintf(buf + off, buf_size - off,
- "\nNTB Hardware Errors:\n");
-
- if (!pci_read_config_word(ndev->ntb.pdev,
- SKX_DEVSTS_OFFSET, &u.v16))
- off += scnprintf(buf + off, buf_size - off,
- "DEVSTS -\t\t%#06x\n", u.v16);
-
- if (!pci_read_config_word(ndev->ntb.pdev,
- SKX_LINK_STATUS_OFFSET, &u.v16))
- off += scnprintf(buf + off, buf_size - off,
- "LNKSTS -\t\t%#06x\n", u.v16);
-
- if (!pci_read_config_dword(ndev->ntb.pdev,
- SKX_UNCERRSTS_OFFSET, &u.v32))
- off += scnprintf(buf + off, buf_size - off,
- "UNCERRSTS -\t\t%#06x\n", u.v32);
-
- if (!pci_read_config_dword(ndev->ntb.pdev,
- SKX_CORERRSTS_OFFSET, &u.v32))
- off += scnprintf(buf + off, buf_size - off,
- "CORERRSTS -\t\t%#06x\n", u.v32);
-
- ret = simple_read_from_buffer(ubuf, count, offp, buf, off);
- kfree(buf);
- return ret;
-}
-
static ssize_t ndev_ntb_debugfs_read(struct file *filp, char __user *ubuf,
size_t count, loff_t *offp)
{
@@ -879,7 +648,7 @@ static ssize_t ndev_ntb_debugfs_read(struct file *filp, char __user *ubuf,
"LMT45 -\t\t\t%#018llx\n", u.v64);
}
- if (pdev_is_xeon(pdev)) {
+ if (pdev_is_gen1(pdev)) {
if (ntb_topo_is_b2b(ndev->ntb.topo)) {
off += scnprintf(buf + off, buf_size - off,
"\nNTB Outgoing B2B XLAT:\n");
@@ -991,9 +760,9 @@ static ssize_t ndev_debugfs_read(struct file *filp, char __user *ubuf,
{
struct intel_ntb_dev *ndev = filp->private_data;
- if (pdev_is_xeon(ndev->ntb.pdev))
+ if (pdev_is_gen1(ndev->ntb.pdev))
return ndev_ntb_debugfs_read(filp, ubuf, count, offp);
- else if (pdev_is_skx_xeon(ndev->ntb.pdev))
+ else if (pdev_is_gen3(ndev->ntb.pdev))
return ndev_ntb3_debugfs_read(filp, ubuf, count, offp);
return -ENXIO;
@@ -1023,7 +792,7 @@ static void ndev_deinit_debugfs(struct intel_ntb_dev *ndev)
debugfs_remove_recursive(ndev->debugfs_dir);
}
-static int intel_ntb_mw_count(struct ntb_dev *ntb, int pidx)
+int intel_ntb_mw_count(struct ntb_dev *ntb, int pidx)
{
if (pidx != NTB_DEF_PEER_IDX)
return -EINVAL;
@@ -1031,10 +800,10 @@ static int intel_ntb_mw_count(struct ntb_dev *ntb, int pidx)
return ntb_ndev(ntb)->mw_count;
}
-static int intel_ntb_mw_get_align(struct ntb_dev *ntb, int pidx, int idx,
- resource_size_t *addr_align,
- resource_size_t *size_align,
- resource_size_t *size_max)
+int intel_ntb_mw_get_align(struct ntb_dev *ntb, int pidx, int idx,
+ resource_size_t *addr_align,
+ resource_size_t *size_align,
+ resource_size_t *size_max)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
resource_size_t bar_size, mw_size;
@@ -1170,9 +939,8 @@ static int intel_ntb_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
return 0;
}
-static u64 intel_ntb_link_is_up(struct ntb_dev *ntb,
- enum ntb_speed *speed,
- enum ntb_width *width)
+u64 intel_ntb_link_is_up(struct ntb_dev *ntb, enum ntb_speed *speed,
+ enum ntb_width *width)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1224,7 +992,7 @@ static int intel_ntb_link_enable(struct ntb_dev *ntb,
return 0;
}
-static int intel_ntb_link_disable(struct ntb_dev *ntb)
+int intel_ntb_link_disable(struct ntb_dev *ntb)
{
struct intel_ntb_dev *ndev;
u32 ntb_cntl;
@@ -1248,14 +1016,14 @@ static int intel_ntb_link_disable(struct ntb_dev *ntb)
return 0;
}
-static int intel_ntb_peer_mw_count(struct ntb_dev *ntb)
+int intel_ntb_peer_mw_count(struct ntb_dev *ntb)
{
/* Numbers of inbound and outbound memory windows match */
return ntb_ndev(ntb)->mw_count;
}
-static int intel_ntb_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
- phys_addr_t *base, resource_size_t *size)
+int intel_ntb_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
+ phys_addr_t *base, resource_size_t *size)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
int bar;
@@ -1283,12 +1051,12 @@ static int intel_ntb_db_is_unsafe(struct ntb_dev *ntb)
return ndev_ignore_unsafe(ntb_ndev(ntb), NTB_UNSAFE_DB);
}
-static u64 intel_ntb_db_valid_mask(struct ntb_dev *ntb)
+u64 intel_ntb_db_valid_mask(struct ntb_dev *ntb)
{
return ntb_ndev(ntb)->db_valid_mask;
}
-static int intel_ntb_db_vector_count(struct ntb_dev *ntb)
+int intel_ntb_db_vector_count(struct ntb_dev *ntb)
{
struct intel_ntb_dev *ndev;
@@ -1297,7 +1065,7 @@ static int intel_ntb_db_vector_count(struct ntb_dev *ntb)
return ndev->db_vec_count;
}
-static u64 intel_ntb_db_vector_mask(struct ntb_dev *ntb, int db_vector)
+u64 intel_ntb_db_vector_mask(struct ntb_dev *ntb, int db_vector)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1325,7 +1093,7 @@ static int intel_ntb_db_clear(struct ntb_dev *ntb, u64 db_bits)
ndev->self_reg->db_bell);
}
-static int intel_ntb_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
+int intel_ntb_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1334,7 +1102,7 @@ static int intel_ntb_db_set_mask(struct ntb_dev *ntb, u64 db_bits)
ndev->self_reg->db_mask);
}
-static int intel_ntb_db_clear_mask(struct ntb_dev *ntb, u64 db_bits)
+int intel_ntb_db_clear_mask(struct ntb_dev *ntb, u64 db_bits)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1343,9 +1111,8 @@ static int intel_ntb_db_clear_mask(struct ntb_dev *ntb, u64 db_bits)
ndev->self_reg->db_mask);
}
-static int intel_ntb_peer_db_addr(struct ntb_dev *ntb,
- phys_addr_t *db_addr,
- resource_size_t *db_size)
+int intel_ntb_peer_db_addr(struct ntb_dev *ntb, phys_addr_t *db_addr,
+ resource_size_t *db_size)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1362,12 +1129,12 @@ static int intel_ntb_peer_db_set(struct ntb_dev *ntb, u64 db_bits)
ndev->peer_reg->db_bell);
}
-static int intel_ntb_spad_is_unsafe(struct ntb_dev *ntb)
+int intel_ntb_spad_is_unsafe(struct ntb_dev *ntb)
{
return ndev_ignore_unsafe(ntb_ndev(ntb), NTB_UNSAFE_SPAD);
}
-static int intel_ntb_spad_count(struct ntb_dev *ntb)
+int intel_ntb_spad_count(struct ntb_dev *ntb)
{
struct intel_ntb_dev *ndev;
@@ -1376,7 +1143,7 @@ static int intel_ntb_spad_count(struct ntb_dev *ntb)
return ndev->spad_count;
}
-static u32 intel_ntb_spad_read(struct ntb_dev *ntb, int idx)
+u32 intel_ntb_spad_read(struct ntb_dev *ntb, int idx)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1385,8 +1152,7 @@ static u32 intel_ntb_spad_read(struct ntb_dev *ntb, int idx)
ndev->self_reg->spad);
}
-static int intel_ntb_spad_write(struct ntb_dev *ntb,
- int idx, u32 val)
+int intel_ntb_spad_write(struct ntb_dev *ntb, int idx, u32 val)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1395,8 +1161,8 @@ static int intel_ntb_spad_write(struct ntb_dev *ntb,
ndev->self_reg->spad);
}
-static int intel_ntb_peer_spad_addr(struct ntb_dev *ntb, int pidx, int sidx,
- phys_addr_t *spad_addr)
+int intel_ntb_peer_spad_addr(struct ntb_dev *ntb, int pidx, int sidx,
+ phys_addr_t *spad_addr)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1404,7 +1170,7 @@ static int intel_ntb_peer_spad_addr(struct ntb_dev *ntb, int pidx, int sidx,
ndev->peer_reg->spad);
}
-static u32 intel_ntb_peer_spad_read(struct ntb_dev *ntb, int pidx, int sidx)
+u32 intel_ntb_peer_spad_read(struct ntb_dev *ntb, int pidx, int sidx)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1413,8 +1179,8 @@ static u32 intel_ntb_peer_spad_read(struct ntb_dev *ntb, int pidx, int sidx)
ndev->peer_reg->spad);
}
-static int intel_ntb_peer_spad_write(struct ntb_dev *ntb, int pidx,
- int sidx, u32 val)
+int intel_ntb_peer_spad_write(struct ntb_dev *ntb, int pidx, int sidx,
+ u32 val)
{
struct intel_ntb_dev *ndev = ntb_ndev(ntb);
@@ -1423,336 +1189,6 @@ static int intel_ntb_peer_spad_write(struct ntb_dev *ntb, int pidx,
ndev->peer_reg->spad);
}
-/* Skylake Xeon NTB */
-
-static int skx_poll_link(struct intel_ntb_dev *ndev)
-{
- u16 reg_val;
- int rc;
-
- ndev->reg->db_iowrite(ndev->db_link_mask,
- ndev->self_mmio +
- ndev->self_reg->db_clear);
-
- rc = pci_read_config_word(ndev->ntb.pdev,
- SKX_LINK_STATUS_OFFSET, &reg_val);
- if (rc)
- return 0;
-
- if (reg_val == ndev->lnk_sta)
- return 0;
-
- ndev->lnk_sta = reg_val;
-
- return 1;
-}
-
-static u64 skx_db_ioread(void __iomem *mmio)
-{
- return ioread64(mmio);
-}
-
-static void skx_db_iowrite(u64 bits, void __iomem *mmio)
-{
- iowrite64(bits, mmio);
-}
-
-static int skx_init_isr(struct intel_ntb_dev *ndev)
-{
- int i;
-
- /*
- * The MSIX vectors and the interrupt status bits are not lined up
- * on Skylake. By default the link status bit is bit 32, however it
- * is by default MSIX vector0. We need to fixup to line them up.
- * The vectors at reset is 1-32,0. We need to reprogram to 0-32.
- */
-
- for (i = 0; i < SKX_DB_MSIX_VECTOR_COUNT; i++)
- iowrite8(i, ndev->self_mmio + SKX_INTVEC_OFFSET + i);
-
- /* move link status down one as workaround */
- if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD) {
- iowrite8(SKX_DB_MSIX_VECTOR_COUNT - 2,
- ndev->self_mmio + SKX_INTVEC_OFFSET +
- (SKX_DB_MSIX_VECTOR_COUNT - 1));
- }
-
- return ndev_init_isr(ndev, SKX_DB_MSIX_VECTOR_COUNT,
- SKX_DB_MSIX_VECTOR_COUNT,
- SKX_DB_MSIX_VECTOR_SHIFT,
- SKX_DB_TOTAL_SHIFT);
-}
-
-static int skx_setup_b2b_mw(struct intel_ntb_dev *ndev,
- const struct intel_b2b_addr *addr,
- const struct intel_b2b_addr *peer_addr)
-{
- struct pci_dev *pdev;
- void __iomem *mmio;
- phys_addr_t bar_addr;
-
- pdev = ndev->ntb.pdev;
- mmio = ndev->self_mmio;
-
- /* setup incoming bar limits == base addrs (zero length windows) */
- bar_addr = addr->bar2_addr64;
- iowrite64(bar_addr, mmio + SKX_IMBAR1XLMT_OFFSET);
- bar_addr = ioread64(mmio + SKX_IMBAR1XLMT_OFFSET);
- dev_dbg(&pdev->dev, "IMBAR1XLMT %#018llx\n", bar_addr);
-
- bar_addr = addr->bar4_addr64;
- iowrite64(bar_addr, mmio + SKX_IMBAR2XLMT_OFFSET);
- bar_addr = ioread64(mmio + SKX_IMBAR2XLMT_OFFSET);
- dev_dbg(&pdev->dev, "IMBAR2XLMT %#018llx\n", bar_addr);
-
- /* zero incoming translation addrs */
- iowrite64(0, mmio + SKX_IMBAR1XBASE_OFFSET);
- iowrite64(0, mmio + SKX_IMBAR2XBASE_OFFSET);
-
- ndev->peer_mmio = ndev->self_mmio;
-
- return 0;
-}
-
-static int skx_init_ntb(struct intel_ntb_dev *ndev)
-{
- int rc;
-
-
- ndev->mw_count = XEON_MW_COUNT;
- ndev->spad_count = SKX_SPAD_COUNT;
- ndev->db_count = SKX_DB_COUNT;
- ndev->db_link_mask = SKX_DB_LINK_BIT;
-
- /* DB fixup for using 31 right now */
- if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD)
- ndev->db_link_mask |= BIT_ULL(31);
-
- switch (ndev->ntb.topo) {
- case NTB_TOPO_B2B_USD:
- case NTB_TOPO_B2B_DSD:
- ndev->self_reg = &skx_pri_reg;
- ndev->peer_reg = &skx_b2b_reg;
- ndev->xlat_reg = &skx_sec_xlat;
-
- if (ndev->ntb.topo == NTB_TOPO_B2B_USD) {
- rc = skx_setup_b2b_mw(ndev,
- &xeon_b2b_dsd_addr,
- &xeon_b2b_usd_addr);
- } else {
- rc = skx_setup_b2b_mw(ndev,
- &xeon_b2b_usd_addr,
- &xeon_b2b_dsd_addr);
- }
-
- if (rc)
- return rc;
-
- /* Enable Bus Master and Memory Space on the secondary side */
- iowrite16(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
- ndev->self_mmio + SKX_SPCICMD_OFFSET);
-
- break;
-
- default:
- return -EINVAL;
- }
-
- ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
-
- ndev->reg->db_iowrite(ndev->db_valid_mask,
- ndev->self_mmio +
- ndev->self_reg->db_mask);
-
- return 0;
-}
-
-static int skx_init_dev(struct intel_ntb_dev *ndev)
-{
- struct pci_dev *pdev;
- u8 ppd;
- int rc;
-
- pdev = ndev->ntb.pdev;
-
- ndev->reg = &skx_reg;
-
- rc = pci_read_config_byte(pdev, XEON_PPD_OFFSET, &ppd);
- if (rc)
- return -EIO;
-
- ndev->ntb.topo = xeon_ppd_topo(ndev, ppd);
- dev_dbg(&pdev->dev, "ppd %#x topo %s\n", ppd,
- ntb_topo_string(ndev->ntb.topo));
- if (ndev->ntb.topo == NTB_TOPO_NONE)
- return -EINVAL;
-
- if (pdev_is_skx_xeon(pdev))
- ndev->hwerr_flags |= NTB_HWERR_MSIX_VECTOR32_BAD;
-
- rc = skx_init_ntb(ndev);
- if (rc)
- return rc;
-
- return skx_init_isr(ndev);
-}
-
-static int intel_ntb3_link_enable(struct ntb_dev *ntb,
- enum ntb_speed max_speed,
- enum ntb_width max_width)
-{
- struct intel_ntb_dev *ndev;
- u32 ntb_ctl;
-
- ndev = container_of(ntb, struct intel_ntb_dev, ntb);
-
- dev_dbg(&ntb->pdev->dev,
- "Enabling link with max_speed %d max_width %d\n",
- max_speed, max_width);
-
- if (max_speed != NTB_SPEED_AUTO)
- dev_dbg(&ntb->pdev->dev, "ignoring max_speed %d\n", max_speed);
- if (max_width != NTB_WIDTH_AUTO)
- dev_dbg(&ntb->pdev->dev, "ignoring max_width %d\n", max_width);
-
- ntb_ctl = ioread32(ndev->self_mmio + ndev->reg->ntb_ctl);
- ntb_ctl &= ~(NTB_CTL_DISABLE | NTB_CTL_CFG_LOCK);
- ntb_ctl |= NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP;
- ntb_ctl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP;
- iowrite32(ntb_ctl, ndev->self_mmio + ndev->reg->ntb_ctl);
-
- return 0;
-}
-static int intel_ntb3_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
- dma_addr_t addr, resource_size_t size)
-{
- struct intel_ntb_dev *ndev = ntb_ndev(ntb);
- unsigned long xlat_reg, limit_reg;
- resource_size_t bar_size, mw_size;
- void __iomem *mmio;
- u64 base, limit, reg_val;
- int bar;
-
- if (pidx != NTB_DEF_PEER_IDX)
- return -EINVAL;
-
- if (idx >= ndev->b2b_idx && !ndev->b2b_off)
- idx += 1;
-
- bar = ndev_mw_to_bar(ndev, idx);
- if (bar < 0)
- return bar;
-
- bar_size = pci_resource_len(ndev->ntb.pdev, bar);
-
- if (idx == ndev->b2b_idx)
- mw_size = bar_size - ndev->b2b_off;
- else
- mw_size = bar_size;
-
- /* hardware requires that addr is aligned to bar size */
- if (addr & (bar_size - 1))
- return -EINVAL;
-
- /* make sure the range fits in the usable mw size */
- if (size > mw_size)
- return -EINVAL;
-
- mmio = ndev->self_mmio;
- xlat_reg = ndev->xlat_reg->bar2_xlat + (idx * 0x10);
- limit_reg = ndev->xlat_reg->bar2_limit + (idx * 0x10);
- base = pci_resource_start(ndev->ntb.pdev, bar);
-
- /* Set the limit if supported, if size is not mw_size */
- if (limit_reg && size != mw_size)
- limit = base + size;
- else
- limit = base + mw_size;
-
- /* set and verify setting the translation address */
- iowrite64(addr, mmio + xlat_reg);
- reg_val = ioread64(mmio + xlat_reg);
- if (reg_val != addr) {
- iowrite64(0, mmio + xlat_reg);
- return -EIO;
- }
-
- dev_dbg(&ntb->pdev->dev, "BAR %d IMBARXBASE: %#Lx\n", bar, reg_val);
-
- /* set and verify setting the limit */
- iowrite64(limit, mmio + limit_reg);
- reg_val = ioread64(mmio + limit_reg);
- if (reg_val != limit) {
- iowrite64(base, mmio + limit_reg);
- iowrite64(0, mmio + xlat_reg);
- return -EIO;
- }
-
- dev_dbg(&ntb->pdev->dev, "BAR %d IMBARXLMT: %#Lx\n", bar, reg_val);
-
- /* setup the EP */
- limit_reg = ndev->xlat_reg->bar2_limit + (idx * 0x10) + 0x4000;
- base = ioread64(mmio + SKX_EMBAR1_OFFSET + (8 * idx));
- base &= ~0xf;
-
- if (limit_reg && size != mw_size)
- limit = base + size;
- else
- limit = base + mw_size;
-
- /* set and verify setting the limit */
- iowrite64(limit, mmio + limit_reg);
- reg_val = ioread64(mmio + limit_reg);
- if (reg_val != limit) {
- iowrite64(base, mmio + limit_reg);
- iowrite64(0, mmio + xlat_reg);
- return -EIO;
- }
-
- dev_dbg(&ntb->pdev->dev, "BAR %d EMBARXLMT: %#Lx\n", bar, reg_val);
-
- return 0;
-}
-
-static int intel_ntb3_peer_db_set(struct ntb_dev *ntb, u64 db_bits)
-{
- struct intel_ntb_dev *ndev = ntb_ndev(ntb);
- int bit;
-
- if (db_bits & ~ndev->db_valid_mask)
- return -EINVAL;
-
- while (db_bits) {
- bit = __ffs(db_bits);
- iowrite32(1, ndev->peer_mmio +
- ndev->peer_reg->db_bell + (bit * 4));
- db_bits &= db_bits - 1;
- }
-
- return 0;
-}
-
-static u64 intel_ntb3_db_read(struct ntb_dev *ntb)
-{
- struct intel_ntb_dev *ndev = ntb_ndev(ntb);
-
- return ndev_db_read(ndev,
- ndev->self_mmio +
- ndev->self_reg->db_clear);
-}
-
-static int intel_ntb3_db_clear(struct ntb_dev *ntb, u64 db_bits)
-{
- struct intel_ntb_dev *ndev = ntb_ndev(ntb);
-
- return ndev_db_write(ndev, db_bits,
- ndev->self_mmio +
- ndev->self_reg->db_clear);
-}
-
-/* XEON */
-
static u64 xeon_db_ioread(void __iomem *mmio)
{
return (u64)ioread16(mmio);
@@ -1785,7 +1221,7 @@ static int xeon_poll_link(struct intel_ntb_dev *ndev)
return 1;
}
-static int xeon_link_is_up(struct intel_ntb_dev *ndev)
+int xeon_link_is_up(struct intel_ntb_dev *ndev)
{
if (ndev->ntb.topo == NTB_TOPO_SEC)
return 1;
@@ -1793,7 +1229,7 @@ static int xeon_link_is_up(struct intel_ntb_dev *ndev)
return NTB_LNK_STA_ACTIVE(ndev->lnk_sta);
}
-static inline enum ntb_topo xeon_ppd_topo(struct intel_ntb_dev *ndev, u8 ppd)
+enum ntb_topo xeon_ppd_topo(struct intel_ntb_dev *ndev, u8 ppd)
{
switch (ppd & XEON_PPD_TOPO_MASK) {
case XEON_PPD_TOPO_B2B_USD:
@@ -2410,7 +1846,7 @@ static int intel_ntb_pci_probe(struct pci_dev *pdev,
node = dev_to_node(&pdev->dev);
- if (pdev_is_xeon(pdev)) {
+ if (pdev_is_gen1(pdev)) {
ndev = kzalloc_node(sizeof(*ndev), GFP_KERNEL, node);
if (!ndev) {
rc = -ENOMEM;
@@ -2427,7 +1863,7 @@ static int intel_ntb_pci_probe(struct pci_dev *pdev,
if (rc)
goto err_init_dev;
- } else if (pdev_is_skx_xeon(pdev)) {
+ } else if (pdev_is_gen3(pdev)) {
ndev = kzalloc_node(sizeof(*ndev), GFP_KERNEL, node);
if (!ndev) {
rc = -ENOMEM;
@@ -2441,7 +1877,7 @@ static int intel_ntb_pci_probe(struct pci_dev *pdev,
if (rc)
goto err_init_pci;
- rc = skx_init_dev(ndev);
+ rc = gen3_init_dev(ndev);
if (rc)
goto err_init_dev;
@@ -2466,7 +1902,7 @@ static int intel_ntb_pci_probe(struct pci_dev *pdev,
err_register:
ndev_deinit_debugfs(ndev);
- if (pdev_is_xeon(pdev) || pdev_is_skx_xeon(pdev))
+ if (pdev_is_gen1(pdev) || pdev_is_gen3(pdev))
xeon_deinit_dev(ndev);
err_init_dev:
intel_ntb_deinit_pci(ndev);
@@ -2482,7 +1918,7 @@ static void intel_ntb_pci_remove(struct pci_dev *pdev)
ntb_unregister_device(&ndev->ntb);
ndev_deinit_debugfs(ndev);
- if (pdev_is_xeon(pdev) || pdev_is_skx_xeon(pdev))
+ if (pdev_is_gen1(pdev) || pdev_is_gen3(pdev))
xeon_deinit_dev(ndev);
intel_ntb_deinit_pci(ndev);
kfree(ndev);
@@ -2537,50 +1973,20 @@ static const struct intel_ntb_xlat_reg xeon_sec_xlat = {
.bar2_xlat = XEON_SBAR23XLAT_OFFSET,
};
-static struct intel_b2b_addr xeon_b2b_usd_addr = {
+struct intel_b2b_addr xeon_b2b_usd_addr = {
.bar2_addr64 = XEON_B2B_BAR2_ADDR64,
.bar4_addr64 = XEON_B2B_BAR4_ADDR64,
.bar4_addr32 = XEON_B2B_BAR4_ADDR32,
.bar5_addr32 = XEON_B2B_BAR5_ADDR32,
};
-static struct intel_b2b_addr xeon_b2b_dsd_addr = {
+struct intel_b2b_addr xeon_b2b_dsd_addr = {
.bar2_addr64 = XEON_B2B_BAR2_ADDR64,
.bar4_addr64 = XEON_B2B_BAR4_ADDR64,
.bar4_addr32 = XEON_B2B_BAR4_ADDR32,
.bar5_addr32 = XEON_B2B_BAR5_ADDR32,
};
-static const struct intel_ntb_reg skx_reg = {
- .poll_link = skx_poll_link,
- .link_is_up = xeon_link_is_up,
- .db_ioread = skx_db_ioread,
- .db_iowrite = skx_db_iowrite,
- .db_size = sizeof(u32),
- .ntb_ctl = SKX_NTBCNTL_OFFSET,
- .mw_bar = {2, 4},
-};
-
-static const struct intel_ntb_alt_reg skx_pri_reg = {
- .db_bell = SKX_EM_DOORBELL_OFFSET,
- .db_clear = SKX_IM_INT_STATUS_OFFSET,
- .db_mask = SKX_IM_INT_DISABLE_OFFSET,
- .spad = SKX_IM_SPAD_OFFSET,
-};
-
-static const struct intel_ntb_alt_reg skx_b2b_reg = {
- .db_bell = SKX_IM_DOORBELL_OFFSET,
- .db_clear = SKX_EM_INT_STATUS_OFFSET,
- .db_mask = SKX_EM_INT_DISABLE_OFFSET,
- .spad = SKX_B2B_SPAD_OFFSET,
-};
-
-static const struct intel_ntb_xlat_reg skx_sec_xlat = {
-/* .bar0_base = SKX_EMBAR0_OFFSET, */
- .bar2_limit = SKX_IMBAR1XLMT_OFFSET,
- .bar2_xlat = SKX_IMBAR1XBASE_OFFSET,
-};
-
/* operations for primary side of local ntb */
static const struct ntb_dev_ops intel_ntb_ops = {
.mw_count = intel_ntb_mw_count,
@@ -2610,33 +2016,6 @@ static const struct ntb_dev_ops intel_ntb_ops = {
.peer_spad_write = intel_ntb_peer_spad_write,
};
-static const struct ntb_dev_ops intel_ntb3_ops = {
- .mw_count = intel_ntb_mw_count,
- .mw_get_align = intel_ntb_mw_get_align,
- .mw_set_trans = intel_ntb3_mw_set_trans,
- .peer_mw_count = intel_ntb_peer_mw_count,
- .peer_mw_get_addr = intel_ntb_peer_mw_get_addr,
- .link_is_up = intel_ntb_link_is_up,
- .link_enable = intel_ntb3_link_enable,
- .link_disable = intel_ntb_link_disable,
- .db_valid_mask = intel_ntb_db_valid_mask,
- .db_vector_count = intel_ntb_db_vector_count,
- .db_vector_mask = intel_ntb_db_vector_mask,
- .db_read = intel_ntb3_db_read,
- .db_clear = intel_ntb3_db_clear,
- .db_set_mask = intel_ntb_db_set_mask,
- .db_clear_mask = intel_ntb_db_clear_mask,
- .peer_db_addr = intel_ntb_peer_db_addr,
- .peer_db_set = intel_ntb3_peer_db_set,
- .spad_is_unsafe = intel_ntb_spad_is_unsafe,
- .spad_count = intel_ntb_spad_count,
- .spad_read = intel_ntb_spad_read,
- .spad_write = intel_ntb_spad_write,
- .peer_spad_addr = intel_ntb_peer_spad_addr,
- .peer_spad_read = intel_ntb_peer_spad_read,
- .peer_spad_write = intel_ntb_peer_spad_write,
-};
-
static const struct file_operations intel_ntb_debugfs_info = {
.owner = THIS_MODULE,
.open = simple_open,
diff --git a/drivers/ntb/hw/intel/ntb_hw_gen1.h b/drivers/ntb/hw/intel/ntb_hw_gen1.h
new file mode 100644
index 0000000..ad8ec14
--- /dev/null
+++ b/drivers/ntb/hw/intel/ntb_hw_gen1.h
@@ -0,0 +1,182 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012-2017 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012-2017 Intel Corporation. All rights reserved.
+ *
+ * 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 copy
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NTB_INTEL_GEN1_H_
+#define _NTB_INTEL_GEN1_H_
+
+#include "ntb_hw_intel.h"
+
+/* Intel Gen1 Xeon hardware */
+#define XEON_PBAR23LMT_OFFSET 0x0000
+#define XEON_PBAR45LMT_OFFSET 0x0008
+#define XEON_PBAR4LMT_OFFSET 0x0008
+#define XEON_PBAR5LMT_OFFSET 0x000c
+#define XEON_PBAR23XLAT_OFFSET 0x0010
+#define XEON_PBAR45XLAT_OFFSET 0x0018
+#define XEON_PBAR4XLAT_OFFSET 0x0018
+#define XEON_PBAR5XLAT_OFFSET 0x001c
+#define XEON_SBAR23LMT_OFFSET 0x0020
+#define XEON_SBAR45LMT_OFFSET 0x0028
+#define XEON_SBAR4LMT_OFFSET 0x0028
+#define XEON_SBAR5LMT_OFFSET 0x002c
+#define XEON_SBAR23XLAT_OFFSET 0x0030
+#define XEON_SBAR45XLAT_OFFSET 0x0038
+#define XEON_SBAR4XLAT_OFFSET 0x0038
+#define XEON_SBAR5XLAT_OFFSET 0x003c
+#define XEON_SBAR0BASE_OFFSET 0x0040
+#define XEON_SBAR23BASE_OFFSET 0x0048
+#define XEON_SBAR45BASE_OFFSET 0x0050
+#define XEON_SBAR4BASE_OFFSET 0x0050
+#define XEON_SBAR5BASE_OFFSET 0x0054
+#define XEON_SBDF_OFFSET 0x005c
+#define XEON_NTBCNTL_OFFSET 0x0058
+#define XEON_PDOORBELL_OFFSET 0x0060
+#define XEON_PDBMSK_OFFSET 0x0062
+#define XEON_SDOORBELL_OFFSET 0x0064
+#define XEON_SDBMSK_OFFSET 0x0066
+#define XEON_USMEMMISS_OFFSET 0x0070
+#define XEON_SPAD_OFFSET 0x0080
+#define XEON_PBAR23SZ_OFFSET 0x00d0
+#define XEON_PBAR45SZ_OFFSET 0x00d1
+#define XEON_PBAR4SZ_OFFSET 0x00d1
+#define XEON_SBAR23SZ_OFFSET 0x00d2
+#define XEON_SBAR45SZ_OFFSET 0x00d3
+#define XEON_SBAR4SZ_OFFSET 0x00d3
+#define XEON_PPD_OFFSET 0x00d4
+#define XEON_PBAR5SZ_OFFSET 0x00d5
+#define XEON_SBAR5SZ_OFFSET 0x00d6
+#define XEON_WCCNTRL_OFFSET 0x00e0
+#define XEON_UNCERRSTS_OFFSET 0x014c
+#define XEON_CORERRSTS_OFFSET 0x0158
+#define XEON_LINK_STATUS_OFFSET 0x01a2
+#define XEON_SPCICMD_OFFSET 0x0504
+#define XEON_DEVCTRL_OFFSET 0x0598
+#define XEON_DEVSTS_OFFSET 0x059a
+#define XEON_SLINK_STATUS_OFFSET 0x05a2
+#define XEON_B2B_SPAD_OFFSET 0x0100
+#define XEON_B2B_DOORBELL_OFFSET 0x0140
+#define XEON_B2B_XLAT_OFFSETL 0x0144
+#define XEON_B2B_XLAT_OFFSETU 0x0148
+#define XEON_PPD_CONN_MASK 0x03
+#define XEON_PPD_CONN_TRANSPARENT 0x00
+#define XEON_PPD_CONN_B2B 0x01
+#define XEON_PPD_CONN_RP 0x02
+#define XEON_PPD_DEV_MASK 0x10
+#define XEON_PPD_DEV_USD 0x00
+#define XEON_PPD_DEV_DSD 0x10
+#define XEON_PPD_SPLIT_BAR_MASK 0x40
+
+#define XEON_PPD_TOPO_MASK (XEON_PPD_CONN_MASK | XEON_PPD_DEV_MASK)
+#define XEON_PPD_TOPO_PRI_USD (XEON_PPD_CONN_RP | XEON_PPD_DEV_USD)
+#define XEON_PPD_TOPO_PRI_DSD (XEON_PPD_CONN_RP | XEON_PPD_DEV_DSD)
+#define XEON_PPD_TOPO_SEC_USD (XEON_PPD_CONN_TRANSPARENT | XEON_PPD_DEV_USD)
+#define XEON_PPD_TOPO_SEC_DSD (XEON_PPD_CONN_TRANSPARENT | XEON_PPD_DEV_DSD)
+#define XEON_PPD_TOPO_B2B_USD (XEON_PPD_CONN_B2B | XEON_PPD_DEV_USD)
+#define XEON_PPD_TOPO_B2B_DSD (XEON_PPD_CONN_B2B | XEON_PPD_DEV_DSD)
+
+#define XEON_MW_COUNT 2
+#define HSX_SPLIT_BAR_MW_COUNT 3
+#define XEON_DB_COUNT 15
+#define XEON_DB_LINK 15
+#define XEON_DB_LINK_BIT BIT_ULL(XEON_DB_LINK)
+#define XEON_DB_MSIX_VECTOR_COUNT 4
+#define XEON_DB_MSIX_VECTOR_SHIFT 5
+#define XEON_DB_TOTAL_SHIFT 16
+#define XEON_SPAD_COUNT 16
+
+/* Use the following addresses for translation between b2b ntb devices in case
+ * the hardware default values are not reliable. */
+#define XEON_B2B_BAR0_ADDR 0x1000000000000000ull
+#define XEON_B2B_BAR2_ADDR64 0x2000000000000000ull
+#define XEON_B2B_BAR4_ADDR64 0x4000000000000000ull
+#define XEON_B2B_BAR4_ADDR32 0x20000000u
+#define XEON_B2B_BAR5_ADDR32 0x40000000u
+
+/* The peer ntb secondary config space is 32KB fixed size */
+#define XEON_B2B_MIN_SIZE 0x8000
+
+/* flags to indicate hardware errata */
+#define NTB_HWERR_SDOORBELL_LOCKUP BIT_ULL(0)
+#define NTB_HWERR_SB01BASE_LOCKUP BIT_ULL(1)
+#define NTB_HWERR_B2BDOORBELL_BIT14 BIT_ULL(2)
+#define NTB_HWERR_MSIX_VECTOR32_BAD BIT_ULL(3)
+
+extern struct intel_b2b_addr xeon_b2b_usd_addr;
+extern struct intel_b2b_addr xeon_b2b_dsd_addr;
+
+int ndev_init_isr(struct intel_ntb_dev *ndev, int msix_min, int msix_max,
+ int msix_shift, int total_shift);
+enum ntb_topo xeon_ppd_topo(struct intel_ntb_dev *ndev, u8 ppd);
+u64 ndev_db_read(struct intel_ntb_dev *ndev, void __iomem *mmio);
+int ndev_db_write(struct intel_ntb_dev *ndev, u64 db_bits,
+ void __iomem *mmio);
+int ndev_mw_to_bar(struct intel_ntb_dev *ndev, int idx);
+int intel_ntb_mw_count(struct ntb_dev *ntb, int pidx);
+int intel_ntb_mw_get_align(struct ntb_dev *ntb, int pidx, int idx,
+ resource_size_t *addr_align, resource_size_t *size_align,
+ resource_size_t *size_max);
+int intel_ntb_peer_mw_count(struct ntb_dev *ntb);
+int intel_ntb_peer_mw_get_addr(struct ntb_dev *ntb, int idx,
+ phys_addr_t *base, resource_size_t *size);
+u64 intel_ntb_link_is_up(struct ntb_dev *ntb, enum ntb_speed *speed,
+ enum ntb_width *width);
+int intel_ntb_link_disable(struct ntb_dev *ntb);
+u64 intel_ntb_db_valid_mask(struct ntb_dev *ntb);
+int intel_ntb_db_vector_count(struct ntb_dev *ntb);
+u64 intel_ntb_db_vector_mask(struct ntb_dev *ntb, int db_vector);
+int intel_ntb_db_set_mask(struct ntb_dev *ntb, u64 db_bits);
+int intel_ntb_db_clear_mask(struct ntb_dev *ntb, u64 db_bits);
+int intel_ntb_peer_db_addr(struct ntb_dev *ntb, phys_addr_t *db_addr,
+ resource_size_t *db_size);
+int intel_ntb_spad_is_unsafe(struct ntb_dev *ntb);
+int intel_ntb_spad_count(struct ntb_dev *ntb);
+u32 intel_ntb_spad_read(struct ntb_dev *ntb, int idx);
+int intel_ntb_spad_write(struct ntb_dev *ntb, int idx, u32 val);
+u32 intel_ntb_peer_spad_read(struct ntb_dev *ntb, int pidx, int sidx);
+int intel_ntb_peer_spad_write(struct ntb_dev *ntb, int pidx, int sidx,
+ u32 val);
+int intel_ntb_peer_spad_addr(struct ntb_dev *ntb, int pidx, int sidx,
+ phys_addr_t *spad_addr);
+int xeon_link_is_up(struct intel_ntb_dev *ndev);
+
+#endif
diff --git a/drivers/ntb/hw/intel/ntb_hw_gen3.c b/drivers/ntb/hw/intel/ntb_hw_gen3.c
new file mode 100644
index 0000000..b3fa247
--- /dev/null
+++ b/drivers/ntb/hw/intel/ntb_hw_gen3.c
@@ -0,0 +1,597 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ * 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 copy
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Intel PCIe GEN3 NTB Linux driver
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/ntb.h>
+
+#include "ntb_hw_intel.h"
+#include "ntb_hw_gen1.h"
+#include "ntb_hw_gen3.h"
+
+static int gen3_poll_link(struct intel_ntb_dev *ndev);
+
+static const struct intel_ntb_reg gen3_reg = {
+ .poll_link = gen3_poll_link,
+ .link_is_up = xeon_link_is_up,
+ .db_ioread = gen3_db_ioread,
+ .db_iowrite = gen3_db_iowrite,
+ .db_size = sizeof(u32),
+ .ntb_ctl = GEN3_NTBCNTL_OFFSET,
+ .mw_bar = {2, 4},
+};
+
+static const struct intel_ntb_alt_reg gen3_pri_reg = {
+ .db_bell = GEN3_EM_DOORBELL_OFFSET,
+ .db_clear = GEN3_IM_INT_STATUS_OFFSET,
+ .db_mask = GEN3_IM_INT_DISABLE_OFFSET,
+ .spad = GEN3_IM_SPAD_OFFSET,
+};
+
+static const struct intel_ntb_alt_reg gen3_b2b_reg = {
+ .db_bell = GEN3_IM_DOORBELL_OFFSET,
+ .db_clear = GEN3_EM_INT_STATUS_OFFSET,
+ .db_mask = GEN3_EM_INT_DISABLE_OFFSET,
+ .spad = GEN3_B2B_SPAD_OFFSET,
+};
+
+static const struct intel_ntb_xlat_reg gen3_sec_xlat = {
+/* .bar0_base = GEN3_EMBAR0_OFFSET, */
+ .bar2_limit = GEN3_IMBAR1XLMT_OFFSET,
+ .bar2_xlat = GEN3_IMBAR1XBASE_OFFSET,
+};
+
+static int gen3_poll_link(struct intel_ntb_dev *ndev)
+{
+ u16 reg_val;
+ int rc;
+
+ ndev->reg->db_iowrite(ndev->db_link_mask,
+ ndev->self_mmio +
+ ndev->self_reg->db_clear);
+
+ rc = pci_read_config_word(ndev->ntb.pdev,
+ GEN3_LINK_STATUS_OFFSET, &reg_val);
+ if (rc)
+ return 0;
+
+ if (reg_val == ndev->lnk_sta)
+ return 0;
+
+ ndev->lnk_sta = reg_val;
+
+ return 1;
+}
+
+static int gen3_init_isr(struct intel_ntb_dev *ndev)
+{
+ int i;
+
+ /*
+ * The MSIX vectors and the interrupt status bits are not lined up
+ * on Skylake. By default the link status bit is bit 32, however it
+ * is by default MSIX vector0. We need to fixup to line them up.
+ * The vectors at reset is 1-32,0. We need to reprogram to 0-32.
+ */
+
+ for (i = 0; i < GEN3_DB_MSIX_VECTOR_COUNT; i++)
+ iowrite8(i, ndev->self_mmio + GEN3_INTVEC_OFFSET + i);
+
+ /* move link status down one as workaround */
+ if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD) {
+ iowrite8(GEN3_DB_MSIX_VECTOR_COUNT - 2,
+ ndev->self_mmio + GEN3_INTVEC_OFFSET +
+ (GEN3_DB_MSIX_VECTOR_COUNT - 1));
+ }
+
+ return ndev_init_isr(ndev, GEN3_DB_MSIX_VECTOR_COUNT,
+ GEN3_DB_MSIX_VECTOR_COUNT,
+ GEN3_DB_MSIX_VECTOR_SHIFT,
+ GEN3_DB_TOTAL_SHIFT);
+}
+
+static int gen3_setup_b2b_mw(struct intel_ntb_dev *ndev,
+ const struct intel_b2b_addr *addr,
+ const struct intel_b2b_addr *peer_addr)
+{
+ struct pci_dev *pdev;
+ void __iomem *mmio;
+ phys_addr_t bar_addr;
+
+ pdev = ndev->ntb.pdev;
+ mmio = ndev->self_mmio;
+
+ /* setup incoming bar limits == base addrs (zero length windows) */
+ bar_addr = addr->bar2_addr64;
+ iowrite64(bar_addr, mmio + GEN3_IMBAR1XLMT_OFFSET);
+ bar_addr = ioread64(mmio + GEN3_IMBAR1XLMT_OFFSET);
+ dev_dbg(&pdev->dev, "IMBAR1XLMT %#018llx\n", bar_addr);
+
+ bar_addr = addr->bar4_addr64;
+ iowrite64(bar_addr, mmio + GEN3_IMBAR2XLMT_OFFSET);
+ bar_addr = ioread64(mmio + GEN3_IMBAR2XLMT_OFFSET);
+ dev_dbg(&pdev->dev, "IMBAR2XLMT %#018llx\n", bar_addr);
+
+ /* zero incoming translation addrs */
+ iowrite64(0, mmio + GEN3_IMBAR1XBASE_OFFSET);
+ iowrite64(0, mmio + GEN3_IMBAR2XBASE_OFFSET);
+
+ ndev->peer_mmio = ndev->self_mmio;
+
+ return 0;
+}
+
+static int gen3_init_ntb(struct intel_ntb_dev *ndev)
+{
+ int rc;
+
+
+ ndev->mw_count = XEON_MW_COUNT;
+ ndev->spad_count = GEN3_SPAD_COUNT;
+ ndev->db_count = GEN3_DB_COUNT;
+ ndev->db_link_mask = GEN3_DB_LINK_BIT;
+
+ /* DB fixup for using 31 right now */
+ if (ndev->hwerr_flags & NTB_HWERR_MSIX_VECTOR32_BAD)
+ ndev->db_link_mask |= BIT_ULL(31);
+
+ switch (ndev->ntb.topo) {
+ case NTB_TOPO_B2B_USD:
+ case NTB_TOPO_B2B_DSD:
+ ndev->self_reg = &gen3_pri_reg;
+ ndev->peer_reg = &gen3_b2b_reg;
+ ndev->xlat_reg = &gen3_sec_xlat;
+
+ if (ndev->ntb.topo == NTB_TOPO_B2B_USD) {
+ rc = gen3_setup_b2b_mw(ndev,
+ &xeon_b2b_dsd_addr,
+ &xeon_b2b_usd_addr);
+ } else {
+ rc = gen3_setup_b2b_mw(ndev,
+ &xeon_b2b_usd_addr,
+ &xeon_b2b_dsd_addr);
+ }
+
+ if (rc)
+ return rc;
+
+ /* Enable Bus Master and Memory Space on the secondary side */
+ iowrite16(PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER,
+ ndev->self_mmio + GEN3_SPCICMD_OFFSET);
+
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ ndev->db_valid_mask = BIT_ULL(ndev->db_count) - 1;
+
+ ndev->reg->db_iowrite(ndev->db_valid_mask,
+ ndev->self_mmio +
+ ndev->self_reg->db_mask);
+
+ return 0;
+}
+
+int gen3_init_dev(struct intel_ntb_dev *ndev)
+{
+ struct pci_dev *pdev;
+ u8 ppd;
+ int rc;
+
+ pdev = ndev->ntb.pdev;
+
+ ndev->reg = &gen3_reg;
+
+ rc = pci_read_config_byte(pdev, XEON_PPD_OFFSET, &ppd);
+ if (rc)
+ return -EIO;
+
+ ndev->ntb.topo = xeon_ppd_topo(ndev, ppd);
+ dev_dbg(&pdev->dev, "ppd %#x topo %s\n", ppd,
+ ntb_topo_string(ndev->ntb.topo));
+ if (ndev->ntb.topo == NTB_TOPO_NONE)
+ return -EINVAL;
+
+ ndev->hwerr_flags |= NTB_HWERR_MSIX_VECTOR32_BAD;
+
+ rc = gen3_init_ntb(ndev);
+ if (rc)
+ return rc;
+
+ return gen3_init_isr(ndev);
+}
+
+ssize_t ndev_ntb3_debugfs_read(struct file *filp, char __user *ubuf,
+ size_t count, loff_t *offp)
+{
+ struct intel_ntb_dev *ndev;
+ void __iomem *mmio;
+ char *buf;
+ size_t buf_size;
+ ssize_t ret, off;
+ union { u64 v64; u32 v32; u16 v16; } u;
+
+ ndev = filp->private_data;
+ mmio = ndev->self_mmio;
+
+ buf_size = min(count, 0x800ul);
+
+ buf = kmalloc(buf_size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ off = 0;
+
+ off += scnprintf(buf + off, buf_size - off,
+ "NTB Device Information:\n");
+
+ off += scnprintf(buf + off, buf_size - off,
+ "Connection Topology -\t%s\n",
+ ntb_topo_string(ndev->ntb.topo));
+
+ off += scnprintf(buf + off, buf_size - off,
+ "NTB CTL -\t\t%#06x\n", ndev->ntb_ctl);
+ off += scnprintf(buf + off, buf_size - off,
+ "LNK STA -\t\t%#06x\n", ndev->lnk_sta);
+
+ if (!ndev->reg->link_is_up(ndev))
+ off += scnprintf(buf + off, buf_size - off,
+ "Link Status -\t\tDown\n");
+ else {
+ off += scnprintf(buf + off, buf_size - off,
+ "Link Status -\t\tUp\n");
+ off += scnprintf(buf + off, buf_size - off,
+ "Link Speed -\t\tPCI-E Gen %u\n",
+ NTB_LNK_STA_SPEED(ndev->lnk_sta));
+ off += scnprintf(buf + off, buf_size - off,
+ "Link Width -\t\tx%u\n",
+ NTB_LNK_STA_WIDTH(ndev->lnk_sta));
+ }
+
+ off += scnprintf(buf + off, buf_size - off,
+ "Memory Window Count -\t%u\n", ndev->mw_count);
+ off += scnprintf(buf + off, buf_size - off,
+ "Scratchpad Count -\t%u\n", ndev->spad_count);
+ off += scnprintf(buf + off, buf_size - off,
+ "Doorbell Count -\t%u\n", ndev->db_count);
+ off += scnprintf(buf + off, buf_size - off,
+ "Doorbell Vector Count -\t%u\n", ndev->db_vec_count);
+ off += scnprintf(buf + off, buf_size - off,
+ "Doorbell Vector Shift -\t%u\n", ndev->db_vec_shift);
+
+ off += scnprintf(buf + off, buf_size - off,
+ "Doorbell Valid Mask -\t%#llx\n", ndev->db_valid_mask);
+ off += scnprintf(buf + off, buf_size - off,
+ "Doorbell Link Mask -\t%#llx\n", ndev->db_link_mask);
+ off += scnprintf(buf + off, buf_size - off,
+ "Doorbell Mask Cached -\t%#llx\n", ndev->db_mask);
+
+ u.v64 = ndev_db_read(ndev, mmio + ndev->self_reg->db_mask);
+ off += scnprintf(buf + off, buf_size - off,
+ "Doorbell Mask -\t\t%#llx\n", u.v64);
+
+ u.v64 = ndev_db_read(ndev, mmio + ndev->self_reg->db_bell);
+ off += scnprintf(buf + off, buf_size - off,
+ "Doorbell Bell -\t\t%#llx\n", u.v64);
+
+ off += scnprintf(buf + off, buf_size - off,
+ "\nNTB Incoming XLAT:\n");
+
+ u.v64 = ioread64(mmio + GEN3_IMBAR1XBASE_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "IMBAR1XBASE -\t\t%#018llx\n", u.v64);
+
+ u.v64 = ioread64(mmio + GEN3_IMBAR2XBASE_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "IMBAR2XBASE -\t\t%#018llx\n", u.v64);
+
+ u.v64 = ioread64(mmio + GEN3_IMBAR1XLMT_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "IMBAR1XLMT -\t\t\t%#018llx\n", u.v64);
+
+ u.v64 = ioread64(mmio + GEN3_IMBAR2XLMT_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "IMBAR2XLMT -\t\t\t%#018llx\n", u.v64);
+
+ if (ntb_topo_is_b2b(ndev->ntb.topo)) {
+ off += scnprintf(buf + off, buf_size - off,
+ "\nNTB Outgoing B2B XLAT:\n");
+
+ u.v64 = ioread64(mmio + GEN3_EMBAR1XBASE_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "EMBAR1XBASE -\t\t%#018llx\n", u.v64);
+
+ u.v64 = ioread64(mmio + GEN3_EMBAR2XBASE_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "EMBAR2XBASE -\t\t%#018llx\n", u.v64);
+
+ u.v64 = ioread64(mmio + GEN3_EMBAR1XLMT_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "EMBAR1XLMT -\t\t%#018llx\n", u.v64);
+
+ u.v64 = ioread64(mmio + GEN3_EMBAR2XLMT_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "EMBAR2XLMT -\t\t%#018llx\n", u.v64);
+
+ off += scnprintf(buf + off, buf_size - off,
+ "\nNTB Secondary BAR:\n");
+
+ u.v64 = ioread64(mmio + GEN3_EMBAR0_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "EMBAR0 -\t\t%#018llx\n", u.v64);
+
+ u.v64 = ioread64(mmio + GEN3_EMBAR1_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "EMBAR1 -\t\t%#018llx\n", u.v64);
+
+ u.v64 = ioread64(mmio + GEN3_EMBAR2_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "EMBAR2 -\t\t%#018llx\n", u.v64);
+ }
+
+ off += scnprintf(buf + off, buf_size - off,
+ "\nNTB Statistics:\n");
+
+ u.v16 = ioread16(mmio + GEN3_USMEMMISS_OFFSET);
+ off += scnprintf(buf + off, buf_size - off,
+ "Upstream Memory Miss -\t%u\n", u.v16);
+
+ off += scnprintf(buf + off, buf_size - off,
+ "\nNTB Hardware Errors:\n");
+
+ if (!pci_read_config_word(ndev->ntb.pdev,
+ GEN3_DEVSTS_OFFSET, &u.v16))
+ off += scnprintf(buf + off, buf_size - off,
+ "DEVSTS -\t\t%#06x\n", u.v16);
+
+ if (!pci_read_config_word(ndev->ntb.pdev,
+ GEN3_LINK_STATUS_OFFSET, &u.v16))
+ off += scnprintf(buf + off, buf_size - off,
+ "LNKSTS -\t\t%#06x\n", u.v16);
+
+ if (!pci_read_config_dword(ndev->ntb.pdev,
+ GEN3_UNCERRSTS_OFFSET, &u.v32))
+ off += scnprintf(buf + off, buf_size - off,
+ "UNCERRSTS -\t\t%#06x\n", u.v32);
+
+ if (!pci_read_config_dword(ndev->ntb.pdev,
+ GEN3_CORERRSTS_OFFSET, &u.v32))
+ off += scnprintf(buf + off, buf_size - off,
+ "CORERRSTS -\t\t%#06x\n", u.v32);
+
+ ret = simple_read_from_buffer(ubuf, count, offp, buf, off);
+ kfree(buf);
+ return ret;
+}
+
+static int intel_ntb3_link_enable(struct ntb_dev *ntb,
+ enum ntb_speed max_speed,
+ enum ntb_width max_width)
+{
+ struct intel_ntb_dev *ndev;
+ u32 ntb_ctl;
+
+ ndev = container_of(ntb, struct intel_ntb_dev, ntb);
+
+ dev_dbg(&ntb->pdev->dev,
+ "Enabling link with max_speed %d max_width %d\n",
+ max_speed, max_width);
+
+ if (max_speed != NTB_SPEED_AUTO)
+ dev_dbg(&ntb->pdev->dev, "ignoring max_speed %d\n", max_speed);
+ if (max_width != NTB_WIDTH_AUTO)
+ dev_dbg(&ntb->pdev->dev, "ignoring max_width %d\n", max_width);
+
+ ntb_ctl = ioread32(ndev->self_mmio + ndev->reg->ntb_ctl);
+ ntb_ctl &= ~(NTB_CTL_DISABLE | NTB_CTL_CFG_LOCK);
+ ntb_ctl |= NTB_CTL_P2S_BAR2_SNOOP | NTB_CTL_S2P_BAR2_SNOOP;
+ ntb_ctl |= NTB_CTL_P2S_BAR4_SNOOP | NTB_CTL_S2P_BAR4_SNOOP;
+ iowrite32(ntb_ctl, ndev->self_mmio + ndev->reg->ntb_ctl);
+
+ return 0;
+}
+static int intel_ntb3_mw_set_trans(struct ntb_dev *ntb, int pidx, int idx,
+ dma_addr_t addr, resource_size_t size)
+{
+ struct intel_ntb_dev *ndev = ntb_ndev(ntb);
+ unsigned long xlat_reg, limit_reg;
+ resource_size_t bar_size, mw_size;
+ void __iomem *mmio;
+ u64 base, limit, reg_val;
+ int bar;
+
+ if (pidx != NTB_DEF_PEER_IDX)
+ return -EINVAL;
+
+ if (idx >= ndev->b2b_idx && !ndev->b2b_off)
+ idx += 1;
+
+ bar = ndev_mw_to_bar(ndev, idx);
+ if (bar < 0)
+ return bar;
+
+ bar_size = pci_resource_len(ndev->ntb.pdev, bar);
+
+ if (idx == ndev->b2b_idx)
+ mw_size = bar_size - ndev->b2b_off;
+ else
+ mw_size = bar_size;
+
+ /* hardware requires that addr is aligned to bar size */
+ if (addr & (bar_size - 1))
+ return -EINVAL;
+
+ /* make sure the range fits in the usable mw size */
+ if (size > mw_size)
+ return -EINVAL;
+
+ mmio = ndev->self_mmio;
+ xlat_reg = ndev->xlat_reg->bar2_xlat + (idx * 0x10);
+ limit_reg = ndev->xlat_reg->bar2_limit + (idx * 0x10);
+ base = pci_resource_start(ndev->ntb.pdev, bar);
+
+ /* Set the limit if supported, if size is not mw_size */
+ if (limit_reg && size != mw_size)
+ limit = base + size;
+ else
+ limit = base + mw_size;
+
+ /* set and verify setting the translation address */
+ iowrite64(addr, mmio + xlat_reg);
+ reg_val = ioread64(mmio + xlat_reg);
+ if (reg_val != addr) {
+ iowrite64(0, mmio + xlat_reg);
+ return -EIO;
+ }
+
+ dev_dbg(&ntb->pdev->dev, "BAR %d IMBARXBASE: %#Lx\n", bar, reg_val);
+
+ /* set and verify setting the limit */
+ iowrite64(limit, mmio + limit_reg);
+ reg_val = ioread64(mmio + limit_reg);
+ if (reg_val != limit) {
+ iowrite64(base, mmio + limit_reg);
+ iowrite64(0, mmio + xlat_reg);
+ return -EIO;
+ }
+
+ dev_dbg(&ntb->pdev->dev, "BAR %d IMBARXLMT: %#Lx\n", bar, reg_val);
+
+ /* setup the EP */
+ limit_reg = ndev->xlat_reg->bar2_limit + (idx * 0x10) + 0x4000;
+ base = ioread64(mmio + GEN3_EMBAR1_OFFSET + (8 * idx));
+ base &= ~0xf;
+
+ if (limit_reg && size != mw_size)
+ limit = base + size;
+ else
+ limit = base + mw_size;
+
+ /* set and verify setting the limit */
+ iowrite64(limit, mmio + limit_reg);
+ reg_val = ioread64(mmio + limit_reg);
+ if (reg_val != limit) {
+ iowrite64(base, mmio + limit_reg);
+ iowrite64(0, mmio + xlat_reg);
+ return -EIO;
+ }
+
+ dev_dbg(&ntb->pdev->dev, "BAR %d EMBARXLMT: %#Lx\n", bar, reg_val);
+
+ return 0;
+}
+
+static int intel_ntb3_peer_db_set(struct ntb_dev *ntb, u64 db_bits)
+{
+ struct intel_ntb_dev *ndev = ntb_ndev(ntb);
+ int bit;
+
+ if (db_bits & ~ndev->db_valid_mask)
+ return -EINVAL;
+
+ while (db_bits) {
+ bit = __ffs(db_bits);
+ iowrite32(1, ndev->peer_mmio +
+ ndev->peer_reg->db_bell + (bit * 4));
+ db_bits &= db_bits - 1;
+ }
+
+ return 0;
+}
+
+static u64 intel_ntb3_db_read(struct ntb_dev *ntb)
+{
+ struct intel_ntb_dev *ndev = ntb_ndev(ntb);
+
+ return ndev_db_read(ndev,
+ ndev->self_mmio +
+ ndev->self_reg->db_clear);
+}
+
+static int intel_ntb3_db_clear(struct ntb_dev *ntb, u64 db_bits)
+{
+ struct intel_ntb_dev *ndev = ntb_ndev(ntb);
+
+ return ndev_db_write(ndev, db_bits,
+ ndev->self_mmio +
+ ndev->self_reg->db_clear);
+}
+
+const struct ntb_dev_ops intel_ntb3_ops = {
+ .mw_count = intel_ntb_mw_count,
+ .mw_get_align = intel_ntb_mw_get_align,
+ .mw_set_trans = intel_ntb3_mw_set_trans,
+ .peer_mw_count = intel_ntb_peer_mw_count,
+ .peer_mw_get_addr = intel_ntb_peer_mw_get_addr,
+ .link_is_up = intel_ntb_link_is_up,
+ .link_enable = intel_ntb3_link_enable,
+ .link_disable = intel_ntb_link_disable,
+ .db_valid_mask = intel_ntb_db_valid_mask,
+ .db_vector_count = intel_ntb_db_vector_count,
+ .db_vector_mask = intel_ntb_db_vector_mask,
+ .db_read = intel_ntb3_db_read,
+ .db_clear = intel_ntb3_db_clear,
+ .db_set_mask = intel_ntb_db_set_mask,
+ .db_clear_mask = intel_ntb_db_clear_mask,
+ .peer_db_addr = intel_ntb_peer_db_addr,
+ .peer_db_set = intel_ntb3_peer_db_set,
+ .spad_is_unsafe = intel_ntb_spad_is_unsafe,
+ .spad_count = intel_ntb_spad_count,
+ .spad_read = intel_ntb_spad_read,
+ .spad_write = intel_ntb_spad_write,
+ .peer_spad_addr = intel_ntb_peer_spad_addr,
+ .peer_spad_read = intel_ntb_peer_spad_read,
+ .peer_spad_write = intel_ntb_peer_spad_write,
+};
+
diff --git a/drivers/ntb/hw/intel/ntb_hw_gen3.h b/drivers/ntb/hw/intel/ntb_hw_gen3.h
new file mode 100644
index 0000000..75fb86c
--- /dev/null
+++ b/drivers/ntb/hw/intel/ntb_hw_gen3.h
@@ -0,0 +1,110 @@
+/*
+ * This file is provided under a dual BSD/GPLv2 license. When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2012-2017 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2012-2017 Intel Corporation. All rights reserved.
+ *
+ * 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 copy
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NTB_INTEL_GEN3_H_
+#define _NTB_INTEL_GEN3_H_
+
+#include "ntb_hw_intel.h"
+
+/* Intel Skylake Xeon hardware */
+#define GEN3_IMBAR1SZ_OFFSET 0x00d0
+#define GEN3_IMBAR2SZ_OFFSET 0x00d1
+#define GEN3_EMBAR1SZ_OFFSET 0x00d2
+#define GEN3_EMBAR2SZ_OFFSET 0x00d3
+#define GEN3_DEVCTRL_OFFSET 0x0098
+#define GEN3_DEVSTS_OFFSET 0x009a
+#define GEN3_UNCERRSTS_OFFSET 0x014c
+#define GEN3_CORERRSTS_OFFSET 0x0158
+#define GEN3_LINK_STATUS_OFFSET 0x01a2
+
+#define GEN3_NTBCNTL_OFFSET 0x0000
+#define GEN3_IMBAR1XBASE_OFFSET 0x0010 /* SBAR2XLAT */
+#define GEN3_IMBAR1XLMT_OFFSET 0x0018 /* SBAR2LMT */
+#define GEN3_IMBAR2XBASE_OFFSET 0x0020 /* SBAR4XLAT */
+#define GEN3_IMBAR2XLMT_OFFSET 0x0028 /* SBAR4LMT */
+#define GEN3_IM_INT_STATUS_OFFSET 0x0040
+#define GEN3_IM_INT_DISABLE_OFFSET 0x0048
+#define GEN3_IM_SPAD_OFFSET 0x0080 /* SPAD */
+#define GEN3_USMEMMISS_OFFSET 0x0070
+#define GEN3_INTVEC_OFFSET 0x00d0
+#define GEN3_IM_DOORBELL_OFFSET 0x0100 /* SDOORBELL0 */
+#define GEN3_B2B_SPAD_OFFSET 0x0180 /* B2B SPAD */
+#define GEN3_EMBAR0XBASE_OFFSET 0x4008 /* B2B_XLAT */
+#define GEN3_EMBAR1XBASE_OFFSET 0x4010 /* PBAR2XLAT */
+#define GEN3_EMBAR1XLMT_OFFSET 0x4018 /* PBAR2LMT */
+#define GEN3_EMBAR2XBASE_OFFSET 0x4020 /* PBAR4XLAT */
+#define GEN3_EMBAR2XLMT_OFFSET 0x4028 /* PBAR4LMT */
+#define GEN3_EM_INT_STATUS_OFFSET 0x4040
+#define GEN3_EM_INT_DISABLE_OFFSET 0x4048
+#define GEN3_EM_SPAD_OFFSET 0x4080 /* remote SPAD */
+#define GEN3_EM_DOORBELL_OFFSET 0x4100 /* PDOORBELL0 */
+#define GEN3_SPCICMD_OFFSET 0x4504 /* SPCICMD */
+#define GEN3_EMBAR0_OFFSET 0x4510 /* SBAR0BASE */
+#define GEN3_EMBAR1_OFFSET 0x4518 /* SBAR23BASE */
+#define GEN3_EMBAR2_OFFSET 0x4520 /* SBAR45BASE */
+
+#define GEN3_DB_COUNT 32
+#define GEN3_DB_LINK 32
+#define GEN3_DB_LINK_BIT BIT_ULL(GEN3_DB_LINK)
+#define GEN3_DB_MSIX_VECTOR_COUNT 33
+#define GEN3_DB_MSIX_VECTOR_SHIFT 1
+#define GEN3_DB_TOTAL_SHIFT 33
+#define GEN3_SPAD_COUNT 16
+
+static inline u64 gen3_db_ioread(void __iomem *mmio)
+{
+ return ioread64(mmio);
+}
+
+static inline void gen3_db_iowrite(u64 bits, void __iomem *mmio)
+{
+ iowrite64(bits, mmio);
+}
+
+ssize_t ndev_ntb3_debugfs_read(struct file *filp, char __user *ubuf,
+ size_t count, loff_t *offp);
+int gen3_init_dev(struct intel_ntb_dev *ndev);
+
+extern const struct ntb_dev_ops intel_ntb3_ops;
+
+#endif
diff --git a/drivers/ntb/hw/intel/ntb_hw_intel.h b/drivers/ntb/hw/intel/ntb_hw_intel.h
index 4415aa7..c49ff89 100644
--- a/drivers/ntb/hw/intel/ntb_hw_intel.h
+++ b/drivers/ntb/hw/intel/ntb_hw_intel.h
@@ -54,6 +54,7 @@
#include <linux/ntb.h>
#include <linux/pci.h>
+/* PCI device IDs */
#define PCI_DEVICE_ID_INTEL_NTB_B2B_JSF 0x3725
#define PCI_DEVICE_ID_INTEL_NTB_PS_JSF 0x3726
#define PCI_DEVICE_ID_INTEL_NTB_SS_JSF 0x3727
@@ -71,132 +72,7 @@
#define PCI_DEVICE_ID_INTEL_NTB_SS_BDX 0x6F0F
#define PCI_DEVICE_ID_INTEL_NTB_B2B_SKX 0x201C
-/* Intel Xeon hardware */
-
-#define XEON_PBAR23LMT_OFFSET 0x0000
-#define XEON_PBAR45LMT_OFFSET 0x0008
-#define XEON_PBAR4LMT_OFFSET 0x0008
-#define XEON_PBAR5LMT_OFFSET 0x000c
-#define XEON_PBAR23XLAT_OFFSET 0x0010
-#define XEON_PBAR45XLAT_OFFSET 0x0018
-#define XEON_PBAR4XLAT_OFFSET 0x0018
-#define XEON_PBAR5XLAT_OFFSET 0x001c
-#define XEON_SBAR23LMT_OFFSET 0x0020
-#define XEON_SBAR45LMT_OFFSET 0x0028
-#define XEON_SBAR4LMT_OFFSET 0x0028
-#define XEON_SBAR5LMT_OFFSET 0x002c
-#define XEON_SBAR23XLAT_OFFSET 0x0030
-#define XEON_SBAR45XLAT_OFFSET 0x0038
-#define XEON_SBAR4XLAT_OFFSET 0x0038
-#define XEON_SBAR5XLAT_OFFSET 0x003c
-#define XEON_SBAR0BASE_OFFSET 0x0040
-#define XEON_SBAR23BASE_OFFSET 0x0048
-#define XEON_SBAR45BASE_OFFSET 0x0050
-#define XEON_SBAR4BASE_OFFSET 0x0050
-#define XEON_SBAR5BASE_OFFSET 0x0054
-#define XEON_SBDF_OFFSET 0x005c
-#define XEON_NTBCNTL_OFFSET 0x0058
-#define XEON_PDOORBELL_OFFSET 0x0060
-#define XEON_PDBMSK_OFFSET 0x0062
-#define XEON_SDOORBELL_OFFSET 0x0064
-#define XEON_SDBMSK_OFFSET 0x0066
-#define XEON_USMEMMISS_OFFSET 0x0070
-#define XEON_SPAD_OFFSET 0x0080
-#define XEON_PBAR23SZ_OFFSET 0x00d0
-#define XEON_PBAR45SZ_OFFSET 0x00d1
-#define XEON_PBAR4SZ_OFFSET 0x00d1
-#define XEON_SBAR23SZ_OFFSET 0x00d2
-#define XEON_SBAR45SZ_OFFSET 0x00d3
-#define XEON_SBAR4SZ_OFFSET 0x00d3
-#define XEON_PPD_OFFSET 0x00d4
-#define XEON_PBAR5SZ_OFFSET 0x00d5
-#define XEON_SBAR5SZ_OFFSET 0x00d6
-#define XEON_WCCNTRL_OFFSET 0x00e0
-#define XEON_UNCERRSTS_OFFSET 0x014c
-#define XEON_CORERRSTS_OFFSET 0x0158
-#define XEON_LINK_STATUS_OFFSET 0x01a2
-#define XEON_SPCICMD_OFFSET 0x0504
-#define XEON_DEVCTRL_OFFSET 0x0598
-#define XEON_DEVSTS_OFFSET 0x059a
-#define XEON_SLINK_STATUS_OFFSET 0x05a2
-#define XEON_B2B_SPAD_OFFSET 0x0100
-#define XEON_B2B_DOORBELL_OFFSET 0x0140
-#define XEON_B2B_XLAT_OFFSETL 0x0144
-#define XEON_B2B_XLAT_OFFSETU 0x0148
-#define XEON_PPD_CONN_MASK 0x03
-#define XEON_PPD_CONN_TRANSPARENT 0x00
-#define XEON_PPD_CONN_B2B 0x01
-#define XEON_PPD_CONN_RP 0x02
-#define XEON_PPD_DEV_MASK 0x10
-#define XEON_PPD_DEV_USD 0x00
-#define XEON_PPD_DEV_DSD 0x10
-#define XEON_PPD_SPLIT_BAR_MASK 0x40
-
-#define XEON_PPD_TOPO_MASK (XEON_PPD_CONN_MASK | XEON_PPD_DEV_MASK)
-#define XEON_PPD_TOPO_PRI_USD (XEON_PPD_CONN_RP | XEON_PPD_DEV_USD)
-#define XEON_PPD_TOPO_PRI_DSD (XEON_PPD_CONN_RP | XEON_PPD_DEV_DSD)
-#define XEON_PPD_TOPO_SEC_USD (XEON_PPD_CONN_TRANSPARENT | XEON_PPD_DEV_USD)
-#define XEON_PPD_TOPO_SEC_DSD (XEON_PPD_CONN_TRANSPARENT | XEON_PPD_DEV_DSD)
-#define XEON_PPD_TOPO_B2B_USD (XEON_PPD_CONN_B2B | XEON_PPD_DEV_USD)
-#define XEON_PPD_TOPO_B2B_DSD (XEON_PPD_CONN_B2B | XEON_PPD_DEV_DSD)
-
-#define XEON_MW_COUNT 2
-#define HSX_SPLIT_BAR_MW_COUNT 3
-#define XEON_DB_COUNT 15
-#define XEON_DB_LINK 15
-#define XEON_DB_LINK_BIT BIT_ULL(XEON_DB_LINK)
-#define XEON_DB_MSIX_VECTOR_COUNT 4
-#define XEON_DB_MSIX_VECTOR_SHIFT 5
-#define XEON_DB_TOTAL_SHIFT 16
-#define XEON_SPAD_COUNT 16
-
-/* Intel Skylake Xeon hardware */
-#define SKX_IMBAR1SZ_OFFSET 0x00d0
-#define SKX_IMBAR2SZ_OFFSET 0x00d1
-#define SKX_EMBAR1SZ_OFFSET 0x00d2
-#define SKX_EMBAR2SZ_OFFSET 0x00d3
-#define SKX_DEVCTRL_OFFSET 0x0098
-#define SKX_DEVSTS_OFFSET 0x009a
-#define SKX_UNCERRSTS_OFFSET 0x014c
-#define SKX_CORERRSTS_OFFSET 0x0158
-#define SKX_LINK_STATUS_OFFSET 0x01a2
-
-#define SKX_NTBCNTL_OFFSET 0x0000
-#define SKX_IMBAR1XBASE_OFFSET 0x0010 /* SBAR2XLAT */
-#define SKX_IMBAR1XLMT_OFFSET 0x0018 /* SBAR2LMT */
-#define SKX_IMBAR2XBASE_OFFSET 0x0020 /* SBAR4XLAT */
-#define SKX_IMBAR2XLMT_OFFSET 0x0028 /* SBAR4LMT */
-#define SKX_IM_INT_STATUS_OFFSET 0x0040
-#define SKX_IM_INT_DISABLE_OFFSET 0x0048
-#define SKX_IM_SPAD_OFFSET 0x0080 /* SPAD */
-#define SKX_USMEMMISS_OFFSET 0x0070
-#define SKX_INTVEC_OFFSET 0x00d0
-#define SKX_IM_DOORBELL_OFFSET 0x0100 /* SDOORBELL0 */
-#define SKX_B2B_SPAD_OFFSET 0x0180 /* B2B SPAD */
-#define SKX_EMBAR0XBASE_OFFSET 0x4008 /* B2B_XLAT */
-#define SKX_EMBAR1XBASE_OFFSET 0x4010 /* PBAR2XLAT */
-#define SKX_EMBAR1XLMT_OFFSET 0x4018 /* PBAR2LMT */
-#define SKX_EMBAR2XBASE_OFFSET 0x4020 /* PBAR4XLAT */
-#define SKX_EMBAR2XLMT_OFFSET 0x4028 /* PBAR4LMT */
-#define SKX_EM_INT_STATUS_OFFSET 0x4040
-#define SKX_EM_INT_DISABLE_OFFSET 0x4048
-#define SKX_EM_SPAD_OFFSET 0x4080 /* remote SPAD */
-#define SKX_EM_DOORBELL_OFFSET 0x4100 /* PDOORBELL0 */
-#define SKX_SPCICMD_OFFSET 0x4504 /* SPCICMD */
-#define SKX_EMBAR0_OFFSET 0x4510 /* SBAR0BASE */
-#define SKX_EMBAR1_OFFSET 0x4518 /* SBAR23BASE */
-#define SKX_EMBAR2_OFFSET 0x4520 /* SBAR45BASE */
-
-#define SKX_DB_COUNT 32
-#define SKX_DB_LINK 32
-#define SKX_DB_LINK_BIT BIT_ULL(SKX_DB_LINK)
-#define SKX_DB_MSIX_VECTOR_COUNT 33
-#define SKX_DB_MSIX_VECTOR_SHIFT 1
-#define SKX_DB_TOTAL_SHIFT 33
-#define SKX_SPAD_COUNT 16
-
/* Ntb control and link status */
-
#define NTB_CTL_CFG_LOCK BIT(0)
#define NTB_CTL_DISABLE BIT(1)
#define NTB_CTL_S2P_BAR2_SNOOP BIT(2)
@@ -213,23 +89,6 @@
#define NTB_LNK_STA_SPEED(x) ((x) & NTB_LNK_STA_SPEED_MASK)
#define NTB_LNK_STA_WIDTH(x) (((x) & NTB_LNK_STA_WIDTH_MASK) >> 4)
-/* Use the following addresses for translation between b2b ntb devices in case
- * the hardware default values are not reliable. */
-#define XEON_B2B_BAR0_ADDR 0x1000000000000000ull
-#define XEON_B2B_BAR2_ADDR64 0x2000000000000000ull
-#define XEON_B2B_BAR4_ADDR64 0x4000000000000000ull
-#define XEON_B2B_BAR4_ADDR32 0x20000000u
-#define XEON_B2B_BAR5_ADDR32 0x40000000u
-
-/* The peer ntb secondary config space is 32KB fixed size */
-#define XEON_B2B_MIN_SIZE 0x8000
-
-/* flags to indicate hardware errata */
-#define NTB_HWERR_SDOORBELL_LOCKUP BIT_ULL(0)
-#define NTB_HWERR_SB01BASE_LOCKUP BIT_ULL(1)
-#define NTB_HWERR_B2BDOORBELL_BIT14 BIT_ULL(2)
-#define NTB_HWERR_MSIX_VECTOR32_BAD BIT_ULL(3)
-
/* flags to indicate unsafe api */
#define NTB_UNSAFE_DB BIT_ULL(0)
#define NTB_UNSAFE_SPAD BIT_ULL(1)
@@ -328,4 +187,64 @@ struct intel_ntb_dev {
#define hb_ndev(__work) container_of(__work, struct intel_ntb_dev, \
hb_timer.work)
+static inline int pdev_is_gen1(struct pci_dev *pdev)
+{
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_NTB_SS_JSF:
+ case PCI_DEVICE_ID_INTEL_NTB_SS_SNB:
+ case PCI_DEVICE_ID_INTEL_NTB_SS_IVT:
+ case PCI_DEVICE_ID_INTEL_NTB_SS_HSX:
+ case PCI_DEVICE_ID_INTEL_NTB_SS_BDX:
+ case PCI_DEVICE_ID_INTEL_NTB_PS_JSF:
+ case PCI_DEVICE_ID_INTEL_NTB_PS_SNB:
+ case PCI_DEVICE_ID_INTEL_NTB_PS_IVT:
+ case PCI_DEVICE_ID_INTEL_NTB_PS_HSX:
+ case PCI_DEVICE_ID_INTEL_NTB_PS_BDX:
+ case PCI_DEVICE_ID_INTEL_NTB_B2B_JSF:
+ case PCI_DEVICE_ID_INTEL_NTB_B2B_SNB:
+ case PCI_DEVICE_ID_INTEL_NTB_B2B_IVT:
+ case PCI_DEVICE_ID_INTEL_NTB_B2B_HSX:
+ case PCI_DEVICE_ID_INTEL_NTB_B2B_BDX:
+ return 1;
+ }
+ return 0;
+}
+
+static inline int pdev_is_gen3(struct pci_dev *pdev)
+{
+ if (pdev->device == PCI_DEVICE_ID_INTEL_NTB_B2B_SKX)
+ return 1;
+
+ return 0;
+}
+
+#ifndef ioread64
+#ifdef readq
+#define ioread64 readq
+#else
+#define ioread64 _ioread64
+static inline u64 _ioread64(void __iomem *mmio)
+{
+ u64 low, high;
+
+ low = ioread32(mmio);
+ high = ioread32(mmio + sizeof(u32));
+ return low | (high << 32);
+}
+#endif
+#endif
+
+#ifndef iowrite64
+#ifdef writeq
+#define iowrite64 writeq
+#else
+#define iowrite64 _iowrite64
+static inline void _iowrite64(u64 val, void __iomem *mmio)
+{
+ iowrite32(val, mmio);
+ iowrite32(val >> 32, mmio + sizeof(u32));
+}
+#endif
+#endif
+
#endif
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index 9878c48..9398959 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -637,7 +637,7 @@ static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt,
*/
node = dev_to_node(&ndev->dev);
for (i = qp->rx_alloc_entry; i < qp->rx_max_entry; i++) {
- entry = kzalloc_node(sizeof(*entry), GFP_ATOMIC, node);
+ entry = kzalloc_node(sizeof(*entry), GFP_KERNEL, node);
if (!entry)
return -ENOMEM;
@@ -1102,7 +1102,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
max_mw_count_for_spads = (spad_count - MW0_SZ_HIGH) / 2;
nt->mw_count = min(mw_count, max_mw_count_for_spads);
- nt->mw_vec = kzalloc_node(mw_count * sizeof(*nt->mw_vec),
+ nt->mw_vec = kcalloc_node(mw_count, sizeof(*nt->mw_vec),
GFP_KERNEL, node);
if (!nt->mw_vec) {
rc = -ENOMEM;
@@ -1143,7 +1143,7 @@ static int ntb_transport_probe(struct ntb_client *self, struct ntb_dev *ndev)
nt->qp_bitmap = qp_bitmap;
nt->qp_bitmap_free = qp_bitmap;
- nt->qp_vec = kzalloc_node(qp_count * sizeof(*nt->qp_vec),
+ nt->qp_vec = kcalloc_node(qp_count, sizeof(*nt->qp_vec),
GFP_KERNEL, node);
if (!nt->qp_vec) {
rc = -ENOMEM;
@@ -1828,7 +1828,7 @@ ntb_transport_create_queue(void *data, struct device *client_dev,
qp->rx_dma_chan ? "DMA" : "CPU");
for (i = 0; i < NTB_QP_DEF_NUM_ENTRIES; i++) {
- entry = kzalloc_node(sizeof(*entry), GFP_ATOMIC, node);
+ entry = kzalloc_node(sizeof(*entry), GFP_KERNEL, node);
if (!entry)
goto err1;
@@ -1839,7 +1839,7 @@ ntb_transport_create_queue(void *data, struct device *client_dev,
qp->rx_alloc_entry = NTB_QP_DEF_NUM_ENTRIES;
for (i = 0; i < qp->tx_max_entry; i++) {
- entry = kzalloc_node(sizeof(*entry), GFP_ATOMIC, node);
+ entry = kzalloc_node(sizeof(*entry), GFP_KERNEL, node);
if (!entry)
goto err2;
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index effb130..46df030 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1808,6 +1808,7 @@ static void nvme_set_queue_limits(struct nvme_ctrl *ctrl,
u32 max_segments =
(ctrl->max_hw_sectors / (ctrl->page_size >> 9)) + 1;
+ max_segments = min_not_zero(max_segments, ctrl->max_segments);
blk_queue_max_hw_sectors(q, ctrl->max_hw_sectors);
blk_queue_max_segments(q, min_t(u32, max_segments, USHRT_MAX));
}
@@ -2208,7 +2209,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
* Verify that the subsystem actually supports multiple
* controllers, else bail out.
*/
- if (!ctrl->opts->discovery_nqn &&
+ if (!(ctrl->opts && ctrl->opts->discovery_nqn) &&
nvme_active_ctrls(found) && !(id->cmic & (1 << 1))) {
dev_err(ctrl->device,
"ignoring ctrl due to duplicate subnqn (%s).\n",
@@ -3197,40 +3198,28 @@ static void nvme_scan_ns_sequential(struct nvme_ctrl *ctrl, unsigned nn)
nvme_remove_invalid_namespaces(ctrl, nn);
}
-static bool nvme_scan_changed_ns_log(struct nvme_ctrl *ctrl)
+static void nvme_clear_changed_ns_log(struct nvme_ctrl *ctrl)
{
size_t log_size = NVME_MAX_CHANGED_NAMESPACES * sizeof(__le32);
__le32 *log;
- int error, i;
- bool ret = false;
+ int error;
log = kzalloc(log_size, GFP_KERNEL);
if (!log)
- return false;
+ return;
+ /*
+ * We need to read the log to clear the AEN, but we don't want to rely
+ * on it for the changed namespace information as userspace could have
+ * raced with us in reading the log page, which could cause us to miss
+ * updates.
+ */
error = nvme_get_log(ctrl, NVME_LOG_CHANGED_NS, log, log_size);
- if (error) {
+ if (error)
dev_warn(ctrl->device,
"reading changed ns log failed: %d\n", error);
- goto out_free_log;
- }
-
- if (log[0] == cpu_to_le32(0xffffffff))
- goto out_free_log;
-
- for (i = 0; i < NVME_MAX_CHANGED_NAMESPACES; i++) {
- u32 nsid = le32_to_cpu(log[i]);
- if (nsid == 0)
- break;
- dev_info(ctrl->device, "rescanning namespace %d.\n", nsid);
- nvme_validate_ns(ctrl, nsid);
- }
- ret = true;
-
-out_free_log:
kfree(log);
- return ret;
}
static void nvme_scan_work(struct work_struct *work)
@@ -3246,9 +3235,8 @@ static void nvme_scan_work(struct work_struct *work)
WARN_ON_ONCE(!ctrl->tagset);
if (test_and_clear_bit(NVME_AER_NOTICE_NS_CHANGED, &ctrl->events)) {
- if (nvme_scan_changed_ns_log(ctrl))
- goto out_sort_namespaces;
dev_info(ctrl->device, "rescanning namespaces.\n");
+ nvme_clear_changed_ns_log(ctrl);
}
if (nvme_identify_ctrl(ctrl, &id))
@@ -3263,7 +3251,6 @@ static void nvme_scan_work(struct work_struct *work)
nvme_scan_ns_sequential(ctrl, nn);
out_free_id:
kfree(id);
-out_sort_namespaces:
down_write(&ctrl->namespaces_rwsem);
list_sort(NULL, &ctrl->namespaces, ns_cmp);
up_write(&ctrl->namespaces_rwsem);
@@ -3641,16 +3628,6 @@ void nvme_start_queues(struct nvme_ctrl *ctrl)
}
EXPORT_SYMBOL_GPL(nvme_start_queues);
-int nvme_reinit_tagset(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set)
-{
- if (!ctrl->ops->reinit_request)
- return 0;
-
- return blk_mq_tagset_iter(set, set->driver_data,
- ctrl->ops->reinit_request);
-}
-EXPORT_SYMBOL_GPL(nvme_reinit_tagset);
-
int __init nvme_core_init(void)
{
int result = -ENOMEM;
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index fa32c12..903eb45 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -536,67 +536,55 @@ static struct nvmf_transport_ops *nvmf_lookup_transport(
return NULL;
}
-blk_status_t nvmf_check_if_ready(struct nvme_ctrl *ctrl, struct request *rq,
- bool queue_live, bool is_connected)
+/*
+ * For something we're not in a state to send to the device the default action
+ * is to busy it and retry it after the controller state is recovered. However,
+ * anything marked for failfast or nvme multipath is immediately failed.
+ *
+ * Note: commands used to initialize the controller will be marked for failfast.
+ * Note: nvme cli/ioctl commands are marked for failfast.
+ */
+blk_status_t nvmf_fail_nonready_command(struct request *rq)
{
- struct nvme_command *cmd = nvme_req(rq)->cmd;
+ if (!blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH))
+ return BLK_STS_RESOURCE;
+ nvme_req(rq)->status = NVME_SC_ABORT_REQ;
+ return BLK_STS_IOERR;
+}
+EXPORT_SYMBOL_GPL(nvmf_fail_nonready_command);
- if (likely(ctrl->state == NVME_CTRL_LIVE && is_connected))
- return BLK_STS_OK;
+bool __nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
+ bool queue_live)
+{
+ struct nvme_request *req = nvme_req(rq);
+
+ /*
+ * If we are in some state of setup or teardown only allow
+ * internally generated commands.
+ */
+ if (!blk_rq_is_passthrough(rq) || (req->flags & NVME_REQ_USERCMD))
+ return false;
+ /*
+ * Only allow commands on a live queue, except for the connect command,
+ * which is require to set the queue live in the appropinquate states.
+ */
switch (ctrl->state) {
case NVME_CTRL_NEW:
case NVME_CTRL_CONNECTING:
- case NVME_CTRL_DELETING:
- /*
- * This is the case of starting a new or deleting an association
- * but connectivity was lost before it was fully created or torn
- * down. We need to error the commands used to initialize the
- * controller so the reconnect can go into a retry attempt. The
- * commands should all be marked REQ_FAILFAST_DRIVER, which will
- * hit the reject path below. Anything else will be queued while
- * the state settles.
- */
- if (!is_connected)
- break;
-
- /*
- * If queue is live, allow only commands that are internally
- * generated pass through. These are commands on the admin
- * queue to initialize the controller. This will reject any
- * ioctl admin cmds received while initializing.
- */
- if (queue_live && !(nvme_req(rq)->flags & NVME_REQ_USERCMD))
- return BLK_STS_OK;
-
- /*
- * If the queue is not live, allow only a connect command. This
- * will reject any ioctl admin cmd as well as initialization
- * commands if the controller reverted the queue to non-live.
- */
- if (!queue_live && blk_rq_is_passthrough(rq) &&
- cmd->common.opcode == nvme_fabrics_command &&
- cmd->fabrics.fctype == nvme_fabrics_type_connect)
- return BLK_STS_OK;
+ if (req->cmd->common.opcode == nvme_fabrics_command &&
+ req->cmd->fabrics.fctype == nvme_fabrics_type_connect)
+ return true;
break;
default:
break;
+ case NVME_CTRL_DEAD:
+ return false;
}
- /*
- * Any other new io is something we're not in a state to send to the
- * device. Default action is to busy it and retry it after the
- * controller state is recovered. However, anything marked for failfast
- * or nvme multipath is immediately failed. Note: commands used to
- * initialize the controller will be marked for failfast.
- * Note: nvme cli/ioctl commands are marked for failfast.
- */
- if (!blk_noretry_request(rq) && !(rq->cmd_flags & REQ_NVME_MPATH))
- return BLK_STS_RESOURCE;
- nvme_req(rq)->status = NVME_SC_ABORT_REQ;
- return BLK_STS_IOERR;
+ return queue_live;
}
-EXPORT_SYMBOL_GPL(nvmf_check_if_ready);
+EXPORT_SYMBOL_GPL(__nvmf_check_ready);
static const match_table_t opt_tokens = {
{ NVMF_OPT_TRANSPORT, "transport=%s" },
diff --git a/drivers/nvme/host/fabrics.h b/drivers/nvme/host/fabrics.h
index 7491a0b..e1818a2 100644
--- a/drivers/nvme/host/fabrics.h
+++ b/drivers/nvme/host/fabrics.h
@@ -162,7 +162,17 @@ void nvmf_unregister_transport(struct nvmf_transport_ops *ops);
void nvmf_free_options(struct nvmf_ctrl_options *opts);
int nvmf_get_address(struct nvme_ctrl *ctrl, char *buf, int size);
bool nvmf_should_reconnect(struct nvme_ctrl *ctrl);
-blk_status_t nvmf_check_if_ready(struct nvme_ctrl *ctrl,
- struct request *rq, bool queue_live, bool is_connected);
+blk_status_t nvmf_fail_nonready_command(struct request *rq);
+bool __nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
+ bool queue_live);
+
+static inline bool nvmf_check_ready(struct nvme_ctrl *ctrl, struct request *rq,
+ bool queue_live)
+{
+ if (likely(ctrl->state == NVME_CTRL_LIVE ||
+ ctrl->state == NVME_CTRL_ADMIN_ONLY))
+ return true;
+ return __nvmf_check_ready(ctrl, rq, queue_live);
+}
#endif /* _NVME_FABRICS_H */
diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
index 0bad658..41d45a1b 100644
--- a/drivers/nvme/host/fc.c
+++ b/drivers/nvme/host/fc.c
@@ -142,6 +142,7 @@ struct nvme_fc_ctrl {
struct nvme_fc_rport *rport;
u32 cnum;
+ bool ioq_live;
bool assoc_active;
u64 association_id;
@@ -1470,21 +1471,6 @@ nvme_fc_xmt_disconnect_assoc(struct nvme_fc_ctrl *ctrl)
static void nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg);
-static int
-nvme_fc_reinit_request(void *data, struct request *rq)
-{
- struct nvme_fc_fcp_op *op = blk_mq_rq_to_pdu(rq);
- struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu;
-
- memset(cmdiu, 0, sizeof(*cmdiu));
- cmdiu->scsi_id = NVME_CMD_SCSI_ID;
- cmdiu->fc_id = NVME_CMD_FC_ID;
- cmdiu->iu_len = cpu_to_be16(sizeof(*cmdiu) / sizeof(u32));
- memset(&op->rsp_iu, 0, sizeof(op->rsp_iu));
-
- return 0;
-}
-
static void
__nvme_fc_exit_request(struct nvme_fc_ctrl *ctrl,
struct nvme_fc_fcp_op *op)
@@ -1893,6 +1879,7 @@ nvme_fc_free_queue(struct nvme_fc_queue *queue)
*/
queue->connection_id = 0;
+ atomic_set(&queue->csn, 1);
}
static void
@@ -2279,14 +2266,13 @@ nvme_fc_queue_rq(struct blk_mq_hw_ctx *hctx,
struct nvme_fc_cmd_iu *cmdiu = &op->cmd_iu;
struct nvme_command *sqe = &cmdiu->sqe;
enum nvmefc_fcp_datadir io_dir;
+ bool queue_ready = test_bit(NVME_FC_Q_LIVE, &queue->flags);
u32 data_len;
blk_status_t ret;
- ret = nvmf_check_if_ready(&queue->ctrl->ctrl, rq,
- test_bit(NVME_FC_Q_LIVE, &queue->flags),
- ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE);
- if (unlikely(ret))
- return ret;
+ if (ctrl->rport->remoteport.port_state != FC_OBJSTATE_ONLINE ||
+ !nvmf_check_ready(&queue->ctrl->ctrl, rq, queue_ready))
+ return nvmf_fail_nonready_command(rq);
ret = nvme_setup_cmd(ns, rq, sqe);
if (ret)
@@ -2463,6 +2449,8 @@ nvme_fc_create_io_queues(struct nvme_fc_ctrl *ctrl)
if (ret)
goto out_delete_hw_queues;
+ ctrl->ioq_live = true;
+
return 0;
out_delete_hw_queues:
@@ -2480,7 +2468,7 @@ out_free_tag_set:
}
static int
-nvme_fc_reinit_io_queues(struct nvme_fc_ctrl *ctrl)
+nvme_fc_recreate_io_queues(struct nvme_fc_ctrl *ctrl)
{
struct nvmf_ctrl_options *opts = ctrl->ctrl.opts;
unsigned int nr_io_queues;
@@ -2500,12 +2488,6 @@ nvme_fc_reinit_io_queues(struct nvme_fc_ctrl *ctrl)
if (ctrl->ctrl.queue_count == 1)
return 0;
- nvme_fc_init_io_queues(ctrl);
-
- ret = nvme_reinit_tagset(&ctrl->ctrl, ctrl->ctrl.tagset);
- if (ret)
- goto out_free_io_queues;
-
ret = nvme_fc_create_hw_io_queues(ctrl, ctrl->ctrl.sqsize + 1);
if (ret)
goto out_free_io_queues;
@@ -2603,8 +2585,6 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
* Create the admin queue
*/
- nvme_fc_init_queue(ctrl, 0);
-
ret = __nvme_fc_create_hw_queue(ctrl, &ctrl->queues[0], 0,
NVME_AQ_DEPTH);
if (ret)
@@ -2615,8 +2595,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
if (ret)
goto out_delete_hw_queue;
- if (ctrl->ctrl.state != NVME_CTRL_NEW)
- blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
+ blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
ret = nvmf_connect_admin_queue(&ctrl->ctrl);
if (ret)
@@ -2689,10 +2668,10 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
*/
if (ctrl->ctrl.queue_count > 1) {
- if (ctrl->ctrl.state == NVME_CTRL_NEW)
+ if (!ctrl->ioq_live)
ret = nvme_fc_create_io_queues(ctrl);
else
- ret = nvme_fc_reinit_io_queues(ctrl);
+ ret = nvme_fc_recreate_io_queues(ctrl);
if (ret)
goto out_term_aen_ops;
}
@@ -2776,8 +2755,7 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl)
* use blk_mq_tagset_busy_itr() and the transport routine to
* terminate the exchanges.
*/
- if (ctrl->ctrl.state != NVME_CTRL_NEW)
- blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
+ blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
nvme_fc_terminate_exchange, &ctrl->ctrl);
@@ -2812,6 +2790,9 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl)
/* re-enable the admin_q so anything new can fast fail */
blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
+ /* resume the io queues so that things will fast fail */
+ nvme_start_queues(&ctrl->ctrl);
+
nvme_fc_ctlr_inactive_on_rport(ctrl);
}
@@ -2826,9 +2807,6 @@ nvme_fc_delete_ctrl(struct nvme_ctrl *nctrl)
* waiting for io to terminate
*/
nvme_fc_delete_association(ctrl);
-
- /* resume the io queues so that things will fast fail */
- nvme_start_queues(nctrl);
}
static void
@@ -2917,7 +2895,6 @@ static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = {
.submit_async_event = nvme_fc_submit_async_event,
.delete_ctrl = nvme_fc_delete_ctrl,
.get_address = nvmf_get_address,
- .reinit_request = nvme_fc_reinit_request,
};
static void
@@ -2934,7 +2911,7 @@ nvme_fc_connect_ctrl_work(struct work_struct *work)
nvme_fc_reconnect_or_delete(ctrl, ret);
else
dev_info(ctrl->ctrl.device,
- "NVME-FC{%d}: controller reconnect complete\n",
+ "NVME-FC{%d}: controller connect complete\n",
ctrl->cnum);
}
@@ -2982,7 +2959,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
{
struct nvme_fc_ctrl *ctrl;
unsigned long flags;
- int ret, idx, retry;
+ int ret, idx;
if (!(rport->remoteport.port_role &
(FC_PORT_ROLE_NVME_DISCOVERY | FC_PORT_ROLE_NVME_TARGET))) {
@@ -3009,11 +2986,13 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
}
ctrl->ctrl.opts = opts;
+ ctrl->ctrl.nr_reconnects = 0;
INIT_LIST_HEAD(&ctrl->ctrl_list);
ctrl->lport = lport;
ctrl->rport = rport;
ctrl->dev = lport->dev;
ctrl->cnum = idx;
+ ctrl->ioq_live = false;
ctrl->assoc_active = false;
init_waitqueue_head(&ctrl->ioabort_wait);
@@ -3032,6 +3011,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
ctrl->ctrl.sqsize = opts->queue_size - 1;
ctrl->ctrl.kato = opts->kato;
+ ctrl->ctrl.cntlid = 0xffff;
ret = -ENOMEM;
ctrl->queues = kcalloc(ctrl->ctrl.queue_count,
@@ -3039,6 +3019,8 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
if (!ctrl->queues)
goto out_free_ida;
+ nvme_fc_init_queue(ctrl, 0);
+
memset(&ctrl->admin_tag_set, 0, sizeof(ctrl->admin_tag_set));
ctrl->admin_tag_set.ops = &nvme_fc_admin_mq_ops;
ctrl->admin_tag_set.queue_depth = NVME_AQ_MQ_TAG_DEPTH;
@@ -3081,62 +3063,24 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
list_add_tail(&ctrl->ctrl_list, &rport->ctrl_list);
spin_unlock_irqrestore(&rport->lock, flags);
- /*
- * It's possible that transactions used to create the association
- * may fail. Examples: CreateAssociation LS or CreateIOConnection
- * LS gets dropped/corrupted/fails; or a frame gets dropped or a
- * command times out for one of the actions to init the controller
- * (Connect, Get/Set_Property, Set_Features, etc). Many of these
- * transport errors (frame drop, LS failure) inherently must kill
- * the association. The transport is coded so that any command used
- * to create the association (prior to a LIVE state transition
- * while NEW or CONNECTING) will fail if it completes in error or
- * times out.
- *
- * As such: as the connect request was mostly likely due to a
- * udev event that discovered the remote port, meaning there is
- * not an admin or script there to restart if the connect
- * request fails, retry the initial connection creation up to
- * three times before giving up and declaring failure.
- */
- for (retry = 0; retry < 3; retry++) {
- ret = nvme_fc_create_association(ctrl);
- if (!ret)
- break;
- }
-
- if (ret) {
- nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING);
- cancel_work_sync(&ctrl->ctrl.reset_work);
- cancel_delayed_work_sync(&ctrl->connect_work);
-
- /* couldn't schedule retry - fail out */
+ if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_RESETTING) ||
+ !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) {
dev_err(ctrl->ctrl.device,
- "NVME-FC{%d}: Connect retry failed\n", ctrl->cnum);
-
- ctrl->ctrl.opts = NULL;
+ "NVME-FC{%d}: failed to init ctrl state\n", ctrl->cnum);
+ goto fail_ctrl;
+ }
- /* initiate nvme ctrl ref counting teardown */
- nvme_uninit_ctrl(&ctrl->ctrl);
+ nvme_get_ctrl(&ctrl->ctrl);
- /* Remove core ctrl ref. */
+ if (!queue_delayed_work(nvme_wq, &ctrl->connect_work, 0)) {
nvme_put_ctrl(&ctrl->ctrl);
-
- /* as we're past the point where we transition to the ref
- * counting teardown path, if we return a bad pointer here,
- * the calling routine, thinking it's prior to the
- * transition, will do an rport put. Since the teardown
- * path also does a rport put, we do an extra get here to
- * so proper order/teardown happens.
- */
- nvme_fc_rport_get(rport);
-
- if (ret > 0)
- ret = -EIO;
- return ERR_PTR(ret);
+ dev_err(ctrl->ctrl.device,
+ "NVME-FC{%d}: failed to schedule initial connect\n",
+ ctrl->cnum);
+ goto fail_ctrl;
}
- nvme_get_ctrl(&ctrl->ctrl);
+ flush_delayed_work(&ctrl->connect_work);
dev_info(ctrl->ctrl.device,
"NVME-FC{%d}: new ctrl: NQN \"%s\"\n",
@@ -3144,6 +3088,30 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
return &ctrl->ctrl;
+fail_ctrl:
+ nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING);
+ cancel_work_sync(&ctrl->ctrl.reset_work);
+ cancel_delayed_work_sync(&ctrl->connect_work);
+
+ ctrl->ctrl.opts = NULL;
+
+ /* initiate nvme ctrl ref counting teardown */
+ nvme_uninit_ctrl(&ctrl->ctrl);
+
+ /* Remove core ctrl ref. */
+ nvme_put_ctrl(&ctrl->ctrl);
+
+ /* as we're past the point where we transition to the ref
+ * counting teardown path, if we return a bad pointer here,
+ * the calling routine, thinking it's prior to the
+ * transition, will do an rport put. Since the teardown
+ * path also does a rport put, we do an extra get here to
+ * so proper order/teardown happens.
+ */
+ nvme_fc_rport_get(rport);
+
+ return ERR_PTR(-EIO);
+
out_cleanup_admin_q:
blk_cleanup_queue(ctrl->ctrl.admin_q);
out_free_admin_tag_set:
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index d7b664a..1ffd3e8 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -12,6 +12,7 @@
*/
#include <linux/moduleparam.h>
+#include <trace/events/block.h>
#include "nvme.h"
static bool multipath = true;
@@ -111,6 +112,9 @@ static blk_qc_t nvme_ns_head_make_request(struct request_queue *q,
if (likely(ns)) {
bio->bi_disk = ns->disk;
bio->bi_opf |= REQ_NVME_MPATH;
+ trace_block_bio_remap(bio->bi_disk->queue, bio,
+ disk_devt(ns->head->disk),
+ bio->bi_iter.bi_sector);
ret = direct_make_request(bio);
} else if (!list_empty_careful(&head->list)) {
dev_warn_ratelimited(dev, "no path available - requeuing I/O\n");
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 34df07d..0c4a33d 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -170,6 +170,7 @@ struct nvme_ctrl {
u64 cap;
u32 page_size;
u32 max_hw_sectors;
+ u32 max_segments;
u16 oncs;
u16 oacs;
u16 nssa;
@@ -321,7 +322,6 @@ struct nvme_ctrl_ops {
void (*submit_async_event)(struct nvme_ctrl *ctrl);
void (*delete_ctrl)(struct nvme_ctrl *ctrl);
int (*get_address)(struct nvme_ctrl *ctrl, char *buf, int size);
- int (*reinit_request)(void *data, struct request *rq);
void (*stop_ctrl)(struct nvme_ctrl *ctrl);
};
@@ -416,7 +416,6 @@ void nvme_unfreeze(struct nvme_ctrl *ctrl);
void nvme_wait_freeze(struct nvme_ctrl *ctrl);
void nvme_wait_freeze_timeout(struct nvme_ctrl *ctrl, long timeout);
void nvme_start_freeze(struct nvme_ctrl *ctrl);
-int nvme_reinit_tagset(struct nvme_ctrl *ctrl, struct blk_mq_tag_set *set);
#define NVME_QID_ANY -1
struct request *nvme_alloc_request(struct request_queue *q,
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index fc33804..ba943f2 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -38,6 +38,13 @@
#define SGES_PER_PAGE (PAGE_SIZE / sizeof(struct nvme_sgl_desc))
+/*
+ * These can be higher, but we need to ensure that any command doesn't
+ * require an sg allocation that needs more than a page of data.
+ */
+#define NVME_MAX_KB_SZ 4096
+#define NVME_MAX_SEGS 127
+
static int use_threaded_interrupts;
module_param(use_threaded_interrupts, int, 0);
@@ -100,6 +107,8 @@ struct nvme_dev {
struct nvme_ctrl ctrl;
struct completion ioq_wait;
+ mempool_t *iod_mempool;
+
/* shadow doorbell buffer support: */
u32 *dbbuf_dbs;
dma_addr_t dbbuf_dbs_dma_addr;
@@ -477,10 +486,7 @@ static blk_status_t nvme_init_iod(struct request *rq, struct nvme_dev *dev)
iod->use_sgl = nvme_pci_use_sgls(dev, rq);
if (nseg > NVME_INT_PAGES || size > NVME_INT_BYTES(dev)) {
- size_t alloc_size = nvme_pci_iod_alloc_size(dev, size, nseg,
- iod->use_sgl);
-
- iod->sg = kmalloc(alloc_size, GFP_ATOMIC);
+ iod->sg = mempool_alloc(dev->iod_mempool, GFP_ATOMIC);
if (!iod->sg)
return BLK_STS_RESOURCE;
} else {
@@ -526,7 +532,7 @@ static void nvme_free_iod(struct nvme_dev *dev, struct request *req)
}
if (iod->sg != iod->inline_sg)
- kfree(iod->sg);
+ mempool_free(iod->sg, dev->iod_mempool);
}
#ifdef CONFIG_BLK_DEV_INTEGRITY
@@ -2280,6 +2286,7 @@ static void nvme_pci_free_ctrl(struct nvme_ctrl *ctrl)
blk_put_queue(dev->ctrl.admin_q);
kfree(dev->queues);
free_opal_dev(dev->ctrl.opal_dev);
+ mempool_destroy(dev->iod_mempool);
kfree(dev);
}
@@ -2289,6 +2296,7 @@ static void nvme_remove_dead_ctrl(struct nvme_dev *dev, int status)
nvme_get_ctrl(&dev->ctrl);
nvme_dev_disable(dev, false);
+ nvme_kill_queues(&dev->ctrl);
if (!queue_work(nvme_wq, &dev->remove_work))
nvme_put_ctrl(&dev->ctrl);
}
@@ -2333,6 +2341,13 @@ static void nvme_reset_work(struct work_struct *work)
if (result)
goto out;
+ /*
+ * Limit the max command size to prevent iod->sg allocations going
+ * over a single page.
+ */
+ dev->ctrl.max_hw_sectors = NVME_MAX_KB_SZ << 1;
+ dev->ctrl.max_segments = NVME_MAX_SEGS;
+
result = nvme_init_identify(&dev->ctrl);
if (result)
goto out;
@@ -2405,7 +2420,6 @@ static void nvme_remove_dead_ctrl_work(struct work_struct *work)
struct nvme_dev *dev = container_of(work, struct nvme_dev, remove_work);
struct pci_dev *pdev = to_pci_dev(dev->dev);
- nvme_kill_queues(&dev->ctrl);
if (pci_get_drvdata(pdev))
device_release_driver(&pdev->dev);
nvme_put_ctrl(&dev->ctrl);
@@ -2509,6 +2523,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int node, result = -ENOMEM;
struct nvme_dev *dev;
unsigned long quirks = id->driver_data;
+ size_t alloc_size;
node = dev_to_node(&pdev->dev);
if (node == NUMA_NO_NODE)
@@ -2546,6 +2561,23 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (result)
goto release_pools;
+ /*
+ * Double check that our mempool alloc size will cover the biggest
+ * command we support.
+ */
+ alloc_size = nvme_pci_iod_alloc_size(dev, NVME_MAX_KB_SZ,
+ NVME_MAX_SEGS, true);
+ WARN_ON_ONCE(alloc_size > PAGE_SIZE);
+
+ dev->iod_mempool = mempool_create_node(1, mempool_kmalloc,
+ mempool_kfree,
+ (void *) alloc_size,
+ GFP_KERNEL, node);
+ if (!dev->iod_mempool) {
+ result = -ENOMEM;
+ goto release_pools;
+ }
+
dev_info(dev->ctrl.device, "pci function %s\n", dev_name(&pdev->dev));
nvme_get_ctrl(&dev->ctrl);
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 2aba038..9544625 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -560,12 +560,6 @@ static void nvme_rdma_free_queue(struct nvme_rdma_queue *queue)
if (!test_and_clear_bit(NVME_RDMA_Q_ALLOCATED, &queue->flags))
return;
- if (nvme_rdma_queue_idx(queue) == 0) {
- nvme_rdma_free_qe(queue->device->dev,
- &queue->ctrl->async_event_sqe,
- sizeof(struct nvme_command), DMA_TO_DEVICE);
- }
-
nvme_rdma_destroy_queue_ib(queue);
rdma_destroy_id(queue->cm_id);
}
@@ -698,7 +692,7 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl,
set = &ctrl->tag_set;
memset(set, 0, sizeof(*set));
set->ops = &nvme_rdma_mq_ops;
- set->queue_depth = nctrl->opts->queue_size;
+ set->queue_depth = nctrl->sqsize + 1;
set->reserved_tags = 1; /* fabric connect */
set->numa_node = NUMA_NO_NODE;
set->flags = BLK_MQ_F_SHOULD_MERGE;
@@ -734,11 +728,12 @@ out:
static void nvme_rdma_destroy_admin_queue(struct nvme_rdma_ctrl *ctrl,
bool remove)
{
- nvme_rdma_stop_queue(&ctrl->queues[0]);
if (remove) {
blk_cleanup_queue(ctrl->ctrl.admin_q);
nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.admin_tagset);
}
+ nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
+ sizeof(struct nvme_command), DMA_TO_DEVICE);
nvme_rdma_free_queue(&ctrl->queues[0]);
}
@@ -755,11 +750,16 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl,
ctrl->max_fr_pages = nvme_rdma_get_max_fr_pages(ctrl->device->dev);
+ error = nvme_rdma_alloc_qe(ctrl->device->dev, &ctrl->async_event_sqe,
+ sizeof(struct nvme_command), DMA_TO_DEVICE);
+ if (error)
+ goto out_free_queue;
+
if (new) {
ctrl->ctrl.admin_tagset = nvme_rdma_alloc_tagset(&ctrl->ctrl, true);
if (IS_ERR(ctrl->ctrl.admin_tagset)) {
error = PTR_ERR(ctrl->ctrl.admin_tagset);
- goto out_free_queue;
+ goto out_free_async_qe;
}
ctrl->ctrl.admin_q = blk_mq_init_queue(&ctrl->admin_tag_set);
@@ -795,12 +795,6 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl,
if (error)
goto out_stop_queue;
- error = nvme_rdma_alloc_qe(ctrl->queues[0].device->dev,
- &ctrl->async_event_sqe, sizeof(struct nvme_command),
- DMA_TO_DEVICE);
- if (error)
- goto out_stop_queue;
-
return 0;
out_stop_queue:
@@ -811,6 +805,9 @@ out_cleanup_queue:
out_free_tagset:
if (new)
nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.admin_tagset);
+out_free_async_qe:
+ nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
+ sizeof(struct nvme_command), DMA_TO_DEVICE);
out_free_queue:
nvme_rdma_free_queue(&ctrl->queues[0]);
return error;
@@ -819,7 +816,6 @@ out_free_queue:
static void nvme_rdma_destroy_io_queues(struct nvme_rdma_ctrl *ctrl,
bool remove)
{
- nvme_rdma_stop_io_queues(ctrl);
if (remove) {
blk_cleanup_queue(ctrl->ctrl.connect_q);
nvme_rdma_free_tagset(&ctrl->ctrl, ctrl->ctrl.tagset);
@@ -888,9 +884,9 @@ static void nvme_rdma_free_ctrl(struct nvme_ctrl *nctrl)
list_del(&ctrl->list);
mutex_unlock(&nvme_rdma_ctrl_mutex);
- kfree(ctrl->queues);
nvmf_free_options(nctrl->opts);
free_ctrl:
+ kfree(ctrl->queues);
kfree(ctrl);
}
@@ -949,6 +945,7 @@ static void nvme_rdma_reconnect_ctrl_work(struct work_struct *work)
return;
destroy_admin:
+ nvme_rdma_stop_queue(&ctrl->queues[0]);
nvme_rdma_destroy_admin_queue(ctrl, false);
requeue:
dev_info(ctrl->ctrl.device, "Failed reconnect attempt %d\n",
@@ -965,12 +962,14 @@ static void nvme_rdma_error_recovery_work(struct work_struct *work)
if (ctrl->ctrl.queue_count > 1) {
nvme_stop_queues(&ctrl->ctrl);
+ nvme_rdma_stop_io_queues(ctrl);
blk_mq_tagset_busy_iter(&ctrl->tag_set,
nvme_cancel_request, &ctrl->ctrl);
nvme_rdma_destroy_io_queues(ctrl, false);
}
blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
+ nvme_rdma_stop_queue(&ctrl->queues[0]);
blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
nvme_cancel_request, &ctrl->ctrl);
nvme_rdma_destroy_admin_queue(ctrl, false);
@@ -1189,21 +1188,38 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue,
count = ib_dma_map_sg(ibdev, req->sg_table.sgl, req->nents,
rq_data_dir(rq) == WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (unlikely(count <= 0)) {
- sg_free_table_chained(&req->sg_table, true);
- return -EIO;
+ ret = -EIO;
+ goto out_free_table;
}
if (count == 1) {
if (rq_data_dir(rq) == WRITE && nvme_rdma_queue_idx(queue) &&
blk_rq_payload_bytes(rq) <=
- nvme_rdma_inline_data_size(queue))
- return nvme_rdma_map_sg_inline(queue, req, c);
+ nvme_rdma_inline_data_size(queue)) {
+ ret = nvme_rdma_map_sg_inline(queue, req, c);
+ goto out;
+ }
- if (dev->pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY)
- return nvme_rdma_map_sg_single(queue, req, c);
+ if (dev->pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) {
+ ret = nvme_rdma_map_sg_single(queue, req, c);
+ goto out;
+ }
}
- return nvme_rdma_map_sg_fr(queue, req, c, count);
+ ret = nvme_rdma_map_sg_fr(queue, req, c, count);
+out:
+ if (unlikely(ret))
+ goto out_unmap_sg;
+
+ return 0;
+
+out_unmap_sg:
+ ib_dma_unmap_sg(ibdev, req->sg_table.sgl,
+ req->nents, rq_data_dir(rq) ==
+ WRITE ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+out_free_table:
+ sg_free_table_chained(&req->sg_table, true);
+ return ret;
}
static void nvme_rdma_send_done(struct ib_cq *cq, struct ib_wc *wc)
@@ -1613,15 +1629,14 @@ static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
struct nvme_rdma_qe *sqe = &req->sqe;
struct nvme_command *c = sqe->data;
struct ib_device *dev;
+ bool queue_ready = test_bit(NVME_RDMA_Q_LIVE, &queue->flags);
blk_status_t ret;
int err;
WARN_ON_ONCE(rq->tag < 0);
- ret = nvmf_check_if_ready(&queue->ctrl->ctrl, rq,
- test_bit(NVME_RDMA_Q_LIVE, &queue->flags), true);
- if (unlikely(ret))
- return ret;
+ if (!nvmf_check_ready(&queue->ctrl->ctrl, rq, queue_ready))
+ return nvmf_fail_nonready_command(rq);
dev = queue->device->dev;
ib_dma_sync_single_for_cpu(dev, sqe->dma,
@@ -1720,6 +1735,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
{
if (ctrl->ctrl.queue_count > 1) {
nvme_stop_queues(&ctrl->ctrl);
+ nvme_rdma_stop_io_queues(ctrl);
blk_mq_tagset_busy_iter(&ctrl->tag_set,
nvme_cancel_request, &ctrl->ctrl);
nvme_rdma_destroy_io_queues(ctrl, shutdown);
@@ -1731,6 +1747,7 @@ static void nvme_rdma_shutdown_ctrl(struct nvme_rdma_ctrl *ctrl, bool shutdown)
nvme_disable_ctrl(&ctrl->ctrl, ctrl->ctrl.cap);
blk_mq_quiesce_queue(ctrl->ctrl.admin_q);
+ nvme_rdma_stop_queue(&ctrl->queues[0]);
blk_mq_tagset_busy_iter(&ctrl->admin_tag_set,
nvme_cancel_request, &ctrl->ctrl);
blk_mq_unquiesce_queue(ctrl->ctrl.admin_q);
@@ -1916,11 +1933,6 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
goto out_free_ctrl;
}
- ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_rdma_ctrl_ops,
- 0 /* no quirks, we're perfect! */);
- if (ret)
- goto out_free_ctrl;
-
INIT_DELAYED_WORK(&ctrl->reconnect_work,
nvme_rdma_reconnect_ctrl_work);
INIT_WORK(&ctrl->err_work, nvme_rdma_error_recovery_work);
@@ -1934,14 +1946,19 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
ctrl->queues = kcalloc(ctrl->ctrl.queue_count, sizeof(*ctrl->queues),
GFP_KERNEL);
if (!ctrl->queues)
- goto out_uninit_ctrl;
+ goto out_free_ctrl;
+
+ ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_rdma_ctrl_ops,
+ 0 /* no quirks, we're perfect! */);
+ if (ret)
+ goto out_kfree_queues;
changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING);
WARN_ON_ONCE(!changed);
ret = nvme_rdma_configure_admin_queue(ctrl, true);
if (ret)
- goto out_kfree_queues;
+ goto out_uninit_ctrl;
/* sanity check icdoff */
if (ctrl->ctrl.icdoff) {
@@ -1958,20 +1975,19 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
goto out_remove_admin_queue;
}
- if (opts->queue_size > ctrl->ctrl.maxcmd) {
- /* warn if maxcmd is lower than queue_size */
- dev_warn(ctrl->ctrl.device,
- "queue_size %zu > ctrl maxcmd %u, clamping down\n",
- opts->queue_size, ctrl->ctrl.maxcmd);
- opts->queue_size = ctrl->ctrl.maxcmd;
- }
-
+ /* only warn if argument is too large here, will clamp later */
if (opts->queue_size > ctrl->ctrl.sqsize + 1) {
- /* warn if sqsize is lower than queue_size */
dev_warn(ctrl->ctrl.device,
"queue_size %zu > ctrl sqsize %u, clamping down\n",
opts->queue_size, ctrl->ctrl.sqsize + 1);
- opts->queue_size = ctrl->ctrl.sqsize + 1;
+ }
+
+ /* warn if maxcmd is lower than sqsize+1 */
+ if (ctrl->ctrl.sqsize + 1 > ctrl->ctrl.maxcmd) {
+ dev_warn(ctrl->ctrl.device,
+ "sqsize %u > ctrl maxcmd %u, clamping down\n",
+ ctrl->ctrl.sqsize + 1, ctrl->ctrl.maxcmd);
+ ctrl->ctrl.sqsize = ctrl->ctrl.maxcmd - 1;
}
if (opts->nr_io_queues) {
@@ -1997,15 +2013,16 @@ static struct nvme_ctrl *nvme_rdma_create_ctrl(struct device *dev,
return &ctrl->ctrl;
out_remove_admin_queue:
+ nvme_rdma_stop_queue(&ctrl->queues[0]);
nvme_rdma_destroy_admin_queue(ctrl, true);
-out_kfree_queues:
- kfree(ctrl->queues);
out_uninit_ctrl:
nvme_uninit_ctrl(&ctrl->ctrl);
nvme_put_ctrl(&ctrl->ctrl);
if (ret > 0)
ret = -EIO;
return ERR_PTR(ret);
+out_kfree_queues:
+ kfree(ctrl->queues);
out_free_ctrl:
kfree(ctrl);
return ERR_PTR(ret);
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 9625328..3880357 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -119,9 +119,11 @@ static void nvmet_execute_get_log_page_smart(struct nvmet_req *req)
else
status = nvmet_get_smart_log_nsid(req, log);
if (status)
- goto out;
+ goto out_free_log;
status = nvmet_copy_to_sgl(req, 0, log, sizeof(*log));
+out_free_log:
+ kfree(log);
out:
nvmet_req_complete(req, status);
}
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index a03da76..74d4b78 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -686,6 +686,14 @@ static void nvmet_start_ctrl(struct nvmet_ctrl *ctrl)
}
ctrl->csts = NVME_CSTS_RDY;
+
+ /*
+ * Controllers that are not yet enabled should not really enforce the
+ * keep alive timeout, but we still want to track a timeout and cleanup
+ * in case a host died before it enabled the controller. Hence, simply
+ * reset the keep alive timer when the controller is enabled.
+ */
+ mod_delayed_work(system_wq, &ctrl->ka_work, ctrl->kato * HZ);
}
static void nvmet_clear_ctrl(struct nvmet_ctrl *ctrl)
diff --git a/drivers/nvme/target/loop.c b/drivers/nvme/target/loop.c
index 1304ec3..d8d91f0 100644
--- a/drivers/nvme/target/loop.c
+++ b/drivers/nvme/target/loop.c
@@ -158,12 +158,11 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
struct nvme_loop_queue *queue = hctx->driver_data;
struct request *req = bd->rq;
struct nvme_loop_iod *iod = blk_mq_rq_to_pdu(req);
+ bool queue_ready = test_bit(NVME_LOOP_Q_LIVE, &queue->flags);
blk_status_t ret;
- ret = nvmf_check_if_ready(&queue->ctrl->ctrl, req,
- test_bit(NVME_LOOP_Q_LIVE, &queue->flags), true);
- if (unlikely(ret))
- return ret;
+ if (!nvmf_check_ready(&queue->ctrl->ctrl, req, queue_ready))
+ return nvmf_fail_nonready_command(req);
ret = nvme_setup_cmd(ns, req, &iod->cmd);
if (ret)
diff --git a/drivers/nvmem/rockchip-efuse.c b/drivers/nvmem/rockchip-efuse.c
index b3b0b64..146de94 100644
--- a/drivers/nvmem/rockchip-efuse.c
+++ b/drivers/nvmem/rockchip-efuse.c
@@ -122,7 +122,8 @@ static int rockchip_rk3328_efuse_read(void *context, unsigned int offset,
addr_offset = offset % RK3399_NBYTES;
addr_len = addr_end - addr_start;
- buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL);
+ buf = kzalloc(array3_size(addr_len, RK3399_NBYTES, sizeof(*buf)),
+ GFP_KERNEL);
if (!buf) {
ret = -ENOMEM;
goto nomem;
@@ -174,7 +175,8 @@ static int rockchip_rk3399_efuse_read(void *context, unsigned int offset,
addr_offset = offset % RK3399_NBYTES;
addr_len = addr_end - addr_start;
- buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL);
+ buf = kzalloc(array3_size(addr_len, RK3399_NBYTES, sizeof(*buf)),
+ GFP_KERNEL);
if (!buf) {
clk_disable_unprepare(efuse->clk);
return -ENOMEM;
diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c
index 26bb637..d020f89 100644
--- a/drivers/nvmem/sunxi_sid.c
+++ b/drivers/nvmem/sunxi_sid.c
@@ -185,7 +185,7 @@ static int sunxi_sid_probe(struct platform_device *pdev)
if (IS_ERR(nvmem))
return PTR_ERR(nvmem);
- randomness = kzalloc(sizeof(u8) * (size), GFP_KERNEL);
+ randomness = kzalloc(size, GFP_KERNEL);
if (!randomness) {
ret = -EINVAL;
goto err_unreg_nvmem;
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 0b49a62..6925d99 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -129,7 +129,7 @@ struct platform_device *of_device_alloc(struct device_node *np,
/* Populate the resource table */
if (num_irq || num_reg) {
- res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL);
+ res = kcalloc(num_irq + num_reg, sizeof(*res), GFP_KERNEL);
if (!res) {
platform_device_put(dev);
return NULL;
@@ -505,6 +505,7 @@ EXPORT_SYMBOL_GPL(of_platform_default_populate);
#ifndef CONFIG_PPC
static const struct of_device_id reserved_mem_matches[] = {
{ .compatible = "qcom,rmtfs-mem" },
+ { .compatible = "qcom,cmd-db" },
{ .compatible = "ramoops" },
{}
};
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index ecee50d..722537e 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -156,7 +156,7 @@ static void __init of_unittest_dynamic(void)
}
/* Array of 4 properties for the purpose of testing */
- prop = kzalloc(sizeof(*prop) * 4, GFP_KERNEL);
+ prop = kcalloc(4, sizeof(*prop), GFP_KERNEL);
if (!prop) {
unittest(0, "kzalloc() failed\n");
return;
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index ab2f3fe..31ff03d 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -598,7 +598,7 @@ static int _generic_set_opp_regulator(const struct opp_table *opp_table,
}
/* Scaling up? Scale voltage before frequency */
- if (freq > old_freq) {
+ if (freq >= old_freq) {
ret = _set_opp_voltage(dev, reg, new_supply);
if (ret)
goto restore_voltage;
diff --git a/drivers/opp/ti-opp-supply.c b/drivers/opp/ti-opp-supply.c
index 370eff3..9e5a9a3 100644
--- a/drivers/opp/ti-opp-supply.c
+++ b/drivers/opp/ti-opp-supply.c
@@ -122,8 +122,8 @@ static int _store_optimized_voltages(struct device *dev,
goto out;
}
- table = kzalloc(sizeof(*data->vdd_table) *
- data->num_vdd_table, GFP_KERNEL);
+ table = kcalloc(data->num_vdd_table, sizeof(*data->vdd_table),
+ GFP_KERNEL);
if (!table) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c
index 32888f2..12ea4a4 100644
--- a/drivers/oprofile/event_buffer.c
+++ b/drivers/oprofile/event_buffer.c
@@ -91,7 +91,7 @@ int alloc_event_buffer(void)
return -EINVAL;
buffer_pos = 0;
- event_buffer = vmalloc(sizeof(unsigned long) * buffer_size);
+ event_buffer = vmalloc(array_size(buffer_size, sizeof(unsigned long)));
if (!event_buffer)
return -ENOMEM;
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig
index 44333bd..a97f4ea 100644
--- a/drivers/parport/Kconfig
+++ b/drivers/parport/Kconfig
@@ -20,7 +20,7 @@ menuconfig PARPORT
drive, PLIP link (Parallel Line Internet Protocol is mainly used to
create a mini network by connecting the parallel ports of two local
machines) etc., then you need to say Y here; please read
- <file:Documentation/parport.txt> and
+ <file:Documentation/admin-guide/parport.rst> and
<file:drivers/parport/BUGS-parport>.
For extensive information about drivers for many devices attaching
@@ -33,7 +33,7 @@ menuconfig PARPORT
the module will be called parport.
If you have more than one parallel port and want to specify which
port and IRQ to be used by this driver at module load time, take a
- look at <file:Documentation/parport.txt>.
+ look at <file:Documentation/admin-guide/parport.rst>.
If unsure, say Y.
@@ -71,7 +71,7 @@ config PARPORT_PC_FIFO
As well as actually having a FIFO, or DMA capability, the kernel
will need to know which IRQ the parallel port has. By default,
parallel port interrupts will not be used, and so neither will the
- FIFO. See <file:Documentation/parport.txt> to find out how to
+ FIFO. See <file:Documentation/admin-guide/parport.rst> to find out how to
specify which IRQ/DMA to use.
config PARPORT_PC_SUPERIO
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index b2f0763..56ff8f6 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -145,8 +145,6 @@ config PCI_HYPERV
PCI devices from a PCI backend to support PCI driver domains.
source "drivers/pci/hotplug/Kconfig"
-source "drivers/pci/cadence/Kconfig"
-source "drivers/pci/dwc/Kconfig"
-source "drivers/pci/host/Kconfig"
+source "drivers/pci/controller/Kconfig"
source "drivers/pci/endpoint/Kconfig"
source "drivers/pci/switch/Kconfig"
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index 84c9eef..5352019 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -28,14 +28,10 @@ obj-$(CONFIG_PCI_PF_STUB) += pci-pf-stub.o
obj-$(CONFIG_PCI_ECAM) += ecam.o
obj-$(CONFIG_XEN_PCIDEV_FRONTEND) += xen-pcifront.o
-obj-y += host/
+obj-y += controller/
obj-y += switch/
# Endpoint library must be initialized before its users
obj-$(CONFIG_PCI_ENDPOINT) += endpoint/
-obj-$(CONFIG_PCIE_CADENCE) += cadence/
-# pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
-obj-y += dwc/
-
ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
diff --git a/drivers/pci/cadence/Kconfig b/drivers/pci/cadence/Kconfig
deleted file mode 100644
index e6824cb..0000000
--- a/drivers/pci/cadence/Kconfig
+++ /dev/null
@@ -1,27 +0,0 @@
-menu "Cadence PCIe controllers support"
-
-config PCIE_CADENCE
- bool
-
-config PCIE_CADENCE_HOST
- bool "Cadence PCIe host controller"
- depends on OF
- depends on PCI
- select IRQ_DOMAIN
- select PCIE_CADENCE
- help
- Say Y here if you want to support the Cadence PCIe controller in host
- mode. This PCIe controller may be embedded into many different vendors
- SoCs.
-
-config PCIE_CADENCE_EP
- bool "Cadence PCIe endpoint controller"
- depends on OF
- depends on PCI_ENDPOINT
- select PCIE_CADENCE
- help
- Say Y here if you want to support the Cadence PCIe controller in
- endpoint mode. This PCIe controller may be embedded into many
- different vendors SoCs.
-
-endmenu
diff --git a/drivers/pci/cadence/Makefile b/drivers/pci/cadence/Makefile
deleted file mode 100644
index 719392b..0000000
--- a/drivers/pci/cadence/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_PCIE_CADENCE) += pcie-cadence.o
-obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o
-obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/controller/Kconfig
index a96e23b..18fa09b 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/controller/Kconfig
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
-menu "PCI host controller drivers"
+menu "PCI controller drivers"
depends on PCI
config PCI_MVEBU
@@ -20,6 +20,34 @@ config PCI_AARDVARK
controller is part of the South Bridge of the Marvel Armada
3700 SoC.
+menu "Cadence PCIe controllers support"
+
+config PCIE_CADENCE
+ bool
+
+config PCIE_CADENCE_HOST
+ bool "Cadence PCIe host controller"
+ depends on OF
+ depends on PCI
+ select IRQ_DOMAIN
+ select PCIE_CADENCE
+ help
+ Say Y here if you want to support the Cadence PCIe controller in host
+ mode. This PCIe controller may be embedded into many different vendors
+ SoCs.
+
+config PCIE_CADENCE_EP
+ bool "Cadence PCIe endpoint controller"
+ depends on OF
+ depends on PCI_ENDPOINT
+ select PCIE_CADENCE
+ help
+ Say Y here if you want to support the Cadence PCIe controller in
+ endpoint mode. This PCIe controller may be embedded into many
+ different vendors SoCs.
+
+endmenu
+
config PCIE_XILINX_NWL
bool "NWL PCIe Core"
depends on ARCH_ZYNQMP || COMPILE_TEST
@@ -243,4 +271,5 @@ config VMD
To compile this driver as a module, choose M here: the
module will be called vmd.
+source "drivers/pci/controller/dwc/Kconfig"
endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/controller/Makefile
index 11d21b0..24322b9 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/controller/Makefile
@@ -1,4 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_PCIE_CADENCE) += pcie-cadence.o
+obj-$(CONFIG_PCIE_CADENCE_HOST) += pcie-cadence-host.o
+obj-$(CONFIG_PCIE_CADENCE_EP) += pcie-cadence-ep.o
obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o
obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
@@ -25,6 +28,9 @@ obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o
obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
obj-$(CONFIG_VMD) += vmd.o
+# pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
+obj-y += dwc/
+
# The following drivers are for devices that use the generic ACPI
# pci_root.c driver but don't support standard ECAM config access.
diff --git a/drivers/pci/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index 16f52c6..16f52c6 100644
--- a/drivers/pci/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
diff --git a/drivers/pci/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index 5d2ce72..5d2ce72 100644
--- a/drivers/pci/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c
index f688204..345aab5 100644
--- a/drivers/pci/dwc/pci-dra7xx.c
+++ b/drivers/pci/controller/dwc/pci-dra7xx.c
@@ -27,7 +27,7 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
-#include "../pci.h"
+#include "../../pci.h"
#include "pcie-designware.h"
/* PCIe controller wrapper DRA7XX configuration registers */
@@ -639,11 +639,11 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
return phy_count;
}
- phy = devm_kzalloc(dev, sizeof(*phy) * phy_count, GFP_KERNEL);
+ phy = devm_kcalloc(dev, phy_count, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
- link = devm_kzalloc(dev, sizeof(*link) * phy_count, GFP_KERNEL);
+ link = devm_kcalloc(dev, phy_count, sizeof(*link), GFP_KERNEL);
if (!link)
return -ENOMEM;
diff --git a/drivers/pci/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c
index 4cc1e5d..4cc1e5d 100644
--- a/drivers/pci/dwc/pci-exynos.c
+++ b/drivers/pci/controller/dwc/pci-exynos.c
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index 80f6046..80f6046 100644
--- a/drivers/pci/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
diff --git a/drivers/pci/dwc/pci-keystone-dw.c b/drivers/pci/controller/dwc/pci-keystone-dw.c
index 0682213..0682213 100644
--- a/drivers/pci/dwc/pci-keystone-dw.c
+++ b/drivers/pci/controller/dwc/pci-keystone-dw.c
diff --git a/drivers/pci/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index 3722a5f..3722a5f 100644
--- a/drivers/pci/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
diff --git a/drivers/pci/dwc/pci-keystone.h b/drivers/pci/controller/dwc/pci-keystone.h
index 8a13da3..8a13da3 100644
--- a/drivers/pci/dwc/pci-keystone.h
+++ b/drivers/pci/controller/dwc/pci-keystone.h
diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/controller/dwc/pci-layerscape.c
index 3724d3e..3724d3e 100644
--- a/drivers/pci/dwc/pci-layerscape.c
+++ b/drivers/pci/controller/dwc/pci-layerscape.c
diff --git a/drivers/pci/dwc/pcie-armada8k.c b/drivers/pci/controller/dwc/pcie-armada8k.c
index 072fd7e..072fd7e 100644
--- a/drivers/pci/dwc/pcie-armada8k.c
+++ b/drivers/pci/controller/dwc/pcie-armada8k.c
diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/controller/dwc/pcie-artpec6.c
index 321b56c..321b56c 100644
--- a/drivers/pci/dwc/pcie-artpec6.c
+++ b/drivers/pci/controller/dwc/pcie-artpec6.c
diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c
index 1eec441..8650416 100644
--- a/drivers/pci/dwc/pcie-designware-ep.c
+++ b/drivers/pci/controller/dwc/pcie-designware-ep.c
@@ -366,19 +366,21 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep)
return -EINVAL;
}
- ep->ib_window_map = devm_kzalloc(dev, sizeof(long) *
+ ep->ib_window_map = devm_kcalloc(dev,
BITS_TO_LONGS(ep->num_ib_windows),
+ sizeof(long),
GFP_KERNEL);
if (!ep->ib_window_map)
return -ENOMEM;
- ep->ob_window_map = devm_kzalloc(dev, sizeof(long) *
+ ep->ob_window_map = devm_kcalloc(dev,
BITS_TO_LONGS(ep->num_ob_windows),
+ sizeof(long),
GFP_KERNEL);
if (!ep->ob_window_map)
return -ENOMEM;
- addr = devm_kzalloc(dev, sizeof(phys_addr_t) * ep->num_ob_windows,
+ addr = devm_kcalloc(dev, ep->num_ob_windows, sizeof(phys_addr_t),
GFP_KERNEL);
if (!addr)
return -ENOMEM;
diff --git a/drivers/pci/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c
index cba1432..781aa03 100644
--- a/drivers/pci/dwc/pcie-designware-host.c
+++ b/drivers/pci/controller/dwc/pcie-designware-host.c
@@ -15,7 +15,7 @@
#include <linux/pci_regs.h>
#include <linux/platform_device.h>
-#include "../pci.h"
+#include "../../pci.h"
#include "pcie-designware.h"
static struct pci_ops dw_pcie_ops;
diff --git a/drivers/pci/dwc/pcie-designware-plat.c b/drivers/pci/controller/dwc/pcie-designware-plat.c
index 5937fed..5937fed 100644
--- a/drivers/pci/dwc/pcie-designware-plat.c
+++ b/drivers/pci/controller/dwc/pcie-designware-plat.c
diff --git a/drivers/pci/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 778c4f7..778c4f7 100644
--- a/drivers/pci/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index bee4e25..bee4e25 100644
--- a/drivers/pci/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
diff --git a/drivers/pci/dwc/pcie-hisi.c b/drivers/pci/controller/dwc/pcie-hisi.c
index 2658aae..6d9e1b2 100644
--- a/drivers/pci/dwc/pcie-hisi.c
+++ b/drivers/pci/controller/dwc/pcie-hisi.c
@@ -19,7 +19,7 @@
#include <linux/pci-acpi.h>
#include <linux/pci-ecam.h>
#include <linux/regmap.h>
-#include "../pci.h"
+#include "../../pci.h"
#if defined(CONFIG_PCI_HISI) || (defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS))
diff --git a/drivers/pci/dwc/pcie-histb.c b/drivers/pci/controller/dwc/pcie-histb.c
index 3611d6c..3611d6c 100644
--- a/drivers/pci/dwc/pcie-histb.c
+++ b/drivers/pci/controller/dwc/pcie-histb.c
diff --git a/drivers/pci/dwc/pcie-kirin.c b/drivers/pci/controller/dwc/pcie-kirin.c
index d2970a0..d2970a0 100644
--- a/drivers/pci/dwc/pcie-kirin.c
+++ b/drivers/pci/controller/dwc/pcie-kirin.c
diff --git a/drivers/pci/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c
index a1d0198..a1d0198 100644
--- a/drivers/pci/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
diff --git a/drivers/pci/dwc/pcie-spear13xx.c b/drivers/pci/controller/dwc/pcie-spear13xx.c
index ecb58f7..ecb58f7 100644
--- a/drivers/pci/dwc/pcie-spear13xx.c
+++ b/drivers/pci/controller/dwc/pcie-spear13xx.c
diff --git a/drivers/pci/host/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
index d3172d5..d3172d5 100644
--- a/drivers/pci/host/pci-aardvark.c
+++ b/drivers/pci/controller/pci-aardvark.c
diff --git a/drivers/pci/host/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c
index a1ebe9e..a1ebe9e 100644
--- a/drivers/pci/host/pci-ftpci100.c
+++ b/drivers/pci/controller/pci-ftpci100.c
diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/controller/pci-host-common.c
index d8f1045..d8f1045 100644
--- a/drivers/pci/host/pci-host-common.c
+++ b/drivers/pci/controller/pci-host-common.c
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/controller/pci-host-generic.c
index dea3ec7..dea3ec7 100644
--- a/drivers/pci/host/pci-host-generic.c
+++ b/drivers/pci/controller/pci-host-generic.c
diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 6cc5036..6cc5036 100644
--- a/drivers/pci/host/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
index 23e2708..23e2708 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/controller/pci-mvebu.c
diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/controller/pci-rcar-gen2.c
index 326171c..326171c 100644
--- a/drivers/pci/host/pci-rcar-gen2.c
+++ b/drivers/pci/controller/pci-rcar-gen2.c
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/controller/pci-tegra.c
index f4f53d0..f4f53d0 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/controller/pci-tegra.c
diff --git a/drivers/pci/host/pci-thunder-ecam.c b/drivers/pci/controller/pci-thunder-ecam.c
index 32d1d7b..32d1d7b 100644
--- a/drivers/pci/host/pci-thunder-ecam.c
+++ b/drivers/pci/controller/pci-thunder-ecam.c
diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/controller/pci-thunder-pem.c
index f127ce8..f127ce8 100644
--- a/drivers/pci/host/pci-thunder-pem.c
+++ b/drivers/pci/controller/pci-thunder-pem.c
diff --git a/drivers/pci/host/pci-v3-semi.c b/drivers/pci/controller/pci-v3-semi.c
index 68b8bfb..68b8bfb 100644
--- a/drivers/pci/host/pci-v3-semi.c
+++ b/drivers/pci/controller/pci-v3-semi.c
diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/controller/pci-versatile.c
index 994f320..994f320 100644
--- a/drivers/pci/host/pci-versatile.c
+++ b/drivers/pci/controller/pci-versatile.c
diff --git a/drivers/pci/host/pci-xgene-msi.c b/drivers/pci/controller/pci-xgene-msi.c
index f4c02da..f4c02da 100644
--- a/drivers/pci/host/pci-xgene-msi.c
+++ b/drivers/pci/controller/pci-xgene-msi.c
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/controller/pci-xgene.c
index d854d67..d854d67 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/controller/pci-xgene.c
diff --git a/drivers/pci/host/pcie-altera-msi.c b/drivers/pci/controller/pcie-altera-msi.c
index 025ef7d..025ef7d 100644
--- a/drivers/pci/host/pcie-altera-msi.c
+++ b/drivers/pci/controller/pcie-altera-msi.c
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/controller/pcie-altera.c
index 7d05e51..7d05e51 100644
--- a/drivers/pci/host/pcie-altera.c
+++ b/drivers/pci/controller/pcie-altera.c
diff --git a/drivers/pci/cadence/pcie-cadence-ep.c b/drivers/pci/controller/pcie-cadence-ep.c
index 3d8283e..e3fe412 100644
--- a/drivers/pci/cadence/pcie-cadence-ep.c
+++ b/drivers/pci/controller/pcie-cadence-ep.c
@@ -467,7 +467,8 @@ static int cdns_pcie_ep_probe(struct platform_device *pdev)
dev_err(dev, "missing \"cdns,max-outbound-regions\"\n");
return ret;
}
- ep->ob_addr = devm_kzalloc(dev, ep->max_regions * sizeof(*ep->ob_addr),
+ ep->ob_addr = devm_kcalloc(dev,
+ ep->max_regions, sizeof(*ep->ob_addr),
GFP_KERNEL);
if (!ep->ob_addr)
return -ENOMEM;
diff --git a/drivers/pci/cadence/pcie-cadence-host.c b/drivers/pci/controller/pcie-cadence-host.c
index a4ebbd3..a4ebbd3 100644
--- a/drivers/pci/cadence/pcie-cadence-host.c
+++ b/drivers/pci/controller/pcie-cadence-host.c
diff --git a/drivers/pci/cadence/pcie-cadence.c b/drivers/pci/controller/pcie-cadence.c
index 138d113..138d113 100644
--- a/drivers/pci/cadence/pcie-cadence.c
+++ b/drivers/pci/controller/pcie-cadence.c
diff --git a/drivers/pci/cadence/pcie-cadence.h b/drivers/pci/controller/pcie-cadence.h
index 4bb2733..4bb2733 100644
--- a/drivers/pci/cadence/pcie-cadence.h
+++ b/drivers/pci/controller/pcie-cadence.h
diff --git a/drivers/pci/host/pcie-iproc-bcma.c b/drivers/pci/controller/pcie-iproc-bcma.c
index aa55b06..aa55b06 100644
--- a/drivers/pci/host/pcie-iproc-bcma.c
+++ b/drivers/pci/controller/pcie-iproc-bcma.c
diff --git a/drivers/pci/host/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c
index 9deb56989..9deb56989 100644
--- a/drivers/pci/host/pcie-iproc-msi.c
+++ b/drivers/pci/controller/pcie-iproc-msi.c
diff --git a/drivers/pci/host/pcie-iproc-platform.c b/drivers/pci/controller/pcie-iproc-platform.c
index f30f5f3..f30f5f3 100644
--- a/drivers/pci/host/pcie-iproc-platform.c
+++ b/drivers/pci/controller/pcie-iproc-platform.c
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/controller/pcie-iproc.c
index 3c76c5f..3c76c5f 100644
--- a/drivers/pci/host/pcie-iproc.c
+++ b/drivers/pci/controller/pcie-iproc.c
diff --git a/drivers/pci/host/pcie-iproc.h b/drivers/pci/controller/pcie-iproc.h
index 814b600..814b600 100644
--- a/drivers/pci/host/pcie-iproc.h
+++ b/drivers/pci/controller/pcie-iproc.h
diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c
index 0baabe3..0baabe3 100644
--- a/drivers/pci/host/pcie-mediatek.c
+++ b/drivers/pci/controller/pcie-mediatek.c
diff --git a/drivers/pci/host/pcie-mobiveil.c b/drivers/pci/controller/pcie-mobiveil.c
index 4d6c20e..4d6c20e 100644
--- a/drivers/pci/host/pcie-mobiveil.c
+++ b/drivers/pci/controller/pcie-mobiveil.c
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/controller/pcie-rcar.c
index 874d75c..874d75c 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/controller/pcie-rcar.c
diff --git a/drivers/pci/host/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c
index fc267a4..6beba8e 100644
--- a/drivers/pci/host/pcie-rockchip-ep.c
+++ b/drivers/pci/controller/pcie-rockchip-ep.c
@@ -593,7 +593,7 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
PCIE_CLIENT_CONFIG);
max_regions = ep->max_regions;
- ep->ob_addr = devm_kzalloc(dev, max_regions * sizeof(*ep->ob_addr),
+ ep->ob_addr = devm_kcalloc(dev, max_regions, sizeof(*ep->ob_addr),
GFP_KERNEL);
if (!ep->ob_addr) {
diff --git a/drivers/pci/host/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c
index 1372d27..1372d27 100644
--- a/drivers/pci/host/pcie-rockchip-host.c
+++ b/drivers/pci/controller/pcie-rockchip-host.c
diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/controller/pcie-rockchip.c
index c53d132..c53d132 100644
--- a/drivers/pci/host/pcie-rockchip.c
+++ b/drivers/pci/controller/pcie-rockchip.c
diff --git a/drivers/pci/host/pcie-rockchip.h b/drivers/pci/controller/pcie-rockchip.h
index 8e87a05..8e87a05 100644
--- a/drivers/pci/host/pcie-rockchip.h
+++ b/drivers/pci/controller/pcie-rockchip.h
diff --git a/drivers/pci/host/pcie-tango.c b/drivers/pci/controller/pcie-tango.c
index 21a208d..21a208d 100644
--- a/drivers/pci/host/pcie-tango.c
+++ b/drivers/pci/controller/pcie-tango.c
diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/controller/pcie-xilinx-nwl.c
index 6a4bbb5..6a4bbb5 100644
--- a/drivers/pci/host/pcie-xilinx-nwl.c
+++ b/drivers/pci/controller/pcie-xilinx-nwl.c
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/controller/pcie-xilinx.c
index b110a3a..b110a3a 100644
--- a/drivers/pci/host/pcie-xilinx.c
+++ b/drivers/pci/controller/pcie-xilinx.c
diff --git a/drivers/pci/host/vmd.c b/drivers/pci/controller/vmd.c
index 942b64f..942b64f 100644
--- a/drivers/pci/host/vmd.c
+++ b/drivers/pci/controller/vmd.c
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index f45b74f..4d88afd 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -474,7 +474,7 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
return 0;
/* Dynamically create the MSI attributes for the PCI device */
- msi_attrs = kzalloc(sizeof(void *) * (num_msi + 1), GFP_KERNEL);
+ msi_attrs = kcalloc(num_msi + 1, sizeof(void *), GFP_KERNEL);
if (!msi_attrs)
return -ENOMEM;
for_each_pci_msi_entry(entry, pdev) {
@@ -501,7 +501,7 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
msi_irq_group->name = "msi_irqs";
msi_irq_group->attrs = msi_attrs;
- msi_irq_groups = kzalloc(sizeof(void *) * 2, GFP_KERNEL);
+ msi_irq_groups = kcalloc(2, sizeof(void *), GFP_KERNEL);
if (!msi_irq_groups)
goto error_irq_group;
msi_irq_groups[0] = msi_irq_group;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 788a200..0c4653c 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -1076,7 +1076,7 @@ void pci_create_legacy_files(struct pci_bus *b)
{
int error;
- b->legacy_io = kzalloc(sizeof(struct bin_attribute) * 2,
+ b->legacy_io = kcalloc(2, sizeof(struct bin_attribute),
GFP_ATOMIC);
if (!b->legacy_io)
goto kzalloc_err;
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index b12e28b..0a1e9d3 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -23,7 +23,42 @@ config HOTPLUG_PCI_PCIE
When in doubt, say N.
-source "drivers/pci/pcie/aer/Kconfig"
+config PCIEAER
+ bool "PCI Express Advanced Error Reporting support"
+ depends on PCIEPORTBUS
+ select RAS
+ default y
+ help
+ This enables PCI Express Root Port Advanced Error Reporting
+ (AER) driver support. Error reporting messages sent to Root
+ Port will be handled by PCI Express AER driver.
+
+config PCIEAER_INJECT
+ tristate "PCI Express error injection support"
+ depends on PCIEAER
+ default n
+ help
+ This enables PCI Express Root Port Advanced Error Reporting
+ (AER) software error injector.
+
+ Debugging AER code is quite difficult because it is hard
+ to trigger various real hardware errors. Software-based
+ error injection can fake almost all kinds of errors with the
+ help of a user space helper tool aer-inject, which can be
+ gotten from:
+ http://www.kernel.org/pub/linux/utils/pci/aer-inject/
+
+#
+# PCI Express ECRC
+#
+config PCIE_ECRC
+ bool "PCI Express ECRC settings control"
+ depends on PCIEAER
+ help
+ Used to override firmware/bios settings for PCI Express ECRC
+ (transaction layer end-to-end CRC checking).
+
+ When in doubt, say N.
#
# PCI Express ASPM
@@ -92,7 +127,7 @@ config PCIE_PME
depends on PCIEPORTBUS && PM
config PCIE_DPC
- bool "PCIe Downstream Port Containment support"
+ bool "PCI Express Downstream Port Containment support"
depends on PCIEPORTBUS && PCIEAER
default n
help
@@ -103,7 +138,7 @@ config PCIE_DPC
it is safe to answer N.
config PCIE_PTM
- bool "PCIe Precision Time Measurement support"
+ bool "PCI Express Precision Time Measurement support"
default n
depends on PCIEPORTBUS
help
diff --git a/drivers/pci/pcie/Makefile b/drivers/pci/pcie/Makefile
index 03f4e0b..ab51408 100644
--- a/drivers/pci/pcie/Makefile
+++ b/drivers/pci/pcie/Makefile
@@ -7,7 +7,8 @@ pcieportdrv-y := portdrv_core.o portdrv_pci.o err.o
obj-$(CONFIG_PCIEPORTBUS) += pcieportdrv.o
obj-$(CONFIG_PCIEASPM) += aspm.o
-obj-$(CONFIG_PCIEAER) += aer/
+obj-$(CONFIG_PCIEAER) += aer.o
+obj-$(CONFIG_PCIEAER_INJECT) += aer_inject.o
obj-$(CONFIG_PCIE_PME) += pme.o
obj-$(CONFIG_PCIE_DPC) += dpc.o
obj-$(CONFIG_PCIE_PTM) += ptm.o
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
new file mode 100644
index 0000000..a2e8838
--- /dev/null
+++ b/drivers/pci/pcie/aer.c
@@ -0,0 +1,1377 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Implement the AER root port service driver. The driver registers an IRQ
+ * handler. When a root port triggers an AER interrupt, the IRQ handler
+ * collects root port status and schedules work.
+ *
+ * Copyright (C) 2006 Intel Corp.
+ * Tom Long Nguyen (tom.l.nguyen@intel.com)
+ * Zhang Yanmin (yanmin.zhang@intel.com)
+ *
+ * (C) Copyright 2009 Hewlett-Packard Development Company, L.P.
+ * Andrew Patterson <andrew.patterson@hp.com>
+ */
+
+#include <linux/cper.h>
+#include <linux/pci.h>
+#include <linux/pci-acpi.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kfifo.h>
+#include <linux/slab.h>
+#include <acpi/apei.h>
+#include <ras/ras_event.h>
+
+#include "../pci.h"
+#include "portdrv.h"
+
+#define AER_ERROR_SOURCES_MAX 100
+#define AER_MAX_MULTI_ERR_DEVICES 5 /* Not likely to have more */
+
+struct aer_err_info {
+ struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
+ int error_dev_num;
+
+ unsigned int id:16;
+
+ unsigned int severity:2; /* 0:NONFATAL | 1:FATAL | 2:COR */
+ unsigned int __pad1:5;
+ unsigned int multi_error_valid:1;
+
+ unsigned int first_error:5;
+ unsigned int __pad2:2;
+ unsigned int tlp_header_valid:1;
+
+ unsigned int status; /* COR/UNCOR Error Status */
+ unsigned int mask; /* COR/UNCOR Error Mask */
+ struct aer_header_log_regs tlp; /* TLP Header */
+};
+
+struct aer_err_source {
+ unsigned int status;
+ unsigned int id;
+};
+
+struct aer_rpc {
+ struct pci_dev *rpd; /* Root Port device */
+ struct work_struct dpc_handler;
+ struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX];
+ struct aer_err_info e_info;
+ unsigned short prod_idx; /* Error Producer Index */
+ unsigned short cons_idx; /* Error Consumer Index */
+ int isr;
+ spinlock_t e_lock; /*
+ * Lock access to Error Status/ID Regs
+ * and error producer/consumer index
+ */
+ struct mutex rpc_mutex; /*
+ * only one thread could do
+ * recovery on the same
+ * root port hierarchy
+ */
+};
+
+#define AER_LOG_TLP_MASKS (PCI_ERR_UNC_POISON_TLP| \
+ PCI_ERR_UNC_ECRC| \
+ PCI_ERR_UNC_UNSUP| \
+ PCI_ERR_UNC_COMP_ABORT| \
+ PCI_ERR_UNC_UNX_COMP| \
+ PCI_ERR_UNC_MALF_TLP)
+
+#define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \
+ PCI_EXP_RTCTL_SENFEE| \
+ PCI_EXP_RTCTL_SEFEE)
+#define ROOT_PORT_INTR_ON_MESG_MASK (PCI_ERR_ROOT_CMD_COR_EN| \
+ PCI_ERR_ROOT_CMD_NONFATAL_EN| \
+ PCI_ERR_ROOT_CMD_FATAL_EN)
+#define ERR_COR_ID(d) (d & 0xffff)
+#define ERR_UNCOR_ID(d) (d >> 16)
+
+static int pcie_aer_disable;
+
+void pci_no_aer(void)
+{
+ pcie_aer_disable = 1;
+}
+
+bool pci_aer_available(void)
+{
+ return !pcie_aer_disable && pci_msi_enabled();
+}
+
+#ifdef CONFIG_PCIE_ECRC
+
+#define ECRC_POLICY_DEFAULT 0 /* ECRC set by BIOS */
+#define ECRC_POLICY_OFF 1 /* ECRC off for performance */
+#define ECRC_POLICY_ON 2 /* ECRC on for data integrity */
+
+static int ecrc_policy = ECRC_POLICY_DEFAULT;
+
+static const char *ecrc_policy_str[] = {
+ [ECRC_POLICY_DEFAULT] = "bios",
+ [ECRC_POLICY_OFF] = "off",
+ [ECRC_POLICY_ON] = "on"
+};
+
+/**
+ * enable_ercr_checking - enable PCIe ECRC checking for a device
+ * @dev: the PCI device
+ *
+ * Returns 0 on success, or negative on failure.
+ */
+static int enable_ecrc_checking(struct pci_dev *dev)
+{
+ int pos;
+ u32 reg32;
+
+ if (!pci_is_pcie(dev))
+ return -ENODEV;
+
+ pos = dev->aer_cap;
+ if (!pos)
+ return -ENODEV;
+
+ pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
+ if (reg32 & PCI_ERR_CAP_ECRC_GENC)
+ reg32 |= PCI_ERR_CAP_ECRC_GENE;
+ if (reg32 & PCI_ERR_CAP_ECRC_CHKC)
+ reg32 |= PCI_ERR_CAP_ECRC_CHKE;
+ pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
+
+ return 0;
+}
+
+/**
+ * disable_ercr_checking - disables PCIe ECRC checking for a device
+ * @dev: the PCI device
+ *
+ * Returns 0 on success, or negative on failure.
+ */
+static int disable_ecrc_checking(struct pci_dev *dev)
+{
+ int pos;
+ u32 reg32;
+
+ if (!pci_is_pcie(dev))
+ return -ENODEV;
+
+ pos = dev->aer_cap;
+ if (!pos)
+ return -ENODEV;
+
+ pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
+ reg32 &= ~(PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
+ pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
+
+ return 0;
+}
+
+/**
+ * pcie_set_ecrc_checking - set/unset PCIe ECRC checking for a device based on global policy
+ * @dev: the PCI device
+ */
+void pcie_set_ecrc_checking(struct pci_dev *dev)
+{
+ switch (ecrc_policy) {
+ case ECRC_POLICY_DEFAULT:
+ return;
+ case ECRC_POLICY_OFF:
+ disable_ecrc_checking(dev);
+ break;
+ case ECRC_POLICY_ON:
+ enable_ecrc_checking(dev);
+ break;
+ default:
+ return;
+ }
+}
+
+/**
+ * pcie_ecrc_get_policy - parse kernel command-line ecrc option
+ */
+void pcie_ecrc_get_policy(char *str)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ecrc_policy_str); i++)
+ if (!strncmp(str, ecrc_policy_str[i],
+ strlen(ecrc_policy_str[i])))
+ break;
+ if (i >= ARRAY_SIZE(ecrc_policy_str))
+ return;
+
+ ecrc_policy = i;
+}
+#endif /* CONFIG_PCIE_ECRC */
+
+#ifdef CONFIG_ACPI_APEI
+static inline int hest_match_pci(struct acpi_hest_aer_common *p,
+ struct pci_dev *pci)
+{
+ return ACPI_HEST_SEGMENT(p->bus) == pci_domain_nr(pci->bus) &&
+ ACPI_HEST_BUS(p->bus) == pci->bus->number &&
+ p->device == PCI_SLOT(pci->devfn) &&
+ p->function == PCI_FUNC(pci->devfn);
+}
+
+static inline bool hest_match_type(struct acpi_hest_header *hest_hdr,
+ struct pci_dev *dev)
+{
+ u16 hest_type = hest_hdr->type;
+ u8 pcie_type = pci_pcie_type(dev);
+
+ if ((hest_type == ACPI_HEST_TYPE_AER_ROOT_PORT &&
+ pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
+ (hest_type == ACPI_HEST_TYPE_AER_ENDPOINT &&
+ pcie_type == PCI_EXP_TYPE_ENDPOINT) ||
+ (hest_type == ACPI_HEST_TYPE_AER_BRIDGE &&
+ (dev->class >> 16) == PCI_BASE_CLASS_BRIDGE))
+ return true;
+ return false;
+}
+
+struct aer_hest_parse_info {
+ struct pci_dev *pci_dev;
+ int firmware_first;
+};
+
+static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr)
+{
+ if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT ||
+ hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT ||
+ hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE)
+ return 1;
+ return 0;
+}
+
+static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
+{
+ struct aer_hest_parse_info *info = data;
+ struct acpi_hest_aer_common *p;
+ int ff;
+
+ if (!hest_source_is_pcie_aer(hest_hdr))
+ return 0;
+
+ p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
+ ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
+
+ /*
+ * If no specific device is supplied, determine whether
+ * FIRMWARE_FIRST is set for *any* PCIe device.
+ */
+ if (!info->pci_dev) {
+ info->firmware_first |= ff;
+ return 0;
+ }
+
+ /* Otherwise, check the specific device */
+ if (p->flags & ACPI_HEST_GLOBAL) {
+ if (hest_match_type(hest_hdr, info->pci_dev))
+ info->firmware_first = ff;
+ } else
+ if (hest_match_pci(p, info->pci_dev))
+ info->firmware_first = ff;
+
+ return 0;
+}
+
+static void aer_set_firmware_first(struct pci_dev *pci_dev)
+{
+ int rc;
+ struct aer_hest_parse_info info = {
+ .pci_dev = pci_dev,
+ .firmware_first = 0,
+ };
+
+ rc = apei_hest_parse(aer_hest_parse, &info);
+
+ if (rc)
+ pci_dev->__aer_firmware_first = 0;
+ else
+ pci_dev->__aer_firmware_first = info.firmware_first;
+ pci_dev->__aer_firmware_first_valid = 1;
+}
+
+int pcie_aer_get_firmware_first(struct pci_dev *dev)
+{
+ if (!pci_is_pcie(dev))
+ return 0;
+
+ if (!dev->__aer_firmware_first_valid)
+ aer_set_firmware_first(dev);
+ return dev->__aer_firmware_first;
+}
+#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
+ PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
+
+static bool aer_firmware_first;
+
+/**
+ * aer_acpi_firmware_first - Check if APEI should control AER.
+ */
+bool aer_acpi_firmware_first(void)
+{
+ static bool parsed = false;
+ struct aer_hest_parse_info info = {
+ .pci_dev = NULL, /* Check all PCIe devices */
+ .firmware_first = 0,
+ };
+
+ if (!parsed) {
+ apei_hest_parse(aer_hest_parse, &info);
+ aer_firmware_first = info.firmware_first;
+ parsed = true;
+ }
+ return aer_firmware_first;
+}
+#endif
+
+#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
+ PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
+
+int pci_enable_pcie_error_reporting(struct pci_dev *dev)
+{
+ if (pcie_aer_get_firmware_first(dev))
+ return -EIO;
+
+ if (!dev->aer_cap)
+ return -EIO;
+
+ return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS);
+}
+EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
+
+int pci_disable_pcie_error_reporting(struct pci_dev *dev)
+{
+ if (pcie_aer_get_firmware_first(dev))
+ return -EIO;
+
+ return pcie_capability_clear_word(dev, PCI_EXP_DEVCTL,
+ PCI_EXP_AER_FLAGS);
+}
+EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
+
+int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
+{
+ int pos;
+ u32 status;
+
+ pos = dev->aer_cap;
+ if (!pos)
+ return -EIO;
+
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+ if (status)
+ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
+
+int pci_cleanup_aer_error_status_regs(struct pci_dev *dev)
+{
+ int pos;
+ u32 status;
+ int port_type;
+
+ if (!pci_is_pcie(dev))
+ return -ENODEV;
+
+ pos = dev->aer_cap;
+ if (!pos)
+ return -EIO;
+
+ port_type = pci_pcie_type(dev);
+ if (port_type == PCI_EXP_TYPE_ROOT_PORT) {
+ pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status);
+ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status);
+ }
+
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
+ pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
+
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+
+ return 0;
+}
+
+int pci_aer_init(struct pci_dev *dev)
+{
+ dev->aer_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
+ return pci_cleanup_aer_error_status_regs(dev);
+}
+
+#define AER_AGENT_RECEIVER 0
+#define AER_AGENT_REQUESTER 1
+#define AER_AGENT_COMPLETER 2
+#define AER_AGENT_TRANSMITTER 3
+
+#define AER_AGENT_REQUESTER_MASK(t) ((t == AER_CORRECTABLE) ? \
+ 0 : (PCI_ERR_UNC_COMP_TIME|PCI_ERR_UNC_UNSUP))
+#define AER_AGENT_COMPLETER_MASK(t) ((t == AER_CORRECTABLE) ? \
+ 0 : PCI_ERR_UNC_COMP_ABORT)
+#define AER_AGENT_TRANSMITTER_MASK(t) ((t == AER_CORRECTABLE) ? \
+ (PCI_ERR_COR_REP_ROLL|PCI_ERR_COR_REP_TIMER) : 0)
+
+#define AER_GET_AGENT(t, e) \
+ ((e & AER_AGENT_COMPLETER_MASK(t)) ? AER_AGENT_COMPLETER : \
+ (e & AER_AGENT_REQUESTER_MASK(t)) ? AER_AGENT_REQUESTER : \
+ (e & AER_AGENT_TRANSMITTER_MASK(t)) ? AER_AGENT_TRANSMITTER : \
+ AER_AGENT_RECEIVER)
+
+#define AER_PHYSICAL_LAYER_ERROR 0
+#define AER_DATA_LINK_LAYER_ERROR 1
+#define AER_TRANSACTION_LAYER_ERROR 2
+
+#define AER_PHYSICAL_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
+ PCI_ERR_COR_RCVR : 0)
+#define AER_DATA_LINK_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
+ (PCI_ERR_COR_BAD_TLP| \
+ PCI_ERR_COR_BAD_DLLP| \
+ PCI_ERR_COR_REP_ROLL| \
+ PCI_ERR_COR_REP_TIMER) : PCI_ERR_UNC_DLP)
+
+#define AER_GET_LAYER_ERROR(t, e) \
+ ((e & AER_PHYSICAL_LAYER_ERROR_MASK(t)) ? AER_PHYSICAL_LAYER_ERROR : \
+ (e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \
+ AER_TRANSACTION_LAYER_ERROR)
+
+/*
+ * AER error strings
+ */
+static const char *aer_error_severity_string[] = {
+ "Uncorrected (Non-Fatal)",
+ "Uncorrected (Fatal)",
+ "Corrected"
+};
+
+static const char *aer_error_layer[] = {
+ "Physical Layer",
+ "Data Link Layer",
+ "Transaction Layer"
+};
+
+static const char *aer_correctable_error_string[] = {
+ "Receiver Error", /* Bit Position 0 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Bad TLP", /* Bit Position 6 */
+ "Bad DLLP", /* Bit Position 7 */
+ "RELAY_NUM Rollover", /* Bit Position 8 */
+ NULL,
+ NULL,
+ NULL,
+ "Replay Timer Timeout", /* Bit Position 12 */
+ "Advisory Non-Fatal", /* Bit Position 13 */
+ "Corrected Internal Error", /* Bit Position 14 */
+ "Header Log Overflow", /* Bit Position 15 */
+};
+
+static const char *aer_uncorrectable_error_string[] = {
+ "Undefined", /* Bit Position 0 */
+ NULL,
+ NULL,
+ NULL,
+ "Data Link Protocol", /* Bit Position 4 */
+ "Surprise Down Error", /* Bit Position 5 */
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "Poisoned TLP", /* Bit Position 12 */
+ "Flow Control Protocol", /* Bit Position 13 */
+ "Completion Timeout", /* Bit Position 14 */
+ "Completer Abort", /* Bit Position 15 */
+ "Unexpected Completion", /* Bit Position 16 */
+ "Receiver Overflow", /* Bit Position 17 */
+ "Malformed TLP", /* Bit Position 18 */
+ "ECRC", /* Bit Position 19 */
+ "Unsupported Request", /* Bit Position 20 */
+ "ACS Violation", /* Bit Position 21 */
+ "Uncorrectable Internal Error", /* Bit Position 22 */
+ "MC Blocked TLP", /* Bit Position 23 */
+ "AtomicOp Egress Blocked", /* Bit Position 24 */
+ "TLP Prefix Blocked Error", /* Bit Position 25 */
+};
+
+static const char *aer_agent_string[] = {
+ "Receiver ID",
+ "Requester ID",
+ "Completer ID",
+ "Transmitter ID"
+};
+
+static void __print_tlp_header(struct pci_dev *dev,
+ struct aer_header_log_regs *t)
+{
+ pci_err(dev, " TLP Header: %08x %08x %08x %08x\n",
+ t->dw0, t->dw1, t->dw2, t->dw3);
+}
+
+static void __aer_print_error(struct pci_dev *dev,
+ struct aer_err_info *info)
+{
+ int i, status;
+ const char *errmsg = NULL;
+ status = (info->status & ~info->mask);
+
+ for (i = 0; i < 32; i++) {
+ if (!(status & (1 << i)))
+ continue;
+
+ if (info->severity == AER_CORRECTABLE)
+ errmsg = i < ARRAY_SIZE(aer_correctable_error_string) ?
+ aer_correctable_error_string[i] : NULL;
+ else
+ errmsg = i < ARRAY_SIZE(aer_uncorrectable_error_string) ?
+ aer_uncorrectable_error_string[i] : NULL;
+
+ if (errmsg)
+ pci_err(dev, " [%2d] %-22s%s\n", i, errmsg,
+ info->first_error == i ? " (First)" : "");
+ else
+ pci_err(dev, " [%2d] Unknown Error Bit%s\n",
+ i, info->first_error == i ? " (First)" : "");
+ }
+}
+
+static void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
+{
+ int layer, agent;
+ int id = ((dev->bus->number << 8) | dev->devfn);
+
+ if (!info->status) {
+ pci_err(dev, "PCIe Bus Error: severity=%s, type=Inaccessible, (Unregistered Agent ID)\n",
+ aer_error_severity_string[info->severity]);
+ goto out;
+ }
+
+ layer = AER_GET_LAYER_ERROR(info->severity, info->status);
+ agent = AER_GET_AGENT(info->severity, info->status);
+
+ pci_err(dev, "PCIe Bus Error: severity=%s, type=%s, (%s)\n",
+ aer_error_severity_string[info->severity],
+ aer_error_layer[layer], aer_agent_string[agent]);
+
+ pci_err(dev, " device [%04x:%04x] error status/mask=%08x/%08x\n",
+ dev->vendor, dev->device,
+ info->status, info->mask);
+
+ __aer_print_error(dev, info);
+
+ if (info->tlp_header_valid)
+ __print_tlp_header(dev, &info->tlp);
+
+out:
+ if (info->id && info->error_dev_num > 1 && info->id == id)
+ pci_err(dev, " Error of this Agent is reported first\n");
+
+ trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
+ info->severity, info->tlp_header_valid, &info->tlp);
+}
+
+static void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
+{
+ u8 bus = info->id >> 8;
+ u8 devfn = info->id & 0xff;
+
+ pci_info(dev, "AER: %s%s error received: %04x:%02x:%02x.%d\n",
+ info->multi_error_valid ? "Multiple " : "",
+ aer_error_severity_string[info->severity],
+ pci_domain_nr(dev->bus), bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+}
+
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+int cper_severity_to_aer(int cper_severity)
+{
+ switch (cper_severity) {
+ case CPER_SEV_RECOVERABLE:
+ return AER_NONFATAL;
+ case CPER_SEV_FATAL:
+ return AER_FATAL;
+ default:
+ return AER_CORRECTABLE;
+ }
+}
+EXPORT_SYMBOL_GPL(cper_severity_to_aer);
+
+void cper_print_aer(struct pci_dev *dev, int aer_severity,
+ struct aer_capability_regs *aer)
+{
+ int layer, agent, tlp_header_valid = 0;
+ u32 status, mask;
+ struct aer_err_info info;
+
+ if (aer_severity == AER_CORRECTABLE) {
+ status = aer->cor_status;
+ mask = aer->cor_mask;
+ } else {
+ status = aer->uncor_status;
+ mask = aer->uncor_mask;
+ tlp_header_valid = status & AER_LOG_TLP_MASKS;
+ }
+
+ layer = AER_GET_LAYER_ERROR(aer_severity, status);
+ agent = AER_GET_AGENT(aer_severity, status);
+
+ memset(&info, 0, sizeof(info));
+ info.severity = aer_severity;
+ info.status = status;
+ info.mask = mask;
+ info.first_error = PCI_ERR_CAP_FEP(aer->cap_control);
+
+ pci_err(dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask);
+ __aer_print_error(dev, &info);
+ pci_err(dev, "aer_layer=%s, aer_agent=%s\n",
+ aer_error_layer[layer], aer_agent_string[agent]);
+
+ if (aer_severity != AER_CORRECTABLE)
+ pci_err(dev, "aer_uncor_severity: 0x%08x\n",
+ aer->uncor_severity);
+
+ if (tlp_header_valid)
+ __print_tlp_header(dev, &aer->header_log);
+
+ trace_aer_event(dev_name(&dev->dev), (status & ~mask),
+ aer_severity, tlp_header_valid, &aer->header_log);
+}
+#endif
+
+/**
+ * add_error_device - list device to be handled
+ * @e_info: pointer to error info
+ * @dev: pointer to pci_dev to be added
+ */
+static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
+{
+ if (e_info->error_dev_num < AER_MAX_MULTI_ERR_DEVICES) {
+ e_info->dev[e_info->error_dev_num] = dev;
+ e_info->error_dev_num++;
+ return 0;
+ }
+ return -ENOSPC;
+}
+
+/**
+ * is_error_source - check whether the device is source of reported error
+ * @dev: pointer to pci_dev to be checked
+ * @e_info: pointer to reported error info
+ */
+static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
+{
+ int pos;
+ u32 status, mask;
+ u16 reg16;
+
+ /*
+ * When bus id is equal to 0, it might be a bad id
+ * reported by root port.
+ */
+ if ((PCI_BUS_NUM(e_info->id) != 0) &&
+ !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) {
+ /* Device ID match? */
+ if (e_info->id == ((dev->bus->number << 8) | dev->devfn))
+ return true;
+
+ /* Continue id comparing if there is no multiple error */
+ if (!e_info->multi_error_valid)
+ return false;
+ }
+
+ /*
+ * When either
+ * 1) bus id is equal to 0. Some ports might lose the bus
+ * id of error source id;
+ * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set
+ * 3) There are multiple errors and prior ID comparing fails;
+ * We check AER status registers to find possible reporter.
+ */
+ if (atomic_read(&dev->enable_cnt) == 0)
+ return false;
+
+ /* Check if AER is enabled */
+ pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &reg16);
+ if (!(reg16 & PCI_EXP_AER_FLAGS))
+ return false;
+
+ pos = dev->aer_cap;
+ if (!pos)
+ return false;
+
+ /* Check if error is recorded */
+ if (e_info->severity == AER_CORRECTABLE) {
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &mask);
+ } else {
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask);
+ }
+ if (status & ~mask)
+ return true;
+
+ return false;
+}
+
+static int find_device_iter(struct pci_dev *dev, void *data)
+{
+ struct aer_err_info *e_info = (struct aer_err_info *)data;
+
+ if (is_error_source(dev, e_info)) {
+ /* List this device */
+ if (add_error_device(e_info, dev)) {
+ /* We cannot handle more... Stop iteration */
+ /* TODO: Should print error message here? */
+ return 1;
+ }
+
+ /* If there is only a single error, stop iteration */
+ if (!e_info->multi_error_valid)
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * find_source_device - search through device hierarchy for source device
+ * @parent: pointer to Root Port pci_dev data structure
+ * @e_info: including detailed error information such like id
+ *
+ * Return true if found.
+ *
+ * Invoked by DPC when error is detected at the Root Port.
+ * Caller of this function must set id, severity, and multi_error_valid of
+ * struct aer_err_info pointed by @e_info properly. This function must fill
+ * e_info->error_dev_num and e_info->dev[], based on the given information.
+ */
+static bool find_source_device(struct pci_dev *parent,
+ struct aer_err_info *e_info)
+{
+ struct pci_dev *dev = parent;
+ int result;
+
+ /* Must reset in this function */
+ e_info->error_dev_num = 0;
+
+ /* Is Root Port an agent that sends error message? */
+ result = find_device_iter(dev, e_info);
+ if (result)
+ return true;
+
+ pci_walk_bus(parent->subordinate, find_device_iter, e_info);
+
+ if (!e_info->error_dev_num) {
+ pci_printk(KERN_DEBUG, parent, "can't find device of ID%04x\n",
+ e_info->id);
+ return false;
+ }
+ return true;
+}
+
+/**
+ * handle_error_source - handle logging error into an event log
+ * @dev: pointer to pci_dev data structure of error source device
+ * @info: comprehensive error information
+ *
+ * Invoked when an error being detected by Root Port.
+ */
+static void handle_error_source(struct pci_dev *dev, struct aer_err_info *info)
+{
+ int pos;
+
+ if (info->severity == AER_CORRECTABLE) {
+ /*
+ * Correctable error does not need software intervention.
+ * No need to go through error recovery process.
+ */
+ pos = dev->aer_cap;
+ if (pos)
+ pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
+ info->status);
+ } else if (info->severity == AER_NONFATAL)
+ pcie_do_nonfatal_recovery(dev);
+ else if (info->severity == AER_FATAL)
+ pcie_do_fatal_recovery(dev, PCIE_PORT_SERVICE_AER);
+}
+
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+
+#define AER_RECOVER_RING_ORDER 4
+#define AER_RECOVER_RING_SIZE (1 << AER_RECOVER_RING_ORDER)
+
+struct aer_recover_entry {
+ u8 bus;
+ u8 devfn;
+ u16 domain;
+ int severity;
+ struct aer_capability_regs *regs;
+};
+
+static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry,
+ AER_RECOVER_RING_SIZE);
+
+static void aer_recover_work_func(struct work_struct *work)
+{
+ struct aer_recover_entry entry;
+ struct pci_dev *pdev;
+
+ while (kfifo_get(&aer_recover_ring, &entry)) {
+ pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus,
+ entry.devfn);
+ if (!pdev) {
+ pr_err("AER recover: Can not find pci_dev for %04x:%02x:%02x:%x\n",
+ entry.domain, entry.bus,
+ PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn));
+ continue;
+ }
+ cper_print_aer(pdev, entry.severity, entry.regs);
+ if (entry.severity == AER_NONFATAL)
+ pcie_do_nonfatal_recovery(pdev);
+ else if (entry.severity == AER_FATAL)
+ pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_AER);
+ pci_dev_put(pdev);
+ }
+}
+
+/*
+ * Mutual exclusion for writers of aer_recover_ring, reader side don't
+ * need lock, because there is only one reader and lock is not needed
+ * between reader and writer.
+ */
+static DEFINE_SPINLOCK(aer_recover_ring_lock);
+static DECLARE_WORK(aer_recover_work, aer_recover_work_func);
+
+void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
+ int severity, struct aer_capability_regs *aer_regs)
+{
+ unsigned long flags;
+ struct aer_recover_entry entry = {
+ .bus = bus,
+ .devfn = devfn,
+ .domain = domain,
+ .severity = severity,
+ .regs = aer_regs,
+ };
+
+ spin_lock_irqsave(&aer_recover_ring_lock, flags);
+ if (kfifo_put(&aer_recover_ring, entry))
+ schedule_work(&aer_recover_work);
+ else
+ pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n",
+ domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+ spin_unlock_irqrestore(&aer_recover_ring_lock, flags);
+}
+EXPORT_SYMBOL_GPL(aer_recover_queue);
+#endif
+
+/**
+ * get_device_error_info - read error status from dev and store it to info
+ * @dev: pointer to the device expected to have a error record
+ * @info: pointer to structure to store the error record
+ *
+ * Return 1 on success, 0 on error.
+ *
+ * Note that @info is reused among all error devices. Clear fields properly.
+ */
+static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
+{
+ int pos, temp;
+
+ /* Must reset in this function */
+ info->status = 0;
+ info->tlp_header_valid = 0;
+
+ pos = dev->aer_cap;
+
+ /* The device might not support AER */
+ if (!pos)
+ return 0;
+
+ if (info->severity == AER_CORRECTABLE) {
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS,
+ &info->status);
+ pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK,
+ &info->mask);
+ if (!(info->status & ~info->mask))
+ return 0;
+ } else if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+ info->severity == AER_NONFATAL) {
+
+ /* Link is still healthy for IO reads */
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
+ &info->status);
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK,
+ &info->mask);
+ if (!(info->status & ~info->mask))
+ return 0;
+
+ /* Get First Error Pointer */
+ pci_read_config_dword(dev, pos + PCI_ERR_CAP, &temp);
+ info->first_error = PCI_ERR_CAP_FEP(temp);
+
+ if (info->status & AER_LOG_TLP_MASKS) {
+ info->tlp_header_valid = 1;
+ pci_read_config_dword(dev,
+ pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0);
+ pci_read_config_dword(dev,
+ pos + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1);
+ pci_read_config_dword(dev,
+ pos + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2);
+ pci_read_config_dword(dev,
+ pos + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3);
+ }
+ }
+
+ return 1;
+}
+
+static inline void aer_process_err_devices(struct aer_err_info *e_info)
+{
+ int i;
+
+ /* Report all before handle them, not to lost records by reset etc. */
+ for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) {
+ if (get_device_error_info(e_info->dev[i], e_info))
+ aer_print_error(e_info->dev[i], e_info);
+ }
+ for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) {
+ if (get_device_error_info(e_info->dev[i], e_info))
+ handle_error_source(e_info->dev[i], e_info);
+ }
+}
+
+/**
+ * aer_isr_one_error - consume an error detected by root port
+ * @rpc: pointer to the root port which holds an error
+ * @e_src: pointer to an error source
+ */
+static void aer_isr_one_error(struct aer_rpc *rpc,
+ struct aer_err_source *e_src)
+{
+ struct pci_dev *pdev = rpc->rpd;
+ struct aer_err_info *e_info = &rpc->e_info;
+
+ /*
+ * There is a possibility that both correctable error and
+ * uncorrectable error being logged. Report correctable error first.
+ */
+ if (e_src->status & PCI_ERR_ROOT_COR_RCV) {
+ e_info->id = ERR_COR_ID(e_src->id);
+ e_info->severity = AER_CORRECTABLE;
+
+ if (e_src->status & PCI_ERR_ROOT_MULTI_COR_RCV)
+ e_info->multi_error_valid = 1;
+ else
+ e_info->multi_error_valid = 0;
+ aer_print_port_info(pdev, e_info);
+
+ if (find_source_device(pdev, e_info))
+ aer_process_err_devices(e_info);
+ }
+
+ if (e_src->status & PCI_ERR_ROOT_UNCOR_RCV) {
+ e_info->id = ERR_UNCOR_ID(e_src->id);
+
+ if (e_src->status & PCI_ERR_ROOT_FATAL_RCV)
+ e_info->severity = AER_FATAL;
+ else
+ e_info->severity = AER_NONFATAL;
+
+ if (e_src->status & PCI_ERR_ROOT_MULTI_UNCOR_RCV)
+ e_info->multi_error_valid = 1;
+ else
+ e_info->multi_error_valid = 0;
+
+ aer_print_port_info(pdev, e_info);
+
+ if (find_source_device(pdev, e_info))
+ aer_process_err_devices(e_info);
+ }
+}
+
+/**
+ * get_e_source - retrieve an error source
+ * @rpc: pointer to the root port which holds an error
+ * @e_src: pointer to store retrieved error source
+ *
+ * Return 1 if an error source is retrieved, otherwise 0.
+ *
+ * Invoked by DPC handler to consume an error.
+ */
+static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src)
+{
+ unsigned long flags;
+
+ /* Lock access to Root error producer/consumer index */
+ spin_lock_irqsave(&rpc->e_lock, flags);
+ if (rpc->prod_idx == rpc->cons_idx) {
+ spin_unlock_irqrestore(&rpc->e_lock, flags);
+ return 0;
+ }
+
+ *e_src = rpc->e_sources[rpc->cons_idx];
+ rpc->cons_idx++;
+ if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
+ rpc->cons_idx = 0;
+ spin_unlock_irqrestore(&rpc->e_lock, flags);
+
+ return 1;
+}
+
+/**
+ * aer_isr - consume errors detected by root port
+ * @work: definition of this work item
+ *
+ * Invoked, as DPC, when root port records new detected error
+ */
+static void aer_isr(struct work_struct *work)
+{
+ struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
+ struct aer_err_source uninitialized_var(e_src);
+
+ mutex_lock(&rpc->rpc_mutex);
+ while (get_e_source(rpc, &e_src))
+ aer_isr_one_error(rpc, &e_src);
+ mutex_unlock(&rpc->rpc_mutex);
+}
+
+/**
+ * aer_irq - Root Port's ISR
+ * @irq: IRQ assigned to Root Port
+ * @context: pointer to Root Port data structure
+ *
+ * Invoked when Root Port detects AER messages.
+ */
+irqreturn_t aer_irq(int irq, void *context)
+{
+ unsigned int status, id;
+ struct pcie_device *pdev = (struct pcie_device *)context;
+ struct aer_rpc *rpc = get_service_data(pdev);
+ int next_prod_idx;
+ unsigned long flags;
+ int pos;
+
+ pos = pdev->port->aer_cap;
+ /*
+ * Must lock access to Root Error Status Reg, Root Error ID Reg,
+ * and Root error producer/consumer index
+ */
+ spin_lock_irqsave(&rpc->e_lock, flags);
+
+ /* Read error status */
+ pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
+ if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
+ spin_unlock_irqrestore(&rpc->e_lock, flags);
+ return IRQ_NONE;
+ }
+
+ /* Read error source and clear error status */
+ pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id);
+ pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
+
+ /* Store error source for later DPC handler */
+ next_prod_idx = rpc->prod_idx + 1;
+ if (next_prod_idx == AER_ERROR_SOURCES_MAX)
+ next_prod_idx = 0;
+ if (next_prod_idx == rpc->cons_idx) {
+ /*
+ * Error Storm Condition - possibly the same error occurred.
+ * Drop the error.
+ */
+ spin_unlock_irqrestore(&rpc->e_lock, flags);
+ return IRQ_HANDLED;
+ }
+ rpc->e_sources[rpc->prod_idx].status = status;
+ rpc->e_sources[rpc->prod_idx].id = id;
+ rpc->prod_idx = next_prod_idx;
+ spin_unlock_irqrestore(&rpc->e_lock, flags);
+
+ /* Invoke DPC handler */
+ schedule_work(&rpc->dpc_handler);
+
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(aer_irq);
+
+static int set_device_error_reporting(struct pci_dev *dev, void *data)
+{
+ bool enable = *((bool *)data);
+ int type = pci_pcie_type(dev);
+
+ if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
+ (type == PCI_EXP_TYPE_UPSTREAM) ||
+ (type == PCI_EXP_TYPE_DOWNSTREAM)) {
+ if (enable)
+ pci_enable_pcie_error_reporting(dev);
+ else
+ pci_disable_pcie_error_reporting(dev);
+ }
+
+ if (enable)
+ pcie_set_ecrc_checking(dev);
+
+ return 0;
+}
+
+/**
+ * set_downstream_devices_error_reporting - enable/disable the error reporting bits on the root port and its downstream ports.
+ * @dev: pointer to root port's pci_dev data structure
+ * @enable: true = enable error reporting, false = disable error reporting.
+ */
+static void set_downstream_devices_error_reporting(struct pci_dev *dev,
+ bool enable)
+{
+ set_device_error_reporting(dev, &enable);
+
+ if (!dev->subordinate)
+ return;
+ pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
+}
+
+/**
+ * aer_enable_rootport - enable Root Port's interrupts when receiving messages
+ * @rpc: pointer to a Root Port data structure
+ *
+ * Invoked when PCIe bus loads AER service driver.
+ */
+static void aer_enable_rootport(struct aer_rpc *rpc)
+{
+ struct pci_dev *pdev = rpc->rpd;
+ int aer_pos;
+ u16 reg16;
+ u32 reg32;
+
+ /* Clear PCIe Capability's Device Status */
+ pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, &reg16);
+ pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, reg16);
+
+ /* Disable system error generation in response to error messages */
+ pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
+ SYSTEM_ERROR_INTR_ON_MESG_MASK);
+
+ aer_pos = pdev->aer_cap;
+ /* Clear error status */
+ pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
+ pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
+ pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
+ pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
+ pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
+ pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
+
+ /*
+ * Enable error reporting for the root port device and downstream port
+ * devices.
+ */
+ set_downstream_devices_error_reporting(pdev, true);
+
+ /* Enable Root Port's interrupt in response to error messages */
+ pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, &reg32);
+ reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
+ pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32);
+}
+
+/**
+ * aer_disable_rootport - disable Root Port's interrupts when receiving messages
+ * @rpc: pointer to a Root Port data structure
+ *
+ * Invoked when PCIe bus unloads AER service driver.
+ */
+static void aer_disable_rootport(struct aer_rpc *rpc)
+{
+ struct pci_dev *pdev = rpc->rpd;
+ u32 reg32;
+ int pos;
+
+ /*
+ * Disable error reporting for the root port device and downstream port
+ * devices.
+ */
+ set_downstream_devices_error_reporting(pdev, false);
+
+ pos = pdev->aer_cap;
+ /* Disable Root's interrupt in response to error messages */
+ pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
+ reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
+ pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32);
+
+ /* Clear Root's error status reg */
+ pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
+ pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
+}
+
+/**
+ * aer_alloc_rpc - allocate Root Port data structure
+ * @dev: pointer to the pcie_dev data structure
+ *
+ * Invoked when Root Port's AER service is loaded.
+ */
+static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
+{
+ struct aer_rpc *rpc;
+
+ rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
+ if (!rpc)
+ return NULL;
+
+ /* Initialize Root lock access, e_lock, to Root Error Status Reg */
+ spin_lock_init(&rpc->e_lock);
+
+ rpc->rpd = dev->port;
+ INIT_WORK(&rpc->dpc_handler, aer_isr);
+ mutex_init(&rpc->rpc_mutex);
+
+ /* Use PCIe bus function to store rpc into PCIe device */
+ set_service_data(dev, rpc);
+
+ return rpc;
+}
+
+/**
+ * aer_remove - clean up resources
+ * @dev: pointer to the pcie_dev data structure
+ *
+ * Invoked when PCI Express bus unloads or AER probe fails.
+ */
+static void aer_remove(struct pcie_device *dev)
+{
+ struct aer_rpc *rpc = get_service_data(dev);
+
+ if (rpc) {
+ /* If register interrupt service, it must be free. */
+ if (rpc->isr)
+ free_irq(dev->irq, dev);
+
+ flush_work(&rpc->dpc_handler);
+ aer_disable_rootport(rpc);
+ kfree(rpc);
+ set_service_data(dev, NULL);
+ }
+}
+
+/**
+ * aer_probe - initialize resources
+ * @dev: pointer to the pcie_dev data structure
+ *
+ * Invoked when PCI Express bus loads AER service driver.
+ */
+static int aer_probe(struct pcie_device *dev)
+{
+ int status;
+ struct aer_rpc *rpc;
+ struct device *device = &dev->port->dev;
+
+ /* Alloc rpc data structure */
+ rpc = aer_alloc_rpc(dev);
+ if (!rpc) {
+ dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n");
+ aer_remove(dev);
+ return -ENOMEM;
+ }
+
+ /* Request IRQ ISR */
+ status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev);
+ if (status) {
+ dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n",
+ dev->irq);
+ aer_remove(dev);
+ return status;
+ }
+
+ rpc->isr = 1;
+
+ aer_enable_rootport(rpc);
+ dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
+ return 0;
+}
+
+/**
+ * aer_root_reset - reset link on Root Port
+ * @dev: pointer to Root Port's pci_dev data structure
+ *
+ * Invoked by Port Bus driver when performing link reset at Root Port.
+ */
+static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
+{
+ u32 reg32;
+ int pos;
+
+ pos = dev->aer_cap;
+
+ /* Disable Root's interrupt in response to error messages */
+ pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
+ reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
+ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
+
+ pci_reset_bridge_secondary_bus(dev);
+ pci_printk(KERN_DEBUG, dev, "Root Port link has been reset\n");
+
+ /* Clear Root Error Status */
+ pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
+ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32);
+
+ /* Enable Root Port's interrupt in response to error messages */
+ pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
+ reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
+ pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
+
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+/**
+ * aer_error_resume - clean up corresponding error status bits
+ * @dev: pointer to Root Port's pci_dev data structure
+ *
+ * Invoked by Port Bus driver during nonfatal recovery.
+ */
+static void aer_error_resume(struct pci_dev *dev)
+{
+ int pos;
+ u32 status, mask;
+ u16 reg16;
+
+ /* Clean up Root device status */
+ pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &reg16);
+ pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
+
+ /* Clean AER Root Error Status */
+ pos = dev->aer_cap;
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
+ pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
+ status &= ~mask; /* Clear corresponding nonfatal bits */
+ pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
+}
+
+static struct pcie_port_service_driver aerdriver = {
+ .name = "aer",
+ .port_type = PCI_EXP_TYPE_ROOT_PORT,
+ .service = PCIE_PORT_SERVICE_AER,
+
+ .probe = aer_probe,
+ .remove = aer_remove,
+ .error_resume = aer_error_resume,
+ .reset_link = aer_root_reset,
+};
+
+/**
+ * aer_service_init - register AER root service driver
+ *
+ * Invoked when AER root service driver is loaded.
+ */
+static int __init aer_service_init(void)
+{
+ if (!pci_aer_available() || aer_acpi_firmware_first())
+ return -ENXIO;
+ return pcie_port_service_register(&aerdriver);
+}
+device_initcall(aer_service_init);
diff --git a/drivers/pci/pcie/aer/Kconfig b/drivers/pci/pcie/aer/Kconfig
deleted file mode 100644
index 5a64eb3..0000000
--- a/drivers/pci/pcie/aer/Kconfig
+++ /dev/null
@@ -1,29 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# PCI Express Root Port Device AER Configuration
-#
-
-config PCIEAER
- bool "Root Port Advanced Error Reporting support"
- depends on PCIEPORTBUS
- select RAS
- default y
- help
- This enables PCI Express Root Port Advanced Error Reporting
- (AER) driver support. Error reporting messages sent to Root
- Port will be handled by PCI Express AER driver.
-
-
-#
-# PCI Express ECRC
-#
-config PCIE_ECRC
- bool "PCI Express ECRC settings control"
- depends on PCIEAER
- help
- Used to override firmware/bios settings for PCI Express ECRC
- (transaction layer end-to-end CRC checking).
-
- When in doubt, say N.
-
-source "drivers/pci/pcie/aer/Kconfig.debug"
diff --git a/drivers/pci/pcie/aer/Kconfig.debug b/drivers/pci/pcie/aer/Kconfig.debug
deleted file mode 100644
index 67e0217..0000000
--- a/drivers/pci/pcie/aer/Kconfig.debug
+++ /dev/null
@@ -1,19 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# PCI Express Root Port Device AER Debug Configuration
-#
-
-config PCIEAER_INJECT
- tristate "PCIe AER error injector support"
- depends on PCIEAER
- default n
- help
- This enables PCI Express Root Port Advanced Error Reporting
- (AER) software error injector.
-
- Debugging PCIe AER code is quite difficult because it is hard
- to trigger various real hardware errors. Software based
- error injection can fake almost all kinds of errors with the
- help of a user space helper tool aer-inject, which can be
- gotten from:
- http://www.kernel.org/pub/linux/utils/pci/aer-inject/
diff --git a/drivers/pci/pcie/aer/Makefile b/drivers/pci/pcie/aer/Makefile
deleted file mode 100644
index 09bd890..0000000
--- a/drivers/pci/pcie/aer/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for PCI-Express Root Port Advanced Error Reporting Driver
-#
-
-obj-$(CONFIG_PCIEAER) += aerdriver.o
-
-obj-$(CONFIG_PCIE_ECRC) += ecrc.o
-
-aerdriver-objs := aerdrv_errprint.o aerdrv_core.o aerdrv.o
-aerdriver-$(CONFIG_ACPI) += aerdrv_acpi.o
-
-obj-$(CONFIG_PCIEAER_INJECT) += aer_inject.o
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
deleted file mode 100644
index 9735c19..0000000
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ /dev/null
@@ -1,371 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Implement the AER root port service driver. The driver registers an IRQ
- * handler. When a root port triggers an AER interrupt, the IRQ handler
- * collects root port status and schedules work.
- *
- * Copyright (C) 2006 Intel Corp.
- * Tom Long Nguyen (tom.l.nguyen@intel.com)
- * Zhang Yanmin (yanmin.zhang@intel.com)
- */
-
-#include <linux/pci.h>
-#include <linux/pci-acpi.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/pm.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-
-#include "aerdrv.h"
-#include "../../pci.h"
-
-static int aer_probe(struct pcie_device *dev);
-static void aer_remove(struct pcie_device *dev);
-static void aer_error_resume(struct pci_dev *dev);
-static pci_ers_result_t aer_root_reset(struct pci_dev *dev);
-
-static struct pcie_port_service_driver aerdriver = {
- .name = "aer",
- .port_type = PCI_EXP_TYPE_ROOT_PORT,
- .service = PCIE_PORT_SERVICE_AER,
-
- .probe = aer_probe,
- .remove = aer_remove,
- .error_resume = aer_error_resume,
- .reset_link = aer_root_reset,
-};
-
-static int pcie_aer_disable;
-
-void pci_no_aer(void)
-{
- pcie_aer_disable = 1;
-}
-
-bool pci_aer_available(void)
-{
- return !pcie_aer_disable && pci_msi_enabled();
-}
-
-static int set_device_error_reporting(struct pci_dev *dev, void *data)
-{
- bool enable = *((bool *)data);
- int type = pci_pcie_type(dev);
-
- if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
- (type == PCI_EXP_TYPE_UPSTREAM) ||
- (type == PCI_EXP_TYPE_DOWNSTREAM)) {
- if (enable)
- pci_enable_pcie_error_reporting(dev);
- else
- pci_disable_pcie_error_reporting(dev);
- }
-
- if (enable)
- pcie_set_ecrc_checking(dev);
-
- return 0;
-}
-
-/**
- * set_downstream_devices_error_reporting - enable/disable the error reporting bits on the root port and its downstream ports.
- * @dev: pointer to root port's pci_dev data structure
- * @enable: true = enable error reporting, false = disable error reporting.
- */
-static void set_downstream_devices_error_reporting(struct pci_dev *dev,
- bool enable)
-{
- set_device_error_reporting(dev, &enable);
-
- if (!dev->subordinate)
- return;
- pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable);
-}
-
-/**
- * aer_enable_rootport - enable Root Port's interrupts when receiving messages
- * @rpc: pointer to a Root Port data structure
- *
- * Invoked when PCIe bus loads AER service driver.
- */
-static void aer_enable_rootport(struct aer_rpc *rpc)
-{
- struct pci_dev *pdev = rpc->rpd;
- int aer_pos;
- u16 reg16;
- u32 reg32;
-
- /* Clear PCIe Capability's Device Status */
- pcie_capability_read_word(pdev, PCI_EXP_DEVSTA, &reg16);
- pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, reg16);
-
- /* Disable system error generation in response to error messages */
- pcie_capability_clear_word(pdev, PCI_EXP_RTCTL,
- SYSTEM_ERROR_INTR_ON_MESG_MASK);
-
- aer_pos = pdev->aer_cap;
- /* Clear error status */
- pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, &reg32);
- pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_STATUS, reg32);
- pci_read_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, &reg32);
- pci_write_config_dword(pdev, aer_pos + PCI_ERR_COR_STATUS, reg32);
- pci_read_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, &reg32);
- pci_write_config_dword(pdev, aer_pos + PCI_ERR_UNCOR_STATUS, reg32);
-
- /*
- * Enable error reporting for the root port device and downstream port
- * devices.
- */
- set_downstream_devices_error_reporting(pdev, true);
-
- /* Enable Root Port's interrupt in response to error messages */
- pci_read_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, &reg32);
- reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
- pci_write_config_dword(pdev, aer_pos + PCI_ERR_ROOT_COMMAND, reg32);
-}
-
-/**
- * aer_disable_rootport - disable Root Port's interrupts when receiving messages
- * @rpc: pointer to a Root Port data structure
- *
- * Invoked when PCIe bus unloads AER service driver.
- */
-static void aer_disable_rootport(struct aer_rpc *rpc)
-{
- struct pci_dev *pdev = rpc->rpd;
- u32 reg32;
- int pos;
-
- /*
- * Disable error reporting for the root port device and downstream port
- * devices.
- */
- set_downstream_devices_error_reporting(pdev, false);
-
- pos = pdev->aer_cap;
- /* Disable Root's interrupt in response to error messages */
- pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
- reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
- pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_COMMAND, reg32);
-
- /* Clear Root's error status reg */
- pci_read_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, &reg32);
- pci_write_config_dword(pdev, pos + PCI_ERR_ROOT_STATUS, reg32);
-}
-
-/**
- * aer_irq - Root Port's ISR
- * @irq: IRQ assigned to Root Port
- * @context: pointer to Root Port data structure
- *
- * Invoked when Root Port detects AER messages.
- */
-irqreturn_t aer_irq(int irq, void *context)
-{
- unsigned int status, id;
- struct pcie_device *pdev = (struct pcie_device *)context;
- struct aer_rpc *rpc = get_service_data(pdev);
- int next_prod_idx;
- unsigned long flags;
- int pos;
-
- pos = pdev->port->aer_cap;
- /*
- * Must lock access to Root Error Status Reg, Root Error ID Reg,
- * and Root error producer/consumer index
- */
- spin_lock_irqsave(&rpc->e_lock, flags);
-
- /* Read error status */
- pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, &status);
- if (!(status & (PCI_ERR_ROOT_UNCOR_RCV|PCI_ERR_ROOT_COR_RCV))) {
- spin_unlock_irqrestore(&rpc->e_lock, flags);
- return IRQ_NONE;
- }
-
- /* Read error source and clear error status */
- pci_read_config_dword(pdev->port, pos + PCI_ERR_ROOT_ERR_SRC, &id);
- pci_write_config_dword(pdev->port, pos + PCI_ERR_ROOT_STATUS, status);
-
- /* Store error source for later DPC handler */
- next_prod_idx = rpc->prod_idx + 1;
- if (next_prod_idx == AER_ERROR_SOURCES_MAX)
- next_prod_idx = 0;
- if (next_prod_idx == rpc->cons_idx) {
- /*
- * Error Storm Condition - possibly the same error occurred.
- * Drop the error.
- */
- spin_unlock_irqrestore(&rpc->e_lock, flags);
- return IRQ_HANDLED;
- }
- rpc->e_sources[rpc->prod_idx].status = status;
- rpc->e_sources[rpc->prod_idx].id = id;
- rpc->prod_idx = next_prod_idx;
- spin_unlock_irqrestore(&rpc->e_lock, flags);
-
- /* Invoke DPC handler */
- schedule_work(&rpc->dpc_handler);
-
- return IRQ_HANDLED;
-}
-EXPORT_SYMBOL_GPL(aer_irq);
-
-/**
- * aer_alloc_rpc - allocate Root Port data structure
- * @dev: pointer to the pcie_dev data structure
- *
- * Invoked when Root Port's AER service is loaded.
- */
-static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
-{
- struct aer_rpc *rpc;
-
- rpc = kzalloc(sizeof(struct aer_rpc), GFP_KERNEL);
- if (!rpc)
- return NULL;
-
- /* Initialize Root lock access, e_lock, to Root Error Status Reg */
- spin_lock_init(&rpc->e_lock);
-
- rpc->rpd = dev->port;
- INIT_WORK(&rpc->dpc_handler, aer_isr);
- mutex_init(&rpc->rpc_mutex);
-
- /* Use PCIe bus function to store rpc into PCIe device */
- set_service_data(dev, rpc);
-
- return rpc;
-}
-
-/**
- * aer_remove - clean up resources
- * @dev: pointer to the pcie_dev data structure
- *
- * Invoked when PCI Express bus unloads or AER probe fails.
- */
-static void aer_remove(struct pcie_device *dev)
-{
- struct aer_rpc *rpc = get_service_data(dev);
-
- if (rpc) {
- /* If register interrupt service, it must be free. */
- if (rpc->isr)
- free_irq(dev->irq, dev);
-
- flush_work(&rpc->dpc_handler);
- aer_disable_rootport(rpc);
- kfree(rpc);
- set_service_data(dev, NULL);
- }
-}
-
-/**
- * aer_probe - initialize resources
- * @dev: pointer to the pcie_dev data structure
- *
- * Invoked when PCI Express bus loads AER service driver.
- */
-static int aer_probe(struct pcie_device *dev)
-{
- int status;
- struct aer_rpc *rpc;
- struct device *device = &dev->port->dev;
-
- /* Alloc rpc data structure */
- rpc = aer_alloc_rpc(dev);
- if (!rpc) {
- dev_printk(KERN_DEBUG, device, "alloc AER rpc failed\n");
- aer_remove(dev);
- return -ENOMEM;
- }
-
- /* Request IRQ ISR */
- status = request_irq(dev->irq, aer_irq, IRQF_SHARED, "aerdrv", dev);
- if (status) {
- dev_printk(KERN_DEBUG, device, "request AER IRQ %d failed\n",
- dev->irq);
- aer_remove(dev);
- return status;
- }
-
- rpc->isr = 1;
-
- aer_enable_rootport(rpc);
- dev_info(device, "AER enabled with IRQ %d\n", dev->irq);
- return 0;
-}
-
-/**
- * aer_root_reset - reset link on Root Port
- * @dev: pointer to Root Port's pci_dev data structure
- *
- * Invoked by Port Bus driver when performing link reset at Root Port.
- */
-static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
-{
- u32 reg32;
- int pos;
-
- pos = dev->aer_cap;
-
- /* Disable Root's interrupt in response to error messages */
- pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
- reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
- pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
-
- pci_reset_bridge_secondary_bus(dev);
- pci_printk(KERN_DEBUG, dev, "Root Port link has been reset\n");
-
- /* Clear Root Error Status */
- pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &reg32);
- pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, reg32);
-
- /* Enable Root Port's interrupt in response to error messages */
- pci_read_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, &reg32);
- reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
- pci_write_config_dword(dev, pos + PCI_ERR_ROOT_COMMAND, reg32);
-
- return PCI_ERS_RESULT_RECOVERED;
-}
-
-/**
- * aer_error_resume - clean up corresponding error status bits
- * @dev: pointer to Root Port's pci_dev data structure
- *
- * Invoked by Port Bus driver during nonfatal recovery.
- */
-static void aer_error_resume(struct pci_dev *dev)
-{
- int pos;
- u32 status, mask;
- u16 reg16;
-
- /* Clean up Root device status */
- pcie_capability_read_word(dev, PCI_EXP_DEVSTA, &reg16);
- pcie_capability_write_word(dev, PCI_EXP_DEVSTA, reg16);
-
- /* Clean AER Root Error Status */
- pos = dev->aer_cap;
- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask);
- status &= ~mask; /* Clear corresponding nonfatal bits */
- pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
-}
-
-/**
- * aer_service_init - register AER root service driver
- *
- * Invoked when AER root service driver is loaded.
- */
-static int __init aer_service_init(void)
-{
- if (!pci_aer_available() || aer_acpi_firmware_first())
- return -ENXIO;
- return pcie_port_service_register(&aerdriver);
-}
-device_initcall(aer_service_init);
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
deleted file mode 100644
index 6e0ad9a..0000000
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2006 Intel Corp.
- * Tom Long Nguyen (tom.l.nguyen@intel.com)
- * Zhang Yanmin (yanmin.zhang@intel.com)
- */
-
-#ifndef _AERDRV_H_
-#define _AERDRV_H_
-
-#include <linux/workqueue.h>
-#include <linux/aer.h>
-#include <linux/interrupt.h>
-
-#include "../portdrv.h"
-
-#define SYSTEM_ERROR_INTR_ON_MESG_MASK (PCI_EXP_RTCTL_SECEE| \
- PCI_EXP_RTCTL_SENFEE| \
- PCI_EXP_RTCTL_SEFEE)
-#define ROOT_PORT_INTR_ON_MESG_MASK (PCI_ERR_ROOT_CMD_COR_EN| \
- PCI_ERR_ROOT_CMD_NONFATAL_EN| \
- PCI_ERR_ROOT_CMD_FATAL_EN)
-#define ERR_COR_ID(d) (d & 0xffff)
-#define ERR_UNCOR_ID(d) (d >> 16)
-
-#define AER_ERROR_SOURCES_MAX 100
-
-#define AER_LOG_TLP_MASKS (PCI_ERR_UNC_POISON_TLP| \
- PCI_ERR_UNC_ECRC| \
- PCI_ERR_UNC_UNSUP| \
- PCI_ERR_UNC_COMP_ABORT| \
- PCI_ERR_UNC_UNX_COMP| \
- PCI_ERR_UNC_MALF_TLP)
-
-#define AER_MAX_MULTI_ERR_DEVICES 5 /* Not likely to have more */
-struct aer_err_info {
- struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
- int error_dev_num;
-
- unsigned int id:16;
-
- unsigned int severity:2; /* 0:NONFATAL | 1:FATAL | 2:COR */
- unsigned int __pad1:5;
- unsigned int multi_error_valid:1;
-
- unsigned int first_error:5;
- unsigned int __pad2:2;
- unsigned int tlp_header_valid:1;
-
- unsigned int status; /* COR/UNCOR Error Status */
- unsigned int mask; /* COR/UNCOR Error Mask */
- struct aer_header_log_regs tlp; /* TLP Header */
-};
-
-struct aer_err_source {
- unsigned int status;
- unsigned int id;
-};
-
-struct aer_rpc {
- struct pci_dev *rpd; /* Root Port device */
- struct work_struct dpc_handler;
- struct aer_err_source e_sources[AER_ERROR_SOURCES_MAX];
- struct aer_err_info e_info;
- unsigned short prod_idx; /* Error Producer Index */
- unsigned short cons_idx; /* Error Consumer Index */
- int isr;
- spinlock_t e_lock; /*
- * Lock access to Error Status/ID Regs
- * and error producer/consumer index
- */
- struct mutex rpc_mutex; /*
- * only one thread could do
- * recovery on the same
- * root port hierarchy
- */
-};
-
-extern struct bus_type pcie_port_bus_type;
-void aer_isr(struct work_struct *work);
-void aer_print_error(struct pci_dev *dev, struct aer_err_info *info);
-void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info);
-irqreturn_t aer_irq(int irq, void *context);
-
-#ifdef CONFIG_ACPI_APEI
-int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
-#else
-static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
-{
- if (pci_dev->__aer_firmware_first_valid)
- return pci_dev->__aer_firmware_first;
- return 0;
-}
-#endif
-#endif /* _AERDRV_H_ */
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c
deleted file mode 100644
index 08c87de..0000000
--- a/drivers/pci/pcie/aer/aerdrv_acpi.c
+++ /dev/null
@@ -1,141 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Access ACPI _OSC method
- *
- * Copyright (C) 2006 Intel Corp.
- * Tom Long Nguyen (tom.l.nguyen@intel.com)
- * Zhang Yanmin (yanmin.zhang@intel.com)
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/pm.h>
-#include <linux/suspend.h>
-#include <linux/acpi.h>
-#include <linux/pci-acpi.h>
-#include <linux/delay.h>
-#include <acpi/apei.h>
-#include "aerdrv.h"
-
-#ifdef CONFIG_ACPI_APEI
-static inline int hest_match_pci(struct acpi_hest_aer_common *p,
- struct pci_dev *pci)
-{
- return ACPI_HEST_SEGMENT(p->bus) == pci_domain_nr(pci->bus) &&
- ACPI_HEST_BUS(p->bus) == pci->bus->number &&
- p->device == PCI_SLOT(pci->devfn) &&
- p->function == PCI_FUNC(pci->devfn);
-}
-
-static inline bool hest_match_type(struct acpi_hest_header *hest_hdr,
- struct pci_dev *dev)
-{
- u16 hest_type = hest_hdr->type;
- u8 pcie_type = pci_pcie_type(dev);
-
- if ((hest_type == ACPI_HEST_TYPE_AER_ROOT_PORT &&
- pcie_type == PCI_EXP_TYPE_ROOT_PORT) ||
- (hest_type == ACPI_HEST_TYPE_AER_ENDPOINT &&
- pcie_type == PCI_EXP_TYPE_ENDPOINT) ||
- (hest_type == ACPI_HEST_TYPE_AER_BRIDGE &&
- (dev->class >> 16) == PCI_BASE_CLASS_BRIDGE))
- return true;
- return false;
-}
-
-struct aer_hest_parse_info {
- struct pci_dev *pci_dev;
- int firmware_first;
-};
-
-static int hest_source_is_pcie_aer(struct acpi_hest_header *hest_hdr)
-{
- if (hest_hdr->type == ACPI_HEST_TYPE_AER_ROOT_PORT ||
- hest_hdr->type == ACPI_HEST_TYPE_AER_ENDPOINT ||
- hest_hdr->type == ACPI_HEST_TYPE_AER_BRIDGE)
- return 1;
- return 0;
-}
-
-static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data)
-{
- struct aer_hest_parse_info *info = data;
- struct acpi_hest_aer_common *p;
- int ff;
-
- if (!hest_source_is_pcie_aer(hest_hdr))
- return 0;
-
- p = (struct acpi_hest_aer_common *)(hest_hdr + 1);
- ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST);
-
- /*
- * If no specific device is supplied, determine whether
- * FIRMWARE_FIRST is set for *any* PCIe device.
- */
- if (!info->pci_dev) {
- info->firmware_first |= ff;
- return 0;
- }
-
- /* Otherwise, check the specific device */
- if (p->flags & ACPI_HEST_GLOBAL) {
- if (hest_match_type(hest_hdr, info->pci_dev))
- info->firmware_first = ff;
- } else
- if (hest_match_pci(p, info->pci_dev))
- info->firmware_first = ff;
-
- return 0;
-}
-
-static void aer_set_firmware_first(struct pci_dev *pci_dev)
-{
- int rc;
- struct aer_hest_parse_info info = {
- .pci_dev = pci_dev,
- .firmware_first = 0,
- };
-
- rc = apei_hest_parse(aer_hest_parse, &info);
-
- if (rc)
- pci_dev->__aer_firmware_first = 0;
- else
- pci_dev->__aer_firmware_first = info.firmware_first;
- pci_dev->__aer_firmware_first_valid = 1;
-}
-
-int pcie_aer_get_firmware_first(struct pci_dev *dev)
-{
- if (!pci_is_pcie(dev))
- return 0;
-
- if (!dev->__aer_firmware_first_valid)
- aer_set_firmware_first(dev);
- return dev->__aer_firmware_first;
-}
-
-static bool aer_firmware_first;
-
-/**
- * aer_acpi_firmware_first - Check if APEI should control AER.
- */
-bool aer_acpi_firmware_first(void)
-{
- static bool parsed = false;
- struct aer_hest_parse_info info = {
- .pci_dev = NULL, /* Check all PCIe devices */
- .firmware_first = 0,
- };
-
- if (!parsed) {
- apei_hest_parse(aer_hest_parse, &info);
- aer_firmware_first = info.firmware_first;
- parsed = true;
- }
- return aer_firmware_first;
-}
-#endif
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
deleted file mode 100644
index 42d4f3f..0000000
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ /dev/null
@@ -1,496 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Implement the core part of PCIe AER. When a PCIe error is delivered, an
- * error message will be collected and printed to console, then an error
- * recovery procedure will be executed by following the PCI error recovery
- * rules.
- *
- * Copyright (C) 2006 Intel Corp.
- * Tom Long Nguyen (tom.l.nguyen@intel.com)
- * Zhang Yanmin (yanmin.zhang@intel.com)
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/pm.h>
-#include <linux/suspend.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/kfifo.h>
-#include "aerdrv.h"
-#include "../../pci.h"
-
-#define PCI_EXP_AER_FLAGS (PCI_EXP_DEVCTL_CERE | PCI_EXP_DEVCTL_NFERE | \
- PCI_EXP_DEVCTL_FERE | PCI_EXP_DEVCTL_URRE)
-
-int pci_enable_pcie_error_reporting(struct pci_dev *dev)
-{
- if (pcie_aer_get_firmware_first(dev))
- return -EIO;
-
- if (!dev->aer_cap)
- return -EIO;
-
- return pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_AER_FLAGS);
-}
-EXPORT_SYMBOL_GPL(pci_enable_pcie_error_reporting);
-
-int pci_disable_pcie_error_reporting(struct pci_dev *dev)
-{
- if (pcie_aer_get_firmware_first(dev))
- return -EIO;
-
- return pcie_capability_clear_word(dev, PCI_EXP_DEVCTL,
- PCI_EXP_AER_FLAGS);
-}
-EXPORT_SYMBOL_GPL(pci_disable_pcie_error_reporting);
-
-int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)
-{
- int pos;
- u32 status;
-
- pos = dev->aer_cap;
- if (!pos)
- return -EIO;
-
- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
- if (status)
- pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(pci_cleanup_aer_uncorrect_error_status);
-
-int pci_cleanup_aer_error_status_regs(struct pci_dev *dev)
-{
- int pos;
- u32 status;
- int port_type;
-
- if (!pci_is_pcie(dev))
- return -ENODEV;
-
- pos = dev->aer_cap;
- if (!pos)
- return -EIO;
-
- port_type = pci_pcie_type(dev);
- if (port_type == PCI_EXP_TYPE_ROOT_PORT) {
- pci_read_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, &status);
- pci_write_config_dword(dev, pos + PCI_ERR_ROOT_STATUS, status);
- }
-
- pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
- pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS, status);
-
- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
- pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status);
-
- return 0;
-}
-
-int pci_aer_init(struct pci_dev *dev)
-{
- dev->aer_cap = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
- return pci_cleanup_aer_error_status_regs(dev);
-}
-
-/**
- * add_error_device - list device to be handled
- * @e_info: pointer to error info
- * @dev: pointer to pci_dev to be added
- */
-static int add_error_device(struct aer_err_info *e_info, struct pci_dev *dev)
-{
- if (e_info->error_dev_num < AER_MAX_MULTI_ERR_DEVICES) {
- e_info->dev[e_info->error_dev_num] = dev;
- e_info->error_dev_num++;
- return 0;
- }
- return -ENOSPC;
-}
-
-/**
- * is_error_source - check whether the device is source of reported error
- * @dev: pointer to pci_dev to be checked
- * @e_info: pointer to reported error info
- */
-static bool is_error_source(struct pci_dev *dev, struct aer_err_info *e_info)
-{
- int pos;
- u32 status, mask;
- u16 reg16;
-
- /*
- * When bus id is equal to 0, it might be a bad id
- * reported by root port.
- */
- if ((PCI_BUS_NUM(e_info->id) != 0) &&
- !(dev->bus->bus_flags & PCI_BUS_FLAGS_NO_AERSID)) {
- /* Device ID match? */
- if (e_info->id == ((dev->bus->number << 8) | dev->devfn))
- return true;
-
- /* Continue id comparing if there is no multiple error */
- if (!e_info->multi_error_valid)
- return false;
- }
-
- /*
- * When either
- * 1) bus id is equal to 0. Some ports might lose the bus
- * id of error source id;
- * 2) bus flag PCI_BUS_FLAGS_NO_AERSID is set
- * 3) There are multiple errors and prior ID comparing fails;
- * We check AER status registers to find possible reporter.
- */
- if (atomic_read(&dev->enable_cnt) == 0)
- return false;
-
- /* Check if AER is enabled */
- pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &reg16);
- if (!(reg16 & PCI_EXP_AER_FLAGS))
- return false;
-
- pos = dev->aer_cap;
- if (!pos)
- return false;
-
- /* Check if error is recorded */
- if (e_info->severity == AER_CORRECTABLE) {
- pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS, &status);
- pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK, &mask);
- } else {
- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status);
- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK, &mask);
- }
- if (status & ~mask)
- return true;
-
- return false;
-}
-
-static int find_device_iter(struct pci_dev *dev, void *data)
-{
- struct aer_err_info *e_info = (struct aer_err_info *)data;
-
- if (is_error_source(dev, e_info)) {
- /* List this device */
- if (add_error_device(e_info, dev)) {
- /* We cannot handle more... Stop iteration */
- /* TODO: Should print error message here? */
- return 1;
- }
-
- /* If there is only a single error, stop iteration */
- if (!e_info->multi_error_valid)
- return 1;
- }
- return 0;
-}
-
-/**
- * find_source_device - search through device hierarchy for source device
- * @parent: pointer to Root Port pci_dev data structure
- * @e_info: including detailed error information such like id
- *
- * Return true if found.
- *
- * Invoked by DPC when error is detected at the Root Port.
- * Caller of this function must set id, severity, and multi_error_valid of
- * struct aer_err_info pointed by @e_info properly. This function must fill
- * e_info->error_dev_num and e_info->dev[], based on the given information.
- */
-static bool find_source_device(struct pci_dev *parent,
- struct aer_err_info *e_info)
-{
- struct pci_dev *dev = parent;
- int result;
-
- /* Must reset in this function */
- e_info->error_dev_num = 0;
-
- /* Is Root Port an agent that sends error message? */
- result = find_device_iter(dev, e_info);
- if (result)
- return true;
-
- pci_walk_bus(parent->subordinate, find_device_iter, e_info);
-
- if (!e_info->error_dev_num) {
- pci_printk(KERN_DEBUG, parent, "can't find device of ID%04x\n",
- e_info->id);
- return false;
- }
- return true;
-}
-
-/**
- * handle_error_source - handle logging error into an event log
- * @dev: pointer to pci_dev data structure of error source device
- * @info: comprehensive error information
- *
- * Invoked when an error being detected by Root Port.
- */
-static void handle_error_source(struct pci_dev *dev, struct aer_err_info *info)
-{
- int pos;
-
- if (info->severity == AER_CORRECTABLE) {
- /*
- * Correctable error does not need software intervention.
- * No need to go through error recovery process.
- */
- pos = dev->aer_cap;
- if (pos)
- pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
- info->status);
- } else if (info->severity == AER_NONFATAL)
- pcie_do_nonfatal_recovery(dev);
- else if (info->severity == AER_FATAL)
- pcie_do_fatal_recovery(dev, PCIE_PORT_SERVICE_AER);
-}
-
-#ifdef CONFIG_ACPI_APEI_PCIEAER
-
-#define AER_RECOVER_RING_ORDER 4
-#define AER_RECOVER_RING_SIZE (1 << AER_RECOVER_RING_ORDER)
-
-struct aer_recover_entry {
- u8 bus;
- u8 devfn;
- u16 domain;
- int severity;
- struct aer_capability_regs *regs;
-};
-
-static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry,
- AER_RECOVER_RING_SIZE);
-
-static void aer_recover_work_func(struct work_struct *work)
-{
- struct aer_recover_entry entry;
- struct pci_dev *pdev;
-
- while (kfifo_get(&aer_recover_ring, &entry)) {
- pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus,
- entry.devfn);
- if (!pdev) {
- pr_err("AER recover: Can not find pci_dev for %04x:%02x:%02x:%x\n",
- entry.domain, entry.bus,
- PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn));
- continue;
- }
- cper_print_aer(pdev, entry.severity, entry.regs);
- if (entry.severity == AER_NONFATAL)
- pcie_do_nonfatal_recovery(pdev);
- else if (entry.severity == AER_FATAL)
- pcie_do_fatal_recovery(pdev, PCIE_PORT_SERVICE_AER);
- pci_dev_put(pdev);
- }
-}
-
-/*
- * Mutual exclusion for writers of aer_recover_ring, reader side don't
- * need lock, because there is only one reader and lock is not needed
- * between reader and writer.
- */
-static DEFINE_SPINLOCK(aer_recover_ring_lock);
-static DECLARE_WORK(aer_recover_work, aer_recover_work_func);
-
-void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
- int severity, struct aer_capability_regs *aer_regs)
-{
- unsigned long flags;
- struct aer_recover_entry entry = {
- .bus = bus,
- .devfn = devfn,
- .domain = domain,
- .severity = severity,
- .regs = aer_regs,
- };
-
- spin_lock_irqsave(&aer_recover_ring_lock, flags);
- if (kfifo_put(&aer_recover_ring, entry))
- schedule_work(&aer_recover_work);
- else
- pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n",
- domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
- spin_unlock_irqrestore(&aer_recover_ring_lock, flags);
-}
-EXPORT_SYMBOL_GPL(aer_recover_queue);
-#endif
-
-/**
- * get_device_error_info - read error status from dev and store it to info
- * @dev: pointer to the device expected to have a error record
- * @info: pointer to structure to store the error record
- *
- * Return 1 on success, 0 on error.
- *
- * Note that @info is reused among all error devices. Clear fields properly.
- */
-static int get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
-{
- int pos, temp;
-
- /* Must reset in this function */
- info->status = 0;
- info->tlp_header_valid = 0;
-
- pos = dev->aer_cap;
-
- /* The device might not support AER */
- if (!pos)
- return 0;
-
- if (info->severity == AER_CORRECTABLE) {
- pci_read_config_dword(dev, pos + PCI_ERR_COR_STATUS,
- &info->status);
- pci_read_config_dword(dev, pos + PCI_ERR_COR_MASK,
- &info->mask);
- if (!(info->status & ~info->mask))
- return 0;
- } else if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
- info->severity == AER_NONFATAL) {
-
- /* Link is still healthy for IO reads */
- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS,
- &info->status);
- pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_MASK,
- &info->mask);
- if (!(info->status & ~info->mask))
- return 0;
-
- /* Get First Error Pointer */
- pci_read_config_dword(dev, pos + PCI_ERR_CAP, &temp);
- info->first_error = PCI_ERR_CAP_FEP(temp);
-
- if (info->status & AER_LOG_TLP_MASKS) {
- info->tlp_header_valid = 1;
- pci_read_config_dword(dev,
- pos + PCI_ERR_HEADER_LOG, &info->tlp.dw0);
- pci_read_config_dword(dev,
- pos + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1);
- pci_read_config_dword(dev,
- pos + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2);
- pci_read_config_dword(dev,
- pos + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3);
- }
- }
-
- return 1;
-}
-
-static inline void aer_process_err_devices(struct aer_err_info *e_info)
-{
- int i;
-
- /* Report all before handle them, not to lost records by reset etc. */
- for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) {
- if (get_device_error_info(e_info->dev[i], e_info))
- aer_print_error(e_info->dev[i], e_info);
- }
- for (i = 0; i < e_info->error_dev_num && e_info->dev[i]; i++) {
- if (get_device_error_info(e_info->dev[i], e_info))
- handle_error_source(e_info->dev[i], e_info);
- }
-}
-
-/**
- * aer_isr_one_error - consume an error detected by root port
- * @rpc: pointer to the root port which holds an error
- * @e_src: pointer to an error source
- */
-static void aer_isr_one_error(struct aer_rpc *rpc,
- struct aer_err_source *e_src)
-{
- struct pci_dev *pdev = rpc->rpd;
- struct aer_err_info *e_info = &rpc->e_info;
-
- /*
- * There is a possibility that both correctable error and
- * uncorrectable error being logged. Report correctable error first.
- */
- if (e_src->status & PCI_ERR_ROOT_COR_RCV) {
- e_info->id = ERR_COR_ID(e_src->id);
- e_info->severity = AER_CORRECTABLE;
-
- if (e_src->status & PCI_ERR_ROOT_MULTI_COR_RCV)
- e_info->multi_error_valid = 1;
- else
- e_info->multi_error_valid = 0;
- aer_print_port_info(pdev, e_info);
-
- if (find_source_device(pdev, e_info))
- aer_process_err_devices(e_info);
- }
-
- if (e_src->status & PCI_ERR_ROOT_UNCOR_RCV) {
- e_info->id = ERR_UNCOR_ID(e_src->id);
-
- if (e_src->status & PCI_ERR_ROOT_FATAL_RCV)
- e_info->severity = AER_FATAL;
- else
- e_info->severity = AER_NONFATAL;
-
- if (e_src->status & PCI_ERR_ROOT_MULTI_UNCOR_RCV)
- e_info->multi_error_valid = 1;
- else
- e_info->multi_error_valid = 0;
-
- aer_print_port_info(pdev, e_info);
-
- if (find_source_device(pdev, e_info))
- aer_process_err_devices(e_info);
- }
-}
-
-/**
- * get_e_source - retrieve an error source
- * @rpc: pointer to the root port which holds an error
- * @e_src: pointer to store retrieved error source
- *
- * Return 1 if an error source is retrieved, otherwise 0.
- *
- * Invoked by DPC handler to consume an error.
- */
-static int get_e_source(struct aer_rpc *rpc, struct aer_err_source *e_src)
-{
- unsigned long flags;
-
- /* Lock access to Root error producer/consumer index */
- spin_lock_irqsave(&rpc->e_lock, flags);
- if (rpc->prod_idx == rpc->cons_idx) {
- spin_unlock_irqrestore(&rpc->e_lock, flags);
- return 0;
- }
-
- *e_src = rpc->e_sources[rpc->cons_idx];
- rpc->cons_idx++;
- if (rpc->cons_idx == AER_ERROR_SOURCES_MAX)
- rpc->cons_idx = 0;
- spin_unlock_irqrestore(&rpc->e_lock, flags);
-
- return 1;
-}
-
-/**
- * aer_isr - consume errors detected by root port
- * @work: definition of this work item
- *
- * Invoked, as DPC, when root port records new detected error
- */
-void aer_isr(struct work_struct *work)
-{
- struct aer_rpc *rpc = container_of(work, struct aer_rpc, dpc_handler);
- struct aer_err_source uninitialized_var(e_src);
-
- mutex_lock(&rpc->rpc_mutex);
- while (get_e_source(rpc, &e_src))
- aer_isr_one_error(rpc, &e_src);
- mutex_unlock(&rpc->rpc_mutex);
-}
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c
deleted file mode 100644
index 4985bdf..0000000
--- a/drivers/pci/pcie/aer/aerdrv_errprint.c
+++ /dev/null
@@ -1,260 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Format error messages and print them to console.
- *
- * Copyright (C) 2006 Intel Corp.
- * Tom Long Nguyen (tom.l.nguyen@intel.com)
- * Zhang Yanmin (yanmin.zhang@intel.com)
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/pm.h>
-#include <linux/suspend.h>
-#include <linux/cper.h>
-
-#include "aerdrv.h"
-#include <ras/ras_event.h>
-
-#define AER_AGENT_RECEIVER 0
-#define AER_AGENT_REQUESTER 1
-#define AER_AGENT_COMPLETER 2
-#define AER_AGENT_TRANSMITTER 3
-
-#define AER_AGENT_REQUESTER_MASK(t) ((t == AER_CORRECTABLE) ? \
- 0 : (PCI_ERR_UNC_COMP_TIME|PCI_ERR_UNC_UNSUP))
-#define AER_AGENT_COMPLETER_MASK(t) ((t == AER_CORRECTABLE) ? \
- 0 : PCI_ERR_UNC_COMP_ABORT)
-#define AER_AGENT_TRANSMITTER_MASK(t) ((t == AER_CORRECTABLE) ? \
- (PCI_ERR_COR_REP_ROLL|PCI_ERR_COR_REP_TIMER) : 0)
-
-#define AER_GET_AGENT(t, e) \
- ((e & AER_AGENT_COMPLETER_MASK(t)) ? AER_AGENT_COMPLETER : \
- (e & AER_AGENT_REQUESTER_MASK(t)) ? AER_AGENT_REQUESTER : \
- (e & AER_AGENT_TRANSMITTER_MASK(t)) ? AER_AGENT_TRANSMITTER : \
- AER_AGENT_RECEIVER)
-
-#define AER_PHYSICAL_LAYER_ERROR 0
-#define AER_DATA_LINK_LAYER_ERROR 1
-#define AER_TRANSACTION_LAYER_ERROR 2
-
-#define AER_PHYSICAL_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
- PCI_ERR_COR_RCVR : 0)
-#define AER_DATA_LINK_LAYER_ERROR_MASK(t) ((t == AER_CORRECTABLE) ? \
- (PCI_ERR_COR_BAD_TLP| \
- PCI_ERR_COR_BAD_DLLP| \
- PCI_ERR_COR_REP_ROLL| \
- PCI_ERR_COR_REP_TIMER) : PCI_ERR_UNC_DLP)
-
-#define AER_GET_LAYER_ERROR(t, e) \
- ((e & AER_PHYSICAL_LAYER_ERROR_MASK(t)) ? AER_PHYSICAL_LAYER_ERROR : \
- (e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \
- AER_TRANSACTION_LAYER_ERROR)
-
-/*
- * AER error strings
- */
-static const char *aer_error_severity_string[] = {
- "Uncorrected (Non-Fatal)",
- "Uncorrected (Fatal)",
- "Corrected"
-};
-
-static const char *aer_error_layer[] = {
- "Physical Layer",
- "Data Link Layer",
- "Transaction Layer"
-};
-
-static const char *aer_correctable_error_string[] = {
- "Receiver Error", /* Bit Position 0 */
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "Bad TLP", /* Bit Position 6 */
- "Bad DLLP", /* Bit Position 7 */
- "RELAY_NUM Rollover", /* Bit Position 8 */
- NULL,
- NULL,
- NULL,
- "Replay Timer Timeout", /* Bit Position 12 */
- "Advisory Non-Fatal", /* Bit Position 13 */
- "Corrected Internal Error", /* Bit Position 14 */
- "Header Log Overflow", /* Bit Position 15 */
-};
-
-static const char *aer_uncorrectable_error_string[] = {
- "Undefined", /* Bit Position 0 */
- NULL,
- NULL,
- NULL,
- "Data Link Protocol", /* Bit Position 4 */
- "Surprise Down Error", /* Bit Position 5 */
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- "Poisoned TLP", /* Bit Position 12 */
- "Flow Control Protocol", /* Bit Position 13 */
- "Completion Timeout", /* Bit Position 14 */
- "Completer Abort", /* Bit Position 15 */
- "Unexpected Completion", /* Bit Position 16 */
- "Receiver Overflow", /* Bit Position 17 */
- "Malformed TLP", /* Bit Position 18 */
- "ECRC", /* Bit Position 19 */
- "Unsupported Request", /* Bit Position 20 */
- "ACS Violation", /* Bit Position 21 */
- "Uncorrectable Internal Error", /* Bit Position 22 */
- "MC Blocked TLP", /* Bit Position 23 */
- "AtomicOp Egress Blocked", /* Bit Position 24 */
- "TLP Prefix Blocked Error", /* Bit Position 25 */
-};
-
-static const char *aer_agent_string[] = {
- "Receiver ID",
- "Requester ID",
- "Completer ID",
- "Transmitter ID"
-};
-
-static void __print_tlp_header(struct pci_dev *dev,
- struct aer_header_log_regs *t)
-{
- pci_err(dev, " TLP Header: %08x %08x %08x %08x\n",
- t->dw0, t->dw1, t->dw2, t->dw3);
-}
-
-static void __aer_print_error(struct pci_dev *dev,
- struct aer_err_info *info)
-{
- int i, status;
- const char *errmsg = NULL;
- status = (info->status & ~info->mask);
-
- for (i = 0; i < 32; i++) {
- if (!(status & (1 << i)))
- continue;
-
- if (info->severity == AER_CORRECTABLE)
- errmsg = i < ARRAY_SIZE(aer_correctable_error_string) ?
- aer_correctable_error_string[i] : NULL;
- else
- errmsg = i < ARRAY_SIZE(aer_uncorrectable_error_string) ?
- aer_uncorrectable_error_string[i] : NULL;
-
- if (errmsg)
- pci_err(dev, " [%2d] %-22s%s\n", i, errmsg,
- info->first_error == i ? " (First)" : "");
- else
- pci_err(dev, " [%2d] Unknown Error Bit%s\n",
- i, info->first_error == i ? " (First)" : "");
- }
-}
-
-void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
-{
- int layer, agent;
- int id = ((dev->bus->number << 8) | dev->devfn);
-
- if (!info->status) {
- pci_err(dev, "PCIe Bus Error: severity=%s, type=Inaccessible, (Unregistered Agent ID)\n",
- aer_error_severity_string[info->severity]);
- goto out;
- }
-
- layer = AER_GET_LAYER_ERROR(info->severity, info->status);
- agent = AER_GET_AGENT(info->severity, info->status);
-
- pci_err(dev, "PCIe Bus Error: severity=%s, type=%s, (%s)\n",
- aer_error_severity_string[info->severity],
- aer_error_layer[layer], aer_agent_string[agent]);
-
- pci_err(dev, " device [%04x:%04x] error status/mask=%08x/%08x\n",
- dev->vendor, dev->device,
- info->status, info->mask);
-
- __aer_print_error(dev, info);
-
- if (info->tlp_header_valid)
- __print_tlp_header(dev, &info->tlp);
-
-out:
- if (info->id && info->error_dev_num > 1 && info->id == id)
- pci_err(dev, " Error of this Agent is reported first\n");
-
- trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask),
- info->severity, info->tlp_header_valid, &info->tlp);
-}
-
-void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
-{
- u8 bus = info->id >> 8;
- u8 devfn = info->id & 0xff;
-
- pci_info(dev, "AER: %s%s error received: %04x:%02x:%02x.%d\n",
- info->multi_error_valid ? "Multiple " : "",
- aer_error_severity_string[info->severity],
- pci_domain_nr(dev->bus), bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
-}
-
-#ifdef CONFIG_ACPI_APEI_PCIEAER
-int cper_severity_to_aer(int cper_severity)
-{
- switch (cper_severity) {
- case CPER_SEV_RECOVERABLE:
- return AER_NONFATAL;
- case CPER_SEV_FATAL:
- return AER_FATAL;
- default:
- return AER_CORRECTABLE;
- }
-}
-EXPORT_SYMBOL_GPL(cper_severity_to_aer);
-
-void cper_print_aer(struct pci_dev *dev, int aer_severity,
- struct aer_capability_regs *aer)
-{
- int layer, agent, tlp_header_valid = 0;
- u32 status, mask;
- struct aer_err_info info;
-
- if (aer_severity == AER_CORRECTABLE) {
- status = aer->cor_status;
- mask = aer->cor_mask;
- } else {
- status = aer->uncor_status;
- mask = aer->uncor_mask;
- tlp_header_valid = status & AER_LOG_TLP_MASKS;
- }
-
- layer = AER_GET_LAYER_ERROR(aer_severity, status);
- agent = AER_GET_AGENT(aer_severity, status);
-
- memset(&info, 0, sizeof(info));
- info.severity = aer_severity;
- info.status = status;
- info.mask = mask;
- info.first_error = PCI_ERR_CAP_FEP(aer->cap_control);
-
- pci_err(dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", status, mask);
- __aer_print_error(dev, &info);
- pci_err(dev, "aer_layer=%s, aer_agent=%s\n",
- aer_error_layer[layer], aer_agent_string[agent]);
-
- if (aer_severity != AER_CORRECTABLE)
- pci_err(dev, "aer_uncor_severity: 0x%08x\n",
- aer->uncor_severity);
-
- if (tlp_header_valid)
- __print_tlp_header(dev, &aer->header_log);
-
- trace_aer_event(dev_name(&dev->dev), (status & ~mask),
- aer_severity, tlp_header_valid, &aer->header_log);
-}
-#endif
diff --git a/drivers/pci/pcie/aer/ecrc.c b/drivers/pci/pcie/aer/ecrc.c
deleted file mode 100644
index 039efb60..0000000
--- a/drivers/pci/pcie/aer/ecrc.c
+++ /dev/null
@@ -1,117 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Enable/disable PCIe ECRC checking
- *
- * (C) Copyright 2009 Hewlett-Packard Development Company, L.P.
- * Andrew Patterson <andrew.patterson@hp.com>
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/pci.h>
-#include <linux/pci_regs.h>
-#include <linux/errno.h>
-#include "../../pci.h"
-
-#define ECRC_POLICY_DEFAULT 0 /* ECRC set by BIOS */
-#define ECRC_POLICY_OFF 1 /* ECRC off for performance */
-#define ECRC_POLICY_ON 2 /* ECRC on for data integrity */
-
-static int ecrc_policy = ECRC_POLICY_DEFAULT;
-
-static const char *ecrc_policy_str[] = {
- [ECRC_POLICY_DEFAULT] = "bios",
- [ECRC_POLICY_OFF] = "off",
- [ECRC_POLICY_ON] = "on"
-};
-
-/**
- * enable_ercr_checking - enable PCIe ECRC checking for a device
- * @dev: the PCI device
- *
- * Returns 0 on success, or negative on failure.
- */
-static int enable_ecrc_checking(struct pci_dev *dev)
-{
- int pos;
- u32 reg32;
-
- if (!pci_is_pcie(dev))
- return -ENODEV;
-
- pos = dev->aer_cap;
- if (!pos)
- return -ENODEV;
-
- pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
- if (reg32 & PCI_ERR_CAP_ECRC_GENC)
- reg32 |= PCI_ERR_CAP_ECRC_GENE;
- if (reg32 & PCI_ERR_CAP_ECRC_CHKC)
- reg32 |= PCI_ERR_CAP_ECRC_CHKE;
- pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
-
- return 0;
-}
-
-/**
- * disable_ercr_checking - disables PCIe ECRC checking for a device
- * @dev: the PCI device
- *
- * Returns 0 on success, or negative on failure.
- */
-static int disable_ecrc_checking(struct pci_dev *dev)
-{
- int pos;
- u32 reg32;
-
- if (!pci_is_pcie(dev))
- return -ENODEV;
-
- pos = dev->aer_cap;
- if (!pos)
- return -ENODEV;
-
- pci_read_config_dword(dev, pos + PCI_ERR_CAP, &reg32);
- reg32 &= ~(PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
- pci_write_config_dword(dev, pos + PCI_ERR_CAP, reg32);
-
- return 0;
-}
-
-/**
- * pcie_set_ecrc_checking - set/unset PCIe ECRC checking for a device based on global policy
- * @dev: the PCI device
- */
-void pcie_set_ecrc_checking(struct pci_dev *dev)
-{
- switch (ecrc_policy) {
- case ECRC_POLICY_DEFAULT:
- return;
- case ECRC_POLICY_OFF:
- disable_ecrc_checking(dev);
- break;
- case ECRC_POLICY_ON:
- enable_ecrc_checking(dev);
- break;
- default:
- return;
- }
-}
-
-/**
- * pcie_ecrc_get_policy - parse kernel command-line ecrc option
- */
-void pcie_ecrc_get_policy(char *str)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ecrc_policy_str); i++)
- if (!strncmp(str, ecrc_policy_str[i],
- strlen(ecrc_policy_str[i])))
- break;
- if (i >= ARRAY_SIZE(ecrc_policy_str))
- return;
-
- ecrc_policy = i;
-}
diff --git a/drivers/pci/pcie/aer/aer_inject.c b/drivers/pci/pcie/aer_inject.c
index a490909..0eb2434 100644
--- a/drivers/pci/pcie/aer/aer_inject.c
+++ b/drivers/pci/pcie/aer_inject.c
@@ -21,7 +21,8 @@
#include <linux/uaccess.h>
#include <linux/stddef.h>
#include <linux/device.h>
-#include "aerdrv.h"
+
+#include "portdrv.h"
/* Override the existing corrected and uncorrected error masks */
static bool aer_mask_override;
diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c
index d643668..921ed97 100644
--- a/drivers/pci/pcie/dpc.c
+++ b/drivers/pci/pcie/dpc.c
@@ -13,7 +13,6 @@
#include "portdrv.h"
#include "../pci.h"
-#include "aer/aerdrv.h"
struct dpc_dev {
struct pcie_device *dev;
diff --git a/drivers/pci/pcie/portdrv.h b/drivers/pci/pcie/portdrv.h
index 2bb5db7..6ffc797 100644
--- a/drivers/pci/pcie/portdrv.h
+++ b/drivers/pci/pcie/portdrv.h
@@ -110,6 +110,21 @@ static inline bool pcie_pme_no_msi(void) { return false; }
static inline void pcie_pme_interrupt_enable(struct pci_dev *dev, bool en) {}
#endif /* !CONFIG_PCIE_PME */
+#ifdef CONFIG_ACPI_APEI
+int pcie_aer_get_firmware_first(struct pci_dev *pci_dev);
+#else
+static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev)
+{
+ if (pci_dev->__aer_firmware_first_valid)
+ return pci_dev->__aer_firmware_first;
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_PCIEAER
+irqreturn_t aer_irq(int irq, void *context);
+#endif
+
struct pcie_port_service_driver *pcie_port_find_service(struct pci_dev *dev,
u32 service);
struct device *pcie_port_find_device(struct pci_dev *dev, u32 service);
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 102646f..ac0672b 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -1481,11 +1481,11 @@ static ssize_t pccard_extract_cis(struct pcmcia_socket *s, char *buf,
u_char *tuplebuffer;
u_char *tempbuffer;
- tuplebuffer = kmalloc(sizeof(u_char) * 256, GFP_KERNEL);
+ tuplebuffer = kmalloc_array(256, sizeof(u_char), GFP_KERNEL);
if (!tuplebuffer)
return -ENOMEM;
- tempbuffer = kmalloc(sizeof(u_char) * 258, GFP_KERNEL);
+ tempbuffer = kmalloc_array(258, sizeof(u_char), GFP_KERNEL);
if (!tempbuffer) {
ret = -ENOMEM;
goto free_tuple;
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 959ae3e..f0af998 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -628,7 +628,7 @@ static int pd6729_pci_probe(struct pci_dev *dev,
char configbyte;
struct pd6729_socket *socket;
- socket = kzalloc(sizeof(struct pd6729_socket) * MAX_SOCKETS,
+ socket = kcalloc(MAX_SOCKETS, sizeof(struct pd6729_socket),
GFP_KERNEL);
if (!socket) {
dev_warn(&dev->dev, "failed to kzalloc socket.\n");
diff --git a/drivers/pinctrl/actions/pinctrl-owl.c b/drivers/pinctrl/actions/pinctrl-owl.c
index 76243ca..b5c880b 100644
--- a/drivers/pinctrl/actions/pinctrl-owl.c
+++ b/drivers/pinctrl/actions/pinctrl-owl.c
@@ -333,7 +333,7 @@ static int owl_pin_config_set(struct pinctrl_dev *pctrldev,
unsigned long flags;
unsigned int param;
u32 reg, bit, width, arg;
- int ret, i;
+ int ret = 0, i;
info = &pctrl->soc->padinfo[pin];
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index 136ccaf..fa53091 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -771,8 +771,8 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
maps_per_pin++;
if (num_pulls)
maps_per_pin++;
- cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps),
- GFP_KERNEL);
+ cur_map = maps = kcalloc(num_pins * maps_per_pin, sizeof(*maps),
+ GFP_KERNEL);
if (!maps)
return -ENOMEM;
diff --git a/drivers/pinctrl/berlin/berlin.c b/drivers/pinctrl/berlin/berlin.c
index a620a8e..d6d183e 100644
--- a/drivers/pinctrl/berlin/berlin.c
+++ b/drivers/pinctrl/berlin/berlin.c
@@ -216,8 +216,9 @@ static int berlin_pinctrl_build_state(struct platform_device *pdev)
}
/* we will reallocate later */
- pctrl->functions = devm_kzalloc(&pdev->dev,
- max_functions * sizeof(*pctrl->functions),
+ pctrl->functions = devm_kcalloc(&pdev->dev,
+ max_functions,
+ sizeof(*pctrl->functions),
GFP_KERNEL);
if (!pctrl->functions)
return -ENOMEM;
@@ -261,8 +262,9 @@ static int berlin_pinctrl_build_state(struct platform_device *pdev)
if (!function->groups) {
function->groups =
- devm_kzalloc(&pdev->dev,
- function->ngroups * sizeof(char *),
+ devm_kcalloc(&pdev->dev,
+ function->ngroups,
+ sizeof(char *),
GFP_KERNEL);
if (!function->groups)
diff --git a/drivers/pinctrl/devicetree.c b/drivers/pinctrl/devicetree.c
index b601039..c4aa411 100644
--- a/drivers/pinctrl/devicetree.c
+++ b/drivers/pinctrl/devicetree.c
@@ -101,10 +101,11 @@ struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
}
static int dt_to_map_one_config(struct pinctrl *p,
- struct pinctrl_dev *pctldev,
+ struct pinctrl_dev *hog_pctldev,
const char *statename,
struct device_node *np_config)
{
+ struct pinctrl_dev *pctldev = NULL;
struct device_node *np_pctldev;
const struct pinctrl_ops *ops;
int ret;
@@ -123,8 +124,10 @@ static int dt_to_map_one_config(struct pinctrl *p,
return -EPROBE_DEFER;
}
/* If we're creating a hog we can use the passed pctldev */
- if (pctldev && (np_pctldev == p->dev->of_node))
+ if (hog_pctldev && (np_pctldev == p->dev->of_node)) {
+ pctldev = hog_pctldev;
break;
+ }
pctldev = get_pinctrl_dev_from_of_node(np_pctldev);
if (pctldev)
break;
diff --git a/drivers/pinctrl/freescale/pinctrl-imx.c b/drivers/pinctrl/freescale/pinctrl-imx.c
index e582a21..1c6bb15 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx.c
@@ -81,7 +81,8 @@ static int imx_dt_node_to_map(struct pinctrl_dev *pctldev,
map_num++;
}
- new_map = kmalloc(sizeof(struct pinctrl_map) * map_num, GFP_KERNEL);
+ new_map = kmalloc_array(map_num, sizeof(struct pinctrl_map),
+ GFP_KERNEL);
if (!new_map)
return -ENOMEM;
@@ -476,10 +477,12 @@ static int imx_pinctrl_parse_groups(struct device_node *np,
config = imx_pinconf_parse_generic_config(np, ipctl);
grp->num_pins = size / pin_size;
- grp->data = devm_kzalloc(ipctl->dev, grp->num_pins *
- sizeof(struct imx_pin), GFP_KERNEL);
- grp->pins = devm_kzalloc(ipctl->dev, grp->num_pins *
- sizeof(unsigned int), GFP_KERNEL);
+ grp->data = devm_kcalloc(ipctl->dev,
+ grp->num_pins, sizeof(struct imx_pin),
+ GFP_KERNEL);
+ grp->pins = devm_kcalloc(ipctl->dev,
+ grp->num_pins, sizeof(unsigned int),
+ GFP_KERNEL);
if (!grp->pins || !grp->data)
return -ENOMEM;
@@ -697,8 +700,9 @@ int imx_pinctrl_probe(struct platform_device *pdev,
if (!ipctl)
return -ENOMEM;
- ipctl->pin_regs = devm_kmalloc(&pdev->dev, sizeof(*ipctl->pin_regs) *
- info->npins, GFP_KERNEL);
+ ipctl->pin_regs = devm_kmalloc_array(&pdev->dev,
+ info->npins, sizeof(*ipctl->pin_regs),
+ GFP_KERNEL);
if (!ipctl->pin_regs)
return -ENOMEM;
diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c
index 5af89de..c3bdd90 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c
@@ -241,7 +241,8 @@ static int imx1_dt_node_to_map(struct pinctrl_dev *pctldev,
for (i = 0; i < grp->npins; i++)
map_num++;
- new_map = kmalloc(sizeof(struct pinctrl_map) * map_num, GFP_KERNEL);
+ new_map = kmalloc_array(map_num, sizeof(struct pinctrl_map),
+ GFP_KERNEL);
if (!new_map)
return -ENOMEM;
@@ -482,10 +483,10 @@ static int imx1_pinctrl_parse_groups(struct device_node *np,
}
grp->npins = size / 12;
- grp->pins = devm_kzalloc(info->dev,
- grp->npins * sizeof(struct imx1_pin), GFP_KERNEL);
- grp->pin_ids = devm_kzalloc(info->dev,
- grp->npins * sizeof(unsigned int), GFP_KERNEL);
+ grp->pins = devm_kcalloc(info->dev,
+ grp->npins, sizeof(struct imx1_pin), GFP_KERNEL);
+ grp->pin_ids = devm_kcalloc(info->dev,
+ grp->npins, sizeof(unsigned int), GFP_KERNEL);
if (!grp->pins || !grp->pin_ids)
return -ENOMEM;
@@ -522,8 +523,8 @@ static int imx1_pinctrl_parse_functions(struct device_node *np,
if (func->num_groups == 0)
return -EINVAL;
- func->groups = devm_kzalloc(info->dev,
- func->num_groups * sizeof(char *), GFP_KERNEL);
+ func->groups = devm_kcalloc(info->dev,
+ func->num_groups, sizeof(char *), GFP_KERNEL);
if (!func->groups)
return -ENOMEM;
@@ -565,12 +566,12 @@ static int imx1_pinctrl_parse_dt(struct platform_device *pdev,
}
info->nfunctions = nfuncs;
- info->functions = devm_kzalloc(&pdev->dev,
- nfuncs * sizeof(struct imx1_pmx_func), GFP_KERNEL);
+ info->functions = devm_kcalloc(&pdev->dev,
+ nfuncs, sizeof(struct imx1_pmx_func), GFP_KERNEL);
info->ngroups = ngroups;
- info->groups = devm_kzalloc(&pdev->dev,
- ngroups * sizeof(struct imx1_pin_group), GFP_KERNEL);
+ info->groups = devm_kcalloc(&pdev->dev,
+ ngroups, sizeof(struct imx1_pin_group), GFP_KERNEL);
if (!info->functions || !info->groups)
diff --git a/drivers/pinctrl/freescale/pinctrl-mxs.c b/drivers/pinctrl/freescale/pinctrl-mxs.c
index 594f3e5..a612e46 100644
--- a/drivers/pinctrl/freescale/pinctrl-mxs.c
+++ b/drivers/pinctrl/freescale/pinctrl-mxs.c
@@ -89,7 +89,7 @@ static int mxs_dt_node_to_map(struct pinctrl_dev *pctldev,
if (!purecfg && config)
new_num = 2;
- new_map = kzalloc(sizeof(*new_map) * new_num, GFP_KERNEL);
+ new_map = kcalloc(new_num, sizeof(*new_map), GFP_KERNEL);
if (!new_map)
return -ENOMEM;
@@ -370,12 +370,12 @@ static int mxs_pinctrl_parse_group(struct platform_device *pdev,
return -EINVAL;
g->npins = length / sizeof(u32);
- g->pins = devm_kzalloc(&pdev->dev, g->npins * sizeof(*g->pins),
+ g->pins = devm_kcalloc(&pdev->dev, g->npins, sizeof(*g->pins),
GFP_KERNEL);
if (!g->pins)
return -ENOMEM;
- g->muxsel = devm_kzalloc(&pdev->dev, g->npins * sizeof(*g->muxsel),
+ g->muxsel = devm_kcalloc(&pdev->dev, g->npins, sizeof(*g->muxsel),
GFP_KERNEL);
if (!g->muxsel)
return -ENOMEM;
@@ -426,13 +426,16 @@ static int mxs_pinctrl_probe_dt(struct platform_device *pdev,
}
}
- soc->functions = devm_kzalloc(&pdev->dev, soc->nfunctions *
- sizeof(*soc->functions), GFP_KERNEL);
+ soc->functions = devm_kcalloc(&pdev->dev,
+ soc->nfunctions,
+ sizeof(*soc->functions),
+ GFP_KERNEL);
if (!soc->functions)
return -ENOMEM;
- soc->groups = devm_kzalloc(&pdev->dev, soc->ngroups *
- sizeof(*soc->groups), GFP_KERNEL);
+ soc->groups = devm_kcalloc(&pdev->dev,
+ soc->ngroups, sizeof(*soc->groups),
+ GFP_KERNEL);
if (!soc->groups)
return -ENOMEM;
@@ -492,7 +495,8 @@ static int mxs_pinctrl_probe_dt(struct platform_device *pdev,
if (strcmp(fn, child->name)) {
f = &soc->functions[idxf++];
- f->groups = devm_kzalloc(&pdev->dev, f->ngroups *
+ f->groups = devm_kcalloc(&pdev->dev,
+ f->ngroups,
sizeof(*f->groups),
GFP_KERNEL);
if (!f->groups)
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt7622.c b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
index ad6da11..e3f1ab2 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt7622.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt7622.c
@@ -1459,6 +1459,9 @@ static int mtk_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
struct mtk_pinctrl *hw = gpiochip_get_data(chip);
unsigned long eint_n;
+ if (!hw->eint)
+ return -ENOTSUPP;
+
eint_n = offset;
return mtk_eint_find_irq(hw->eint, eint_n);
@@ -1471,7 +1474,8 @@ static int mtk_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long eint_n;
u32 debounce;
- if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
+ if (!hw->eint ||
+ pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
return -ENOTSUPP;
debounce = pinconf_to_config_argument(config);
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index b379969..16ff56f9 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -1000,11 +1000,6 @@ static int mtk_eint_init(struct mtk_pinctrl *pctl, struct platform_device *pdev)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "Unable to get eint resource\n");
- return -ENODEV;
- }
-
pctl->eint->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pctl->eint->base))
return PTR_ERR(pctl->eint->base);
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 674ffdf..53cf800 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -856,9 +856,10 @@ static int armada_37xx_fill_group(struct armada_37xx_pinctrl *info)
struct armada_37xx_pin_group *grp = &info->groups[n];
int i, j, f;
- grp->pins = devm_kzalloc(info->dev,
- (grp->npins + grp->extra_npins) *
- sizeof(*grp->pins), GFP_KERNEL);
+ grp->pins = devm_kcalloc(info->dev,
+ grp->npins + grp->extra_npins,
+ sizeof(*grp->pins),
+ GFP_KERNEL);
if (!grp->pins)
return -ENOMEM;
@@ -908,7 +909,8 @@ static int armada_37xx_fill_func(struct armada_37xx_pinctrl *info)
const char **groups;
int g;
- funcs[n].groups = devm_kzalloc(info->dev, funcs[n].ngroups *
+ funcs[n].groups = devm_kcalloc(info->dev,
+ funcs[n].ngroups,
sizeof(*(funcs[n].groups)),
GFP_KERNEL);
if (!funcs[n].groups)
@@ -948,8 +950,9 @@ static int armada_37xx_pinctrl_register(struct platform_device *pdev,
ctrldesc->pmxops = &armada_37xx_pmx_ops;
ctrldesc->confops = &armada_37xx_pinconf_ops;
- pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
- pin_data->nr_pins, GFP_KERNEL);
+ pindesc = devm_kcalloc(&pdev->dev,
+ pin_data->nr_pins, sizeof(*pindesc),
+ GFP_KERNEL);
if (!pindesc)
return -ENOMEM;
@@ -968,8 +971,10 @@ static int armada_37xx_pinctrl_register(struct platform_device *pdev,
* we allocate functions for number of pins and hope there are
* fewer unique functions than pins available
*/
- info->funcs = devm_kzalloc(&pdev->dev, pin_data->nr_pins *
- sizeof(struct armada_37xx_pmx_func), GFP_KERNEL);
+ info->funcs = devm_kcalloc(&pdev->dev,
+ pin_data->nr_pins,
+ sizeof(struct armada_37xx_pmx_func),
+ GFP_KERNEL);
if (!info->funcs)
return -ENOMEM;
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
index 5e82846..43231fd 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-xp.c
@@ -630,8 +630,8 @@ static int armada_xp_pinctrl_probe(struct platform_device *pdev)
nregs = DIV_ROUND_UP(soc->nmodes, MVEBU_MPPS_PER_REG);
- mpp_saved_regs = devm_kmalloc(&pdev->dev, nregs * sizeof(u32),
- GFP_KERNEL);
+ mpp_saved_regs = devm_kmalloc_array(&pdev->dev, nregs, sizeof(u32),
+ GFP_KERNEL);
if (!mpp_saved_regs)
return -ENOMEM;
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 9e05cfa..d7ec711 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -501,8 +501,9 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
/* we allocate functions for number of pins and hope
* there are fewer unique functions than pins available */
- funcs = devm_kzalloc(&pdev->dev, funcsize *
- sizeof(struct mvebu_pinctrl_function), GFP_KERNEL);
+ funcs = devm_kcalloc(&pdev->dev,
+ funcsize, sizeof(struct mvebu_pinctrl_function),
+ GFP_KERNEL);
if (!funcs)
return -ENOMEM;
@@ -549,8 +550,9 @@ static int mvebu_pinctrl_build_functions(struct platform_device *pdev,
/* allocate group name array if not done already */
if (!f->groups) {
- f->groups = devm_kzalloc(&pdev->dev,
- f->num_groups * sizeof(char *),
+ f->groups = devm_kcalloc(&pdev->dev,
+ f->num_groups,
+ sizeof(char *),
GFP_KERNEL);
if (!f->groups)
return -ENOMEM;
@@ -622,8 +624,10 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
}
}
- pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins *
- sizeof(struct pinctrl_pin_desc), GFP_KERNEL);
+ pdesc = devm_kcalloc(&pdev->dev,
+ pctl->desc.npins,
+ sizeof(struct pinctrl_pin_desc),
+ GFP_KERNEL);
if (!pdesc)
return -ENOMEM;
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index bafb3d4..67e4d9f 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -945,27 +945,30 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
return PTR_ERR(atmel_pioctrl->clk);
}
- atmel_pioctrl->pins = devm_kzalloc(dev, sizeof(*atmel_pioctrl->pins)
- * atmel_pioctrl->npins, GFP_KERNEL);
+ atmel_pioctrl->pins = devm_kcalloc(dev,
+ atmel_pioctrl->npins,
+ sizeof(*atmel_pioctrl->pins),
+ GFP_KERNEL);
if (!atmel_pioctrl->pins)
return -ENOMEM;
- pin_desc = devm_kzalloc(dev, sizeof(*pin_desc)
- * atmel_pioctrl->npins, GFP_KERNEL);
+ pin_desc = devm_kcalloc(dev, atmel_pioctrl->npins, sizeof(*pin_desc),
+ GFP_KERNEL);
if (!pin_desc)
return -ENOMEM;
atmel_pinctrl_desc.pins = pin_desc;
atmel_pinctrl_desc.npins = atmel_pioctrl->npins;
/* One pin is one group since a pin can achieve all functions. */
- group_names = devm_kzalloc(dev, sizeof(*group_names)
- * atmel_pioctrl->npins, GFP_KERNEL);
+ group_names = devm_kcalloc(dev,
+ atmel_pioctrl->npins, sizeof(*group_names),
+ GFP_KERNEL);
if (!group_names)
return -ENOMEM;
atmel_pioctrl->group_names = group_names;
- atmel_pioctrl->groups = devm_kzalloc(&pdev->dev,
- sizeof(*atmel_pioctrl->groups) * atmel_pioctrl->npins,
+ atmel_pioctrl->groups = devm_kcalloc(&pdev->dev,
+ atmel_pioctrl->npins, sizeof(*atmel_pioctrl->groups),
GFP_KERNEL);
if (!atmel_pioctrl->groups)
return -ENOMEM;
@@ -1001,20 +1004,24 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
atmel_pioctrl->gpio_chip->parent = dev;
atmel_pioctrl->gpio_chip->names = atmel_pioctrl->group_names;
- atmel_pioctrl->pm_wakeup_sources = devm_kzalloc(dev,
- sizeof(*atmel_pioctrl->pm_wakeup_sources)
- * atmel_pioctrl->nbanks, GFP_KERNEL);
+ atmel_pioctrl->pm_wakeup_sources = devm_kcalloc(dev,
+ atmel_pioctrl->nbanks,
+ sizeof(*atmel_pioctrl->pm_wakeup_sources),
+ GFP_KERNEL);
if (!atmel_pioctrl->pm_wakeup_sources)
return -ENOMEM;
- atmel_pioctrl->pm_suspend_backup = devm_kzalloc(dev,
- sizeof(*atmel_pioctrl->pm_suspend_backup)
- * atmel_pioctrl->nbanks, GFP_KERNEL);
+ atmel_pioctrl->pm_suspend_backup = devm_kcalloc(dev,
+ atmel_pioctrl->nbanks,
+ sizeof(*atmel_pioctrl->pm_suspend_backup),
+ GFP_KERNEL);
if (!atmel_pioctrl->pm_suspend_backup)
return -ENOMEM;
- atmel_pioctrl->irqs = devm_kzalloc(dev, sizeof(*atmel_pioctrl->irqs)
- * atmel_pioctrl->nbanks, GFP_KERNEL);
+ atmel_pioctrl->irqs = devm_kcalloc(dev,
+ atmel_pioctrl->nbanks,
+ sizeof(*atmel_pioctrl->irqs),
+ GFP_KERNEL);
if (!atmel_pioctrl->irqs)
return -ENOMEM;
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 297f1d1..50f0ec4 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -269,7 +269,8 @@ static int at91_dt_node_to_map(struct pinctrl_dev *pctldev,
}
map_num += grp->npins;
- new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num, GFP_KERNEL);
+ new_map = devm_kcalloc(pctldev->dev, map_num, sizeof(*new_map),
+ GFP_KERNEL);
if (!new_map)
return -ENOMEM;
@@ -1049,7 +1050,8 @@ static int at91_pinctrl_mux_mask(struct at91_pinctrl *info,
}
info->nmux = size / gpio_banks;
- info->mux_mask = devm_kzalloc(info->dev, sizeof(u32) * size, GFP_KERNEL);
+ info->mux_mask = devm_kcalloc(info->dev, size, sizeof(u32),
+ GFP_KERNEL);
if (!info->mux_mask)
return -ENOMEM;
@@ -1087,10 +1089,12 @@ static int at91_pinctrl_parse_groups(struct device_node *np,
}
grp->npins = size / 4;
- pin = grp->pins_conf = devm_kzalloc(info->dev, grp->npins * sizeof(struct at91_pmx_pin),
- GFP_KERNEL);
- grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
- GFP_KERNEL);
+ pin = grp->pins_conf = devm_kcalloc(info->dev,
+ grp->npins,
+ sizeof(struct at91_pmx_pin),
+ GFP_KERNEL);
+ grp->pins = devm_kcalloc(info->dev, grp->npins, sizeof(unsigned int),
+ GFP_KERNEL);
if (!grp->pins_conf || !grp->pins)
return -ENOMEM;
@@ -1129,8 +1133,8 @@ static int at91_pinctrl_parse_functions(struct device_node *np,
dev_err(info->dev, "no groups defined\n");
return -EINVAL;
}
- func->groups = devm_kzalloc(info->dev,
- func->ngroups * sizeof(char *), GFP_KERNEL);
+ func->groups = devm_kcalloc(info->dev,
+ func->ngroups, sizeof(char *), GFP_KERNEL);
if (!func->groups)
return -ENOMEM;
@@ -1192,12 +1196,16 @@ static int at91_pinctrl_probe_dt(struct platform_device *pdev,
dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
- info->functions = devm_kzalloc(&pdev->dev, info->nfunctions * sizeof(struct at91_pmx_func),
+ info->functions = devm_kcalloc(&pdev->dev,
+ info->nfunctions,
+ sizeof(struct at91_pmx_func),
GFP_KERNEL);
if (!info->functions)
return -ENOMEM;
- info->groups = devm_kzalloc(&pdev->dev, info->ngroups * sizeof(struct at91_pin_group),
+ info->groups = devm_kcalloc(&pdev->dev,
+ info->ngroups,
+ sizeof(struct at91_pin_group),
GFP_KERNEL);
if (!info->groups)
return -ENOMEM;
@@ -1256,7 +1264,9 @@ static int at91_pinctrl_probe(struct platform_device *pdev)
at91_pinctrl_desc.name = dev_name(&pdev->dev);
at91_pinctrl_desc.npins = gpio_banks * MAX_NB_GPIO_PER_BANK;
at91_pinctrl_desc.pins = pdesc =
- devm_kzalloc(&pdev->dev, sizeof(*pdesc) * at91_pinctrl_desc.npins, GFP_KERNEL);
+ devm_kcalloc(&pdev->dev,
+ at91_pinctrl_desc.npins, sizeof(*pdesc),
+ GFP_KERNEL);
if (!at91_pinctrl_desc.pins)
return -ENOMEM;
@@ -1763,7 +1773,7 @@ static int at91_gpio_probe(struct platform_device *pdev)
chip->ngpio = ngpio;
}
- names = devm_kzalloc(&pdev->dev, sizeof(char *) * chip->ngpio,
+ names = devm_kcalloc(&pdev->dev, chip->ngpio, sizeof(char *),
GFP_KERNEL);
if (!names) {
diff --git a/drivers/pinctrl/pinctrl-axp209.c b/drivers/pinctrl/pinctrl-axp209.c
index 1231bbb..a52779f 100644
--- a/drivers/pinctrl/pinctrl-axp209.c
+++ b/drivers/pinctrl/pinctrl-axp209.c
@@ -328,7 +328,8 @@ static void axp20x_funcs_groups_from_mask(struct device *dev, unsigned int mask,
func->ngroups = ngroups;
if (func->ngroups > 0) {
- func->groups = devm_kzalloc(dev, ngroups * sizeof(const char *),
+ func->groups = devm_kcalloc(dev,
+ ngroups, sizeof(const char *),
GFP_KERNEL);
group = func->groups;
for_each_set_bit(bit, &mask_cpy, mask_len) {
@@ -358,8 +359,8 @@ static void axp20x_build_funcs_groups(struct platform_device *pdev)
/* Every pin supports GPIO_OUT and GPIO_IN functions */
for (i = 0; i <= AXP20X_FUNC_GPIO_IN; i++) {
pctl->funcs[i].ngroups = npins;
- pctl->funcs[i].groups = devm_kzalloc(&pdev->dev,
- npins * sizeof(char *),
+ pctl->funcs[i].groups = devm_kcalloc(&pdev->dev,
+ npins, sizeof(char *),
GFP_KERNEL);
for (pin = 0; pin < npins; pin++)
pctl->funcs[i].groups[pin] = pctl->desc->pins[pin].name;
diff --git a/drivers/pinctrl/pinctrl-digicolor.c b/drivers/pinctrl/pinctrl-digicolor.c
index ce269ce..5353b23 100644
--- a/drivers/pinctrl/pinctrl-digicolor.c
+++ b/drivers/pinctrl/pinctrl-digicolor.c
@@ -291,10 +291,11 @@ static int dc_pinctrl_probe(struct platform_device *pdev)
if (IS_ERR(pmap->regs))
return PTR_ERR(pmap->regs);
- pins = devm_kzalloc(&pdev->dev, sizeof(*pins)*PINS_COUNT, GFP_KERNEL);
+ pins = devm_kcalloc(&pdev->dev, PINS_COUNT, sizeof(*pins),
+ GFP_KERNEL);
if (!pins)
return -ENOMEM;
- pin_names = devm_kzalloc(&pdev->dev, name_len * PINS_COUNT,
+ pin_names = devm_kcalloc(&pdev->dev, PINS_COUNT, name_len,
GFP_KERNEL);
if (!pin_names)
return -ENOMEM;
diff --git a/drivers/pinctrl/pinctrl-ingenic.c b/drivers/pinctrl/pinctrl-ingenic.c
index ac38a3f..a1d7156 100644
--- a/drivers/pinctrl/pinctrl-ingenic.c
+++ b/drivers/pinctrl/pinctrl-ingenic.c
@@ -770,8 +770,8 @@ static int ingenic_pinctrl_probe(struct platform_device *pdev)
pctl_desc->pmxops = &ingenic_pmxops;
pctl_desc->confops = &ingenic_confops;
pctl_desc->npins = chip_info->num_chips * PINS_PER_GPIO_CHIP;
- pctl_desc->pins = jzpc->pdesc = devm_kzalloc(&pdev->dev,
- sizeof(*jzpc->pdesc) * pctl_desc->npins, GFP_KERNEL);
+ pctl_desc->pins = jzpc->pdesc = devm_kcalloc(&pdev->dev,
+ pctl_desc->npins, sizeof(*jzpc->pdesc), GFP_KERNEL);
if (!jzpc->pdesc)
return -ENOMEM;
diff --git a/drivers/pinctrl/pinctrl-lantiq.c b/drivers/pinctrl/pinctrl-lantiq.c
index 41dc39c..81632af 100644
--- a/drivers/pinctrl/pinctrl-lantiq.c
+++ b/drivers/pinctrl/pinctrl-lantiq.c
@@ -158,7 +158,8 @@ static int ltq_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
for_each_child_of_node(np_config, np)
max_maps += ltq_pinctrl_dt_subnode_size(np);
- *map = kzalloc(max_maps * sizeof(struct pinctrl_map) * 2, GFP_KERNEL);
+ *map = kzalloc(array3_size(max_maps, sizeof(struct pinctrl_map), 2),
+ GFP_KERNEL);
if (!*map)
return -ENOMEM;
tmp = *map;
diff --git a/drivers/pinctrl/pinctrl-lpc18xx.c b/drivers/pinctrl/pinctrl-lpc18xx.c
index d090f37..190f17e 100644
--- a/drivers/pinctrl/pinctrl-lpc18xx.c
+++ b/drivers/pinctrl/pinctrl-lpc18xx.c
@@ -1308,8 +1308,9 @@ static int lpc18xx_create_group_func_map(struct device *dev,
}
scu->func[func].ngroups = ngroups;
- scu->func[func].groups = devm_kzalloc(dev, ngroups *
- sizeof(char *), GFP_KERNEL);
+ scu->func[func].groups = devm_kcalloc(dev,
+ ngroups, sizeof(char *),
+ GFP_KERNEL);
if (!scu->func[func].groups)
return -ENOMEM;
diff --git a/drivers/pinctrl/pinctrl-ocelot.c b/drivers/pinctrl/pinctrl-ocelot.c
index b5b3547..15bb1cb 100644
--- a/drivers/pinctrl/pinctrl-ocelot.c
+++ b/drivers/pinctrl/pinctrl-ocelot.c
@@ -330,7 +330,8 @@ static int ocelot_create_group_func_map(struct device *dev,
}
info->func[f].ngroups = npins;
- info->func[f].groups = devm_kzalloc(dev, npins *
+ info->func[f].groups = devm_kcalloc(dev,
+ npins,
sizeof(char *),
GFP_KERNEL);
if (!info->func[f].groups)
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index 1882713..f4a6142 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -507,7 +507,7 @@ static int rockchip_dt_node_to_map(struct pinctrl_dev *pctldev,
}
map_num += grp->npins;
- new_map = devm_kzalloc(pctldev->dev, sizeof(*new_map) * map_num,
+ new_map = devm_kcalloc(pctldev->dev, map_num, sizeof(*new_map),
GFP_KERNEL);
if (!new_map)
return -ENOMEM;
@@ -2473,10 +2473,11 @@ static int rockchip_pinctrl_parse_groups(struct device_node *np,
grp->npins = size / 4;
- grp->pins = devm_kzalloc(info->dev, grp->npins * sizeof(unsigned int),
+ grp->pins = devm_kcalloc(info->dev, grp->npins, sizeof(unsigned int),
GFP_KERNEL);
- grp->data = devm_kzalloc(info->dev, grp->npins *
- sizeof(struct rockchip_pin_config),
+ grp->data = devm_kcalloc(info->dev,
+ grp->npins,
+ sizeof(struct rockchip_pin_config),
GFP_KERNEL);
if (!grp->pins || !grp->data)
return -ENOMEM;
@@ -2528,8 +2529,8 @@ static int rockchip_pinctrl_parse_functions(struct device_node *np,
if (func->ngroups <= 0)
return 0;
- func->groups = devm_kzalloc(info->dev,
- func->ngroups * sizeof(char *), GFP_KERNEL);
+ func->groups = devm_kcalloc(info->dev,
+ func->ngroups, sizeof(char *), GFP_KERNEL);
if (!func->groups)
return -ENOMEM;
@@ -2560,13 +2561,15 @@ static int rockchip_pinctrl_parse_dt(struct platform_device *pdev,
dev_dbg(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
dev_dbg(&pdev->dev, "ngroups = %d\n", info->ngroups);
- info->functions = devm_kzalloc(dev, info->nfunctions *
+ info->functions = devm_kcalloc(dev,
+ info->nfunctions,
sizeof(struct rockchip_pmx_func),
GFP_KERNEL);
if (!info->functions)
return -EINVAL;
- info->groups = devm_kzalloc(dev, info->ngroups *
+ info->groups = devm_kcalloc(dev,
+ info->ngroups,
sizeof(struct rockchip_pin_group),
GFP_KERNEL);
if (!info->groups)
@@ -2604,8 +2607,9 @@ static int rockchip_pinctrl_register(struct platform_device *pdev,
ctrldesc->pmxops = &rockchip_pmx_ops;
ctrldesc->confops = &rockchip_pinconf_ops;
- pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
- info->ctrl->nr_pins, GFP_KERNEL);
+ pindesc = devm_kcalloc(&pdev->dev,
+ info->ctrl->nr_pins, sizeof(*pindesc),
+ GFP_KERNEL);
if (!pindesc)
return -ENOMEM;
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 9c3c005..e5647da 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -712,8 +712,8 @@ static int pcs_allocate_pin_table(struct pcs_device *pcs)
}
dev_dbg(pcs->dev, "allocating %i pins\n", nr_pins);
- pcs->pins.pa = devm_kzalloc(pcs->dev,
- sizeof(*pcs->pins.pa) * nr_pins,
+ pcs->pins.pa = devm_kcalloc(pcs->dev,
+ nr_pins, sizeof(*pcs->pins.pa),
GFP_KERNEL);
if (!pcs->pins.pa)
return -ENOMEM;
@@ -924,15 +924,15 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
if (!nconfs)
return 0;
- func->conf = devm_kzalloc(pcs->dev,
- sizeof(struct pcs_conf_vals) * nconfs,
+ func->conf = devm_kcalloc(pcs->dev,
+ nconfs, sizeof(struct pcs_conf_vals),
GFP_KERNEL);
if (!func->conf)
return -ENOMEM;
func->nconfs = nconfs;
conf = &(func->conf[0]);
m++;
- settings = devm_kzalloc(pcs->dev, sizeof(unsigned long) * nconfs,
+ settings = devm_kcalloc(pcs->dev, nconfs, sizeof(unsigned long),
GFP_KERNEL);
if (!settings)
return -ENOMEM;
@@ -988,11 +988,11 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
return -EINVAL;
}
- vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows, GFP_KERNEL);
+ vals = devm_kcalloc(pcs->dev, rows, sizeof(*vals), GFP_KERNEL);
if (!vals)
return -ENOMEM;
- pins = devm_kzalloc(pcs->dev, sizeof(*pins) * rows, GFP_KERNEL);
+ pins = devm_kcalloc(pcs->dev, rows, sizeof(*pins), GFP_KERNEL);
if (!pins)
goto free_vals;
@@ -1089,13 +1089,15 @@ static int pcs_parse_bits_in_pinctrl_entry(struct pcs_device *pcs,
npins_in_row = pcs->width / pcs->bits_per_pin;
- vals = devm_kzalloc(pcs->dev, sizeof(*vals) * rows * npins_in_row,
- GFP_KERNEL);
+ vals = devm_kzalloc(pcs->dev,
+ array3_size(rows, npins_in_row, sizeof(*vals)),
+ GFP_KERNEL);
if (!vals)
return -ENOMEM;
- pins = devm_kzalloc(pcs->dev, sizeof(*pins) * rows * npins_in_row,
- GFP_KERNEL);
+ pins = devm_kzalloc(pcs->dev,
+ array3_size(rows, npins_in_row, sizeof(*pins)),
+ GFP_KERNEL);
if (!pins)
goto free_vals;
@@ -1217,7 +1219,7 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
pcs = pinctrl_dev_get_drvdata(pctldev);
/* create 2 maps. One is for pinmux, and the other is for pinconf. */
- *map = devm_kzalloc(pcs->dev, sizeof(**map) * 2, GFP_KERNEL);
+ *map = devm_kcalloc(pcs->dev, 2, sizeof(**map), GFP_KERNEL);
if (!*map)
return -ENOMEM;
@@ -1588,8 +1590,11 @@ static int pcs_save_context(struct pcs_device *pcs)
mux_bytes = pcs->width / BITS_PER_BYTE;
- if (!pcs->saved_vals)
+ if (!pcs->saved_vals) {
pcs->saved_vals = devm_kzalloc(pcs->dev, pcs->size, GFP_ATOMIC);
+ if (!pcs->saved_vals)
+ return -ENOMEM;
+ }
switch (pcs->width) {
case 64:
@@ -1649,8 +1654,13 @@ static int pinctrl_single_suspend(struct platform_device *pdev,
if (!pcs)
return -EINVAL;
- if (pcs->flags & PCS_CONTEXT_LOSS_OFF)
- pcs_save_context(pcs);
+ if (pcs->flags & PCS_CONTEXT_LOSS_OFF) {
+ int ret;
+
+ ret = pcs_save_context(pcs);
+ if (ret < 0)
+ return ret;
+ }
return pinctrl_force_sleep(pcs->pctl);
}
diff --git a/drivers/pinctrl/pinctrl-st.c b/drivers/pinctrl/pinctrl-st.c
index 2081c67..0966bb0 100644
--- a/drivers/pinctrl/pinctrl-st.c
+++ b/drivers/pinctrl/pinctrl-st.c
@@ -823,8 +823,8 @@ static int st_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
}
map_num = grp->npins + 1;
- new_map = devm_kzalloc(pctldev->dev,
- sizeof(*new_map) * map_num, GFP_KERNEL);
+ new_map = devm_kcalloc(pctldev->dev,
+ map_num, sizeof(*new_map), GFP_KERNEL);
if (!new_map)
return -ENOMEM;
@@ -1191,9 +1191,9 @@ static int st_pctl_dt_parse_groups(struct device_node *np,
grp->npins = npins;
grp->name = np->name;
- grp->pins = devm_kzalloc(info->dev, npins * sizeof(u32), GFP_KERNEL);
- grp->pin_conf = devm_kzalloc(info->dev,
- npins * sizeof(*conf), GFP_KERNEL);
+ grp->pins = devm_kcalloc(info->dev, npins, sizeof(u32), GFP_KERNEL);
+ grp->pin_conf = devm_kcalloc(info->dev,
+ npins, sizeof(*conf), GFP_KERNEL);
if (!grp->pins || !grp->pin_conf)
return -ENOMEM;
@@ -1249,8 +1249,8 @@ static int st_pctl_parse_functions(struct device_node *np,
dev_err(info->dev, "No groups defined\n");
return -EINVAL;
}
- func->groups = devm_kzalloc(info->dev,
- func->ngroups * sizeof(char *), GFP_KERNEL);
+ func->groups = devm_kcalloc(info->dev,
+ func->ngroups, sizeof(char *), GFP_KERNEL);
if (!func->groups)
return -ENOMEM;
@@ -1573,14 +1573,15 @@ static int st_pctl_probe_dt(struct platform_device *pdev,
dev_info(&pdev->dev, "nfunctions = %d\n", info->nfunctions);
dev_info(&pdev->dev, "ngroups = %d\n", info->ngroups);
- info->functions = devm_kzalloc(&pdev->dev,
- info->nfunctions * sizeof(*info->functions), GFP_KERNEL);
+ info->functions = devm_kcalloc(&pdev->dev,
+ info->nfunctions, sizeof(*info->functions), GFP_KERNEL);
- info->groups = devm_kzalloc(&pdev->dev,
- info->ngroups * sizeof(*info->groups) , GFP_KERNEL);
+ info->groups = devm_kcalloc(&pdev->dev,
+ info->ngroups, sizeof(*info->groups),
+ GFP_KERNEL);
- info->banks = devm_kzalloc(&pdev->dev,
- info->nbanks * sizeof(*info->banks), GFP_KERNEL);
+ info->banks = devm_kcalloc(&pdev->dev,
+ info->nbanks, sizeof(*info->banks), GFP_KERNEL);
if (!info->functions || !info->groups || !info->banks)
return -ENOMEM;
@@ -1608,8 +1609,8 @@ static int st_pctl_probe_dt(struct platform_device *pdev,
}
pctl_desc->npins = info->nbanks * ST_GPIO_PINS_PER_BANK;
- pdesc = devm_kzalloc(&pdev->dev,
- sizeof(*pdesc) * pctl_desc->npins, GFP_KERNEL);
+ pdesc = devm_kcalloc(&pdev->dev,
+ pctl_desc->npins, sizeof(*pdesc), GFP_KERNEL);
if (!pdesc)
return -ENOMEM;
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index cd0f402..93f8bd0 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -1727,8 +1727,8 @@ static int pinmux_xway_probe(struct platform_device *pdev)
xway_chip.ngpio = xway_soc->pin_count;
/* load our pad descriptors */
- xway_info.pads = devm_kzalloc(&pdev->dev,
- sizeof(struct pinctrl_pin_desc) * xway_chip.ngpio,
+ xway_info.pads = devm_kcalloc(&pdev->dev,
+ xway_chip.ngpio, sizeof(struct pinctrl_pin_desc),
GFP_KERNEL);
if (!xway_info.pads)
return -ENOMEM;
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 0a625a6..a263ddd 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -491,8 +491,9 @@ int exynos_eint_wkup_init(struct samsung_pinctrl_drv_data *d)
continue;
}
- weint_data = devm_kzalloc(dev, bank->nr_pins
- * sizeof(*weint_data), GFP_KERNEL);
+ weint_data = devm_kcalloc(dev,
+ bank->nr_pins, sizeof(*weint_data),
+ GFP_KERNEL);
if (!weint_data)
return -ENOMEM;
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 618945a..698c7d8 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -674,7 +674,7 @@ static struct samsung_pin_group *samsung_pinctrl_create_groups(
const struct pinctrl_pin_desc *pdesc;
int i;
- groups = devm_kzalloc(dev, ctrldesc->npins * sizeof(*groups),
+ groups = devm_kcalloc(dev, ctrldesc->npins, sizeof(*groups),
GFP_KERNEL);
if (!groups)
return ERR_PTR(-EINVAL);
@@ -711,7 +711,7 @@ static int samsung_pinctrl_create_function(struct device *dev,
func->name = func_np->full_name;
- func->groups = devm_kzalloc(dev, npins * sizeof(char *), GFP_KERNEL);
+ func->groups = devm_kcalloc(dev, npins, sizeof(char *), GFP_KERNEL);
if (!func->groups)
return -ENOMEM;
@@ -768,7 +768,7 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions(
}
}
- functions = devm_kzalloc(dev, func_cnt * sizeof(*functions),
+ functions = devm_kcalloc(dev, func_cnt, sizeof(*functions),
GFP_KERNEL);
if (!functions)
return ERR_PTR(-ENOMEM);
@@ -860,8 +860,9 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
ctrldesc->pmxops = &samsung_pinmux_ops;
ctrldesc->confops = &samsung_pinconf_ops;
- pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) *
- drvdata->nr_pins, GFP_KERNEL);
+ pindesc = devm_kcalloc(&pdev->dev,
+ drvdata->nr_pins, sizeof(*pindesc),
+ GFP_KERNEL);
if (!pindesc)
return -ENOMEM;
ctrldesc->pins = pindesc;
@@ -875,8 +876,10 @@ static int samsung_pinctrl_register(struct platform_device *pdev,
* allocate space for storing the dynamically generated names for all
* the pins which belong to this pin-controller.
*/
- pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH *
- drvdata->nr_pins, GFP_KERNEL);
+ pin_names = devm_kzalloc(&pdev->dev,
+ array3_size(sizeof(char), PIN_NAME_LENGTH,
+ drvdata->nr_pins),
+ GFP_KERNEL);
if (!pin_names)
return -ENOMEM;
diff --git a/drivers/pinctrl/sh-pfc/core.c b/drivers/pinctrl/sh-pfc/core.c
index eb06981..c671c3c 100644
--- a/drivers/pinctrl/sh-pfc/core.c
+++ b/drivers/pinctrl/sh-pfc/core.c
@@ -57,7 +57,7 @@ static int sh_pfc_map_resources(struct sh_pfc *pfc,
return -EINVAL;
/* Allocate memory windows and IRQs arrays. */
- windows = devm_kzalloc(pfc->dev, num_windows * sizeof(*windows),
+ windows = devm_kcalloc(pfc->dev, num_windows, sizeof(*windows),
GFP_KERNEL);
if (windows == NULL)
return -ENOMEM;
@@ -66,7 +66,7 @@ static int sh_pfc_map_resources(struct sh_pfc *pfc,
pfc->windows = windows;
if (num_irqs) {
- irqs = devm_kzalloc(pfc->dev, num_irqs * sizeof(*irqs),
+ irqs = devm_kcalloc(pfc->dev, num_irqs, sizeof(*irqs),
GFP_KERNEL);
if (irqs == NULL)
return -ENOMEM;
@@ -444,7 +444,7 @@ static int sh_pfc_init_ranges(struct sh_pfc *pfc)
}
pfc->nr_ranges = nr_ranges;
- pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges) * nr_ranges,
+ pfc->ranges = devm_kcalloc(pfc->dev, nr_ranges, sizeof(*pfc->ranges),
GFP_KERNEL);
if (pfc->ranges == NULL)
return -ENOMEM;
diff --git a/drivers/pinctrl/sh-pfc/gpio.c b/drivers/pinctrl/sh-pfc/gpio.c
index 946d9be..6ffdc6b 100644
--- a/drivers/pinctrl/sh-pfc/gpio.c
+++ b/drivers/pinctrl/sh-pfc/gpio.c
@@ -107,7 +107,7 @@ static int gpio_setup_data_regs(struct sh_pfc_chip *chip)
for (i = 0; pfc->info->data_regs[i].reg_width; ++i)
;
- chip->regs = devm_kzalloc(pfc->dev, i * sizeof(*chip->regs),
+ chip->regs = devm_kcalloc(pfc->dev, i, sizeof(*chip->regs),
GFP_KERNEL);
if (chip->regs == NULL)
return -ENOMEM;
@@ -224,8 +224,9 @@ static int gpio_pin_setup(struct sh_pfc_chip *chip)
struct gpio_chip *gc = &chip->gpio_chip;
int ret;
- chip->pins = devm_kzalloc(pfc->dev, pfc->info->nr_pins *
- sizeof(*chip->pins), GFP_KERNEL);
+ chip->pins = devm_kcalloc(pfc->dev,
+ pfc->info->nr_pins, sizeof(*chip->pins),
+ GFP_KERNEL);
if (chip->pins == NULL)
return -ENOMEM;
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index 70db216..654dc20 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -770,14 +770,14 @@ static int sh_pfc_map_pins(struct sh_pfc *pfc, struct sh_pfc_pinctrl *pmx)
unsigned int i;
/* Allocate and initialize the pins and configs arrays. */
- pmx->pins = devm_kzalloc(pfc->dev,
- sizeof(*pmx->pins) * pfc->info->nr_pins,
+ pmx->pins = devm_kcalloc(pfc->dev,
+ pfc->info->nr_pins, sizeof(*pmx->pins),
GFP_KERNEL);
if (unlikely(!pmx->pins))
return -ENOMEM;
- pmx->configs = devm_kzalloc(pfc->dev,
- sizeof(*pmx->configs) * pfc->info->nr_pins,
+ pmx->configs = devm_kcalloc(pfc->dev,
+ pfc->info->nr_pins, sizeof(*pmx->configs),
GFP_KERNEL);
if (unlikely(!pmx->configs))
return -ENOMEM;
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index ca2347d..505845c 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -108,7 +108,7 @@ static int sirfsoc_dt_node_to_map(struct pinctrl_dev *pctldev,
return -ENODEV;
}
- *map = kzalloc(sizeof(**map) * count, GFP_KERNEL);
+ *map = kcalloc(count, sizeof(**map), GFP_KERNEL);
if (!*map)
return -ENOMEM;
diff --git a/drivers/pinctrl/spear/pinctrl-plgpio.c b/drivers/pinctrl/spear/pinctrl-plgpio.c
index d2123e3..9d90647 100644
--- a/drivers/pinctrl/spear/pinctrl-plgpio.c
+++ b/drivers/pinctrl/spear/pinctrl-plgpio.c
@@ -538,9 +538,9 @@ static int plgpio_probe(struct platform_device *pdev)
dev_warn(&pdev->dev, "clk_get() failed, work without it\n");
#ifdef CONFIG_PM_SLEEP
- plgpio->csave_regs = devm_kzalloc(&pdev->dev,
- sizeof(*plgpio->csave_regs) *
+ plgpio->csave_regs = devm_kcalloc(&pdev->dev,
DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),
+ sizeof(*plgpio->csave_regs),
GFP_KERNEL);
if (!plgpio->csave_regs)
return -ENOMEM;
diff --git a/drivers/pinctrl/spear/pinctrl-spear.c b/drivers/pinctrl/spear/pinctrl-spear.c
index efe79d3..c4f8503 100644
--- a/drivers/pinctrl/spear/pinctrl-spear.c
+++ b/drivers/pinctrl/spear/pinctrl-spear.c
@@ -172,7 +172,7 @@ static int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
return -ENODEV;
}
- *map = kzalloc(sizeof(**map) * count, GFP_KERNEL);
+ *map = kcalloc(count, sizeof(**map), GFP_KERNEL);
if (!*map)
return -ENOMEM;
diff --git a/drivers/pinctrl/sprd/pinctrl-sprd.c b/drivers/pinctrl/sprd/pinctrl-sprd.c
index ba1c2ca..78c2f54 100644
--- a/drivers/pinctrl/sprd/pinctrl-sprd.c
+++ b/drivers/pinctrl/sprd/pinctrl-sprd.c
@@ -879,8 +879,9 @@ static int sprd_pinctrl_parse_groups(struct device_node *np,
grp->name = np->name;
grp->npins = ret;
- grp->pins = devm_kzalloc(sprd_pctl->dev, grp->npins *
- sizeof(unsigned int), GFP_KERNEL);
+ grp->pins = devm_kcalloc(sprd_pctl->dev,
+ grp->npins, sizeof(unsigned int),
+ GFP_KERNEL);
if (!grp->pins)
return -ENOMEM;
@@ -931,14 +932,15 @@ static int sprd_pinctrl_parse_dt(struct sprd_pinctrl *sprd_pctl)
if (!info->ngroups)
return 0;
- info->groups = devm_kzalloc(sprd_pctl->dev, info->ngroups *
+ info->groups = devm_kcalloc(sprd_pctl->dev,
+ info->ngroups,
sizeof(struct sprd_pin_group),
GFP_KERNEL);
if (!info->groups)
return -ENOMEM;
- info->grp_names = devm_kzalloc(sprd_pctl->dev,
- info->ngroups * sizeof(char *),
+ info->grp_names = devm_kcalloc(sprd_pctl->dev,
+ info->ngroups, sizeof(char *),
GFP_KERNEL);
if (!info->grp_names)
return -ENOMEM;
@@ -980,8 +982,8 @@ static int sprd_pinctrl_add_pins(struct sprd_pinctrl *sprd_pctl,
int i;
info->npins = pins_cnt;
- info->pins = devm_kzalloc(sprd_pctl->dev,
- info->npins * sizeof(struct sprd_pin),
+ info->pins = devm_kcalloc(sprd_pctl->dev,
+ info->npins, sizeof(struct sprd_pin),
GFP_KERNEL);
if (!info->pins)
return -ENOMEM;
@@ -1057,7 +1059,8 @@ int sprd_pinctrl_core_probe(struct platform_device *pdev,
return ret;
}
- pin_desc = devm_kzalloc(&pdev->dev, pinctrl_info->npins *
+ pin_desc = devm_kcalloc(&pdev->dev,
+ pinctrl_info->npins,
sizeof(struct pinctrl_pin_desc),
GFP_KERNEL);
if (!pin_desc)
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 25e80a5..4d9bf9b 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -277,7 +277,7 @@ static unsigned long *sunxi_pctrl_build_pin_config(struct device_node *node,
if (!configlen)
return NULL;
- pinconfig = kzalloc(configlen * sizeof(*pinconfig), GFP_KERNEL);
+ pinconfig = kcalloc(configlen, sizeof(*pinconfig), GFP_KERNEL);
if (!pinconfig)
return ERR_PTR(-ENOMEM);
@@ -352,7 +352,7 @@ static int sunxi_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
* any configuration.
*/
nmaps = npins * 2;
- *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL);
+ *map = kmalloc_array(nmaps, sizeof(struct pinctrl_map), GFP_KERNEL);
if (!*map)
return -ENOMEM;
@@ -1055,8 +1055,8 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
* this means that the number of pins is the maximum group
* number we will ever see.
*/
- pctl->groups = devm_kzalloc(&pdev->dev,
- pctl->desc->npins * sizeof(*pctl->groups),
+ pctl->groups = devm_kcalloc(&pdev->dev,
+ pctl->desc->npins, sizeof(*pctl->groups),
GFP_KERNEL);
if (!pctl->groups)
return -ENOMEM;
@@ -1079,8 +1079,9 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
* We suppose that we won't have any more functions than pins,
* we'll reallocate that later anyway
*/
- pctl->functions = devm_kzalloc(&pdev->dev,
- pctl->ngroups * sizeof(*pctl->functions),
+ pctl->functions = devm_kcalloc(&pdev->dev,
+ pctl->ngroups,
+ sizeof(*pctl->functions),
GFP_KERNEL);
if (!pctl->functions)
return -ENOMEM;
@@ -1137,8 +1138,9 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
if (!func_item->groups) {
func_item->groups =
- devm_kzalloc(&pdev->dev,
- func_item->ngroups * sizeof(*func_item->groups),
+ devm_kcalloc(&pdev->dev,
+ func_item->ngroups,
+ sizeof(*func_item->groups),
GFP_KERNEL);
if (!func_item->groups)
return -ENOMEM;
@@ -1281,8 +1283,8 @@ int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
return ret;
}
- pins = devm_kzalloc(&pdev->dev,
- pctl->desc->npins * sizeof(*pins),
+ pins = devm_kcalloc(&pdev->dev,
+ pctl->desc->npins, sizeof(*pins),
GFP_KERNEL);
if (!pins)
return -ENOMEM;
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c
index 49c7c14..f974eee 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra.c
@@ -665,8 +665,8 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
* Each mux group will appear in 4 functions' list of groups.
* This over-allocates slightly, since not all groups are mux groups.
*/
- pmx->group_pins = devm_kzalloc(&pdev->dev,
- soc_data->ngroups * 4 * sizeof(*pmx->group_pins),
+ pmx->group_pins = devm_kcalloc(&pdev->dev,
+ soc_data->ngroups * 4, sizeof(*pmx->group_pins),
GFP_KERNEL);
if (!pmx->group_pins)
return -ENOMEM;
@@ -708,7 +708,7 @@ int tegra_pinctrl_probe(struct platform_device *pdev,
}
pmx->nbanks = i;
- pmx->regs = devm_kzalloc(&pdev->dev, pmx->nbanks * sizeof(*pmx->regs),
+ pmx->regs = devm_kcalloc(&pdev->dev, pmx->nbanks, sizeof(*pmx->regs),
GFP_KERNEL);
if (!pmx->regs)
return -ENOMEM;
diff --git a/drivers/pinctrl/ti/pinctrl-ti-iodelay.c b/drivers/pinctrl/ti/pinctrl-ti-iodelay.c
index a8a6510..8782c34 100644
--- a/drivers/pinctrl/ti/pinctrl-ti-iodelay.c
+++ b/drivers/pinctrl/ti/pinctrl-ti-iodelay.c
@@ -510,11 +510,11 @@ static int ti_iodelay_dt_node_to_map(struct pinctrl_dev *pctldev,
goto free_map;
}
- pins = devm_kzalloc(iod->dev, sizeof(*pins) * rows, GFP_KERNEL);
+ pins = devm_kcalloc(iod->dev, rows, sizeof(*pins), GFP_KERNEL);
if (!pins)
goto free_group;
- cfg = devm_kzalloc(iod->dev, sizeof(*cfg) * rows, GFP_KERNEL);
+ cfg = devm_kcalloc(iod->dev, rows, sizeof(*cfg), GFP_KERNEL);
if (!cfg) {
error = -ENOMEM;
goto free_pins;
@@ -749,7 +749,7 @@ static int ti_iodelay_alloc_pins(struct device *dev,
nr_pins = ti_iodelay_offset_to_pin(iod, r->regmap_config->max_register);
dev_dbg(dev, "Allocating %i pins\n", nr_pins);
- iod->pa = devm_kzalloc(dev, sizeof(*iod->pa) * nr_pins, GFP_KERNEL);
+ iod->pa = devm_kcalloc(dev, nr_pins, sizeof(*iod->pa), GFP_KERNEL);
if (!iod->pa)
return -ENOMEM;
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c
index d73956b..c08318a 100644
--- a/drivers/pinctrl/vt8500/pinctrl-wmt.c
+++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c
@@ -352,7 +352,7 @@ static int wmt_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
if (num_pulls)
maps_per_pin++;
- cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps),
+ cur_map = maps = kcalloc(num_pins * maps_per_pin, sizeof(*maps),
GFP_KERNEL);
if (!maps)
return -ENOMEM;
diff --git a/drivers/pinctrl/zte/pinctrl-zx.c b/drivers/pinctrl/zte/pinctrl-zx.c
index ded366b..caa44dd 100644
--- a/drivers/pinctrl/zte/pinctrl-zx.c
+++ b/drivers/pinctrl/zte/pinctrl-zx.c
@@ -277,7 +277,7 @@ static int zx_pinctrl_build_state(struct platform_device *pdev)
/* Every single pin composes a group */
ngroups = info->npins;
- groups = devm_kzalloc(&pdev->dev, ngroups * sizeof(*groups),
+ groups = devm_kcalloc(&pdev->dev, ngroups, sizeof(*groups),
GFP_KERNEL);
if (!groups)
return -ENOMEM;
@@ -362,8 +362,8 @@ static int zx_pinctrl_build_state(struct platform_device *pdev)
func = functions + j;
if (!func->group_names) {
- func->group_names = devm_kzalloc(&pdev->dev,
- func->num_group_names *
+ func->group_names = devm_kcalloc(&pdev->dev,
+ func->num_group_names,
sizeof(*func->group_names),
GFP_KERNEL);
if (!func->group_names) {
diff --git a/drivers/platform/chrome/cros_ec_debugfs.c b/drivers/platform/chrome/cros_ec_debugfs.c
index cc265ed..c62ee8e 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.c
+++ b/drivers/platform/chrome/cros_ec_debugfs.c
@@ -470,3 +470,23 @@ void cros_ec_debugfs_remove(struct cros_ec_dev *ec)
cros_ec_cleanup_console_log(ec->debug_info);
}
EXPORT_SYMBOL(cros_ec_debugfs_remove);
+
+void cros_ec_debugfs_suspend(struct cros_ec_dev *ec)
+{
+ /*
+ * cros_ec_debugfs_init() failures are non-fatal; it's also possible
+ * that we initted things but decided that console log wasn't supported.
+ * We'll use the same set of checks that cros_ec_debugfs_remove() +
+ * cros_ec_cleanup_console_log() end up using to handle those cases.
+ */
+ if (ec->debug_info && ec->debug_info->log_buffer.buf)
+ cancel_delayed_work_sync(&ec->debug_info->log_poll_work);
+}
+EXPORT_SYMBOL(cros_ec_debugfs_suspend);
+
+void cros_ec_debugfs_resume(struct cros_ec_dev *ec)
+{
+ if (ec->debug_info && ec->debug_info->log_buffer.buf)
+ schedule_delayed_work(&ec->debug_info->log_poll_work, 0);
+}
+EXPORT_SYMBOL(cros_ec_debugfs_resume);
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
index ea9e7f4..ac97aa0 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -55,13 +55,16 @@
#define MLXREG_HOTPLUG_RST_CNTR 3
#define MLXREG_HOTPLUG_ATTRS_MAX 24
+#define MLXREG_HOTPLUG_NOT_ASSERT 3
/**
* struct mlxreg_hotplug_priv_data - platform private data:
* @irq: platform device interrupt number;
+ * @dev: basic device;
* @pdev: platform device;
* @plat: platform data;
- * @dwork: delayed work template;
+ * @regmap: register map handle;
+ * @dwork_irq: delayed work template;
* @lock: spin lock;
* @hwmon: hwmon device;
* @mlxreg_hotplug_attr: sysfs attributes array;
@@ -71,6 +74,8 @@
* @cell: location of top aggregation interrupt register;
* @mask: top aggregation interrupt common mask;
* @aggr_cache: last value of aggregation register status;
+ * @after_probe: flag indication probing completion;
+ * @not_asserted: number of entries in workqueue with no signal assertion;
*/
struct mlxreg_hotplug_priv_data {
int irq;
@@ -79,7 +84,6 @@ struct mlxreg_hotplug_priv_data {
struct mlxreg_hotplug_platform_data *plat;
struct regmap *regmap;
struct delayed_work dwork_irq;
- struct delayed_work dwork;
spinlock_t lock; /* sync with interrupt */
struct device *hwmon;
struct attribute *mlxreg_hotplug_attr[MLXREG_HOTPLUG_ATTRS_MAX + 1];
@@ -91,6 +95,7 @@ struct mlxreg_hotplug_priv_data {
u32 mask;
u32 aggr_cache;
bool after_probe;
+ u8 not_asserted;
};
static int mlxreg_hotplug_device_create(struct mlxreg_hotplug_priv_data *priv,
@@ -217,7 +222,8 @@ static int mlxreg_hotplug_attr_init(struct mlxreg_hotplug_priv_data *priv)
}
}
- priv->group.attrs = devm_kzalloc(&priv->pdev->dev, num_attrs *
+ priv->group.attrs = devm_kcalloc(&priv->pdev->dev,
+ num_attrs,
sizeof(struct attribute *),
GFP_KERNEL);
if (!priv->group.attrs)
@@ -408,6 +414,18 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work)
aggr_asserted = priv->aggr_cache ^ regval;
priv->aggr_cache = regval;
+ /*
+ * Handler is invoked, but no assertion is detected at top aggregation
+ * status level. Set aggr_asserted to mask value to allow handler extra
+ * run over all relevant signals to recover any missed signal.
+ */
+ if (priv->not_asserted == MLXREG_HOTPLUG_NOT_ASSERT) {
+ priv->not_asserted = 0;
+ aggr_asserted = pdata->mask;
+ }
+ if (!aggr_asserted)
+ goto unmask_event;
+
/* Handle topology and health configuration changes. */
for (i = 0; i < pdata->counter; i++, item++) {
if (aggr_asserted & item->aggr_mask) {
@@ -418,27 +436,26 @@ static void mlxreg_hotplug_work_handler(struct work_struct *work)
}
}
- if (aggr_asserted) {
- spin_lock_irqsave(&priv->lock, flags);
+ spin_lock_irqsave(&priv->lock, flags);
- /*
- * It is possible, that some signals have been inserted, while
- * interrupt has been masked by mlxreg_hotplug_work_handler.
- * In this case such signals will be missed. In order to handle
- * these signals delayed work is canceled and work task
- * re-scheduled for immediate execution. It allows to handle
- * missed signals, if any. In other case work handler just
- * validates that no new signals have been received during
- * masking.
- */
- cancel_delayed_work(&priv->dwork_irq);
- schedule_delayed_work(&priv->dwork_irq, 0);
+ /*
+ * It is possible, that some signals have been inserted, while
+ * interrupt has been masked by mlxreg_hotplug_work_handler. In this
+ * case such signals will be missed. In order to handle these signals
+ * delayed work is canceled and work task re-scheduled for immediate
+ * execution. It allows to handle missed signals, if any. In other case
+ * work handler just validates that no new signals have been received
+ * during masking.
+ */
+ cancel_delayed_work(&priv->dwork_irq);
+ schedule_delayed_work(&priv->dwork_irq, 0);
- spin_unlock_irqrestore(&priv->lock, flags);
+ spin_unlock_irqrestore(&priv->lock, flags);
- return;
- }
+ return;
+unmask_event:
+ priv->not_asserted++;
/* Unmask aggregation event (no need acknowledge). */
ret = regmap_write(priv->regmap, pdata->cell +
MLXREG_HOTPLUG_AGGR_MASK_OFF, pdata->mask);
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index f27cb18..ac4d488 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -1052,7 +1052,7 @@ config SAMSUNG_LAPTOP
function keys, wireless LED, LCD backlight level.
It may also provide some sysfs files described in
- <file:Documentation/ABI/testing/sysfs-platform-samsung-laptop>
+ <file:Documentation/ABI/testing/sysfs-driver-samsung-laptop>
To compile this driver as a module, choose M here: the module
will be called samsung-laptop.
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 1be71f9..8952173 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -129,6 +129,7 @@ static const struct key_entry acer_wmi_keymap[] __initconst = {
{KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
{KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} },
{KE_KEY, 0x86, {KEY_WLAN} },
+ {KE_KEY, 0x87, {KEY_POWER} },
{KE_END, 0}
};
diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c
index 9d7dbd9..d975462 100644
--- a/drivers/platform/x86/alienware-wmi.c
+++ b/drivers/platform/x86/alienware-wmi.c
@@ -458,19 +458,19 @@ static int alienware_zone_init(struct platform_device *dev)
* - zone_data num_zones is for the distinct zones
*/
zone_dev_attrs =
- kzalloc(sizeof(struct device_attribute) * (quirks->num_zones + 1),
+ kcalloc(quirks->num_zones + 1, sizeof(struct device_attribute),
GFP_KERNEL);
if (!zone_dev_attrs)
return -ENOMEM;
zone_attrs =
- kzalloc(sizeof(struct attribute *) * (quirks->num_zones + 2),
+ kcalloc(quirks->num_zones + 2, sizeof(struct attribute *),
GFP_KERNEL);
if (!zone_attrs)
return -ENOMEM;
zone_data =
- kzalloc(sizeof(struct platform_zone) * (quirks->num_zones),
+ kcalloc(quirks->num_zones, sizeof(struct platform_zone),
GFP_KERNEL);
if (!zone_data)
return -ENOMEM;
diff --git a/drivers/platform/x86/apple-gmux.c b/drivers/platform/x86/apple-gmux.c
index 7c4eb86..fd2ffeb 100644
--- a/drivers/platform/x86/apple-gmux.c
+++ b/drivers/platform/x86/apple-gmux.c
@@ -495,7 +495,7 @@ static int gmux_set_power_state(enum vga_switcheroo_client_id id,
return gmux_set_discrete_state(apple_gmux_data, state);
}
-static int gmux_get_client_id(struct pci_dev *pdev)
+static enum vga_switcheroo_client_id gmux_get_client_id(struct pci_dev *pdev)
{
/*
* Early Macbook Pros with switchable graphics use nvidia
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index c4768be..700c48d 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -1593,8 +1593,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
int idx)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
- struct asus_laptop *asus = platform_get_drvdata(pdev);
+ struct asus_laptop *asus = dev_get_drvdata(dev);
acpi_handle handle = asus->handle;
bool supported;
diff --git a/drivers/platform/x86/asus-wireless.c b/drivers/platform/x86/asus-wireless.c
index f086469..6afd011 100644
--- a/drivers/platform/x86/asus-wireless.c
+++ b/drivers/platform/x86/asus-wireless.c
@@ -72,7 +72,7 @@ static u64 asus_wireless_method(acpi_handle handle, const char *method,
acpi_handle_err(handle,
"Failed to eval method %s, param %#x (%d)\n",
method, param, s);
- acpi_handle_debug(handle, "%s returned %#x\n", method, (uint) ret);
+ acpi_handle_debug(handle, "%s returned %#llx\n", method, ret);
return ret;
}
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index ffffb99..3d523ca 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -1875,8 +1875,7 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj,
struct attribute *attr, int idx)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
- struct asus_wmi *asus = platform_get_drvdata(pdev);
+ struct asus_wmi *asus = dev_get_drvdata(dev);
bool ok = true;
int devid = -1;
diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index c52c672..f1fa861 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -38,6 +38,7 @@
struct quirk_entry {
bool touchpad_led;
bool kbd_led_levels_off_1;
+ bool kbd_missing_ac_tag;
bool needs_kbd_timeouts;
/*
@@ -68,6 +69,10 @@ static struct quirk_entry quirk_dell_xps13_9333 = {
.kbd_timeouts = { 0, 5, 15, 60, 5 * 60, 15 * 60, -1 },
};
+static struct quirk_entry quirk_dell_xps13_9370 = {
+ .kbd_missing_ac_tag = true,
+};
+
static struct quirk_entry quirk_dell_latitude_e6410 = {
.kbd_led_levels_off_1 = true,
};
@@ -293,6 +298,15 @@ static const struct dmi_system_id dell_quirks[] __initconst = {
},
{
.callback = dmi_matched,
+ .ident = "Dell XPS 13 9370",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9370"),
+ },
+ .driver_data = &quirk_dell_xps13_9370,
+ },
+ {
+ .callback = dmi_matched,
.ident = "Dell Latitude E6410",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
@@ -1401,7 +1415,8 @@ static inline int kbd_init_info(void)
* timeout value which is shared for both battery and AC power
* settings. So do not try to set AC values on old models.
*/
- if (dell_smbios_find_token(KBD_LED_AC_TOKEN))
+ if ((quirks && quirks->kbd_missing_ac_tag) ||
+ dell_smbios_find_token(KBD_LED_AC_TOKEN))
kbd_timeout_ac_supported = true;
kbd_get_state(&state);
diff --git a/drivers/platform/x86/dell-smbios-base.c b/drivers/platform/x86/dell-smbios-base.c
index 33fb2a2..9dc282e 100644
--- a/drivers/platform/x86/dell-smbios-base.c
+++ b/drivers/platform/x86/dell-smbios-base.c
@@ -555,11 +555,10 @@ static void free_group(struct platform_device *pdev)
static int __init dell_smbios_init(void)
{
- const struct dmi_device *valid;
int ret, wmi, smm;
- valid = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Dell System", NULL);
- if (!valid) {
+ if (!dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "Dell System", NULL) &&
+ !dmi_find_device(DMI_DEV_TYPE_OEM_STRING, "www.dell.com", NULL)) {
pr_err("Unable to run on non-Dell system\n");
return -ENODEV;
}
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index 8d10219..16c7f3d 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -233,7 +233,7 @@ static const u16 bios_to_linux_keycode[256] = {
[18] = KEY_PROG1,
[19] = KEY_BRIGHTNESSDOWN,
[20] = KEY_BRIGHTNESSUP,
- [21] = KEY_UNKNOWN,
+ [21] = KEY_BRIGHTNESS_AUTO,
[22] = KEY_KBDILLUMTOGGLE,
[23] = KEY_UNKNOWN,
[24] = KEY_SWITCHVIDEOMODE,
@@ -261,6 +261,12 @@ static const u16 bios_to_linux_keycode[256] = {
* override them.
*/
static const struct key_entry dell_wmi_keymap_type_0010[] = {
+ /* Fn-lock switched to function keys */
+ { KE_IGNORE, 0x0, { KEY_RESERVED } },
+
+ /* Fn-lock switched to multimedia keys */
+ { KE_IGNORE, 0x1, { KEY_RESERVED } },
+
/* Mic mute */
{ KE_KEY, 0x150, { KEY_MICMUTE } },
@@ -296,6 +302,14 @@ static const struct key_entry dell_wmi_keymap_type_0010[] = {
{ KE_KEY, 0x851, { KEY_PROG2 } },
{ KE_KEY, 0x852, { KEY_PROG3 } },
+ /*
+ * Radio disable (notify only -- there is no model for which the
+ * WMI event is supposed to trigger an action).
+ */
+ { KE_IGNORE, 0xe008, { KEY_RFKILL } },
+
+ /* Fn-lock */
+ { KE_IGNORE, 0xe035, { KEY_RESERVED } },
};
/*
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index cd95b6f..6afeaec 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -91,6 +91,9 @@
#define FLAG_RFKILL BIT(5)
#define FLAG_LID BIT(8)
#define FLAG_DOCK BIT(9)
+#define FLAG_TOUCHPAD_TOGGLE BIT(26)
+#define FLAG_MICMUTE BIT(29)
+#define FLAG_SOFTKEYS (FLAG_RFKILL | FLAG_TOUCHPAD_TOGGLE | FLAG_MICMUTE)
/* FUNC interface - LED control */
#define FUNC_LED_OFF BIT(0)
@@ -456,14 +459,15 @@ static void acpi_fujitsu_bl_notify(struct acpi_device *device, u32 event)
/* ACPI device for hotkey handling */
static const struct key_entry keymap_default[] = {
- { KE_KEY, KEY1_CODE, { KEY_PROG1 } },
- { KE_KEY, KEY2_CODE, { KEY_PROG2 } },
- { KE_KEY, KEY3_CODE, { KEY_PROG3 } },
- { KE_KEY, KEY4_CODE, { KEY_PROG4 } },
- { KE_KEY, KEY5_CODE, { KEY_RFKILL } },
- { KE_KEY, BIT(5), { KEY_RFKILL } },
- { KE_KEY, BIT(26), { KEY_TOUCHPAD_TOGGLE } },
- { KE_KEY, BIT(29), { KEY_MICMUTE } },
+ { KE_KEY, KEY1_CODE, { KEY_PROG1 } },
+ { KE_KEY, KEY2_CODE, { KEY_PROG2 } },
+ { KE_KEY, KEY3_CODE, { KEY_PROG3 } },
+ { KE_KEY, KEY4_CODE, { KEY_PROG4 } },
+ { KE_KEY, KEY5_CODE, { KEY_RFKILL } },
+ /* Soft keys read from status flags */
+ { KE_KEY, FLAG_RFKILL, { KEY_RFKILL } },
+ { KE_KEY, FLAG_TOUCHPAD_TOGGLE, { KEY_TOUCHPAD_TOGGLE } },
+ { KE_KEY, FLAG_MICMUTE, { KEY_MICMUTE } },
{ KE_END, 0 }
};
@@ -903,7 +907,8 @@ static void acpi_fujitsu_laptop_release(struct acpi_device *device)
static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
{
struct fujitsu_laptop *priv = acpi_driver_data(device);
- int scancode, i = 0, ret;
+ unsigned long flags;
+ int scancode, i = 0;
unsigned int irb;
if (event != ACPI_FUJITSU_NOTIFY_CODE) {
@@ -930,21 +935,17 @@ static void acpi_fujitsu_laptop_notify(struct acpi_device *device, u32 event)
"Unknown GIRB result [%x]\n", irb);
}
- /* On some models (first seen on the Skylake-based Lifebook
- * E736/E746/E756), the touchpad toggle hotkey (Fn+F4) is
- * handled in software; its state is queried using FUNC_FLAGS
+ /*
+ * First seen on the Skylake-based Lifebook E736/E746/E756), the
+ * touchpad toggle hotkey (Fn+F4) is handled in software. Other models
+ * have since added additional "soft keys". These are reported in the
+ * status flags queried using FUNC_FLAGS.
*/
- if (priv->flags_supported & (BIT(5) | BIT(26) | BIT(29))) {
- ret = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0);
- if (ret & BIT(5))
- sparse_keymap_report_event(priv->input,
- BIT(5), 1, true);
- if (ret & BIT(26))
- sparse_keymap_report_event(priv->input,
- BIT(26), 1, true);
- if (ret & BIT(29))
- sparse_keymap_report_event(priv->input,
- BIT(29), 1, true);
+ if (priv->flags_supported & (FLAG_SOFTKEYS)) {
+ flags = call_fext_func(device, FUNC_FLAGS, 0x1, 0x0, 0x0);
+ flags &= (FLAG_SOFTKEYS);
+ for_each_set_bit(i, &flags, BITS_PER_LONG)
+ sparse_keymap_report_event(priv->input, BIT(i), 1, true);
}
}
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 535199c..45b7cb0 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -43,6 +43,7 @@
#define IDEAPAD_RFKILL_DEV_NUM (3)
#define BM_CONSERVATION_BIT (5)
+#define HA_FNLOCK_BIT (10)
#define CFG_BT_BIT (16)
#define CFG_3G_BIT (17)
@@ -59,6 +60,8 @@ static const char *const ideapad_wmi_fnesc_events[] = {
enum {
BMCMD_CONSERVATION_ON = 3,
BMCMD_CONSERVATION_OFF = 5,
+ HACMD_FNLOCK_ON = 0xe,
+ HACMD_FNLOCK_OFF = 0xf,
};
enum {
@@ -139,11 +142,11 @@ static int method_gbmd(acpi_handle handle, unsigned long *ret)
return result;
}
-static int method_sbmc(acpi_handle handle, int cmd)
+static int method_int1(acpi_handle handle, char *method, int cmd)
{
acpi_status status;
- status = acpi_execute_simple_method(handle, "SBMC", cmd);
+ status = acpi_execute_simple_method(handle, method, cmd);
return ACPI_FAILURE(status) ? -1 : 0;
}
@@ -487,7 +490,7 @@ static ssize_t conservation_mode_store(struct device *dev,
if (ret)
return ret;
- ret = method_sbmc(priv->adev->handle, state ?
+ ret = method_int1(priv->adev->handle, "SBMC", state ?
BMCMD_CONSERVATION_ON :
BMCMD_CONSERVATION_OFF);
if (ret < 0)
@@ -497,11 +500,51 @@ static ssize_t conservation_mode_store(struct device *dev,
static DEVICE_ATTR_RW(conservation_mode);
+static ssize_t fn_lock_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct ideapad_private *priv = dev_get_drvdata(dev);
+ unsigned long result;
+ int hals;
+ int fail = read_method_int(priv->adev->handle, "HALS", &hals);
+
+ if (fail)
+ return sprintf(buf, "-1\n");
+
+ result = hals;
+ return sprintf(buf, "%u\n", test_bit(HA_FNLOCK_BIT, &result));
+}
+
+static ssize_t fn_lock_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ideapad_private *priv = dev_get_drvdata(dev);
+ bool state;
+ int ret;
+
+ ret = kstrtobool(buf, &state);
+ if (ret)
+ return ret;
+
+ ret = method_int1(priv->adev->handle, "SALS", state ?
+ HACMD_FNLOCK_ON :
+ HACMD_FNLOCK_OFF);
+ if (ret < 0)
+ return -EIO;
+ return count;
+}
+
+static DEVICE_ATTR_RW(fn_lock);
+
+
static struct attribute *ideapad_attributes[] = {
&dev_attr_camera_power.attr,
&dev_attr_fan_mode.attr,
&dev_attr_touchpad.attr,
&dev_attr_conservation_mode.attr,
+ &dev_attr_fn_lock.attr,
NULL
};
@@ -522,6 +565,9 @@ static umode_t ideapad_is_visible(struct kobject *kobj,
} else if (attr == &dev_attr_conservation_mode.attr) {
supported = acpi_has_method(priv->adev->handle, "GBMD") &&
acpi_has_method(priv->adev->handle, "SBMC");
+ } else if (attr == &dev_attr_fn_lock.attr) {
+ supported = acpi_has_method(priv->adev->handle, "HALS") &&
+ acpi_has_method(priv->adev->handle, "SALS");
} else
supported = true;
@@ -1080,6 +1126,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
},
},
{
+ .ident = "Lenovo ideapad MIIX 720-12IKB",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "MIIX 720-12IKB"),
+ },
+ },
+ {
.ident = "Lenovo Legion Y520-15IKBN",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
@@ -1163,6 +1216,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo YOGA 920-13IKB"),
},
},
+ {
+ .ident = "Lenovo Zhaoyang E42-80",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "ZHAOYANG E42-80"),
+ },
+ },
{}
};
diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c
index a0c9585..014fc16 100644
--- a/drivers/platform/x86/intel_ips.c
+++ b/drivers/platform/x86/intel_ips.c
@@ -964,12 +964,12 @@ static int ips_monitor(void *data)
u16 *mcp_samples, *ctv1_samples, *ctv2_samples, *mch_samples;
u8 cur_seqno, last_seqno;
- mcp_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL);
- ctv1_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL);
- ctv2_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL);
- mch_samples = kzalloc(sizeof(u16) * IPS_SAMPLE_COUNT, GFP_KERNEL);
- cpu_samples = kzalloc(sizeof(u32) * IPS_SAMPLE_COUNT, GFP_KERNEL);
- mchp_samples = kzalloc(sizeof(u32) * IPS_SAMPLE_COUNT, GFP_KERNEL);
+ mcp_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u16), GFP_KERNEL);
+ ctv1_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u16), GFP_KERNEL);
+ ctv2_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u16), GFP_KERNEL);
+ mch_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u16), GFP_KERNEL);
+ cpu_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u32), GFP_KERNEL);
+ mchp_samples = kcalloc(IPS_SAMPLE_COUNT, sizeof(u32), GFP_KERNEL);
if (!mcp_samples || !ctv1_samples || !ctv2_samples || !mch_samples ||
!cpu_samples || !mchp_samples) {
dev_err(ips->dev,
diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c
index 2c85f75..75c8fef 100644
--- a/drivers/platform/x86/intel_scu_ipc.c
+++ b/drivers/platform/x86/intel_scu_ipc.c
@@ -584,11 +584,11 @@ int intel_scu_ipc_i2c_cntrl(u32 addr, u32 *data)
if (cmd == IPC_I2C_READ) {
writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
/* Write not getting updated without delay */
- mdelay(1);
+ usleep_range(1000, 2000);
*data = readl(scu->i2c_base + I2C_DATA_ADDR);
} else if (cmd == IPC_I2C_WRITE) {
writel(*data, scu->i2c_base + I2C_DATA_ADDR);
- mdelay(1);
+ usleep_range(1000, 2000);
writel(addr, scu->i2c_base + IPC_I2C_CNTRL_ADDR);
} else {
dev_err(scu->dev,
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index 7a0bd24..a0fd9aa 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -47,6 +47,11 @@
/* LPC bus IO offsets */
#define MLXPLAT_CPLD_LPC_I2C_BASE_ADRR 0x2000
#define MLXPLAT_CPLD_LPC_REG_BASE_ADRR 0x2500
+#define MLXPLAT_CPLD_LPC_REG_LED1_OFFSET 0x20
+#define MLXPLAT_CPLD_LPC_REG_LED2_OFFSET 0x21
+#define MLXPLAT_CPLD_LPC_REG_LED3_OFFSET 0x22
+#define MLXPLAT_CPLD_LPC_REG_LED4_OFFSET 0x23
+#define MLXPLAT_CPLD_LPC_REG_LED5_OFFSET 0x24
#define MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET 0x3a
#define MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET 0x3b
#define MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET 0x40
@@ -84,6 +89,8 @@
#define MLXPLAT_CPLD_PWR_MASK GENMASK(1, 0)
#define MLXPLAT_CPLD_FAN_MASK GENMASK(3, 0)
#define MLXPLAT_CPLD_FAN_NG_MASK GENMASK(5, 0)
+#define MLXPLAT_CPLD_LED_LO_NIBBLE_MASK GENMASK(7, 4)
+#define MLXPLAT_CPLD_LED_HI_NIBBLE_MASK GENMASK(3, 0)
/* Default I2C parent bus number */
#define MLXPLAT_CPLD_PHYS_ADAPTER_DEF_NR 1
@@ -114,11 +121,13 @@
* @pdev_i2c - i2c controller platform device
* @pdev_mux - array of mux platform devices
* @pdev_hotplug - hotplug platform devices
+ * @pdev_led - led platform devices
*/
struct mlxplat_priv {
struct platform_device *pdev_i2c;
struct platform_device *pdev_mux[MLXPLAT_CPLD_LPC_MUX_DEVS];
struct platform_device *pdev_hotplug;
+ struct platform_device *pdev_led;
};
/* Regions for LPC I2C controller and LPC base register space */
@@ -592,9 +601,227 @@ struct mlxreg_core_hotplug_platform_data mlxplat_mlxcpld_default_ng_data = {
.mask_low = MLXPLAT_CPLD_LOW_AGGR_MASK_LOW,
};
+/* Platform led default data */
+static struct mlxreg_core_data mlxplat_mlxcpld_default_led_data[] = {
+ {
+ .label = "status:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "status:red",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
+ },
+ {
+ .label = "psu:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "psu:red",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "fan1:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan1:red",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan2:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "fan2:red",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "fan3:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan3:red",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan4:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "fan4:red",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+};
+
+static struct mlxreg_core_platform_data mlxplat_default_led_data = {
+ .data = mlxplat_mlxcpld_default_led_data,
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_led_data),
+};
+
+/* Platform led MSN21xx system family data */
+static struct mlxreg_core_data mlxplat_mlxcpld_msn21xx_led_data[] = {
+ {
+ .label = "status:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "status:red",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
+ },
+ {
+ .label = "fan:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan:red",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "psu1:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "psu1:red",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "psu2:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "psu2:red",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "uid:blue",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED5_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+};
+
+static struct mlxreg_core_platform_data mlxplat_msn21xx_led_data = {
+ .data = mlxplat_mlxcpld_msn21xx_led_data,
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_msn21xx_led_data),
+};
+
+/* Platform led for default data for 200GbE systems */
+static struct mlxreg_core_data mlxplat_mlxcpld_default_ng_led_data[] = {
+ {
+ .label = "status:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "status:orange",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK
+ },
+ {
+ .label = "psu:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "psu:orange",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED1_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "fan1:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan1:orange",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan2:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "fan2:orange",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED2_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "fan3:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan3:orange",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan4:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "fan4:orange",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED3_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "fan5:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan5:orange",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_LO_NIBBLE_MASK,
+ },
+ {
+ .label = "fan6:green",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+ {
+ .label = "fan6:orange",
+ .reg = MLXPLAT_CPLD_LPC_REG_LED4_OFFSET,
+ .mask = MLXPLAT_CPLD_LED_HI_NIBBLE_MASK,
+ },
+};
+
+static struct mlxreg_core_platform_data mlxplat_default_ng_led_data = {
+ .data = mlxplat_mlxcpld_default_ng_led_data,
+ .counter = ARRAY_SIZE(mlxplat_mlxcpld_default_ng_led_data),
+};
+
+
static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_PSU_EVENT_OFFSET:
@@ -611,6 +838,11 @@ static bool mlxplat_mlxcpld_writeable_reg(struct device *dev, unsigned int reg)
static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
@@ -632,6 +864,11 @@ static bool mlxplat_mlxcpld_readable_reg(struct device *dev, unsigned int reg)
static bool mlxplat_mlxcpld_volatile_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
+ case MLXPLAT_CPLD_LPC_REG_LED1_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED2_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED3_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED4_OFFSET:
+ case MLXPLAT_CPLD_LPC_REG_LED5_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGR_MASK_OFFSET:
case MLXPLAT_CPLD_LPC_REG_AGGRLO_OFFSET:
@@ -692,6 +929,7 @@ static struct resource mlxplat_mlxcpld_resources[] = {
static struct platform_device *mlxplat_dev;
static struct mlxreg_core_hotplug_platform_data *mlxplat_hotplug;
+static struct mlxreg_core_platform_data *mlxplat_led;
static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
{
@@ -705,6 +943,7 @@ static int __init mlxplat_dmi_default_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_default_data;
mlxplat_hotplug->deferred_nr =
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
+ mlxplat_led = &mlxplat_default_led_data;
return 1;
};
@@ -721,6 +960,7 @@ static int __init mlxplat_dmi_msn21xx_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_msn21xx_data;
mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
+ mlxplat_led = &mlxplat_msn21xx_led_data;
return 1;
};
@@ -737,6 +977,7 @@ static int __init mlxplat_dmi_msn274x_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_msn274x_data;
mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
+ mlxplat_led = &mlxplat_default_led_data;
return 1;
};
@@ -753,6 +994,7 @@ static int __init mlxplat_dmi_msn201x_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_msn201x_data;
mlxplat_hotplug->deferred_nr =
mlxplat_default_channels[i - 1][MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
+ mlxplat_led = &mlxplat_default_ng_led_data;
return 1;
};
@@ -769,6 +1011,7 @@ static int __init mlxplat_dmi_qmb7xx_matched(const struct dmi_system_id *dmi)
mlxplat_hotplug = &mlxplat_mlxcpld_default_ng_data;
mlxplat_hotplug->deferred_nr =
mlxplat_msn21xx_channels[MLXPLAT_CPLD_GRP_CHNL_NUM - 1];
+ mlxplat_led = &mlxplat_msn21xx_led_data;
return 1;
};
@@ -844,6 +1087,36 @@ static const struct dmi_system_id mlxplat_dmi_table[] __initconst = {
DMI_MATCH(DMI_PRODUCT_NAME, "SN34"),
},
},
+ {
+ .callback = mlxplat_dmi_default_matched,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0001"),
+ },
+ },
+ {
+ .callback = mlxplat_dmi_msn21xx_matched,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0002"),
+ },
+ },
+ {
+ .callback = mlxplat_dmi_msn274x_matched,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0003"),
+ },
+ },
+ {
+ .callback = mlxplat_dmi_msn201x_matched,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0004"),
+ },
+ },
+ {
+ .callback = mlxplat_dmi_qmb7xx_matched,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "VMOD0005"),
+ },
+ },
{ }
};
@@ -960,14 +1233,27 @@ static int __init mlxplat_init(void)
goto fail_platform_mux_register;
}
+ /* Add LED driver. */
+ mlxplat_led->regmap = mlxplat_hotplug->regmap;
+ priv->pdev_led = platform_device_register_resndata(
+ &mlxplat_dev->dev, "leds-mlxreg",
+ PLATFORM_DEVID_NONE, NULL, 0,
+ mlxplat_led, sizeof(*mlxplat_led));
+ if (IS_ERR(priv->pdev_led)) {
+ err = PTR_ERR(priv->pdev_led);
+ goto fail_platform_hotplug_register;
+ }
+
/* Sync registers with hardware. */
regcache_mark_dirty(mlxplat_hotplug->regmap);
err = regcache_sync(mlxplat_hotplug->regmap);
if (err)
- goto fail_platform_hotplug_register;
+ goto fail_platform_led_register;
return 0;
+fail_platform_led_register:
+ platform_device_unregister(priv->pdev_led);
fail_platform_hotplug_register:
platform_device_unregister(priv->pdev_hotplug);
fail_platform_mux_register:
@@ -986,6 +1272,7 @@ static void __exit mlxplat_exit(void)
struct mlxplat_priv *priv = platform_get_drvdata(mlxplat_dev);
int i;
+ platform_device_unregister(priv->pdev_led);
platform_device_unregister(priv->pdev_hotplug);
for (i = ARRAY_SIZE(mlxplat_mux_data) - 1; i >= 0 ; i--)
diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c
index 5c39b32..8361ad7 100644
--- a/drivers/platform/x86/panasonic-laptop.c
+++ b/drivers/platform/x86/panasonic-laptop.c
@@ -571,7 +571,7 @@ static int acpi_pcc_hotkey_add(struct acpi_device *device)
return -ENOMEM;
}
- pcc->sinf = kzalloc(sizeof(u32) * (num_sifr + 1), GFP_KERNEL);
+ pcc->sinf = kcalloc(num_sifr + 1, sizeof(u32), GFP_KERNEL);
if (!pcc->sinf) {
result = -ENOMEM;
goto out_hotkey;
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
index 03305e0..7b160ee 100644
--- a/drivers/platform/x86/samsung-laptop.c
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -1216,8 +1216,7 @@ static umode_t samsung_sysfs_is_visible(struct kobject *kobj,
struct attribute *attr, int idx)
{
struct device *dev = container_of(kobj, struct device, kobj);
- struct platform_device *pdev = to_platform_device(dev);
- struct samsung_laptop *samsung = platform_get_drvdata(pdev);
+ struct samsung_laptop *samsung = dev_get_drvdata(dev);
bool ok = true;
if (attr == &dev_attr_performance_level.attr)
diff --git a/drivers/platform/x86/silead_dmi.c b/drivers/platform/x86/silead_dmi.c
index 452aaca..853a7ce 100644
--- a/drivers/platform/x86/silead_dmi.c
+++ b/drivers/platform/x86/silead_dmi.c
@@ -53,6 +53,20 @@ static const struct silead_ts_dmi_data jumper_ezpad_mini3_data = {
.properties = jumper_ezpad_mini3_props,
};
+static const struct property_entry jumper_ezpad_6_pro_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1980),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1500),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl3692-jumper-ezpad-6-pro.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
+ { }
+};
+
+static const struct silead_ts_dmi_data jumper_ezpad_6_pro_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = jumper_ezpad_6_pro_props,
+};
+
static const struct property_entry dexp_ursus_7w_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 890),
PROPERTY_ENTRY_U32("touchscreen-size-y", 630),
@@ -127,7 +141,25 @@ static const struct silead_ts_dmi_data pipo_w2s_data = {
.properties = pipo_w2s_props,
};
-static const struct property_entry pov_mobii_wintab_p800w_props[] = {
+static const struct property_entry pov_mobii_wintab_p800w_v20_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-min-x", 32),
+ PROPERTY_ENTRY_U32("touchscreen-min-y", 16),
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1692),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1146),
+ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+ PROPERTY_ENTRY_STRING("firmware-name",
+ "gsl3680-pov-mobii-wintab-p800w-v20.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
+ { }
+};
+
+static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_v20_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = pov_mobii_wintab_p800w_v20_props,
+};
+
+static const struct property_entry pov_mobii_wintab_p800w_v21_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1800),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1150),
PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
@@ -137,9 +169,9 @@ static const struct property_entry pov_mobii_wintab_p800w_props[] = {
{ }
};
-static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_data = {
+static const struct silead_ts_dmi_data pov_mobii_wintab_p800w_v21_data = {
.acpi_name = "MSSL1680:00",
- .properties = pov_mobii_wintab_p800w_props,
+ .properties = pov_mobii_wintab_p800w_v21_props,
};
static const struct property_entry itworks_tw891_props[] = {
@@ -277,6 +309,23 @@ static const struct silead_ts_dmi_data teclast_x3_plus_data = {
.properties = teclast_x3_plus_props,
};
+static const struct property_entry onda_v891w_v1_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-min-x", 46),
+ PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1676),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1130),
+ PROPERTY_ENTRY_STRING("firmware-name",
+ "gsl3680-onda-v891w-v1.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
+ { }
+};
+
+static const struct silead_ts_dmi_data onda_v891w_v1_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = onda_v891w_v1_props,
+};
+
static const struct dmi_system_id silead_ts_dmi_table[] = {
{
/* CUBE iwork8 Air */
@@ -297,6 +346,17 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
},
},
{
+ /* Jumper EZpad 6 Pro */
+ .driver_data = (void *)&jumper_ezpad_6_pro_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Jumper"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "EZpad"),
+ DMI_MATCH(DMI_BIOS_VERSION, "5.12"),
+ /* Above matches are too generic, add bios-date match */
+ DMI_MATCH(DMI_BIOS_DATE, "08/18/2017"),
+ },
+ },
+ {
/* DEXP Ursus 7W */
.driver_data = (void *)&dexp_ursus_7w_data,
.matches = {
@@ -361,8 +421,19 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
},
},
{
- /* Point of View mobii wintab p800w */
- .driver_data = (void *)&pov_mobii_wintab_p800w_data,
+ /* Point of View mobii wintab p800w (v2.0) */
+ .driver_data = (void *)&pov_mobii_wintab_p800w_v20_data,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ DMI_MATCH(DMI_BIOS_VERSION, "3BAIR1014"),
+ /* Above matches are too generic, add bios-date match */
+ DMI_MATCH(DMI_BIOS_DATE, "10/24/2014"),
+ },
+ },
+ {
+ /* Point of View mobii wintab p800w (v2.1) */
+ .driver_data = (void *)&pov_mobii_wintab_p800w_v21_data,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
@@ -413,6 +484,15 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
},
},
{
+ /* Chuwi Hi8 (H1D_S806_206) */
+ .driver_data = (void *)&chuwi_hi8_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "BayTrail"),
+ DMI_MATCH(DMI_BIOS_VERSION, "H1D_S806_206"),
+ },
+ },
+ {
/* Chuwi Vi8 (CWI506) */
.driver_data = (void *)&chuwi_vi8_data,
.matches = {
@@ -463,6 +543,17 @@ static const struct dmi_system_id silead_ts_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Y8W81"),
},
},
+ {
+ /* ONDA V891w revision P891WBEBV1B00 aka v1 */
+ .driver_data = (void *)&onda_v891w_v1_data,
+ .matches = {
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "ONDA"),
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "ONDA Tablet"),
+ DMI_EXACT_MATCH(DMI_BOARD_VERSION, "V001"),
+ /* Exact match, different versions need different fw */
+ DMI_EXACT_MATCH(DMI_BIOS_VERSION, "ONDA.W89EBBN08"),
+ },
+ },
{ },
};
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index da1ca48..cae9b05 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -212,7 +212,12 @@ enum tpacpi_hkey_event_t {
TP_HKEY_EV_ALARM_BAT_XHOT = 0x6012, /* battery critically hot */
TP_HKEY_EV_ALARM_SENSOR_HOT = 0x6021, /* sensor too hot */
TP_HKEY_EV_ALARM_SENSOR_XHOT = 0x6022, /* sensor critically hot */
- TP_HKEY_EV_THM_TABLE_CHANGED = 0x6030, /* thermal table changed */
+ TP_HKEY_EV_THM_TABLE_CHANGED = 0x6030, /* windows; thermal table changed */
+ TP_HKEY_EV_THM_CSM_COMPLETED = 0x6032, /* windows; thermal control set
+ * command completed. Related to
+ * AML DYTC */
+ TP_HKEY_EV_THM_TRANSFM_CHANGED = 0x60F0, /* windows; thermal transformation
+ * changed. Related to AML GMTS */
/* AC-related events */
TP_HKEY_EV_AC_CHANGED = 0x6040, /* AC status changed */
@@ -4034,15 +4039,23 @@ static bool hotkey_notify_6xxx(const u32 hkey,
bool *send_acpi_ev,
bool *ignore_acpi_ev)
{
- bool known = true;
-
/* 0x6000-0x6FFF: thermal alarms/notices and keyboard events */
*send_acpi_ev = true;
*ignore_acpi_ev = false;
switch (hkey) {
case TP_HKEY_EV_THM_TABLE_CHANGED:
- pr_info("EC reports that Thermal Table has changed\n");
+ pr_debug("EC reports: Thermal Table has changed\n");
+ /* recommended action: do nothing, we don't have
+ * Lenovo ATM information */
+ return true;
+ case TP_HKEY_EV_THM_CSM_COMPLETED:
+ pr_debug("EC reports: Thermal Control Command set completed (DYTC)\n");
+ /* recommended action: do nothing, we don't have
+ * Lenovo ATM information */
+ return true;
+ case TP_HKEY_EV_THM_TRANSFM_CHANGED:
+ pr_debug("EC reports: Thermal Transformation changed (GMTS)\n");
/* recommended action: do nothing, we don't have
* Lenovo ATM information */
return true;
@@ -4083,7 +4096,7 @@ static bool hotkey_notify_6xxx(const u32 hkey,
tpacpi_input_send_tabletsw();
hotkey_tablet_mode_notify_change();
*send_acpi_ev = false;
- break;
+ return true;
case TP_HKEY_EV_PALM_DETECTED:
case TP_HKEY_EV_PALM_UNDETECTED:
@@ -4092,13 +4105,12 @@ static bool hotkey_notify_6xxx(const u32 hkey,
return true;
default:
- pr_warn("unknown possible thermal alarm or keyboard event received\n");
- known = false;
+ /* report simply as unknown, no sensor dump */
+ return false;
}
thermal_dump_all_sensors();
-
- return known;
+ return true;
}
static void hotkey_notify(struct ibm_struct *ibm, u32 event)
@@ -6006,7 +6018,7 @@ static int __init led_init(struct ibm_init_struct *iibm)
if (led_supported == TPACPI_LED_NONE)
return 1;
- tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS,
+ tpacpi_leds = kcalloc(TPACPI_LED_NUMLEDS, sizeof(*tpacpi_leds),
GFP_KERNEL);
if (!tpacpi_leds) {
pr_err("Out of memory for LED data\n");
diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c
index 2a50b46..faa1a67 100644
--- a/drivers/power/supply/charger-manager.c
+++ b/drivers/power/supply/charger-manager.c
@@ -1380,7 +1380,7 @@ static int charger_manager_register_sysfs(struct charger_manager *cm)
snprintf(buf, 10, "charger.%d", i);
str = devm_kzalloc(cm->dev,
- sizeof(char) * (strlen(buf) + 1), GFP_KERNEL);
+ strlen(buf) + 1, GFP_KERNEL);
if (!str)
return -ENOMEM;
@@ -1522,8 +1522,10 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev)
of_property_read_u32(np, "cm-num-chargers", &num_chgs);
if (num_chgs) {
/* Allocate empty bin at the tail of array */
- desc->psy_charger_stat = devm_kzalloc(dev, sizeof(char *)
- * (num_chgs + 1), GFP_KERNEL);
+ desc->psy_charger_stat = devm_kcalloc(dev,
+ num_chgs + 1,
+ sizeof(char *),
+ GFP_KERNEL);
if (desc->psy_charger_stat) {
int i;
for (i = 0; i < num_chgs; i++)
@@ -1555,8 +1557,9 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev)
struct charger_regulator *chg_regs;
struct device_node *child;
- chg_regs = devm_kzalloc(dev, sizeof(*chg_regs)
- * desc->num_charger_regulators,
+ chg_regs = devm_kcalloc(dev,
+ desc->num_charger_regulators,
+ sizeof(*chg_regs),
GFP_KERNEL);
if (!chg_regs)
return ERR_PTR(-ENOMEM);
@@ -1573,9 +1576,10 @@ static struct charger_desc *of_cm_parse_desc(struct device *dev)
/* charger cables */
chg_regs->num_cables = of_get_child_count(child);
if (chg_regs->num_cables) {
- cables = devm_kzalloc(dev, sizeof(*cables)
- * chg_regs->num_cables,
- GFP_KERNEL);
+ cables = devm_kcalloc(dev,
+ chg_regs->num_cables,
+ sizeof(*cables),
+ GFP_KERNEL);
if (!cables) {
of_node_put(child);
return ERR_PTR(-ENOMEM);
@@ -1725,10 +1729,11 @@ static int charger_manager_probe(struct platform_device *pdev)
cm->charger_psy_desc.name = cm->psy_name_buf;
/* Allocate for psy properties because they may vary */
- cm->charger_psy_desc.properties = devm_kzalloc(&pdev->dev,
- sizeof(enum power_supply_property)
- * (ARRAY_SIZE(default_charger_props) +
- NUM_CHARGER_PSY_OPTIONAL), GFP_KERNEL);
+ cm->charger_psy_desc.properties =
+ devm_kcalloc(&pdev->dev,
+ ARRAY_SIZE(default_charger_props) +
+ NUM_CHARGER_PSY_OPTIONAL,
+ sizeof(enum power_supply_property), GFP_KERNEL);
if (!cm->charger_psy_desc.properties)
return -ENOMEM;
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index f57ab0a..d21f478 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -263,8 +263,8 @@ static int power_supply_check_supplies(struct power_supply *psy)
if (!psy->supplied_from)
return -ENOMEM;
- *psy->supplied_from = devm_kzalloc(&psy->dev,
- sizeof(char *) * (cnt - 1),
+ *psy->supplied_from = devm_kcalloc(&psy->dev,
+ cnt - 1, sizeof(char *),
GFP_KERNEL);
if (!*psy->supplied_from)
return -ENOMEM;
diff --git a/drivers/power/supply/wm97xx_battery.c b/drivers/power/supply/wm97xx_battery.c
index bd4f666..6754e76 100644
--- a/drivers/power/supply/wm97xx_battery.c
+++ b/drivers/power/supply/wm97xx_battery.c
@@ -201,7 +201,7 @@ static int wm97xx_bat_probe(struct platform_device *dev)
if (pdata->min_voltage >= 0)
props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */
- prop = kzalloc(props * sizeof(*prop), GFP_KERNEL);
+ prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
if (!prop) {
ret = -ENOMEM;
goto err3;
diff --git a/drivers/power/supply/z2_battery.c b/drivers/power/supply/z2_battery.c
index 8a43b49..bcc2d1a 100644
--- a/drivers/power/supply/z2_battery.c
+++ b/drivers/power/supply/z2_battery.c
@@ -146,7 +146,7 @@ static int z2_batt_ps_init(struct z2_charger *charger, int props)
if (info->min_voltage >= 0)
props++; /* POWER_SUPPLY_PROP_VOLTAGE_MIN */
- prop = kzalloc(props * sizeof(*prop), GFP_KERNEL);
+ prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
if (!prop)
return -ENOMEM;
diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c
index 64b2b25..9e2f274 100644
--- a/drivers/powercap/powercap_sys.c
+++ b/drivers/powercap/powercap_sys.c
@@ -545,15 +545,16 @@ struct powercap_zone *powercap_register_zone(
dev_set_name(&power_zone->dev, "%s:%x",
dev_name(power_zone->dev.parent),
power_zone->id);
- power_zone->constraints = kzalloc(sizeof(*power_zone->constraints) *
- nr_constraints, GFP_KERNEL);
+ power_zone->constraints = kcalloc(nr_constraints,
+ sizeof(*power_zone->constraints),
+ GFP_KERNEL);
if (!power_zone->constraints)
goto err_const_alloc;
nr_attrs = nr_constraints * POWERCAP_CONSTRAINTS_ATTRS +
POWERCAP_ZONE_MAX_ATTRS + 1;
- power_zone->zone_dev_attrs = kzalloc(sizeof(void *) *
- nr_attrs, GFP_KERNEL);
+ power_zone->zone_dev_attrs = kcalloc(nr_attrs, sizeof(void *),
+ GFP_KERNEL);
if (!power_zone->zone_dev_attrs)
goto err_attr_alloc;
create_power_zone_common_attributes(power_zone);
diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c
index 767c485..547dbda 100644
--- a/drivers/ptp/ptp_chardev.c
+++ b/drivers/ptp/ptp_chardev.c
@@ -221,7 +221,7 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
}
pct = &sysoff->ts[0];
for (i = 0; i < sysoff->n_samples; i++) {
- getnstimeofday64(&ts);
+ ktime_get_real_ts64(&ts);
pct->sec = ts.tv_sec;
pct->nsec = ts.tv_nsec;
pct++;
@@ -230,7 +230,7 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
pct->nsec = ts.tv_nsec;
pct++;
}
- getnstimeofday64(&ts);
+ ktime_get_real_ts64(&ts);
pct->sec = ts.tv_sec;
pct->nsec = ts.tv_nsec;
if (copy_to_user((void __user *)arg, sysoff, sizeof(*sysoff)))
diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c
index 1468a16..e8652c1 100644
--- a/drivers/ptp/ptp_qoriq.c
+++ b/drivers/ptp/ptp_qoriq.c
@@ -374,7 +374,7 @@ static int qoriq_ptp_probe(struct platform_device *dev)
pr_err("ioremap ptp registers failed\n");
goto no_ioremap;
}
- getnstimeofday64(&now);
+ ktime_get_real_ts64(&now);
ptp_qoriq_settime(&qoriq_ptp->caps, &now);
tmr_ctrl =
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 4635cb3..a4d262d 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -401,7 +401,7 @@ config PWM_STI
config PWM_STM32
tristate "STMicroelectronics STM32 PWM"
- depends on MFD_STM32_TIMERS || COMPILE_TEST
+ depends on MFD_STM32_TIMERS
help
Generic PWM framework driver for STM32 SoCs.
diff --git a/drivers/pwm/pwm-atmel-tcb.c b/drivers/pwm/pwm-atmel-tcb.c
index 4fb1be2..0d0f837 100644
--- a/drivers/pwm/pwm-atmel-tcb.c
+++ b/drivers/pwm/pwm-atmel-tcb.c
@@ -460,8 +460,7 @@ MODULE_DEVICE_TABLE(of, atmel_tcb_pwm_dt_ids);
#ifdef CONFIG_PM_SLEEP
static int atmel_tcb_pwm_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
+ struct atmel_tcb_pwm_chip *tcbpwm = dev_get_drvdata(dev);
void __iomem *base = tcbpwm->tc->regs;
int i;
@@ -478,8 +477,7 @@ static int atmel_tcb_pwm_suspend(struct device *dev)
static int atmel_tcb_pwm_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct atmel_tcb_pwm_chip *tcbpwm = platform_get_drvdata(pdev);
+ struct atmel_tcb_pwm_chip *tcbpwm = dev_get_drvdata(dev);
void __iomem *base = tcbpwm->tc->regs;
int i;
diff --git a/drivers/pwm/pwm-lp3943.c b/drivers/pwm/pwm-lp3943.c
index 52584e9..15b40a8 100644
--- a/drivers/pwm/pwm-lp3943.c
+++ b/drivers/pwm/pwm-lp3943.c
@@ -225,7 +225,7 @@ static int lp3943_pwm_parse_dt(struct device *dev,
if (num_outputs == 0)
continue;
- output = devm_kzalloc(dev, sizeof(*output) * num_outputs,
+ output = devm_kcalloc(dev, num_outputs, sizeof(*output),
GFP_KERNEL);
if (!output)
return -ENOMEM;
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
index 5d6ed15..5561b9e 100644
--- a/drivers/pwm/pwm-lpss-platform.c
+++ b/drivers/pwm/pwm-lpss-platform.c
@@ -74,6 +74,10 @@ static int pwm_lpss_remove_platform(struct platform_device *pdev)
return pwm_lpss_remove(lpwm);
}
+static SIMPLE_DEV_PM_OPS(pwm_lpss_platform_pm_ops,
+ pwm_lpss_suspend,
+ pwm_lpss_resume);
+
static const struct acpi_device_id pwm_lpss_acpi_match[] = {
{ "80860F09", (unsigned long)&pwm_lpss_byt_info },
{ "80862288", (unsigned long)&pwm_lpss_bsw_info },
@@ -86,6 +90,7 @@ static struct platform_driver pwm_lpss_driver_platform = {
.driver = {
.name = "pwm-lpss",
.acpi_match_table = pwm_lpss_acpi_match,
+ .pm = &pwm_lpss_platform_pm_ops,
},
.probe = pwm_lpss_probe_platform,
.remove = pwm_lpss_remove_platform,
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index 8db0d40..4721a26 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -32,10 +32,13 @@
/* Size of each PWM register space if multiple */
#define PWM_SIZE 0x400
+#define MAX_PWMS 4
+
struct pwm_lpss_chip {
struct pwm_chip chip;
void __iomem *regs;
const struct pwm_lpss_boardinfo *info;
+ u32 saved_ctrl[MAX_PWMS];
};
static inline struct pwm_lpss_chip *to_lpwm(struct pwm_chip *chip)
@@ -177,6 +180,9 @@ struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
unsigned long c;
int ret;
+ if (WARN_ON(info->npwm > MAX_PWMS))
+ return ERR_PTR(-ENODEV);
+
lpwm = devm_kzalloc(dev, sizeof(*lpwm), GFP_KERNEL);
if (!lpwm)
return ERR_PTR(-ENOMEM);
@@ -212,6 +218,30 @@ int pwm_lpss_remove(struct pwm_lpss_chip *lpwm)
}
EXPORT_SYMBOL_GPL(pwm_lpss_remove);
+int pwm_lpss_suspend(struct device *dev)
+{
+ struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < lpwm->info->npwm; i++)
+ lpwm->saved_ctrl[i] = readl(lpwm->regs + i * PWM_SIZE + PWM);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pwm_lpss_suspend);
+
+int pwm_lpss_resume(struct device *dev)
+{
+ struct pwm_lpss_chip *lpwm = dev_get_drvdata(dev);
+ int i;
+
+ for (i = 0; i < lpwm->info->npwm; i++)
+ writel(lpwm->saved_ctrl[i], lpwm->regs + i * PWM_SIZE + PWM);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pwm_lpss_resume);
+
MODULE_DESCRIPTION("PWM driver for Intel LPSS");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/pwm/pwm-lpss.h b/drivers/pwm/pwm-lpss.h
index 98306bb..7a4238a 100644
--- a/drivers/pwm/pwm-lpss.h
+++ b/drivers/pwm/pwm-lpss.h
@@ -28,5 +28,7 @@ struct pwm_lpss_boardinfo {
struct pwm_lpss_chip *pwm_lpss_probe(struct device *dev, struct resource *r,
const struct pwm_lpss_boardinfo *info);
int pwm_lpss_remove(struct pwm_lpss_chip *lpwm);
+int pwm_lpss_suspend(struct device *dev);
+int pwm_lpss_resume(struct device *dev);
#endif /* __PWM_LPSS_H */
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
index 0767deb..822860b 100644
--- a/drivers/pwm/pwm-meson.c
+++ b/drivers/pwm/pwm-meson.c
@@ -541,8 +541,8 @@ static int meson_pwm_probe(struct platform_device *pdev)
meson->data = of_device_get_match_data(&pdev->dev);
meson->inverter_mask = BIT(meson->chip.npwm) - 1;
- channels = devm_kcalloc(&pdev->dev, meson->chip.npwm, sizeof(*meson),
- GFP_KERNEL);
+ channels = devm_kcalloc(&pdev->dev, meson->chip.npwm,
+ sizeof(*channels), GFP_KERNEL);
if (!channels)
return -ENOMEM;
diff --git a/drivers/pwm/pwm-rcar.c b/drivers/pwm/pwm-rcar.c
index 91d11f2..748f614 100644
--- a/drivers/pwm/pwm-rcar.c
+++ b/drivers/pwm/pwm-rcar.c
@@ -261,8 +261,7 @@ MODULE_DEVICE_TABLE(of, rcar_pwm_of_table);
#ifdef CONFIG_PM_SLEEP
static struct pwm_device *rcar_pwm_dev_to_pwm_dev(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rcar_pwm_chip *rcar_pwm = platform_get_drvdata(pdev);
+ struct rcar_pwm_chip *rcar_pwm = dev_get_drvdata(dev);
struct pwm_chip *chip = &rcar_pwm->chip;
return &chip->pwms[0];
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index 2708212..4f84255 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -8,6 +8,7 @@
* pwm-atmel.c from Bo Shen
*/
+#include <linux/bitfield.h>
#include <linux/mfd/stm32-timers.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -25,6 +26,7 @@ struct stm32_pwm {
struct regmap *regmap;
u32 max_arr;
bool have_complementary_output;
+ u32 capture[4] ____cacheline_aligned; /* DMA'able buffer */
};
struct stm32_breakinput {
@@ -62,6 +64,258 @@ static int write_ccrx(struct stm32_pwm *dev, int ch, u32 value)
return -EINVAL;
}
+#define TIM_CCER_CC12P (TIM_CCER_CC1P | TIM_CCER_CC2P)
+#define TIM_CCER_CC12E (TIM_CCER_CC1E | TIM_CCER_CC2E)
+#define TIM_CCER_CC34P (TIM_CCER_CC3P | TIM_CCER_CC4P)
+#define TIM_CCER_CC34E (TIM_CCER_CC3E | TIM_CCER_CC4E)
+
+/*
+ * Capture using PWM input mode:
+ * ___ ___
+ * TI[1, 2, 3 or 4]: ........._| |________|
+ * ^0 ^1 ^2
+ * . . .
+ * . . XXXXX
+ * . . XXXXX |
+ * . XXXXX . |
+ * XXXXX . . |
+ * COUNTER: ______XXXXX . . . |_XXX
+ * start^ . . . ^stop
+ * . . . .
+ * v v . v
+ * v
+ * CCR1/CCR3: tx..........t0...........t2
+ * CCR2/CCR4: tx..............t1.........
+ *
+ * DMA burst transfer: | |
+ * v v
+ * DMA buffer: { t0, tx } { t2, t1 }
+ * DMA done: ^
+ *
+ * 0: IC1/3 snapchot on rising edge: counter value -> CCR1/CCR3
+ * + DMA transfer CCR[1/3] & CCR[2/4] values (t0, tx: doesn't care)
+ * 1: IC2/4 snapchot on falling edge: counter value -> CCR2/CCR4
+ * 2: IC1/3 snapchot on rising edge: counter value -> CCR1/CCR3
+ * + DMA transfer CCR[1/3] & CCR[2/4] values (t2, t1)
+ *
+ * DMA done, compute:
+ * - Period = t2 - t0
+ * - Duty cycle = t1 - t0
+ */
+static int stm32_pwm_raw_capture(struct stm32_pwm *priv, struct pwm_device *pwm,
+ unsigned long tmo_ms, u32 *raw_prd,
+ u32 *raw_dty)
+{
+ struct device *parent = priv->chip.dev->parent;
+ enum stm32_timers_dmas dma_id;
+ u32 ccen, ccr;
+ int ret;
+
+ /* Ensure registers have been updated, enable counter and capture */
+ regmap_update_bits(priv->regmap, TIM_EGR, TIM_EGR_UG, TIM_EGR_UG);
+ regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, TIM_CR1_CEN);
+
+ /* Use cc1 or cc3 DMA resp for PWM input channels 1 & 2 or 3 & 4 */
+ dma_id = pwm->hwpwm < 2 ? STM32_TIMERS_DMA_CH1 : STM32_TIMERS_DMA_CH3;
+ ccen = pwm->hwpwm < 2 ? TIM_CCER_CC12E : TIM_CCER_CC34E;
+ ccr = pwm->hwpwm < 2 ? TIM_CCR1 : TIM_CCR3;
+ regmap_update_bits(priv->regmap, TIM_CCER, ccen, ccen);
+
+ /*
+ * Timer DMA burst mode. Request 2 registers, 2 bursts, to get both
+ * CCR1 & CCR2 (or CCR3 & CCR4) on each capture event.
+ * We'll get two capture snapchots: { CCR1, CCR2 }, { CCR1, CCR2 }
+ * or { CCR3, CCR4 }, { CCR3, CCR4 }
+ */
+ ret = stm32_timers_dma_burst_read(parent, priv->capture, dma_id, ccr, 2,
+ 2, tmo_ms);
+ if (ret)
+ goto stop;
+
+ /* Period: t2 - t0 (take care of counter overflow) */
+ if (priv->capture[0] <= priv->capture[2])
+ *raw_prd = priv->capture[2] - priv->capture[0];
+ else
+ *raw_prd = priv->max_arr - priv->capture[0] + priv->capture[2];
+
+ /* Duty cycle capture requires at least two capture units */
+ if (pwm->chip->npwm < 2)
+ *raw_dty = 0;
+ else if (priv->capture[0] <= priv->capture[3])
+ *raw_dty = priv->capture[3] - priv->capture[0];
+ else
+ *raw_dty = priv->max_arr - priv->capture[0] + priv->capture[3];
+
+ if (*raw_dty > *raw_prd) {
+ /*
+ * Race beetween PWM input and DMA: it may happen
+ * falling edge triggers new capture on TI2/4 before DMA
+ * had a chance to read CCR2/4. It means capture[1]
+ * contains period + duty_cycle. So, subtract period.
+ */
+ *raw_dty -= *raw_prd;
+ }
+
+stop:
+ regmap_update_bits(priv->regmap, TIM_CCER, ccen, 0);
+ regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0);
+
+ return ret;
+}
+
+static int stm32_pwm_capture(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_capture *result, unsigned long tmo_ms)
+{
+ struct stm32_pwm *priv = to_stm32_pwm_dev(chip);
+ unsigned long long prd, div, dty;
+ unsigned long rate;
+ unsigned int psc = 0, icpsc, scale;
+ u32 raw_prd = 0, raw_dty = 0;
+ int ret = 0;
+
+ mutex_lock(&priv->lock);
+
+ if (active_channels(priv)) {
+ ret = -EBUSY;
+ goto unlock;
+ }
+
+ ret = clk_enable(priv->clk);
+ if (ret) {
+ dev_err(priv->chip.dev, "failed to enable counter clock\n");
+ goto unlock;
+ }
+
+ rate = clk_get_rate(priv->clk);
+ if (!rate) {
+ ret = -EINVAL;
+ goto clk_dis;
+ }
+
+ /* prescaler: fit timeout window provided by upper layer */
+ div = (unsigned long long)rate * (unsigned long long)tmo_ms;
+ do_div(div, MSEC_PER_SEC);
+ prd = div;
+ while ((div > priv->max_arr) && (psc < MAX_TIM_PSC)) {
+ psc++;
+ div = prd;
+ do_div(div, psc + 1);
+ }
+ regmap_write(priv->regmap, TIM_ARR, priv->max_arr);
+ regmap_write(priv->regmap, TIM_PSC, psc);
+
+ /* Map TI1 or TI2 PWM input to IC1 & IC2 (or TI3/4 to IC3 & IC4) */
+ regmap_update_bits(priv->regmap,
+ pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2,
+ TIM_CCMR_CC1S | TIM_CCMR_CC2S, pwm->hwpwm & 0x1 ?
+ TIM_CCMR_CC1S_TI2 | TIM_CCMR_CC2S_TI2 :
+ TIM_CCMR_CC1S_TI1 | TIM_CCMR_CC2S_TI1);
+
+ /* Capture period on IC1/3 rising edge, duty cycle on IC2/4 falling. */
+ regmap_update_bits(priv->regmap, TIM_CCER, pwm->hwpwm < 2 ?
+ TIM_CCER_CC12P : TIM_CCER_CC34P, pwm->hwpwm < 2 ?
+ TIM_CCER_CC2P : TIM_CCER_CC4P);
+
+ ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, &raw_dty);
+ if (ret)
+ goto stop;
+
+ /*
+ * Got a capture. Try to improve accuracy at high rates:
+ * - decrease counter clock prescaler, scale up to max rate.
+ * - use input prescaler, capture once every /2 /4 or /8 edges.
+ */
+ if (raw_prd) {
+ u32 max_arr = priv->max_arr - 0x1000; /* arbitrary margin */
+
+ scale = max_arr / min(max_arr, raw_prd);
+ } else {
+ scale = priv->max_arr; /* bellow resolution, use max scale */
+ }
+
+ if (psc && scale > 1) {
+ /* 2nd measure with new scale */
+ psc /= scale;
+ regmap_write(priv->regmap, TIM_PSC, psc);
+ ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd,
+ &raw_dty);
+ if (ret)
+ goto stop;
+ }
+
+ /* Compute intermediate period not to exceed timeout at low rates */
+ prd = (unsigned long long)raw_prd * (psc + 1) * NSEC_PER_SEC;
+ do_div(prd, rate);
+
+ for (icpsc = 0; icpsc < MAX_TIM_ICPSC ; icpsc++) {
+ /* input prescaler: also keep arbitrary margin */
+ if (raw_prd >= (priv->max_arr - 0x1000) >> (icpsc + 1))
+ break;
+ if (prd >= (tmo_ms * NSEC_PER_MSEC) >> (icpsc + 2))
+ break;
+ }
+
+ if (!icpsc)
+ goto done;
+
+ /* Last chance to improve period accuracy, using input prescaler */
+ regmap_update_bits(priv->regmap,
+ pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2,
+ TIM_CCMR_IC1PSC | TIM_CCMR_IC2PSC,
+ FIELD_PREP(TIM_CCMR_IC1PSC, icpsc) |
+ FIELD_PREP(TIM_CCMR_IC2PSC, icpsc));
+
+ ret = stm32_pwm_raw_capture(priv, pwm, tmo_ms, &raw_prd, &raw_dty);
+ if (ret)
+ goto stop;
+
+ if (raw_dty >= (raw_prd >> icpsc)) {
+ /*
+ * We may fall here using input prescaler, when input
+ * capture starts on high side (before falling edge).
+ * Example with icpsc to capture on each 4 events:
+ *
+ * start 1st capture 2nd capture
+ * v v v
+ * ___ _____ _____ _____ _____ ____
+ * TI1..4 |__| |__| |__| |__| |__|
+ * v v . . . . . v v
+ * icpsc1/3: . 0 . 1 . 2 . 3 . 0
+ * icpsc2/4: 0 1 2 3 0
+ * v v v v
+ * CCR1/3 ......t0..............................t2
+ * CCR2/4 ..t1..............................t1'...
+ * . . .
+ * Capture0: .<----------------------------->.
+ * Capture1: .<-------------------------->. .
+ * . . .
+ * Period: .<------> . .
+ * Low side: .<>.
+ *
+ * Result:
+ * - Period = Capture0 / icpsc
+ * - Duty = Period - Low side = Period - (Capture0 - Capture1)
+ */
+ raw_dty = (raw_prd >> icpsc) - (raw_prd - raw_dty);
+ }
+
+done:
+ prd = (unsigned long long)raw_prd * (psc + 1) * NSEC_PER_SEC;
+ result->period = DIV_ROUND_UP_ULL(prd, rate << icpsc);
+ dty = (unsigned long long)raw_dty * (psc + 1) * NSEC_PER_SEC;
+ result->duty_cycle = DIV_ROUND_UP_ULL(dty, rate);
+stop:
+ regmap_write(priv->regmap, TIM_CCER, 0);
+ regmap_write(priv->regmap, pwm->hwpwm < 2 ? TIM_CCMR1 : TIM_CCMR2, 0);
+ regmap_write(priv->regmap, TIM_PSC, 0);
+clk_dis:
+ clk_disable(priv->clk);
+unlock:
+ mutex_unlock(&priv->lock);
+
+ return ret;
+}
+
static int stm32_pwm_config(struct stm32_pwm *priv, int ch,
int duty_ns, int period_ns)
{
@@ -230,6 +484,7 @@ static int stm32_pwm_apply_locked(struct pwm_chip *chip, struct pwm_device *pwm,
static const struct pwm_ops stm32pwm_ops = {
.owner = THIS_MODULE,
.apply = stm32_pwm_apply_locked,
+ .capture = IS_ENABLED(CONFIG_DMA_ENGINE) ? stm32_pwm_capture : NULL,
};
static int stm32_pwm_set_breakinput(struct stm32_pwm *priv,
diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c
index 0434ab7..a8cb8d2 100644
--- a/drivers/rapidio/devices/rio_mport_cdev.c
+++ b/drivers/rapidio/devices/rio_mport_cdev.c
@@ -975,7 +975,7 @@ static int rio_mport_transfer_ioctl(struct file *filp, void __user *arg)
priv->md->properties.transfer_mode) == 0)
return -ENODEV;
- transfer = vmalloc(transaction.count * sizeof(*transfer));
+ transfer = vmalloc(array_size(sizeof(*transfer), transaction.count));
if (!transfer)
return -ENOMEM;
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 161b927..fd7b517 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -425,9 +425,9 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
rswitch = rdev->rswitch;
rswitch->port_ok = 0;
spin_lock_init(&rswitch->lock);
- rswitch->route_table = kzalloc(sizeof(u8)*
- RIO_MAX_ROUTE_ENTRIES(port->sys_size),
- GFP_KERNEL);
+ rswitch->route_table =
+ kzalloc(RIO_MAX_ROUTE_ENTRIES(port->sys_size),
+ GFP_KERNEL);
if (!rswitch->route_table)
goto cleanup;
/* Initialize switch route table */
diff --git a/drivers/regulator/act8865-regulator.c b/drivers/regulator/act8865-regulator.c
index 7652477..21e2048 100644
--- a/drivers/regulator/act8865-regulator.c
+++ b/drivers/regulator/act8865-regulator.c
@@ -424,9 +424,10 @@ static int act8865_pdata_from_dt(struct device *dev,
if (matched <= 0)
return matched;
- pdata->regulators = devm_kzalloc(dev,
- sizeof(struct act8865_regulator_data) *
- num_matches, GFP_KERNEL);
+ pdata->regulators = devm_kcalloc(dev,
+ num_matches,
+ sizeof(struct act8865_regulator_data),
+ GFP_KERNEL);
if (!pdata->regulators)
return -ENOMEM;
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index 874d415..565a713 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -239,8 +239,10 @@ static int as3711_regulator_probe(struct platform_device *pdev)
}
}
- regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
- sizeof(struct as3711_regulator), GFP_KERNEL);
+ regs = devm_kcalloc(&pdev->dev,
+ AS3711_REGULATOR_NUM,
+ sizeof(struct as3711_regulator),
+ GFP_KERNEL);
if (!regs)
return -ENOMEM;
diff --git a/drivers/regulator/bcm590xx-regulator.c b/drivers/regulator/bcm590xx-regulator.c
index 9dd7154..92d6d7b 100644
--- a/drivers/regulator/bcm590xx-regulator.c
+++ b/drivers/regulator/bcm590xx-regulator.c
@@ -383,8 +383,10 @@ static int bcm590xx_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, pmu);
- pmu->desc = devm_kzalloc(&pdev->dev, BCM590XX_NUM_REGS *
- sizeof(struct regulator_desc), GFP_KERNEL);
+ pmu->desc = devm_kcalloc(&pdev->dev,
+ BCM590XX_NUM_REGS,
+ sizeof(struct regulator_desc),
+ GFP_KERNEL);
if (!pmu->desc)
return -ENOMEM;
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index 6a8f9cd..2df26f3 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -681,8 +681,8 @@ static struct da9063_regulators_pdata *da9063_parse_regulators_dt(
if (!pdata)
return ERR_PTR(-ENOMEM);
- pdata->regulator_data = devm_kzalloc(&pdev->dev,
- num * sizeof(*pdata->regulator_data),
+ pdata->regulator_data = devm_kcalloc(&pdev->dev,
+ num, sizeof(*pdata->regulator_data),
GFP_KERNEL);
if (!pdata->regulator_data)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index a86b899..b2f5ec4 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -172,8 +172,8 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
if (ret > 0) {
config->nr_gpios = ret;
- config->gpios = devm_kzalloc(dev,
- sizeof(struct gpio) * config->nr_gpios,
+ config->gpios = devm_kcalloc(dev,
+ config->nr_gpios, sizeof(struct gpio),
GFP_KERNEL);
if (!config->gpios)
return ERR_PTR(-ENOMEM);
@@ -214,9 +214,9 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
return ERR_PTR(-EINVAL);
}
- config->states = devm_kzalloc(dev,
- sizeof(struct gpio_regulator_state)
- * (proplen / 2),
+ config->states = devm_kcalloc(dev,
+ proplen / 2,
+ sizeof(struct gpio_regulator_state),
GFP_KERNEL);
if (!config->states)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c
index 66bbaa9..cc52779 100644
--- a/drivers/regulator/max1586.c
+++ b/drivers/regulator/max1586.c
@@ -194,8 +194,10 @@ static int of_get_max1586_platform_data(struct device *dev,
if (matched <= 0)
return matched;
- pdata->subdevs = devm_kzalloc(dev, sizeof(struct max1586_subdev_data) *
- matched, GFP_KERNEL);
+ pdata->subdevs = devm_kcalloc(dev,
+ matched,
+ sizeof(struct max1586_subdev_data),
+ GFP_KERNEL);
if (!pdata->subdevs)
return -ENOMEM;
diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c
index a618342..4cf6897 100644
--- a/drivers/regulator/max8660.c
+++ b/drivers/regulator/max8660.c
@@ -351,8 +351,10 @@ static int max8660_pdata_from_dt(struct device *dev,
if (matched <= 0)
return matched;
- pdata->subdevs = devm_kzalloc(dev, sizeof(struct max8660_subdev_data) *
- matched, GFP_KERNEL);
+ pdata->subdevs = devm_kcalloc(dev,
+ matched,
+ sizeof(struct max8660_subdev_data),
+ GFP_KERNEL);
if (!pdata->subdevs)
return -ENOMEM;
diff --git a/drivers/regulator/max8997-regulator.c b/drivers/regulator/max8997-regulator.c
index 559b9ac..a8ea30e 100644
--- a/drivers/regulator/max8997-regulator.c
+++ b/drivers/regulator/max8997-regulator.c
@@ -929,8 +929,9 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
/* count the number of regulators to be supported in pmic */
pdata->num_regulators = of_get_child_count(regulators_np);
- rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
- pdata->num_regulators, GFP_KERNEL);
+ rdata = devm_kcalloc(&pdev->dev,
+ pdata->num_regulators, sizeof(*rdata),
+ GFP_KERNEL);
if (!rdata) {
of_node_put(regulators_np);
return -ENOMEM;
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index 6a2b61c..6b9f262 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -670,8 +670,9 @@ static int max8998_pmic_dt_parse_pdata(struct max8998_dev *iodev,
/* count the number of regulators to be supported in pmic */
pdata->num_regulators = of_get_child_count(regulators_np);
- rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
- pdata->num_regulators, GFP_KERNEL);
+ rdata = devm_kcalloc(iodev->dev,
+ pdata->num_regulators, sizeof(*rdata),
+ GFP_KERNEL);
if (!rdata) {
of_node_put(regulators_np);
return -ENOMEM;
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c
index 41271ae..da4fb98 100644
--- a/drivers/regulator/mc13xxx-regulator-core.c
+++ b/drivers/regulator/mc13xxx-regulator-core.c
@@ -171,7 +171,7 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
if (!parent)
return NULL;
- data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators,
+ data = devm_kcalloc(&pdev->dev, priv->num_regulators, sizeof(*data),
GFP_KERNEL);
if (!data) {
of_node_put(parent);
diff --git a/drivers/regulator/pbias-regulator.c b/drivers/regulator/pbias-regulator.c
index 8f782d2..92b41a6 100644
--- a/drivers/regulator/pbias-regulator.c
+++ b/drivers/regulator/pbias-regulator.c
@@ -173,8 +173,9 @@ static int pbias_regulator_probe(struct platform_device *pdev)
if (count < 0)
return count;
- drvdata = devm_kzalloc(&pdev->dev, sizeof(struct pbias_regulator_data)
- * count, GFP_KERNEL);
+ drvdata = devm_kcalloc(&pdev->dev,
+ count, sizeof(struct pbias_regulator_data),
+ GFP_KERNEL);
if (!drvdata)
return -ENOMEM;
diff --git a/drivers/regulator/rc5t583-regulator.c b/drivers/regulator/rc5t583-regulator.c
index d0f1340..2ec51af 100644
--- a/drivers/regulator/rc5t583-regulator.c
+++ b/drivers/regulator/rc5t583-regulator.c
@@ -132,8 +132,10 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
return -ENODEV;
}
- regs = devm_kzalloc(&pdev->dev, RC5T583_REGULATOR_MAX *
- sizeof(struct rc5t583_regulator), GFP_KERNEL);
+ regs = devm_kcalloc(&pdev->dev,
+ RC5T583_REGULATOR_MAX,
+ sizeof(struct rc5t583_regulator),
+ GFP_KERNEL);
if (!regs)
return -ENOMEM;
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 7726b87..d1207ec 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -1139,8 +1139,8 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
return -EINVAL;
}
- s2mps11->ext_control_gpio = devm_kmalloc(&pdev->dev,
- sizeof(*s2mps11->ext_control_gpio) * rdev_num,
+ s2mps11->ext_control_gpio = devm_kmalloc_array(&pdev->dev,
+ rdev_num, sizeof(*s2mps11->ext_control_gpio),
GFP_KERNEL);
if (!s2mps11->ext_control_gpio)
return -ENOMEM;
@@ -1162,7 +1162,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
}
}
- rdata = kzalloc(sizeof(*rdata) * rdev_num, GFP_KERNEL);
+ rdata = kcalloc(rdev_num, sizeof(*rdata), GFP_KERNEL);
if (!rdata)
return -ENOMEM;
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index b8443a3..0cbc980 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -553,13 +553,15 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
/* count the number of regulators to be supported in pmic */
pdata->num_regulators = of_get_child_count(regulators_np);
- rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) *
- pdata->num_regulators, GFP_KERNEL);
+ rdata = devm_kcalloc(&pdev->dev,
+ pdata->num_regulators, sizeof(*rdata),
+ GFP_KERNEL);
if (!rdata)
return -ENOMEM;
- rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) *
- pdata->num_regulators, GFP_KERNEL);
+ rmode = devm_kcalloc(&pdev->dev,
+ pdata->num_regulators, sizeof(*rmode),
+ GFP_KERNEL);
if (!rmode)
return -ENOMEM;
diff --git a/drivers/regulator/ti-abb-regulator.c b/drivers/regulator/ti-abb-regulator.c
index d2f9942..cced1ff 100644
--- a/drivers/regulator/ti-abb-regulator.c
+++ b/drivers/regulator/ti-abb-regulator.c
@@ -532,13 +532,13 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb,
}
num_entries /= num_values;
- info = devm_kzalloc(dev, sizeof(*info) * num_entries, GFP_KERNEL);
+ info = devm_kcalloc(dev, num_entries, sizeof(*info), GFP_KERNEL);
if (!info)
return -ENOMEM;
abb->info = info;
- volt_table = devm_kzalloc(dev, sizeof(unsigned int) * num_entries,
+ volt_table = devm_kcalloc(dev, num_entries, sizeof(unsigned int),
GFP_KERNEL);
if (!volt_table)
return -ENOMEM;
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index 2d398fa..edaef9e 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -331,8 +331,9 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
if (!tps65090_pdata)
return ERR_PTR(-ENOMEM);
- reg_pdata = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX *
- sizeof(*reg_pdata), GFP_KERNEL);
+ reg_pdata = devm_kcalloc(&pdev->dev,
+ TPS65090_REGULATOR_MAX, sizeof(*reg_pdata),
+ GFP_KERNEL);
if (!reg_pdata)
return ERR_PTR(-ENOMEM);
@@ -429,8 +430,9 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
return tps65090_pdata ? PTR_ERR(tps65090_pdata) : -EINVAL;
}
- pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic),
- GFP_KERNEL);
+ pmic = devm_kcalloc(&pdev->dev,
+ TPS65090_REGULATOR_MAX, sizeof(*pmic),
+ GFP_KERNEL);
if (!pmic)
return -ENOMEM;
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c
index 7b12e88..fc12bad 100644
--- a/drivers/regulator/tps65217-regulator.c
+++ b/drivers/regulator/tps65217-regulator.c
@@ -229,8 +229,9 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
unsigned int val;
/* Allocate memory for strobes */
- tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) *
- TPS65217_NUM_REGULATOR, GFP_KERNEL);
+ tps->strobes = devm_kcalloc(&pdev->dev,
+ TPS65217_NUM_REGULATOR, sizeof(u8),
+ GFP_KERNEL);
platform_set_drvdata(pdev, tps);
diff --git a/drivers/regulator/tps65218-regulator.c b/drivers/regulator/tps65218-regulator.c
index 1827185..6209bee 100644
--- a/drivers/regulator/tps65218-regulator.c
+++ b/drivers/regulator/tps65218-regulator.c
@@ -324,8 +324,9 @@ static int tps65218_regulator_probe(struct platform_device *pdev)
config.regmap = tps->regmap;
/* Allocate memory for strobes */
- tps->strobes = devm_kzalloc(&pdev->dev, sizeof(u8) *
- TPS65218_NUM_REGULATOR, GFP_KERNEL);
+ tps->strobes = devm_kcalloc(&pdev->dev,
+ TPS65218_NUM_REGULATOR, sizeof(u8),
+ GFP_KERNEL);
if (!tps->strobes)
return -ENOMEM;
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index 81672a5..02ccdaa 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -1131,18 +1131,24 @@ static int tps65910_probe(struct platform_device *pdev)
return -ENODEV;
}
- pmic->desc = devm_kzalloc(&pdev->dev, pmic->num_regulators *
- sizeof(struct regulator_desc), GFP_KERNEL);
+ pmic->desc = devm_kcalloc(&pdev->dev,
+ pmic->num_regulators,
+ sizeof(struct regulator_desc),
+ GFP_KERNEL);
if (!pmic->desc)
return -ENOMEM;
- pmic->info = devm_kzalloc(&pdev->dev, pmic->num_regulators *
- sizeof(struct tps_info *), GFP_KERNEL);
+ pmic->info = devm_kcalloc(&pdev->dev,
+ pmic->num_regulators,
+ sizeof(struct tps_info *),
+ GFP_KERNEL);
if (!pmic->info)
return -ENOMEM;
- pmic->rdev = devm_kzalloc(&pdev->dev, pmic->num_regulators *
- sizeof(struct regulator_dev *), GFP_KERNEL);
+ pmic->rdev = devm_kcalloc(&pdev->dev,
+ pmic->num_regulators,
+ sizeof(struct regulator_dev *),
+ GFP_KERNEL);
if (!pmic->rdev)
return -ENOMEM;
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
index d4cc60a..1001147 100644
--- a/drivers/regulator/tps80031-regulator.c
+++ b/drivers/regulator/tps80031-regulator.c
@@ -691,8 +691,8 @@ static int tps80031_regulator_probe(struct platform_device *pdev)
return -EINVAL;
}
- pmic = devm_kzalloc(&pdev->dev,
- TPS80031_REGULATOR_MAX * sizeof(*pmic), GFP_KERNEL);
+ pmic = devm_kcalloc(&pdev->dev,
+ TPS80031_REGULATOR_MAX, sizeof(*pmic), GFP_KERNEL);
if (!pmic)
return -ENOMEM;
diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 0272740..cd1c168 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -24,7 +24,6 @@ config IMX_REMOTEPROC
config OMAP_REMOTEPROC
tristate "OMAP remoteproc support"
- depends on HAS_DMA
depends on ARCH_OMAP4 || SOC_OMAP5
depends on OMAP_IOMMU
select MAILBOX
diff --git a/drivers/remoteproc/da8xx_remoteproc.c b/drivers/remoteproc/da8xx_remoteproc.c
index bf3b903..b668e32 100644
--- a/drivers/remoteproc/da8xx_remoteproc.c
+++ b/drivers/remoteproc/da8xx_remoteproc.c
@@ -25,7 +25,7 @@
#include "remoteproc_internal.h"
static char *da8xx_fw_name;
-module_param(da8xx_fw_name, charp, S_IRUGO);
+module_param(da8xx_fw_name, charp, 0444);
MODULE_PARM_DESC(da8xx_fw_name,
"Name of DSP firmware file in /lib/firmware (if not specified defaults to 'rproc-dsp-fw')");
@@ -138,6 +138,7 @@ static int da8xx_rproc_start(struct rproc *rproc)
struct device *dev = rproc->dev.parent;
struct da8xx_rproc *drproc = (struct da8xx_rproc *)rproc->priv;
struct clk *dsp_clk = drproc->dsp_clk;
+ int ret;
/* hw requires the start (boot) address be on 1KB boundary */
if (rproc->bootaddr & 0x3ff) {
@@ -148,7 +149,12 @@ static int da8xx_rproc_start(struct rproc *rproc)
writel(rproc->bootaddr, drproc->bootreg);
- clk_enable(dsp_clk);
+ ret = clk_prepare_enable(dsp_clk);
+ if (ret) {
+ dev_err(dev, "clk_prepare_enable() failed: %d\n", ret);
+ return ret;
+ }
+
davinci_clk_reset_deassert(dsp_clk);
return 0;
@@ -159,7 +165,7 @@ static int da8xx_rproc_stop(struct rproc *rproc)
struct da8xx_rproc *drproc = rproc->priv;
davinci_clk_reset_assert(drproc->dsp_clk);
- clk_disable(drproc->dsp_clk);
+ clk_disable_unprepare(drproc->dsp_clk);
return 0;
}
diff --git a/drivers/remoteproc/qcom_q6v5_pil.c b/drivers/remoteproc/qcom_q6v5_pil.c
index cbbafdc..2bf8e7c 100644
--- a/drivers/remoteproc/qcom_q6v5_pil.c
+++ b/drivers/remoteproc/qcom_q6v5_pil.c
@@ -57,6 +57,8 @@
#define RMB_PMI_META_DATA_REG 0x10
#define RMB_PMI_CODE_START_REG 0x14
#define RMB_PMI_CODE_LENGTH_REG 0x18
+#define RMB_MBA_MSS_STATUS 0x40
+#define RMB_MBA_ALT_RESET 0x44
#define RMB_CMD_META_DATA_READY 0x1
#define RMB_CMD_LOAD_READY 0x2
@@ -104,6 +106,13 @@
#define QDSP6SS_XO_CBCR 0x0038
#define QDSP6SS_ACC_OVERRIDE_VAL 0x20
+/* QDSP6v65 parameters */
+#define QDSP6SS_SLEEP 0x3C
+#define QDSP6SS_BOOT_CORE_START 0x400
+#define QDSP6SS_BOOT_CMD 0x404
+#define SLEEP_CHECK_MAX_LOOPS 200
+#define BOOT_FSM_TIMEOUT 10000
+
struct reg_info {
struct regulator *reg;
int uV;
@@ -121,9 +130,11 @@ struct rproc_hexagon_res {
struct qcom_mss_reg_res *proxy_supply;
struct qcom_mss_reg_res *active_supply;
char **proxy_clk_names;
+ char **reset_clk_names;
char **active_clk_names;
int version;
bool need_mem_protection;
+ bool has_alt_reset;
};
struct q6v5 {
@@ -143,9 +154,15 @@ struct q6v5 {
struct qcom_smem_state *state;
unsigned stop_bit;
+ int handover_irq;
+
+ bool proxy_unvoted;
+
struct clk *active_clks[8];
+ struct clk *reset_clks[4];
struct clk *proxy_clks[4];
int active_clk_count;
+ int reset_clk_count;
int proxy_clk_count;
struct reg_info active_regs[1];
@@ -166,10 +183,12 @@ struct q6v5 {
void *mpss_region;
size_t mpss_size;
+ struct qcom_rproc_glink glink_subdev;
struct qcom_rproc_subdev smd_subdev;
struct qcom_rproc_ssr ssr_subdev;
struct qcom_sysmon *sysmon;
bool need_mem_protection;
+ bool has_alt_reset;
int mpss_perm;
int mba_perm;
int version;
@@ -179,6 +198,7 @@ enum {
MSS_MSM8916,
MSS_MSM8974,
MSS_MSM8996,
+ MSS_SDM845,
};
static int q6v5_regulator_init(struct device *dev, struct reg_info *regs,
@@ -333,6 +353,29 @@ static int q6v5_load(struct rproc *rproc, const struct firmware *fw)
return 0;
}
+static int q6v5_reset_assert(struct q6v5 *qproc)
+{
+ if (qproc->has_alt_reset)
+ return reset_control_reset(qproc->mss_restart);
+ else
+ return reset_control_assert(qproc->mss_restart);
+}
+
+static int q6v5_reset_deassert(struct q6v5 *qproc)
+{
+ int ret;
+
+ if (qproc->has_alt_reset) {
+ writel(1, qproc->rmb_base + RMB_MBA_ALT_RESET);
+ ret = reset_control_reset(qproc->mss_restart);
+ writel(0, qproc->rmb_base + RMB_MBA_ALT_RESET);
+ } else {
+ ret = reset_control_deassert(qproc->mss_restart);
+ }
+
+ return ret;
+}
+
static int q6v5_rmb_pbl_wait(struct q6v5 *qproc, int ms)
{
unsigned long timeout;
@@ -385,8 +428,35 @@ static int q6v5proc_reset(struct q6v5 *qproc)
int ret;
int i;
+ if (qproc->version == MSS_SDM845) {
+ val = readl(qproc->reg_base + QDSP6SS_SLEEP);
+ val |= 0x1;
+ writel(val, qproc->reg_base + QDSP6SS_SLEEP);
- if (qproc->version == MSS_MSM8996) {
+ ret = readl_poll_timeout(qproc->reg_base + QDSP6SS_SLEEP,
+ val, !(val & BIT(31)), 1,
+ SLEEP_CHECK_MAX_LOOPS);
+ if (ret) {
+ dev_err(qproc->dev, "QDSP6SS Sleep clock timed out\n");
+ return -ETIMEDOUT;
+ }
+
+ /* De-assert QDSP6 stop core */
+ writel(1, qproc->reg_base + QDSP6SS_BOOT_CORE_START);
+ /* Trigger boot FSM */
+ writel(1, qproc->reg_base + QDSP6SS_BOOT_CMD);
+
+ ret = readl_poll_timeout(qproc->rmb_base + RMB_MBA_MSS_STATUS,
+ val, (val & BIT(0)) != 0, 10, BOOT_FSM_TIMEOUT);
+ if (ret) {
+ dev_err(qproc->dev, "Boot FSM failed to complete.\n");
+ /* Reset the modem so that boot FSM is in reset state */
+ q6v5_reset_deassert(qproc);
+ return ret;
+ }
+
+ goto pbl_wait;
+ } else if (qproc->version == MSS_MSM8996) {
/* Override the ACC value if required */
writel(QDSP6SS_ACC_OVERRIDE_VAL,
qproc->reg_base + QDSP6SS_STRAP_ACC);
@@ -494,6 +564,7 @@ static int q6v5proc_reset(struct q6v5 *qproc)
val &= ~Q6SS_STOP_CORE;
writel(val, qproc->reg_base + QDSP6SS_RESET_REG);
+pbl_wait:
/* Wait for PBL status */
ret = q6v5_rmb_pbl_wait(qproc, 1000);
if (ret == -ETIMEDOUT) {
@@ -615,7 +686,7 @@ static int q6v5_mpss_load(struct q6v5 *qproc)
struct elf32_hdr *ehdr;
phys_addr_t mpss_reloc;
phys_addr_t boot_addr;
- phys_addr_t min_addr = (phys_addr_t)ULLONG_MAX;
+ phys_addr_t min_addr = PHYS_ADDR_MAX;
phys_addr_t max_addr = 0;
bool relocate = false;
char seg_name[10];
@@ -727,11 +798,15 @@ static int q6v5_start(struct rproc *rproc)
int xfermemop_ret;
int ret;
+ qproc->proxy_unvoted = false;
+
+ enable_irq(qproc->handover_irq);
+
ret = q6v5_regulator_enable(qproc, qproc->proxy_regs,
qproc->proxy_reg_count);
if (ret) {
dev_err(qproc->dev, "failed to enable proxy supplies\n");
- return ret;
+ goto disable_irqs;
}
ret = q6v5_clk_enable(qproc->dev, qproc->proxy_clks,
@@ -747,12 +822,20 @@ static int q6v5_start(struct rproc *rproc)
dev_err(qproc->dev, "failed to enable supplies\n");
goto disable_proxy_clk;
}
- ret = reset_control_deassert(qproc->mss_restart);
+
+ ret = q6v5_clk_enable(qproc->dev, qproc->reset_clks,
+ qproc->reset_clk_count);
if (ret) {
- dev_err(qproc->dev, "failed to deassert mss restart\n");
+ dev_err(qproc->dev, "failed to enable reset clocks\n");
goto disable_vdd;
}
+ ret = q6v5_reset_deassert(qproc);
+ if (ret) {
+ dev_err(qproc->dev, "failed to deassert mss restart\n");
+ goto disable_reset_clks;
+ }
+
ret = q6v5_clk_enable(qproc->dev, qproc->active_clks,
qproc->active_clk_count);
if (ret) {
@@ -761,13 +844,11 @@ static int q6v5_start(struct rproc *rproc)
}
/* Assign MBA image access in DDR to q6 */
- xfermemop_ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true,
- qproc->mba_phys,
- qproc->mba_size);
- if (xfermemop_ret) {
+ ret = q6v5_xfer_mem_ownership(qproc, &qproc->mba_perm, true,
+ qproc->mba_phys, qproc->mba_size);
+ if (ret) {
dev_err(qproc->dev,
- "assigning Q6 access to mba memory failed: %d\n",
- xfermemop_ret);
+ "assigning Q6 access to mba memory failed: %d\n", ret);
goto disable_active_clks;
}
@@ -810,11 +891,6 @@ static int q6v5_start(struct rproc *rproc)
"Failed to reclaim mba buffer system may become unstable\n");
qproc->running = true;
- q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
- qproc->proxy_clk_count);
- q6v5_regulator_disable(qproc, qproc->proxy_regs,
- qproc->proxy_reg_count);
-
return 0;
reclaim_mpss:
@@ -842,7 +918,10 @@ disable_active_clks:
qproc->active_clk_count);
assert_reset:
- reset_control_assert(qproc->mss_restart);
+ q6v5_reset_assert(qproc);
+disable_reset_clks:
+ q6v5_clk_disable(qproc->dev, qproc->reset_clks,
+ qproc->reset_clk_count);
disable_vdd:
q6v5_regulator_disable(qproc, qproc->active_regs,
qproc->active_reg_count);
@@ -853,6 +932,9 @@ disable_proxy_reg:
q6v5_regulator_disable(qproc, qproc->proxy_regs,
qproc->proxy_reg_count);
+disable_irqs:
+ disable_irq(qproc->handover_irq);
+
return ret;
}
@@ -892,7 +974,19 @@ static int q6v5_stop(struct rproc *rproc)
qproc->mpss_phys, qproc->mpss_size);
WARN_ON(ret);
- reset_control_assert(qproc->mss_restart);
+ q6v5_reset_assert(qproc);
+
+ disable_irq(qproc->handover_irq);
+
+ if (!qproc->proxy_unvoted) {
+ q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
+ qproc->proxy_clk_count);
+ q6v5_regulator_disable(qproc, qproc->proxy_regs,
+ qproc->proxy_reg_count);
+ }
+
+ q6v5_clk_disable(qproc->dev, qproc->reset_clks,
+ qproc->reset_clk_count);
q6v5_clk_disable(qproc->dev, qproc->active_clks,
qproc->active_clk_count);
q6v5_regulator_disable(qproc, qproc->active_regs,
@@ -960,7 +1054,7 @@ static irqreturn_t q6v5_fatal_interrupt(int irq, void *dev)
return IRQ_HANDLED;
}
-static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
+static irqreturn_t q6v5_ready_interrupt(int irq, void *dev)
{
struct q6v5 *qproc = dev;
@@ -968,6 +1062,20 @@ static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
return IRQ_HANDLED;
}
+static irqreturn_t q6v5_handover_interrupt(int irq, void *dev)
+{
+ struct q6v5 *qproc = dev;
+
+ q6v5_clk_disable(qproc->dev, qproc->proxy_clks,
+ qproc->proxy_clk_count);
+ q6v5_regulator_disable(qproc, qproc->proxy_regs,
+ qproc->proxy_reg_count);
+
+ qproc->proxy_unvoted = true;
+
+ return IRQ_HANDLED;
+}
+
static irqreturn_t q6v5_stop_ack_interrupt(int irq, void *dev)
{
struct q6v5 *qproc = dev;
@@ -1051,22 +1159,23 @@ static int q6v5_request_irq(struct q6v5 *qproc,
const char *name,
irq_handler_t thread_fn)
{
+ int irq;
int ret;
- ret = platform_get_irq_byname(pdev, name);
- if (ret < 0) {
+ irq = platform_get_irq_byname(pdev, name);
+ if (irq < 0) {
dev_err(&pdev->dev, "no %s IRQ defined\n", name);
- return ret;
+ return irq;
}
- ret = devm_request_threaded_irq(&pdev->dev, ret,
+ ret = devm_request_threaded_irq(&pdev->dev, irq,
NULL, thread_fn,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
"q6v5", qproc);
if (ret)
dev_err(&pdev->dev, "request %s IRQ failed\n", name);
- return ret;
+ return ret ? : irq;
}
static int q6v5_alloc_memory_region(struct q6v5 *qproc)
@@ -1157,6 +1266,14 @@ static int q6v5_probe(struct platform_device *pdev)
}
qproc->proxy_clk_count = ret;
+ ret = q6v5_init_clocks(&pdev->dev, qproc->reset_clks,
+ desc->reset_clk_names);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to get reset clocks.\n");
+ goto free_rproc;
+ }
+ qproc->reset_clk_count = ret;
+
ret = q6v5_init_clocks(&pdev->dev, qproc->active_clks,
desc->active_clk_names);
if (ret < 0) {
@@ -1186,6 +1303,7 @@ static int q6v5_probe(struct platform_device *pdev)
goto free_rproc;
qproc->version = desc->version;
+ qproc->has_alt_reset = desc->has_alt_reset;
qproc->need_mem_protection = desc->need_mem_protection;
ret = q6v5_request_irq(qproc, pdev, "wdog", q6v5_wdog_interrupt);
if (ret < 0)
@@ -1195,9 +1313,15 @@ static int q6v5_probe(struct platform_device *pdev)
if (ret < 0)
goto free_rproc;
+ ret = q6v5_request_irq(qproc, pdev, "ready", q6v5_ready_interrupt);
+ if (ret < 0)
+ goto free_rproc;
+
ret = q6v5_request_irq(qproc, pdev, "handover", q6v5_handover_interrupt);
if (ret < 0)
goto free_rproc;
+ qproc->handover_irq = ret;
+ disable_irq(qproc->handover_irq);
ret = q6v5_request_irq(qproc, pdev, "stop-ack", q6v5_stop_ack_interrupt);
if (ret < 0)
@@ -1210,6 +1334,7 @@ static int q6v5_probe(struct platform_device *pdev)
}
qproc->mpss_perm = BIT(QCOM_SCM_VMID_HLOS);
qproc->mba_perm = BIT(QCOM_SCM_VMID_HLOS);
+ qcom_add_glink_subdev(rproc, &qproc->glink_subdev);
qcom_add_smd_subdev(rproc, &qproc->smd_subdev);
qcom_add_ssr_subdev(rproc, &qproc->ssr_subdev, "mpss");
qproc->sysmon = qcom_add_sysmon_subdev(rproc, "modem", 0x12);
@@ -1233,6 +1358,7 @@ static int q6v5_remove(struct platform_device *pdev)
rproc_del(qproc->rproc);
qcom_remove_sysmon_subdev(qproc->sysmon);
+ qcom_remove_glink_subdev(qproc->rproc, &qproc->glink_subdev);
qcom_remove_smd_subdev(qproc->rproc, &qproc->smd_subdev);
qcom_remove_ssr_subdev(qproc->rproc, &qproc->ssr_subdev);
rproc_free(qproc->rproc);
@@ -1240,6 +1366,31 @@ static int q6v5_remove(struct platform_device *pdev)
return 0;
}
+static const struct rproc_hexagon_res sdm845_mss = {
+ .hexagon_mba_image = "mba.mbn",
+ .proxy_clk_names = (char*[]){
+ "xo",
+ "axis2",
+ "prng",
+ NULL
+ },
+ .reset_clk_names = (char*[]){
+ "iface",
+ "snoc_axi",
+ NULL
+ },
+ .active_clk_names = (char*[]){
+ "bus",
+ "mem",
+ "gpll0_mss",
+ "mnoc_axi",
+ NULL
+ },
+ .need_mem_protection = true,
+ .has_alt_reset = true,
+ .version = MSS_SDM845,
+};
+
static const struct rproc_hexagon_res msm8996_mss = {
.hexagon_mba_image = "mba.mbn",
.proxy_clk_names = (char*[]){
@@ -1255,6 +1406,7 @@ static const struct rproc_hexagon_res msm8996_mss = {
NULL
},
.need_mem_protection = true,
+ .has_alt_reset = false,
.version = MSS_MSM8996,
};
@@ -1286,6 +1438,7 @@ static const struct rproc_hexagon_res msm8916_mss = {
NULL
},
.need_mem_protection = false,
+ .has_alt_reset = false,
.version = MSS_MSM8916,
};
@@ -1325,6 +1478,7 @@ static const struct rproc_hexagon_res msm8974_mss = {
NULL
},
.need_mem_protection = false,
+ .has_alt_reset = false,
.version = MSS_MSM8974,
};
@@ -1333,6 +1487,7 @@ static const struct of_device_id q6v5_of_match[] = {
{ .compatible = "qcom,msm8916-mss-pil", .data = &msm8916_mss},
{ .compatible = "qcom,msm8974-mss-pil", .data = &msm8974_mss},
{ .compatible = "qcom,msm8996-mss-pil", .data = &msm8996_mss},
+ { .compatible = "qcom,sdm845-mss-pil", .data = &sdm845_mss},
{ },
};
MODULE_DEVICE_TABLE(of, q6v5_of_match);
diff --git a/drivers/reset/reset-ti-syscon.c b/drivers/reset/reset-ti-syscon.c
index 99520b0..a2635c2 100644
--- a/drivers/reset/reset-ti-syscon.c
+++ b/drivers/reset/reset-ti-syscon.c
@@ -189,7 +189,8 @@ static int ti_syscon_reset_probe(struct platform_device *pdev)
}
nr_controls = (size / sizeof(*list)) / 7;
- controls = devm_kzalloc(dev, nr_controls * sizeof(*controls), GFP_KERNEL);
+ controls = devm_kcalloc(dev, nr_controls, sizeof(*controls),
+ GFP_KERNEL);
if (!controls)
return -ENOMEM;
diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c
index ac18f2f..e9030ff 100644
--- a/drivers/reset/reset-uniphier.c
+++ b/drivers/reset/reset-uniphier.c
@@ -63,6 +63,9 @@ static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (Ether, SATA, USB3) */
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */
+ UNIPHIER_RESETX(28, 0x2000, 18), /* SATA0 */
+ UNIPHIER_RESETX(29, 0x2004, 18), /* SATA1 */
+ UNIPHIER_RESETX(30, 0x2000, 19), /* SATA-PHY */
UNIPHIER_RESETX(40, 0x2000, 13), /* AIO */
UNIPHIER_RESET_END,
};
@@ -73,6 +76,7 @@ static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (PCIe, USB3) */
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */
+ UNIPHIER_RESETX(24, 0x2008, 2), /* PCIe */
UNIPHIER_RESETX(40, 0x2000, 13), /* AIO */
UNIPHIER_RESET_END,
};
@@ -89,7 +93,7 @@ static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
UNIPHIER_RESETX(20, 0x2014, 5), /* USB31-PHY0 */
UNIPHIER_RESETX(21, 0x2014, 1), /* USB31-PHY1 */
UNIPHIER_RESETX(28, 0x2014, 12), /* SATA */
- UNIPHIER_RESET(29, 0x2014, 8), /* SATA-PHY (active high) */
+ UNIPHIER_RESET(30, 0x2014, 8), /* SATA-PHY (active high) */
UNIPHIER_RESETX(40, 0x2000, 13), /* AIO */
UNIPHIER_RESET_END,
};
@@ -99,6 +103,7 @@ static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */
UNIPHIER_RESETX(6, 0x200c, 6), /* Ether */
UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC, MIO) */
+ UNIPHIER_RESETX(9, 0x200c, 9), /* HSC */
UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */
UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */
UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */
@@ -110,11 +115,13 @@ static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */
UNIPHIER_RESETX(6, 0x200c, 6), /* Ether */
UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC) */
+ UNIPHIER_RESETX(9, 0x200c, 9), /* HSC */
UNIPHIER_RESETX(14, 0x200c, 5), /* USB30 */
UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */
UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */
UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */
UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */
+ UNIPHIER_RESETX(24, 0x200c, 4), /* PCIe */
UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */
UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */
UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */
@@ -134,6 +141,10 @@ static const struct uniphier_reset_data uniphier_pxs3_sys_reset_data[] = {
UNIPHIER_RESETX(18, 0x200c, 20), /* USB30-PHY2 */
UNIPHIER_RESETX(20, 0x200c, 17), /* USB31-PHY0 */
UNIPHIER_RESETX(21, 0x200c, 19), /* USB31-PHY1 */
+ UNIPHIER_RESETX(24, 0x200c, 3), /* PCIe */
+ UNIPHIER_RESETX(28, 0x200c, 7), /* SATA0 */
+ UNIPHIER_RESETX(29, 0x200c, 8), /* SATA1 */
+ UNIPHIER_RESETX(30, 0x200c, 21), /* SATA-PHY */
UNIPHIER_RESET_END,
};
diff --git a/drivers/rpmsg/Kconfig b/drivers/rpmsg/Kconfig
index 65a9f6b..d0322b4 100644
--- a/drivers/rpmsg/Kconfig
+++ b/drivers/rpmsg/Kconfig
@@ -1,3 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0
+
menu "Rpmsg drivers"
# RPMSG always gets selected by whoever wants it
@@ -39,6 +41,7 @@ config RPMSG_QCOM_GLINK_SMEM
config RPMSG_QCOM_SMD
tristate "Qualcomm Shared Memory Driver (SMD)"
+ depends on MAILBOX
depends on QCOM_SMEM
select RPMSG
help
diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c
index 768ef54..f505f58 100644
--- a/drivers/rpmsg/qcom_glink_native.c
+++ b/drivers/rpmsg/qcom_glink_native.c
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016-2017, Linaro Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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/idr.h>
diff --git a/drivers/rpmsg/qcom_glink_native.h b/drivers/rpmsg/qcom_glink_native.h
index 0cae8a8..624184f 100644
--- a/drivers/rpmsg/qcom_glink_native.h
+++ b/drivers/rpmsg/qcom_glink_native.h
@@ -1,14 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2016-2017, Linaro Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 __QCOM_GLINK_NATIVE_H__
diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c
index 69b25d1..f64f45d 100644
--- a/drivers/rpmsg/qcom_glink_rpm.c
+++ b/drivers/rpmsg/qcom_glink_rpm.c
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016-2017, Linaro Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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/idr.h>
diff --git a/drivers/rpmsg/qcom_glink_smem.c b/drivers/rpmsg/qcom_glink_smem.c
index 3fa9d43..2b5cf27 100644
--- a/drivers/rpmsg/qcom_glink_smem.c
+++ b/drivers/rpmsg/qcom_glink_smem.c
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016, Linaro Ltd
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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/io.h>
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index 5ce9bf7..6437bbe 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -1,19 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015, Sony Mobile Communications AB.
* Copyright (c) 2012-2013, The Linux Foundation. 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 and
- * only 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/interrupt.h>
#include <linux/io.h>
+#include <linux/mailbox_client.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_irq.h>
@@ -107,6 +100,8 @@ static const struct {
* @ipc_regmap: regmap handle holding the outgoing ipc register
* @ipc_offset: offset within @ipc_regmap of the register for ipc
* @ipc_bit: bit in the register at @ipc_offset of @ipc_regmap
+ * @mbox_client: mailbox client handle
+ * @mbox_chan: apcs ipc mailbox channel handle
* @channels: list of all channels detected on this edge
* @channels_lock: guard for modifications of @channels
* @allocated: array of bitmaps representing already allocated channels
@@ -129,6 +124,9 @@ struct qcom_smd_edge {
int ipc_offset;
int ipc_bit;
+ struct mbox_client mbox_client;
+ struct mbox_chan *mbox_chan;
+
struct list_head channels;
spinlock_t channels_lock;
@@ -366,7 +364,17 @@ static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)
{
struct qcom_smd_edge *edge = channel->edge;
- regmap_write(edge->ipc_regmap, edge->ipc_offset, BIT(edge->ipc_bit));
+ if (edge->mbox_chan) {
+ /*
+ * We can ignore a failing mbox_send_message() as the only
+ * possible cause is that the FIFO in the framework is full of
+ * other writes to the same bit.
+ */
+ mbox_send_message(edge->mbox_chan, NULL);
+ mbox_client_txdone(edge->mbox_chan, 0);
+ } else {
+ regmap_write(edge->ipc_regmap, edge->ipc_offset, BIT(edge->ipc_bit));
+ }
}
/*
@@ -1100,12 +1108,12 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
void *info;
int ret;
- channel = devm_kzalloc(&edge->dev, sizeof(*channel), GFP_KERNEL);
+ channel = kzalloc(sizeof(*channel), GFP_KERNEL);
if (!channel)
return ERR_PTR(-ENOMEM);
channel->edge = edge;
- channel->name = devm_kstrdup(&edge->dev, name, GFP_KERNEL);
+ channel->name = kstrdup(name, GFP_KERNEL);
if (!channel->name)
return ERR_PTR(-ENOMEM);
@@ -1156,8 +1164,8 @@ static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *ed
return channel;
free_name_and_channel:
- devm_kfree(&edge->dev, channel->name);
- devm_kfree(&edge->dev, channel);
+ kfree(channel->name);
+ kfree(channel);
return ERR_PTR(ret);
}
@@ -1326,27 +1334,37 @@ static int qcom_smd_parse_edge(struct device *dev,
key = "qcom,remote-pid";
of_property_read_u32(node, key, &edge->remote_pid);
- syscon_np = of_parse_phandle(node, "qcom,ipc", 0);
- if (!syscon_np) {
- dev_err(dev, "no qcom,ipc node\n");
- return -ENODEV;
- }
+ edge->mbox_client.dev = dev;
+ edge->mbox_client.knows_txdone = true;
+ edge->mbox_chan = mbox_request_channel(&edge->mbox_client, 0);
+ if (IS_ERR(edge->mbox_chan)) {
+ if (PTR_ERR(edge->mbox_chan) != -ENODEV)
+ return PTR_ERR(edge->mbox_chan);
- edge->ipc_regmap = syscon_node_to_regmap(syscon_np);
- if (IS_ERR(edge->ipc_regmap))
- return PTR_ERR(edge->ipc_regmap);
+ edge->mbox_chan = NULL;
- key = "qcom,ipc";
- ret = of_property_read_u32_index(node, key, 1, &edge->ipc_offset);
- if (ret < 0) {
- dev_err(dev, "no offset in %s\n", key);
- return -EINVAL;
- }
+ syscon_np = of_parse_phandle(node, "qcom,ipc", 0);
+ if (!syscon_np) {
+ dev_err(dev, "no qcom,ipc node\n");
+ return -ENODEV;
+ }
- ret = of_property_read_u32_index(node, key, 2, &edge->ipc_bit);
- if (ret < 0) {
- dev_err(dev, "no bit in %s\n", key);
- return -EINVAL;
+ edge->ipc_regmap = syscon_node_to_regmap(syscon_np);
+ if (IS_ERR(edge->ipc_regmap))
+ return PTR_ERR(edge->ipc_regmap);
+
+ key = "qcom,ipc";
+ ret = of_property_read_u32_index(node, key, 1, &edge->ipc_offset);
+ if (ret < 0) {
+ dev_err(dev, "no offset in %s\n", key);
+ return -EINVAL;
+ }
+
+ ret = of_property_read_u32_index(node, key, 2, &edge->ipc_bit);
+ if (ret < 0) {
+ dev_err(dev, "no bit in %s\n", key);
+ return -EINVAL;
+ }
}
ret = of_property_read_string(node, "label", &edge->name);
@@ -1378,13 +1396,13 @@ static int qcom_smd_parse_edge(struct device *dev,
*/
static void qcom_smd_edge_release(struct device *dev)
{
- struct qcom_smd_channel *channel;
+ struct qcom_smd_channel *channel, *tmp;
struct qcom_smd_edge *edge = to_smd_edge(dev);
- list_for_each_entry(channel, &edge->channels, list) {
- SET_RX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED);
- SET_RX_CHANNEL_INFO(channel, head, 0);
- SET_RX_CHANNEL_INFO(channel, tail, 0);
+ list_for_each_entry_safe(channel, tmp, &edge->channels, list) {
+ list_del(&channel->list);
+ kfree(channel->name);
+ kfree(channel);
}
kfree(edge);
@@ -1453,6 +1471,9 @@ struct qcom_smd_edge *qcom_smd_register_edge(struct device *parent,
return edge;
unregister_dev:
+ if (!IS_ERR_OR_NULL(edge->mbox_chan))
+ mbox_free_channel(edge->mbox_chan);
+
device_unregister(&edge->dev);
return ERR_PTR(ret);
}
@@ -1481,6 +1502,7 @@ int qcom_smd_unregister_edge(struct qcom_smd_edge *edge)
if (ret)
dev_warn(&edge->dev, "can't remove smd device: %d\n", ret);
+ mbox_free_channel(edge->mbox_chan);
device_unregister(&edge->dev);
return 0;
diff --git a/drivers/rpmsg/rpmsg_char.c b/drivers/rpmsg/rpmsg_char.c
index 1efdf9f..76a4477 100644
--- a/drivers/rpmsg/rpmsg_char.c
+++ b/drivers/rpmsg/rpmsg_char.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016, Linaro Ltd.
* Copyright (c) 2012, Michal Simek <monstr@monstr.eu>
@@ -7,15 +8,6 @@
*
* Based on rpmsg performance statistics driver by Michal Simek, which in turn
* was based on TI & Google OMX rpmsg driver.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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/cdev.h>
#include <linux/device.h>
diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c
index 920a02f..b714a54 100644
--- a/drivers/rpmsg/rpmsg_core.c
+++ b/drivers/rpmsg/rpmsg_core.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* remote processor messaging bus
*
@@ -6,15 +7,6 @@
*
* Ohad Ben-Cohen <ohad@wizery.com>
* Brian Swetland <swetland@google.com>
- *
- * 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__
@@ -333,11 +325,49 @@ field##_show(struct device *dev, \
} \
static DEVICE_ATTR_RO(field);
+#define rpmsg_string_attr(field, member) \
+static ssize_t \
+field##_store(struct device *dev, struct device_attribute *attr, \
+ const char *buf, size_t sz) \
+{ \
+ struct rpmsg_device *rpdev = to_rpmsg_device(dev); \
+ char *new, *old; \
+ \
+ new = kstrndup(buf, sz, GFP_KERNEL); \
+ if (!new) \
+ return -ENOMEM; \
+ new[strcspn(new, "\n")] = '\0'; \
+ \
+ device_lock(dev); \
+ old = rpdev->member; \
+ if (strlen(new)) { \
+ rpdev->member = new; \
+ } else { \
+ kfree(new); \
+ rpdev->member = NULL; \
+ } \
+ device_unlock(dev); \
+ \
+ kfree(old); \
+ \
+ return sz; \
+} \
+static ssize_t \
+field##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct rpmsg_device *rpdev = to_rpmsg_device(dev); \
+ \
+ return sprintf(buf, "%s\n", rpdev->member); \
+} \
+static DEVICE_ATTR_RW(field)
+
/* for more info, see Documentation/ABI/testing/sysfs-bus-rpmsg */
rpmsg_show_attr(name, id.name, "%s\n");
rpmsg_show_attr(src, src, "0x%x\n");
rpmsg_show_attr(dst, dst, "0x%x\n");
rpmsg_show_attr(announce, announce ? "true" : "false", "%s\n");
+rpmsg_string_attr(driver_override, driver_override);
static ssize_t modalias_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -359,6 +389,7 @@ static struct attribute *rpmsg_dev_attrs[] = {
&dev_attr_dst.attr,
&dev_attr_src.attr,
&dev_attr_announce.attr,
+ &dev_attr_driver_override.attr,
NULL,
};
ATTRIBUTE_GROUPS(rpmsg_dev);
diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h
index 685aa70..0d791c3 100644
--- a/drivers/rpmsg/rpmsg_internal.h
+++ b/drivers/rpmsg/rpmsg_internal.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* remote processor messaging bus internals
*
@@ -6,15 +7,6 @@
*
* Ohad Ben-Cohen <ohad@wizery.com>
* Brian Swetland <swetland@google.com>
- *
- * 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 __RPMSG_INTERNAL_H__
diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c
index 82b8300..664f957 100644
--- a/drivers/rpmsg/virtio_rpmsg_bus.c
+++ b/drivers/rpmsg/virtio_rpmsg_bus.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Virtio-based remote processor messaging bus
*
@@ -6,15 +7,6 @@
*
* Ohad Ben-Cohen <ohad@wizery.com>
* Brian Swetland <swetland@google.com>
- *
- * 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__
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 59e6ded..a2ba5db 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1613,7 +1613,7 @@ config RTC_DRV_JZ4740
If you say yes here you get support for the Ingenic JZ47xx SoCs RTC
controllers.
- This driver can also be buillt as a module. If so, the module
+ This driver can also be built as a module. If so, the module
will be called rtc-jz4740.
config RTC_DRV_LPC24XX
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 7cbdc92..6d4012d 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -441,6 +441,11 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
int err;
+ if (!rtc->ops)
+ return -ENODEV;
+ else if (!rtc->ops->set_alarm)
+ return -EINVAL;
+
err = rtc_valid_tm(&alarm->time);
if (err != 0)
return err;
diff --git a/drivers/rtc/nvmem.c b/drivers/rtc/nvmem.c
index 17ec4c8d..36ab183 100644
--- a/drivers/rtc/nvmem.c
+++ b/drivers/rtc/nvmem.c
@@ -94,7 +94,7 @@ int rtc_nvmem_register(struct rtc_device *rtc,
nvmem_config->dev = rtc->dev.parent;
nvmem_config->owner = rtc->owner;
rtc->nvmem = nvmem_register(nvmem_config);
- if (IS_ERR_OR_NULL(rtc->nvmem))
+ if (IS_ERR(rtc->nvmem))
return PTR_ERR(rtc->nvmem);
/* Register the old ABI */
diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c
index 6cbafef..cab293c 100644
--- a/drivers/rtc/rtc-88pm80x.c
+++ b/drivers/rtc/rtc-88pm80x.c
@@ -52,10 +52,8 @@ struct pm80x_rtc_info {
struct regmap *map;
struct rtc_device *rtc_dev;
struct device *dev;
- struct delayed_work calib_work;
int irq;
- int vrtc;
};
static irqreturn_t rtc_update_handler(int irq, void *data)
@@ -100,13 +98,13 @@ static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
next->tm_min = alrm->tm_min;
next->tm_sec = alrm->tm_sec;
- rtc_tm_to_time(now, &now_time);
- rtc_tm_to_time(next, &next_time);
+ now_time = rtc_tm_to_time64(now);
+ next_time = rtc_tm_to_time64(next);
if (next_time < now_time) {
/* Advance one day */
next_time += 60 * 60 * 24;
- rtc_time_to_tm(next_time, next);
+ rtc_time64_to_tm(next_time, next);
}
}
@@ -125,7 +123,7 @@ static int pm80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
ticks = base + data;
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
base, data, ticks);
- rtc_time_to_tm(ticks, tm);
+ rtc_time64_to_tm(ticks, tm);
return 0;
}
@@ -134,13 +132,8 @@ static int pm80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
struct pm80x_rtc_info *info = dev_get_drvdata(dev);
unsigned char buf[4];
unsigned long ticks, base, data;
- if (tm->tm_year > 206) {
- dev_dbg(info->dev,
- "Set time %d out of range. Please set time between 1970 to 2106.\n",
- 1900 + tm->tm_year);
- return -EINVAL;
- }
- rtc_tm_to_time(tm, &ticks);
+
+ ticks = rtc_tm_to_time64(tm);
/* load 32-bit read-only counter */
regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4);
@@ -174,7 +167,7 @@ static int pm80x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
base, data, ticks);
- rtc_time_to_tm(ticks, &alrm->time);
+ rtc_time64_to_tm(ticks, &alrm->time);
regmap_read(info->map, PM800_RTC_CONTROL, &ret);
alrm->enabled = (ret & PM800_ALARM1_EN) ? 1 : 0;
alrm->pending = (ret & (PM800_ALARM | PM800_ALARM_WAKEUP)) ? 1 : 0;
@@ -202,11 +195,11 @@ static int pm80x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
base, data, ticks);
- rtc_time_to_tm(ticks, &now_tm);
+ rtc_time64_to_tm(ticks, &now_tm);
dev_dbg(info->dev, "%s, now time : %lu\n", __func__, ticks);
rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
/* get new ticks for alarm in 24 hours */
- rtc_tm_to_time(&alarm_tm, &ticks);
+ ticks = rtc_tm_to_time64(&alarm_tm);
dev_dbg(info->dev, "%s, alarm time: %lu\n", __func__, ticks);
data = ticks - base;
@@ -254,8 +247,6 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
struct pm80x_rtc_pdata *pdata = dev_get_platdata(&pdev->dev);
struct pm80x_rtc_info *info;
struct device_node *node = pdev->dev.of_node;
- struct rtc_time tm;
- unsigned long ticks = 0;
int ret;
if (!pdata && !node) {
@@ -294,6 +285,10 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
info->dev = &pdev->dev;
dev_set_drvdata(&pdev->dev, info);
+ info->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(info->rtc_dev))
+ return PTR_ERR(info->rtc_dev);
+
ret = pm80x_request_irq(chip, info->irq, rtc_update_handler,
IRQF_ONESHOT, "rtc", info);
if (ret < 0) {
@@ -302,30 +297,11 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
goto out;
}
- ret = pm80x_rtc_read_time(&pdev->dev, &tm);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to read initial time.\n");
- goto out_rtc;
- }
- if ((tm.tm_year < 70) || (tm.tm_year > 138)) {
- tm.tm_year = 70;
- tm.tm_mon = 0;
- tm.tm_mday = 1;
- tm.tm_hour = 0;
- tm.tm_min = 0;
- tm.tm_sec = 0;
- ret = pm80x_rtc_set_time(&pdev->dev, &tm);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to set initial time.\n");
- goto out_rtc;
- }
- }
- rtc_tm_to_time(&tm, &ticks);
+ info->rtc_dev->ops = &pm80x_rtc_ops;
+ info->rtc_dev->range_max = U32_MAX;
- info->rtc_dev = devm_rtc_device_register(&pdev->dev, "88pm80x-rtc",
- &pm80x_rtc_ops, THIS_MODULE);
- if (IS_ERR(info->rtc_dev)) {
- ret = PTR_ERR(info->rtc_dev);
+ ret = rtc_register_device(info->rtc_dev);
+ if (ret) {
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
goto out_rtc;
}
diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c
index 8dc4519..2233601 100644
--- a/drivers/rtc/rtc-ab-b5ze-s3.c
+++ b/drivers/rtc/rtc-ab-b5ze-s3.c
@@ -265,15 +265,6 @@ static int abb5zes3_rtc_set_time(struct device *dev, struct rtc_time *tm)
u8 regs[ABB5ZES3_REG_RTC_SC + ABB5ZES3_RTC_SEC_LEN];
int ret;
- /*
- * Year register is 8-bit wide and bcd-coded, i.e records values
- * between 0 and 99. tm_year is an offset from 1900 and we are
- * interested in the 2000-2099 range, so any value less than 100
- * is invalid.
- */
- if (tm->tm_year < 100)
- return -EINVAL;
-
regs[ABB5ZES3_REG_RTC_SC] = bin2bcd(tm->tm_sec); /* MSB=0 clears OSC */
regs[ABB5ZES3_REG_RTC_MN] = bin2bcd(tm->tm_min);
regs[ABB5ZES3_REG_RTC_HR] = bin2bcd(tm->tm_hour); /* 24-hour format */
@@ -925,6 +916,14 @@ static int abb5zes3_probe(struct i2c_client *client,
if (ret)
goto err;
+ data->rtc = devm_rtc_allocate_device(dev);
+ ret = PTR_ERR_OR_ZERO(data->rtc);
+ if (ret) {
+ dev_err(dev, "%s: unable to allocate RTC device (%d)\n",
+ __func__, ret);
+ goto err;
+ }
+
if (client->irq > 0) {
ret = devm_request_threaded_irq(dev, client->irq, NULL,
_abb5zes3_rtc_interrupt,
@@ -942,14 +941,9 @@ static int abb5zes3_probe(struct i2c_client *client,
}
}
- data->rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops,
- THIS_MODULE);
- ret = PTR_ERR_OR_ZERO(data->rtc);
- if (ret) {
- dev_err(dev, "%s: unable to register RTC device (%d)\n",
- __func__, ret);
- goto err;
- }
+ data->rtc->ops = &rtc_ops;
+ data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ data->rtc->range_max = RTC_TIMESTAMP_END_2099;
/* Enable battery low detection interrupt if battery not already low */
if (!data->battery_low && data->irq) {
@@ -961,6 +955,8 @@ static int abb5zes3_probe(struct i2c_client *client,
}
}
+ ret = rtc_register_device(data->rtc);
+
err:
if (ret && data && data->irq)
device_init_wakeup(dev, false);
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index de81ece..caa71d0 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -440,6 +440,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1);
rtc->ops = &at91_rtc_ops;
+ rtc->range_min = RTC_TIMESTAMP_BEGIN_1900;
+ rtc->range_max = RTC_TIMESTAMP_END_2099;
ret = rtc_register_device(rtc);
if (ret)
goto err_clk;
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c
index bd170cb..d768f67 100644
--- a/drivers/rtc/rtc-bq4802.c
+++ b/drivers/rtc/rtc-bq4802.c
@@ -48,8 +48,7 @@ static void bq4802_write_mem(struct bq4802 *p, int off, u8 val)
static int bq4802_read_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct bq4802 *p = platform_get_drvdata(pdev);
+ struct bq4802 *p = dev_get_drvdata(dev);
unsigned long flags;
unsigned int century;
u8 val;
@@ -91,8 +90,7 @@ static int bq4802_read_time(struct device *dev, struct rtc_time *tm)
static int bq4802_set_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct bq4802 *p = platform_get_drvdata(pdev);
+ struct bq4802 *p = dev_get_drvdata(dev);
u8 sec, min, hrs, day, mon, yrs, century, val;
unsigned long flags;
unsigned int year;
diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c
index bdd6674..f4010a7 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -145,9 +145,6 @@ static int brcmstb_waketmr_settime(struct device *dev,
sec = rtc_tm_to_time64(tm);
- if (sec > U32_MAX || sec < 0)
- return -EINVAL;
-
writel_relaxed(sec, timer->base + BRCMSTB_WKTMR_COUNTER);
return 0;
@@ -184,9 +181,6 @@ static int brcmstb_waketmr_setalarm(struct device *dev,
else
sec = 0;
- if (sec > U32_MAX || sec < 0)
- return -EINVAL;
-
brcmstb_waketmr_set_alarm(timer, sec);
return 0;
@@ -229,6 +223,10 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
if (IS_ERR(timer->base))
return PTR_ERR(timer->base);
+ timer->rtc = devm_rtc_allocate_device(dev);
+ if (IS_ERR(timer->rtc))
+ return PTR_ERR(timer->rtc);
+
/*
* Set wakeup capability before requesting wakeup interrupt, so we can
* process boot-time "wakeups" (e.g., from S5 soft-off)
@@ -261,11 +259,12 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
timer->reboot_notifier.notifier_call = brcmstb_waketmr_reboot;
register_reboot_notifier(&timer->reboot_notifier);
- timer->rtc = rtc_device_register("brcmstb-waketmr", dev,
- &brcmstb_waketmr_ops, THIS_MODULE);
- if (IS_ERR(timer->rtc)) {
+ timer->rtc->ops = &brcmstb_waketmr_ops;
+ timer->rtc->range_max = U32_MAX;
+
+ ret = rtc_register_device(timer->rtc);
+ if (ret) {
dev_err(dev, "unable to register device\n");
- ret = PTR_ERR(timer->rtc);
goto err_notifier;
}
@@ -288,7 +287,6 @@ static int brcmstb_waketmr_remove(struct platform_device *pdev)
struct brcmstb_waketmr *timer = dev_get_drvdata(&pdev->dev);
unregister_reboot_notifier(&timer->reboot_notifier);
- rtc_device_unregister(timer->rtc);
return 0;
}
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 1b3738a..cd3a241 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -43,11 +43,24 @@
#include <linux/of_platform.h>
#ifdef CONFIG_X86
#include <asm/i8259.h>
+#include <asm/processor.h>
+#include <linux/dmi.h>
#endif
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <linux/mc146818rtc.h>
+/*
+ * Use ACPI SCI to replace HPET interrupt for RTC Alarm event
+ *
+ * If cleared, ACPI SCI is only used to wake up the system from suspend
+ *
+ * If set, ACPI SCI is used to handle UIE/AIE and system wakeup
+ */
+
+static bool use_acpi_alarm;
+module_param(use_acpi_alarm, bool, 0444);
+
struct cmos_rtc {
struct rtc_device *rtc;
struct device *dev;
@@ -153,6 +166,12 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler)
#endif
+/* Don't use HPET for RTC Alarm event if ACPI Fixed event is used */
+static int use_hpet_alarm(void)
+{
+ return is_hpet_enabled() && !use_acpi_alarm;
+}
+
/*----------------------------------------------------------------*/
#ifdef RTC_PORT
@@ -298,7 +317,7 @@ static void cmos_checkintr(struct cmos_rtc *cmos, unsigned char rtc_control)
*/
rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- if (is_hpet_enabled())
+ if (use_hpet_alarm())
return;
rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
@@ -318,7 +337,13 @@ static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask)
rtc_control |= mask;
CMOS_WRITE(rtc_control, RTC_CONTROL);
- hpet_set_rtc_irq_bit(mask);
+ if (use_hpet_alarm())
+ hpet_set_rtc_irq_bit(mask);
+
+ if ((mask & RTC_AIE) && use_acpi_alarm) {
+ if (cmos->wake_on)
+ cmos->wake_on(cmos->dev);
+ }
cmos_checkintr(cmos, rtc_control);
}
@@ -330,7 +355,13 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask)
rtc_control = CMOS_READ(RTC_CONTROL);
rtc_control &= ~mask;
CMOS_WRITE(rtc_control, RTC_CONTROL);
- hpet_mask_rtc_irq_bit(mask);
+ if (use_hpet_alarm())
+ hpet_mask_rtc_irq_bit(mask);
+
+ if ((mask & RTC_AIE) && use_acpi_alarm) {
+ if (cmos->wake_off)
+ cmos->wake_off(cmos->dev);
+ }
cmos_checkintr(cmos, rtc_control);
}
@@ -448,10 +479,14 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
CMOS_WRITE(mon, cmos->mon_alrm);
}
- /* FIXME the HPET alarm glue currently ignores day_alrm
- * and mon_alrm ...
- */
- hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
+ if (use_hpet_alarm()) {
+ /*
+ * FIXME the HPET alarm glue currently ignores day_alrm
+ * and mon_alrm ...
+ */
+ hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min,
+ t->time.tm_sec);
+ }
if (t->enabled)
cmos_irq_enable(cmos, RTC_AIE);
@@ -508,7 +543,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq)
"batt_status\t: %s\n",
(rtc_control & RTC_PIE) ? "yes" : "no",
(rtc_control & RTC_UIE) ? "yes" : "no",
- is_hpet_enabled() ? "yes" : "no",
+ use_hpet_alarm() ? "yes" : "no",
// (rtc_control & RTC_SQWE) ? "yes" : "no",
(rtc_control & RTC_DM_BINARY) ? "no" : "yes",
(rtc_control & RTC_DST_EN) ? "yes" : "no",
@@ -614,7 +649,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
*/
irqstat = CMOS_READ(RTC_INTR_FLAGS);
rtc_control = CMOS_READ(RTC_CONTROL);
- if (is_hpet_enabled())
+ if (use_hpet_alarm())
irqstat = (unsigned long)irq & 0xF0;
/* If we were suspended, RTC_CONTROL may not be accurate since the
@@ -633,7 +668,8 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
cmos_rtc.suspend_ctrl &= ~RTC_AIE;
rtc_control &= ~RTC_AIE;
CMOS_WRITE(rtc_control, RTC_CONTROL);
- hpet_mask_rtc_irq_bit(RTC_AIE);
+ if (use_hpet_alarm())
+ hpet_mask_rtc_irq_bit(RTC_AIE);
CMOS_READ(RTC_INTR_FLAGS);
}
spin_unlock(&rtc_lock);
@@ -762,7 +798,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
* need to do something about other clock frequencies.
*/
cmos_rtc.rtc->irq_freq = 1024;
- hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
+ if (use_hpet_alarm())
+ hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
}
@@ -780,12 +817,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
goto cleanup1;
}
- hpet_rtc_timer_init();
+ if (use_hpet_alarm())
+ hpet_rtc_timer_init();
if (is_valid_irq(rtc_irq)) {
irq_handler_t rtc_cmos_int_handler;
- if (is_hpet_enabled()) {
+ if (use_hpet_alarm()) {
rtc_cmos_int_handler = hpet_rtc_interrupt;
retval = hpet_register_irq_handler(cmos_interrupt);
if (retval) {
@@ -824,7 +862,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
"alarms up to one day",
cmos_rtc.century ? ", y3k" : "",
nvmem_cfg.size,
- is_hpet_enabled() ? ", hpet irqs" : "");
+ use_hpet_alarm() ? ", hpet irqs" : "");
return 0;
@@ -858,7 +896,8 @@ static void cmos_do_remove(struct device *dev)
if (is_valid_irq(cmos->irq)) {
free_irq(cmos->irq, cmos->rtc);
- hpet_unregister_irq_handler(cmos_interrupt);
+ if (use_hpet_alarm())
+ hpet_unregister_irq_handler(cmos_interrupt);
}
cmos->rtc = NULL;
@@ -935,13 +974,13 @@ static int cmos_suspend(struct device *dev)
mask = RTC_IRQMASK;
tmp &= ~mask;
CMOS_WRITE(tmp, RTC_CONTROL);
- hpet_mask_rtc_irq_bit(mask);
-
+ if (use_hpet_alarm())
+ hpet_mask_rtc_irq_bit(mask);
cmos_checkintr(cmos, tmp);
}
spin_unlock_irq(&rtc_lock);
- if (tmp & RTC_AIE) {
+ if ((tmp & RTC_AIE) && !use_acpi_alarm) {
cmos->enabled_wake = 1;
if (cmos->wake_on)
cmos->wake_on(dev);
@@ -976,8 +1015,26 @@ static void cmos_check_wkalrm(struct device *dev)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
struct rtc_wkalrm current_alarm;
+ time64_t t_now;
time64_t t_current_expires;
time64_t t_saved_expires;
+ struct rtc_time now;
+
+ /* Check if we have RTC Alarm armed */
+ if (!(cmos->suspend_ctrl & RTC_AIE))
+ return;
+
+ cmos_read_time(dev, &now);
+ t_now = rtc_tm_to_time64(&now);
+
+ /*
+ * ACPI RTC wake event is cleared after resume from STR,
+ * ACK the rtc irq here
+ */
+ if (t_now >= cmos->alarm_expires && use_acpi_alarm) {
+ cmos_interrupt(0, (void *)cmos->rtc);
+ return;
+ }
cmos_read_alarm(dev, &current_alarm);
t_current_expires = rtc_tm_to_time64(&current_alarm.time);
@@ -996,7 +1053,7 @@ static int __maybe_unused cmos_resume(struct device *dev)
struct cmos_rtc *cmos = dev_get_drvdata(dev);
unsigned char tmp;
- if (cmos->enabled_wake) {
+ if (cmos->enabled_wake && !use_acpi_alarm) {
if (cmos->wake_off)
cmos->wake_off(dev);
else
@@ -1014,16 +1071,17 @@ static int __maybe_unused cmos_resume(struct device *dev)
if (tmp & RTC_IRQMASK) {
unsigned char mask;
- if (device_may_wakeup(dev))
+ if (device_may_wakeup(dev) && use_hpet_alarm())
hpet_rtc_timer_init();
do {
CMOS_WRITE(tmp, RTC_CONTROL);
- hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK);
+ if (use_hpet_alarm())
+ hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK);
mask = CMOS_READ(RTC_INTR_FLAGS);
mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
- if (!is_hpet_enabled() || !is_intr(mask))
+ if (!use_hpet_alarm() || !is_intr(mask))
break;
/* force one-shot behavior if HPET blocked
@@ -1068,16 +1126,27 @@ static u32 rtc_handler(void *context)
unsigned char rtc_intr;
unsigned long flags;
- spin_lock_irqsave(&rtc_lock, flags);
- if (cmos_rtc.suspend_ctrl)
- rtc_control = CMOS_READ(RTC_CONTROL);
- if (rtc_control & RTC_AIE) {
- cmos_rtc.suspend_ctrl &= ~RTC_AIE;
- CMOS_WRITE(rtc_control, RTC_CONTROL);
- rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
- rtc_update_irq(cmos->rtc, 1, rtc_intr);
+
+ /*
+ * Always update rtc irq when ACPI is used as RTC Alarm.
+ * Or else, ACPI SCI is enabled during suspend/resume only,
+ * update rtc irq in that case.
+ */
+ if (use_acpi_alarm)
+ cmos_interrupt(0, (void *)cmos->rtc);
+ else {
+ /* Fix me: can we use cmos_interrupt() here as well? */
+ spin_lock_irqsave(&rtc_lock, flags);
+ if (cmos_rtc.suspend_ctrl)
+ rtc_control = CMOS_READ(RTC_CONTROL);
+ if (rtc_control & RTC_AIE) {
+ cmos_rtc.suspend_ctrl &= ~RTC_AIE;
+ CMOS_WRITE(rtc_control, RTC_CONTROL);
+ rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
+ rtc_update_irq(cmos->rtc, 1, rtc_intr);
+ }
+ spin_unlock_irqrestore(&rtc_lock, flags);
}
- spin_unlock_irqrestore(&rtc_lock, flags);
pm_wakeup_hard_event(dev);
acpi_clear_event(ACPI_EVENT_RTC);
@@ -1107,6 +1176,28 @@ static void rtc_wake_off(struct device *dev)
acpi_disable_event(ACPI_EVENT_RTC, 0);
}
+#ifdef CONFIG_X86
+/* Enable use_acpi_alarm mode for Intel platforms no earlier than 2015 */
+static void use_acpi_alarm_quirks(void)
+{
+ int year;
+
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+ return;
+
+ if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
+ return;
+
+ if (!is_hpet_enabled())
+ return;
+
+ if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2015)
+ use_acpi_alarm = true;
+}
+#else
+static inline void use_acpi_alarm_quirks(void) { }
+#endif
+
/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find
* its device node and pass extra config data. This helps its driver use
* capabilities that the now-obsolete mc146818 didn't have, and informs it
@@ -1119,6 +1210,8 @@ static void cmos_wake_setup(struct device *dev)
if (acpi_disabled)
return;
+ use_acpi_alarm_quirks();
+
rtc_wake_setup(dev);
acpi_rtc_info.wake_on = rtc_wake_on;
acpi_rtc_info.wake_off = rtc_wake_off;
diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c
index bf7ced0..e544429 100644
--- a/drivers/rtc/rtc-cros-ec.c
+++ b/drivers/rtc/rtc-cros-ec.c
@@ -1,19 +1,8 @@
-/*
- * RTC driver for Chrome OS Embedded Controller
- *
- * Copyright (c) 2017, Google, Inc
- *
- * Author: Stephen Barber <smbarber@chromium.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.
- */
+// SPDX-License-Identifier: GPL-2.0
+// RTC driver for ChromeOS Embedded Controller.
+//
+// Copyright (C) 2017 Google, Inc.
+// Author: Stephen Barber <smbarber@chromium.org>
#include <linux/kernel.h>
#include <linux/mfd/cros_ec.h>
@@ -409,5 +398,5 @@ module_platform_driver(cros_ec_rtc_driver);
MODULE_DESCRIPTION("RTC driver for Chrome OS ECs");
MODULE_AUTHOR("Stephen Barber <smbarber@chromium.org>");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/drivers/rtc/rtc-ds1216.c b/drivers/rtc/rtc-ds1216.c
index 5f15871..50fabe1 100644
--- a/drivers/rtc/rtc-ds1216.c
+++ b/drivers/rtc/rtc-ds1216.c
@@ -76,8 +76,7 @@ static void ds1216_switch_ds_to_clock(u8 __iomem *ioaddr)
static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ds1216_priv *priv = platform_get_drvdata(pdev);
+ struct ds1216_priv *priv = dev_get_drvdata(dev);
struct ds1216_regs regs;
ds1216_switch_ds_to_clock(priv->ioaddr);
@@ -104,8 +103,7 @@ static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ds1216_priv *priv = platform_get_drvdata(pdev);
+ struct ds1216_priv *priv = dev_get_drvdata(dev);
struct ds1216_regs regs;
ds1216_switch_ds_to_clock(priv->ioaddr);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index a13e59e..e9ec416 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -201,6 +201,7 @@ static const struct chip_desc chips[last_ds_type] = {
.century_reg = DS1307_REG_HOUR,
.century_enable_bit = DS1340_BIT_CENTURY_EN,
.century_bit = DS1340_BIT_CENTURY,
+ .do_trickle_setup = &do_trickle_setup_ds1339,
.trickle_charger_reg = 0x08,
},
[ds_1341] = {
@@ -1371,6 +1372,7 @@ static void ds1307_clks_register(struct ds1307 *ds1307)
static const struct regmap_config regmap_config = {
.reg_bits = 8,
.val_bits = 8,
+ .max_register = 0x9,
};
static int ds1307_probe(struct i2c_client *client,
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index a7d5ca42..b8b6e51 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -314,8 +314,7 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata)
static int
ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
if (pdata->irq <= 0)
return -EINVAL;
@@ -334,8 +333,7 @@ ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int
ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
if (pdata->irq <= 0)
return -EINVAL;
@@ -373,8 +371,7 @@ ds1511_interrupt(int irq, void *dev_id)
static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
if (pdata->irq <= 0)
return -EINVAL;
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index 2441b9a..34af7a8 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -73,8 +73,7 @@ struct rtc_plat_data {
static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
u8 century;
@@ -98,8 +97,7 @@ static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
unsigned int year, month, day, hour, minute, second, week;
unsigned int century;
@@ -155,8 +153,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata)
static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
if (pdata->irq <= 0)
return -EINVAL;
@@ -172,8 +169,7 @@ static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
if (pdata->irq <= 0)
return -EINVAL;
@@ -208,8 +204,7 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id)
static int ds1553_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
if (pdata->irq <= 0)
return -EINVAL;
diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c
index 1a39829..5c0db6c 100644
--- a/drivers/rtc/rtc-ds1685.c
+++ b/drivers/rtc/rtc-ds1685.c
@@ -267,8 +267,7 @@ ds1685_rtc_get_ssn(struct ds1685_priv *rtc, u8 *ssn)
static int
ds1685_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ds1685_priv *rtc = platform_get_drvdata(pdev);
+ struct ds1685_priv *rtc = dev_get_drvdata(dev);
u8 ctrlb, century;
u8 seconds, minutes, hours, wday, mday, month, years;
@@ -317,8 +316,7 @@ ds1685_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int
ds1685_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ds1685_priv *rtc = platform_get_drvdata(pdev);
+ struct ds1685_priv *rtc = dev_get_drvdata(dev);
u8 ctrlb, seconds, minutes, hours, wday, mday, month, years, century;
/* Fetch the time info from rtc_time. */
@@ -394,8 +392,7 @@ ds1685_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int
ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ds1685_priv *rtc = platform_get_drvdata(pdev);
+ struct ds1685_priv *rtc = dev_get_drvdata(dev);
u8 seconds, minutes, hours, mday, ctrlb, ctrlc;
int ret;
@@ -453,8 +450,7 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int
ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ds1685_priv *rtc = platform_get_drvdata(pdev);
+ struct ds1685_priv *rtc = dev_get_drvdata(dev);
u8 ctrlb, seconds, minutes, hours, mday;
int ret;
@@ -1119,8 +1115,7 @@ static ssize_t
ds1685_rtc_sysfs_battery_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ds1685_priv *rtc = platform_get_drvdata(pdev);
+ struct ds1685_priv *rtc = dev_get_drvdata(dev);
u8 ctrld;
ctrld = rtc->read(rtc, RTC_CTRL_D);
@@ -1140,8 +1135,7 @@ static ssize_t
ds1685_rtc_sysfs_auxbatt_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ds1685_priv *rtc = platform_get_drvdata(pdev);
+ struct ds1685_priv *rtc = dev_get_drvdata(dev);
u8 ctrl4a;
ds1685_rtc_switch_to_bank1(rtc);
@@ -1163,8 +1157,7 @@ static ssize_t
ds1685_rtc_sysfs_serial_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct ds1685_priv *rtc = platform_get_drvdata(pdev);
+ struct ds1685_priv *rtc = dev_get_drvdata(dev);
u8 ssn[8];
ds1685_rtc_switch_to_bank1(rtc);
@@ -2044,6 +2037,26 @@ ds1685_rtc_probe(struct platform_device *pdev)
rtc->write(rtc, RTC_EXT_CTRL_4B,
(rtc->read(rtc, RTC_EXT_CTRL_4B) | RTC_CTRL_4B_KSE));
+ rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(rtc_dev))
+ return PTR_ERR(rtc_dev);
+
+ rtc_dev->ops = &ds1685_rtc_ops;
+
+ /* Century bit is useless because leap year fails in 1900 and 2100 */
+ rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
+
+ /* Maximum periodic rate is 8192Hz (0.122070ms). */
+ rtc_dev->max_user_freq = RTC_MAX_USER_FREQ;
+
+ /* See if the platform doesn't support UIE. */
+ if (pdata->uie_unsupported)
+ rtc_dev->uie_unsupported = 1;
+ rtc->uie_unsupported = pdata->uie_unsupported;
+
+ rtc->dev = rtc_dev;
+
/*
* Fetch the IRQ and setup the interrupt handler.
*
@@ -2076,32 +2089,13 @@ ds1685_rtc_probe(struct platform_device *pdev)
/* Setup complete. */
ds1685_rtc_switch_to_bank0(rtc);
- /* Register the device as an RTC. */
- rtc_dev = rtc_device_register(pdev->name, &pdev->dev,
- &ds1685_rtc_ops, THIS_MODULE);
-
- /* Success? */
- if (IS_ERR(rtc_dev))
- return PTR_ERR(rtc_dev);
-
- /* Maximum periodic rate is 8192Hz (0.122070ms). */
- rtc_dev->max_user_freq = RTC_MAX_USER_FREQ;
-
- /* See if the platform doesn't support UIE. */
- if (pdata->uie_unsupported)
- rtc_dev->uie_unsupported = 1;
- rtc->uie_unsupported = pdata->uie_unsupported;
-
- rtc->dev = rtc_dev;
-
#ifdef CONFIG_SYSFS
ret = ds1685_rtc_sysfs_register(&pdev->dev);
if (ret)
- rtc_device_unregister(rtc->dev);
+ return ret;
#endif
- /* Done! */
- return ret;
+ return rtc_register_device(rtc_dev);
}
/**
@@ -2117,8 +2111,6 @@ ds1685_rtc_remove(struct platform_device *pdev)
ds1685_rtc_sysfs_unregister(&pdev->dev);
#endif
- rtc_device_unregister(rtc->dev);
-
/* Read Ctrl B and clear PIE/AIE/UIE. */
rtc->write(rtc, RTC_CTRL_B,
(rtc->read(rtc, RTC_CTRL_B) &
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 2d78118..5a4c2c5 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -58,8 +58,7 @@ struct rtc_plat_data {
static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr_rtc;
u8 century;
@@ -83,8 +82,7 @@ static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr_rtc;
unsigned int year, month, day, hour, minute, second, week;
unsigned int century;
@@ -154,8 +152,6 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
int ret = 0;
struct nvmem_config nvmem_cfg = {
.name = "ds1742_nvram",
- .word_size = 1,
- .stride = 1,
.reg_read = ds1742_nvram_read,
.reg_write = ds1742_nvram_write,
};
diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c
index af8d6be..61f798c 100644
--- a/drivers/rtc/rtc-ftrtc010.c
+++ b/drivers/rtc/rtc-ftrtc010.c
@@ -73,8 +73,8 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct ftrtc010_rtc *rtc = dev_get_drvdata(dev);
- unsigned int days, hour, min, sec;
- unsigned long offset, time;
+ u32 days, hour, min, sec, offset;
+ timeu64_t time;
sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
@@ -84,7 +84,7 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
time = offset + days * 86400 + hour * 3600 + min * 60 + sec;
- rtc_time_to_tm(time, tm);
+ rtc_time64_to_tm(time, tm);
return 0;
}
@@ -92,13 +92,10 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int ftrtc010_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct ftrtc010_rtc *rtc = dev_get_drvdata(dev);
- unsigned int sec, min, hour, day;
- unsigned long offset, time;
+ u32 sec, min, hour, day, offset;
+ timeu64_t time;
- if (tm->tm_year >= 2148) /* EPOCH Year + 179 */
- return -EINVAL;
-
- rtc_tm_to_time(tm, &time);
+ time = rtc_tm_to_time64(tm);
sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
@@ -120,6 +117,7 @@ static const struct rtc_class_ops ftrtc010_rtc_ops = {
static int ftrtc010_rtc_probe(struct platform_device *pdev)
{
+ u32 days, hour, min, sec;
struct ftrtc010_rtc *rtc;
struct device *dev = &pdev->dev;
struct resource *res;
@@ -166,14 +164,27 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev)
if (!rtc->rtc_base)
return -ENOMEM;
+ rtc->rtc_dev = devm_rtc_allocate_device(dev);
+ if (IS_ERR(rtc->rtc_dev))
+ return PTR_ERR(rtc->rtc_dev);
+
+ rtc->rtc_dev->ops = &ftrtc010_rtc_ops;
+
+ sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
+ min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
+ hour = readl(rtc->rtc_base + FTRTC010_RTC_HOUR);
+ days = readl(rtc->rtc_base + FTRTC010_RTC_DAYS);
+
+ rtc->rtc_dev->range_min = (u64)days * 86400 + hour * 3600 +
+ min * 60 + sec;
+ rtc->rtc_dev->range_max = U32_MAX + rtc->rtc_dev->range_min;
+
ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt,
IRQF_SHARED, pdev->name, dev);
if (unlikely(ret))
return ret;
- rtc->rtc_dev = rtc_device_register(pdev->name, dev,
- &ftrtc010_rtc_ops, THIS_MODULE);
- return PTR_ERR_OR_ZERO(rtc->rtc_dev);
+ return rtc_register_device(rtc->rtc_dev);
}
static int ftrtc010_rtc_remove(struct platform_device *pdev)
@@ -184,7 +195,6 @@ static int ftrtc010_rtc_remove(struct platform_device *pdev)
clk_disable_unprepare(rtc->extclk);
if (!IS_ERR(rtc->pclk))
clk_disable_unprepare(rtc->pclk);
- rtc_device_unregister(rtc->rtc_dev);
return 0;
}
diff --git a/drivers/rtc/rtc-lpc32xx.c b/drivers/rtc/rtc-lpc32xx.c
index 3ba8723..910e600 100644
--- a/drivers/rtc/rtc-lpc32xx.c
+++ b/drivers/rtc/rtc-lpc32xx.c
@@ -294,11 +294,10 @@ static int lpc32xx_rtc_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
static int lpc32xx_rtc_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);
+ struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
if (rtc->irq >= 0) {
- if (device_may_wakeup(&pdev->dev))
+ if (device_may_wakeup(dev))
enable_irq_wake(rtc->irq);
else
disable_irq_wake(rtc->irq);
@@ -309,10 +308,9 @@ static int lpc32xx_rtc_suspend(struct device *dev)
static int lpc32xx_rtc_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);
+ struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
- if (rtc->irq >= 0 && device_may_wakeup(&pdev->dev))
+ if (rtc->irq >= 0 && device_may_wakeup(dev))
disable_irq_wake(rtc->irq);
return 0;
@@ -321,8 +319,7 @@ static int lpc32xx_rtc_resume(struct device *dev)
/* Unconditionally disable the alarm */
static int lpc32xx_rtc_freeze(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);
+ struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
spin_lock_irq(&rtc->lock);
@@ -337,8 +334,7 @@ static int lpc32xx_rtc_freeze(struct device *dev)
static int lpc32xx_rtc_thaw(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);
+ struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
if (rtc->alarm_enabled) {
spin_lock_irq(&rtc->lock);
diff --git a/drivers/rtc/rtc-ls1x.c b/drivers/rtc/rtc-ls1x.c
index 045af11..f4c2486 100644
--- a/drivers/rtc/rtc-ls1x.c
+++ b/drivers/rtc/rtc-ls1x.c
@@ -87,16 +87,17 @@
static int ls1x_rtc_read_time(struct device *dev, struct rtc_time *rtm)
{
- unsigned long v, t;
+ unsigned long v;
+ time64_t t;
v = readl(SYS_TOYREAD0);
t = readl(SYS_TOYREAD1);
memset(rtm, 0, sizeof(struct rtc_time));
- t = mktime((t & LS1X_YEAR_MASK), ls1x_get_month(v),
+ t = mktime64((t & LS1X_YEAR_MASK), ls1x_get_month(v),
ls1x_get_day(v), ls1x_get_hour(v),
ls1x_get_min(v), ls1x_get_sec(v));
- rtc_time_to_tm(t, rtm);
+ rtc_time64_to_tm(t, rtm);
return 0;
}
@@ -147,15 +148,13 @@ static int ls1x_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtcdev;
unsigned long v;
- int ret;
v = readl(SYS_COUNTER_CNTRL);
if (!(v & RTC_CNTR_OK)) {
dev_err(&pdev->dev, "rtc counters not working\n");
- ret = -ENODEV;
- goto err;
+ return -ENODEV;
}
- ret = -ETIMEDOUT;
+
/* set to 1 HZ if needed */
if (readl(SYS_TOYTRIM) != 32767) {
v = 0x100000;
@@ -164,7 +163,7 @@ static int ls1x_rtc_probe(struct platform_device *pdev)
if (!v) {
dev_err(&pdev->dev, "time out\n");
- goto err;
+ return -ETIMEDOUT;
}
writel(32767, SYS_TOYTRIM);
}
@@ -172,17 +171,16 @@ static int ls1x_rtc_probe(struct platform_device *pdev)
while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS)
usleep_range(1000, 3000);
- rtcdev = devm_rtc_device_register(&pdev->dev, "ls1x-rtc",
- &ls1x_rtc_ops , THIS_MODULE);
- if (IS_ERR(rtcdev)) {
- ret = PTR_ERR(rtcdev);
- goto err;
- }
+ rtcdev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(rtcdev))
+ return PTR_ERR(rtcdev);
platform_set_drvdata(pdev, rtcdev);
- return 0;
-err:
- return ret;
+ rtcdev->ops = &ls1x_rtc_ops;
+ rtcdev->range_min = RTC_TIMESTAMP_BEGIN_1900;
+ rtcdev->range_max = RTC_TIMESTAMP_END_2099;
+
+ return rtc_register_device(rtcdev);
}
static struct platform_driver ls1x_rtc_driver = {
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 216fac6..1053a40 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -47,8 +47,7 @@ struct m48t59_private {
static void
m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct m48t59_private *m48t59 = dev_get_drvdata(dev);
writeb(val, m48t59->ioaddr+ofs);
}
@@ -56,8 +55,7 @@ m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val)
static u8
m48t59_mem_readb(struct device *dev, u32 ofs)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct m48t59_private *m48t59 = dev_get_drvdata(dev);
return readb(m48t59->ioaddr+ofs);
}
@@ -67,9 +65,8 @@ m48t59_mem_readb(struct device *dev, u32 ofs)
*/
static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
- struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct m48t59_plat_data *pdata = dev_get_platdata(dev);
+ struct m48t59_private *m48t59 = dev_get_drvdata(dev);
unsigned long flags;
u8 val;
@@ -110,9 +107,8 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
- struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct m48t59_plat_data *pdata = dev_get_platdata(dev);
+ struct m48t59_private *m48t59 = dev_get_drvdata(dev);
unsigned long flags;
u8 val = 0;
int year = tm->tm_year;
@@ -157,9 +153,8 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
*/
static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
- struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct m48t59_plat_data *pdata = dev_get_platdata(dev);
+ struct m48t59_private *m48t59 = dev_get_drvdata(dev);
struct rtc_time *tm = &alrm->time;
unsigned long flags;
u8 val;
@@ -204,9 +199,8 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
*/
static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
- struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct m48t59_plat_data *pdata = dev_get_platdata(dev);
+ struct m48t59_private *m48t59 = dev_get_drvdata(dev);
struct rtc_time *tm = &alrm->time;
u8 mday, hour, min, sec;
unsigned long flags;
@@ -265,9 +259,8 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
*/
static int m48t59_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
- struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct m48t59_plat_data *pdata = dev_get_platdata(dev);
+ struct m48t59_private *m48t59 = dev_get_drvdata(dev);
unsigned long flags;
spin_lock_irqsave(&m48t59->lock, flags);
@@ -282,9 +275,8 @@ static int m48t59_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
- struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct m48t59_plat_data *pdata = dev_get_platdata(dev);
+ struct m48t59_private *m48t59 = dev_get_drvdata(dev);
unsigned long flags;
u8 val;
@@ -303,9 +295,8 @@ static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq)
static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id)
{
struct device *dev = (struct device *)dev_id;
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t59_plat_data *pdata = dev_get_platdata(&pdev->dev);
- struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
+ struct m48t59_plat_data *pdata = dev_get_platdata(dev);
+ struct m48t59_private *m48t59 = dev_get_drvdata(dev);
u8 event;
spin_lock(&m48t59->lock);
diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c
index fcb9de5..097a4d4 100644
--- a/drivers/rtc/rtc-mrst.c
+++ b/drivers/rtc/rtc-mrst.c
@@ -45,7 +45,6 @@ struct mrst_rtc {
struct rtc_device *rtc;
struct device *dev;
int irq;
- struct resource *iomem;
u8 enabled_wake;
u8 suspend_ctrl;
@@ -329,24 +328,22 @@ static int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem,
if (!iomem)
return -ENODEV;
- iomem = request_mem_region(iomem->start, resource_size(iomem),
- driver_name);
+ iomem = devm_request_mem_region(dev, iomem->start, resource_size(iomem),
+ driver_name);
if (!iomem) {
dev_dbg(dev, "i/o mem already in use.\n");
return -EBUSY;
}
mrst_rtc.irq = rtc_irq;
- mrst_rtc.iomem = iomem;
mrst_rtc.dev = dev;
dev_set_drvdata(dev, &mrst_rtc);
- mrst_rtc.rtc = rtc_device_register(driver_name, dev,
- &mrst_rtc_ops, THIS_MODULE);
- if (IS_ERR(mrst_rtc.rtc)) {
- retval = PTR_ERR(mrst_rtc.rtc);
- goto cleanup0;
- }
+ mrst_rtc.rtc = devm_rtc_allocate_device(dev);
+ if (IS_ERR(mrst_rtc.rtc))
+ return PTR_ERR(mrst_rtc.rtc);
+
+ mrst_rtc.rtc->ops = &mrst_rtc_ops;
rename_region(iomem, dev_name(&mrst_rtc.rtc->dev));
@@ -359,23 +356,27 @@ static int vrtc_mrst_do_probe(struct device *dev, struct resource *iomem,
dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n");
if (rtc_irq) {
- retval = request_irq(rtc_irq, mrst_rtc_irq,
- 0, dev_name(&mrst_rtc.rtc->dev),
- mrst_rtc.rtc);
+ retval = devm_request_irq(dev, rtc_irq, mrst_rtc_irq,
+ 0, dev_name(&mrst_rtc.rtc->dev),
+ mrst_rtc.rtc);
if (retval < 0) {
dev_dbg(dev, "IRQ %d is already in use, err %d\n",
rtc_irq, retval);
- goto cleanup1;
+ goto cleanup0;
}
}
+
+ retval = rtc_register_device(mrst_rtc.rtc);
+ if (retval) {
+ retval = PTR_ERR(mrst_rtc.rtc);
+ goto cleanup0;
+ }
+
dev_dbg(dev, "initialised\n");
return 0;
-cleanup1:
- rtc_device_unregister(mrst_rtc.rtc);
cleanup0:
mrst_rtc.dev = NULL;
- release_mem_region(iomem->start, resource_size(iomem));
dev_err(dev, "rtc-mrst: unable to initialise\n");
return retval;
}
@@ -390,20 +391,10 @@ static void rtc_mrst_do_shutdown(void)
static void rtc_mrst_do_remove(struct device *dev)
{
struct mrst_rtc *mrst = dev_get_drvdata(dev);
- struct resource *iomem;
rtc_mrst_do_shutdown();
- if (mrst->irq)
- free_irq(mrst->irq, mrst->rtc);
-
- rtc_device_unregister(mrst->rtc);
mrst->rtc = NULL;
-
- iomem = mrst->iomem;
- release_mem_region(iomem->start, resource_size(iomem));
- mrst->iomem = NULL;
-
mrst->dev = NULL;
}
diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c
index 1a61fa5..385f830 100644
--- a/drivers/rtc/rtc-mt6397.c
+++ b/drivers/rtc/rtc-mt6397.c
@@ -322,10 +322,9 @@ static int mtk_rtc_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rtc->addr_base = res->start;
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- rtc->irq = irq_create_mapping(mt6397_chip->irq_domain, res->start);
- if (rtc->irq <= 0)
- return -EINVAL;
+ rtc->irq = platform_get_irq(pdev, 0);
+ if (rtc->irq < 0)
+ return rtc->irq;
rtc->regmap = mt6397_chip->regmap;
rtc->dev = &pdev->dev;
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index bc52dbb..4b198b3 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -176,8 +176,7 @@ static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
static int mv_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
if (pdata->irq < 0)
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index bce427d..878c6ee 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -1,13 +1,6 @@
-/*
- * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
#include <linux/io.h>
#include <linux/rtc.h>
@@ -109,8 +102,7 @@ static inline int is_imx1_rtc(struct rtc_plat_data *data)
*/
static time64_t get_alarm_or_time(struct device *dev, int time_alarm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
u32 day = 0, hr = 0, min = 0, sec = 0, hr_min = 0;
@@ -139,8 +131,7 @@ static time64_t get_alarm_or_time(struct device *dev, int time_alarm)
static void set_alarm_or_time(struct device *dev, int time_alarm, time64_t time)
{
u32 tod, day, hr, min, sec, temp;
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
day = div_s64_rem(time, 86400, &tod);
@@ -176,8 +167,7 @@ static void set_alarm_or_time(struct device *dev, int time_alarm, time64_t time)
static void rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
{
time64_t time;
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
time = rtc_tm_to_time64(alrm);
@@ -190,8 +180,7 @@ static void rtc_update_alarm(struct device *dev, struct rtc_time *alrm)
static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit,
unsigned int enabled)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
u32 reg;
@@ -266,8 +255,7 @@ static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm)
*/
static int mxc_rtc_set_mmss(struct device *dev, time64_t time)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
/*
* TTC_DAYR register is 9-bit in MX1 SoC, save time and day of year only
@@ -295,8 +283,7 @@ static int mxc_rtc_set_mmss(struct device *dev, time64_t time)
*/
static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
rtc_time64_to_tm(get_alarm_or_time(dev, MXC_RTC_ALARM), &alrm->time);
@@ -310,8 +297,7 @@ static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
*/
static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
rtc_update_alarm(dev, &alrm->time);
diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c
index 9e14efb..c75f26d 100644
--- a/drivers/rtc/rtc-mxc_v2.c
+++ b/drivers/rtc/rtc-mxc_v2.c
@@ -165,11 +165,6 @@ static int mxc_rtc_set_time(struct device *dev, struct rtc_time *tm)
time64_t time = rtc_tm_to_time64(tm);
int ret;
- if (time > U32_MAX) {
- dev_err(dev, "RTC exceeded by %llus\n", time - U32_MAX);
- return -EINVAL;
- }
-
ret = mxc_rtc_lock(pdata);
if (ret)
return ret;
@@ -198,7 +193,7 @@ static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (ret)
return ret;
- rtc_time_to_tm(readl(ioaddr + SRTC_LPSAR), &alrm->time);
+ rtc_time64_to_tm(readl(ioaddr + SRTC_LPSAR), &alrm->time);
alrm->pending = !!(readl(ioaddr + SRTC_LPSR) & SRTC_LPSR_ALP);
return mxc_rtc_unlock(pdata);
}
@@ -248,11 +243,6 @@ static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (ret)
return ret;
- if (time > U32_MAX) {
- dev_err(dev, "Hopefully I am out of service by then :-(\n");
- return -EINVAL;
- }
-
writel((u32)time, pdata->ioaddr + SRTC_LPSAR);
/* clear alarm interrupt status bit */
@@ -343,6 +333,13 @@ static int mxc_rtc_probe(struct platform_device *pdev)
return ret;
}
+ pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(pdata->rtc))
+ return PTR_ERR(pdata->rtc);
+
+ pdata->rtc->ops = &mxc_rtc_ops;
+ pdata->rtc->range_max = U32_MAX;
+
clk_disable(pdata->clk);
platform_set_drvdata(pdev, pdata);
ret =
@@ -354,15 +351,11 @@ static int mxc_rtc_probe(struct platform_device *pdev)
return ret;
}
- pdata->rtc =
- devm_rtc_device_register(&pdev->dev, pdev->name, &mxc_rtc_ops,
- THIS_MODULE);
- if (IS_ERR(pdata->rtc)) {
+ ret = rtc_register_device(pdata->rtc);
+ if (ret < 0)
clk_unprepare(pdata->clk);
- return PTR_ERR(pdata->rtc);
- }
- return 0;
+ return ret;
}
static int mxc_rtc_remove(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-pcap.c b/drivers/rtc/rtc-pcap.c
index c05f524..f176cb9 100644
--- a/drivers/rtc/rtc-pcap.c
+++ b/drivers/rtc/rtc-pcap.c
@@ -43,8 +43,7 @@ static irqreturn_t pcap_rtc_irq(int irq, void *_pcap_rtc)
static int pcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev);
+ struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
struct rtc_time *tm = &alrm->time;
unsigned long secs;
u32 tod; /* time of day, seconds since midnight */
@@ -63,8 +62,7 @@ static int pcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int pcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev);
+ struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
struct rtc_time *tm = &alrm->time;
unsigned long secs;
u32 tod, days;
@@ -82,8 +80,7 @@ static int pcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev);
+ struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
unsigned long secs;
u32 tod, days;
@@ -100,8 +97,7 @@ static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int pcap_rtc_set_mmss(struct device *dev, unsigned long secs)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev);
+ struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
u32 tod, days;
tod = secs % SEC_PER_DAY;
@@ -115,8 +111,7 @@ static int pcap_rtc_set_mmss(struct device *dev, unsigned long secs)
static int pcap_rtc_irq_enable(struct device *dev, int pirq, unsigned int en)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev);
+ struct pcap_rtc *pcap_rtc = dev_get_drvdata(dev);
if (en)
enable_irq(pcap_to_irq(pcap_rtc->pcap, pirq));
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
index 47304f5..e1887b8 100644
--- a/drivers/rtc/rtc-pxa.c
+++ b/drivers/rtc/rtc-pxa.c
@@ -363,7 +363,7 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
sa1100_rtc->rtar = pxa_rtc->base + 0x4;
sa1100_rtc->rttr = pxa_rtc->base + 0xc;
ret = sa1100_rtc_init(pdev, sa1100_rtc);
- if (!ret) {
+ if (ret) {
dev_err(dev, "Unable to init SA1100 RTC sub-device\n");
return ret;
}
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c
index 32caadf9..eac8821 100644
--- a/drivers/rtc/rtc-rx8581.c
+++ b/drivers/rtc/rtc-rx8581.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/bcd.h>
+#include <linux/regmap.h>
#include <linux/rtc.h>
#include <linux/log2.h>
@@ -51,52 +52,20 @@
#define RX8581_CTRL_RESET 0x01 /* RESET bit */
struct rx8581 {
- struct i2c_client *client;
+ struct regmap *regmap;
struct rtc_device *rtc;
- s32 (*read_block_data)(const struct i2c_client *client, u8 command,
- u8 length, u8 *values);
- s32 (*write_block_data)(const struct i2c_client *client, u8 command,
- u8 length, const u8 *values);
};
-static struct i2c_driver rx8581_driver;
-
-static int rx8581_read_block_data(const struct i2c_client *client, u8 command,
- u8 length, u8 *values)
-{
- s32 i, data;
-
- for (i = 0; i < length; i++) {
- data = i2c_smbus_read_byte_data(client, command + i);
- if (data < 0)
- return data;
- values[i] = data;
- }
- return i;
-}
-
-static int rx8581_write_block_data(const struct i2c_client *client, u8 command,
- u8 length, const u8 *values)
-{
- s32 i, ret;
-
- for (i = 0; i < length; i++) {
- ret = i2c_smbus_write_byte_data(client, command + i,
- values[i]);
- if (ret < 0)
- return ret;
- }
- return length;
-}
-
/*
* In the routines that deal directly with the rx8581 hardware, we use
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
*/
-static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
+ struct i2c_client *client = to_i2c_client(dev);
unsigned char date[7];
- int data, err;
+ unsigned int data;
+ int err;
struct rx8581 *rx8581 = i2c_get_clientdata(client);
/* First we ensure that the "update flag" is not set, we read the
@@ -104,45 +73,38 @@ static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm)
* has been set, we know that the time has changed during the read so
* we repeat the whole process again.
*/
- data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG);
- if (data < 0) {
- dev_err(&client->dev, "Unable to read device flags\n");
- return -EIO;
+ err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data);
+ if (err < 0)
+ return err;
+
+ if (data & RX8581_FLAG_VLF) {
+ dev_warn(dev,
+ "low voltage detected, date/time is not reliable.\n");
+ return -EINVAL;
}
do {
/* If update flag set, clear it */
if (data & RX8581_FLAG_UF) {
- err = i2c_smbus_write_byte_data(client,
- RX8581_REG_FLAG, (data & ~RX8581_FLAG_UF));
- if (err != 0) {
- dev_err(&client->dev, "Unable to write device flags\n");
- return -EIO;
- }
+ err = regmap_write(rx8581->regmap, RX8581_REG_FLAG,
+ data & ~RX8581_FLAG_UF);
+ if (err < 0)
+ return err;
}
/* Now read time and date */
- err = rx8581->read_block_data(client, RX8581_REG_SC,
- 7, date);
- if (err < 0) {
- dev_err(&client->dev, "Unable to read date\n");
- return -EIO;
- }
+ err = regmap_bulk_read(rx8581->regmap, RX8581_REG_SC, date,
+ sizeof(date));
+ if (err < 0)
+ return err;
/* Check flag register */
- data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG);
- if (data < 0) {
- dev_err(&client->dev, "Unable to read device flags\n");
- return -EIO;
- }
+ err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data);
+ if (err < 0)
+ return err;
} while (data & RX8581_FLAG_UF);
- if (data & RX8581_FLAG_VLF)
- dev_info(&client->dev,
- "low voltage detected, date/time is not reliable.\n");
-
- dev_dbg(&client->dev,
- "%s: raw data is sec=%02x, min=%02x, hr=%02x, "
+ dev_dbg(dev, "%s: raw data is sec=%02x, min=%02x, hr=%02x, "
"wday=%02x, mday=%02x, mon=%02x, year=%02x\n",
__func__,
date[0], date[1], date[2], date[3], date[4], date[5], date[6]);
@@ -153,12 +115,9 @@ static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_wday = ilog2(date[RX8581_REG_DW] & 0x7F);
tm->tm_mday = bcd2bin(date[RX8581_REG_DM] & 0x3F);
tm->tm_mon = bcd2bin(date[RX8581_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
- tm->tm_year = bcd2bin(date[RX8581_REG_YR]);
- if (tm->tm_year < 70)
- tm->tm_year += 100; /* assume we are in 1970...2069 */
-
+ tm->tm_year = bcd2bin(date[RX8581_REG_YR]) + 100;
- dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
@@ -167,13 +126,14 @@ static int rx8581_get_datetime(struct i2c_client *client, struct rtc_time *tm)
return 0;
}
-static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)
+static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- int data, err;
+ struct i2c_client *client = to_i2c_client(dev);
+ int err;
unsigned char buf[7];
struct rx8581 *rx8581 = i2c_get_clientdata(client);
- dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
@@ -190,69 +150,30 @@ static int rx8581_set_datetime(struct i2c_client *client, struct rtc_time *tm)
buf[RX8581_REG_MO] = bin2bcd(tm->tm_mon + 1);
/* year and century */
- buf[RX8581_REG_YR] = bin2bcd(tm->tm_year % 100);
+ buf[RX8581_REG_YR] = bin2bcd(tm->tm_year - 100);
buf[RX8581_REG_DW] = (0x1 << tm->tm_wday);
/* Stop the clock */
- data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL);
- if (data < 0) {
- dev_err(&client->dev, "Unable to read control register\n");
- return -EIO;
- }
-
- err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL,
- (data | RX8581_CTRL_STOP));
- if (err < 0) {
- dev_err(&client->dev, "Unable to write control register\n");
- return -EIO;
- }
+ err = regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL,
+ RX8581_CTRL_STOP, RX8581_CTRL_STOP);
+ if (err < 0)
+ return err;
/* write register's data */
- err = rx8581->write_block_data(client, RX8581_REG_SC, 7, buf);
- if (err < 0) {
- dev_err(&client->dev, "Unable to write to date registers\n");
- return -EIO;
- }
+ err = regmap_bulk_write(rx8581->regmap, RX8581_REG_SC,
+ buf, sizeof(buf));
+ if (err < 0)
+ return err;
/* get VLF and clear it */
- data = i2c_smbus_read_byte_data(client, RX8581_REG_FLAG);
- if (data < 0) {
- dev_err(&client->dev, "Unable to read flag register\n");
- return -EIO;
- }
-
- err = i2c_smbus_write_byte_data(client, RX8581_REG_FLAG,
- (data & ~(RX8581_FLAG_VLF)));
- if (err != 0) {
- dev_err(&client->dev, "Unable to write flag register\n");
- return -EIO;
- }
+ err = regmap_update_bits(rx8581->regmap, RX8581_REG_FLAG,
+ RX8581_FLAG_VLF, 0);
+ if (err < 0)
+ return err;
/* Restart the clock */
- data = i2c_smbus_read_byte_data(client, RX8581_REG_CTRL);
- if (data < 0) {
- dev_err(&client->dev, "Unable to read control register\n");
- return -EIO;
- }
-
- err = i2c_smbus_write_byte_data(client, RX8581_REG_CTRL,
- (data & ~(RX8581_CTRL_STOP)));
- if (err != 0) {
- dev_err(&client->dev, "Unable to write control register\n");
- return -EIO;
- }
-
- return 0;
-}
-
-static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm)
-{
- return rx8581_get_datetime(to_i2c_client(dev), tm);
-}
-
-static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm)
-{
- return rx8581_set_datetime(to_i2c_client(dev), tm);
+ return regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL,
+ RX8581_CTRL_STOP, 0);
}
static const struct rtc_class_ops rx8581_rtc_ops = {
@@ -264,38 +185,35 @@ static int rx8581_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct rx8581 *rx8581;
+ static const struct regmap_config config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xf,
+ };
dev_dbg(&client->dev, "%s\n", __func__);
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)
- && !i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
- return -EIO;
-
rx8581 = devm_kzalloc(&client->dev, sizeof(struct rx8581), GFP_KERNEL);
if (!rx8581)
return -ENOMEM;
i2c_set_clientdata(client, rx8581);
- rx8581->client = client;
-
- if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) {
- rx8581->read_block_data = i2c_smbus_read_i2c_block_data;
- rx8581->write_block_data = i2c_smbus_write_i2c_block_data;
- } else {
- rx8581->read_block_data = rx8581_read_block_data;
- rx8581->write_block_data = rx8581_write_block_data;
- }
- rx8581->rtc = devm_rtc_device_register(&client->dev,
- rx8581_driver.driver.name, &rx8581_rtc_ops, THIS_MODULE);
+ rx8581->regmap = devm_regmap_init_i2c(client, &config);
+ if (IS_ERR(rx8581->regmap))
+ return PTR_ERR(rx8581->regmap);
- if (IS_ERR(rx8581->rtc)) {
- dev_err(&client->dev,
- "unable to register the class device\n");
+ rx8581->rtc = devm_rtc_allocate_device(&client->dev);
+ if (IS_ERR(rx8581->rtc))
return PTR_ERR(rx8581->rtc);
- }
- return 0;
+ rx8581->rtc->ops = &rx8581_rtc_ops;
+ rx8581->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ rx8581->rtc->range_max = RTC_TIMESTAMP_END_2099;
+ rx8581->rtc->start_secs = 0;
+ rx8581->rtc->set_start_time = true;
+
+ return rtc_register_device(rx8581->rtc);
}
static const struct i2c_device_id rx8581_id[] = {
diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c
index 00d87d1..deea5c3 100644
--- a/drivers/rtc/rtc-sc27xx.c
+++ b/drivers/rtc/rtc-sc27xx.c
@@ -35,6 +35,8 @@
#define SPRD_RTC_DAY_ALM_VALUE 0x4c
#define SPRD_RTC_SPG_VALUE 0x50
#define SPRD_RTC_SPG_UPD 0x54
+#define SPRD_RTC_PWR_CTRL 0x58
+#define SPRD_RTC_PWR_STS 0x5c
#define SPRD_RTC_SEC_AUXALM_UPD 0x60
#define SPRD_RTC_MIN_AUXALM_UPD 0x64
#define SPRD_RTC_HOUR_AUXALM_UPD 0x68
@@ -86,7 +88,13 @@
/* SPG values definition for SPRD_RTC_SPG_UPD register */
#define SPRD_RTC_POWEROFF_ALM_FLAG BIT(8)
-#define SPRD_RTC_POWER_RESET_FLAG BIT(9)
+
+/* power control/status definition */
+#define SPRD_RTC_POWER_RESET_VALUE 0x96
+#define SPRD_RTC_POWER_STS_CLEAR GENMASK(7, 0)
+#define SPRD_RTC_POWER_STS_SHIFT 8
+#define SPRD_RTC_POWER_STS_VALID \
+ (~SPRD_RTC_POWER_RESET_VALUE << SPRD_RTC_POWER_STS_SHIFT)
/* timeout of synchronizing time and alarm registers (us) */
#define SPRD_RTC_POLL_TIMEOUT 200000
@@ -383,7 +391,6 @@ static int sprd_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct sprd_rtc *rtc = dev_get_drvdata(dev);
time64_t secs = rtc_tm_to_time64(tm);
- u32 val;
int ret;
ret = sprd_rtc_set_secs(rtc, SPRD_RTC_TIME, secs);
@@ -391,27 +398,20 @@ static int sprd_rtc_set_time(struct device *dev, struct rtc_time *tm)
return ret;
if (!rtc->valid) {
- /*
- * Set SPRD_RTC_POWER_RESET_FLAG to indicate now RTC has valid
- * time values.
- */
- ret = regmap_update_bits(rtc->regmap,
- rtc->base + SPRD_RTC_SPG_UPD,
- SPRD_RTC_POWER_RESET_FLAG,
- SPRD_RTC_POWER_RESET_FLAG);
+ /* Clear RTC power status firstly */
+ ret = regmap_write(rtc->regmap, rtc->base + SPRD_RTC_PWR_CTRL,
+ SPRD_RTC_POWER_STS_CLEAR);
if (ret)
return ret;
- ret = regmap_read_poll_timeout(rtc->regmap,
- rtc->base + SPRD_RTC_INT_RAW_STS,
- val, (val & SPRD_RTC_SPG_UPD_EN),
- SPRD_RTC_POLL_DELAY_US,
- SPRD_RTC_POLL_TIMEOUT);
- if (ret) {
- dev_err(rtc->dev, "failed to update SPG value:%d\n",
- ret);
+ /*
+ * Set RTC power status to indicate now RTC has valid time
+ * values.
+ */
+ ret = regmap_write(rtc->regmap, rtc->base + SPRD_RTC_PWR_CTRL,
+ SPRD_RTC_POWER_STS_VALID);
+ if (ret)
return ret;
- }
rtc->valid = true;
}
@@ -562,15 +562,16 @@ static int sprd_rtc_check_power_down(struct sprd_rtc *rtc)
u32 val;
int ret;
- ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_SPG_VALUE, &val);
+ ret = regmap_read(rtc->regmap, rtc->base + SPRD_RTC_PWR_STS, &val);
if (ret)
return ret;
/*
- * If the SPRD_RTC_POWER_RESET_FLAG was not set, which means the RTC has
- * been powered down, so the RTC time values are invalid.
+ * If the RTC power status value is SPRD_RTC_POWER_RESET_VALUE, which
+ * means the RTC has been powered down, so the RTC time values are
+ * invalid.
*/
- rtc->valid = (val & SPRD_RTC_POWER_RESET_FLAG) ? true : false;
+ rtc->valid = val == SPRD_RTC_POWER_RESET_VALUE ? false : true;
return 0;
}
@@ -600,6 +601,10 @@ static int sprd_rtc_probe(struct platform_device *pdev)
return rtc->irq;
}
+ rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(rtc->rtc))
+ return PTR_ERR(rtc->rtc);
+
rtc->dev = &pdev->dev;
platform_set_drvdata(pdev, rtc);
@@ -626,10 +631,14 @@ static int sprd_rtc_probe(struct platform_device *pdev)
return ret;
}
- rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
- &sprd_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc->rtc))
- return PTR_ERR(rtc->rtc);
+ rtc->rtc->ops = &sprd_rtc_ops;
+ rtc->rtc->range_min = 0;
+ rtc->rtc->range_max = 5662310399LL;
+ ret = rtc_register_device(rtc->rtc);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register rtc device\n");
+ return ret;
+ }
device_init_wakeup(&pdev->dev, 1);
return 0;
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 4e8ab37..4f98543 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -359,8 +359,7 @@ static int sh_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct sh_rtc *rtc = platform_get_drvdata(pdev);
+ struct sh_rtc *rtc = dev_get_drvdata(dev);
unsigned int sec128, sec2, yr, yr100, cf_bit;
do {
@@ -419,8 +418,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct sh_rtc *rtc = platform_get_drvdata(pdev);
+ struct sh_rtc *rtc = dev_get_drvdata(dev);
unsigned int tmp;
int year;
@@ -475,8 +473,7 @@ static inline int sh_rtc_read_alarm_value(struct sh_rtc *rtc, int reg_off)
static int sh_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct sh_rtc *rtc = platform_get_drvdata(pdev);
+ struct sh_rtc *rtc = dev_get_drvdata(dev);
struct rtc_time *tm = &wkalrm->time;
spin_lock_irq(&rtc->lock);
@@ -509,8 +506,7 @@ static inline void sh_rtc_write_alarm_value(struct sh_rtc *rtc,
static int sh_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct sh_rtc *rtc = platform_get_drvdata(pdev);
+ struct sh_rtc *rtc = dev_get_drvdata(dev);
unsigned int rcr1;
struct rtc_time *tm = &wkalrm->time;
int mon;
@@ -723,8 +719,7 @@ static int __exit sh_rtc_remove(struct platform_device *pdev)
static void sh_rtc_set_irq_wake(struct device *dev, int enabled)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct sh_rtc *rtc = platform_get_drvdata(pdev);
+ struct sh_rtc *rtc = dev_get_drvdata(dev);
irq_set_irq_wake(rtc->periodic_irq, enabled);
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index 9af591d..8a75cc3 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -1,13 +1,6 @@
-/*
- * Copyright (C) 2011-2012 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
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (C) 2011-2012 Freescale Semiconductor, Inc.
#include <linux/init.h>
#include <linux/io.h>
diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c
index d522266..bee75ca 100644
--- a/drivers/rtc/rtc-st-lpc.c
+++ b/drivers/rtc/rtc-st-lpc.c
@@ -212,6 +212,10 @@ static int st_rtc_probe(struct platform_device *pdev)
if (!rtc)
return -ENOMEM;
+ rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(rtc->rtc_dev))
+ return PTR_ERR(rtc->rtc_dev);
+
spin_lock_init(&rtc->lock);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -253,26 +257,19 @@ static int st_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc);
- rtc->rtc_dev = rtc_device_register("st-lpc-rtc", &pdev->dev,
- &st_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc->rtc_dev)) {
+ rtc->rtc_dev->ops = &st_rtc_ops;
+ rtc->rtc_dev->range_max = U64_MAX;
+ do_div(rtc->rtc_dev->range_max, rtc->clkrate);
+
+ ret = rtc_register_device(rtc->rtc_dev);
+ if (ret) {
clk_disable_unprepare(rtc->clk);
- return PTR_ERR(rtc->rtc_dev);
+ return ret;
}
return 0;
}
-static int st_rtc_remove(struct platform_device *pdev)
-{
- struct st_rtc *rtc = platform_get_drvdata(pdev);
-
- if (likely(rtc->rtc_dev))
- rtc_device_unregister(rtc->rtc_dev);
-
- return 0;
-}
-
#ifdef CONFIG_PM_SLEEP
static int st_rtc_suspend(struct device *dev)
{
@@ -325,7 +322,6 @@ static struct platform_driver st_rtc_platform_driver = {
.of_match_table = st_rtc_match,
},
.probe = st_rtc_probe,
- .remove = st_rtc_remove,
};
module_platform_driver(st_rtc_platform_driver);
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index e70b78d..fccbecb 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -74,8 +74,7 @@ struct rtc_plat_data {
static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
u8 flags;
@@ -97,8 +96,7 @@ static int stk17ta8_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int stk17ta8_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
void __iomem *ioaddr = pdata->ioaddr;
unsigned int year, month, day, hour, minute, second, week;
unsigned int century;
@@ -163,8 +161,7 @@ static void stk17ta8_rtc_update_alarm(struct rtc_plat_data *pdata)
static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
if (pdata->irq <= 0)
return -EINVAL;
@@ -180,8 +177,7 @@ static int stk17ta8_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int stk17ta8_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
if (pdata->irq <= 0)
return -EINVAL;
@@ -217,8 +213,7 @@ static irqreturn_t stk17ta8_rtc_interrupt(int irq, void *dev_id)
static int stk17ta8_rtc_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
+ struct rtc_plat_data *pdata = dev_get_drvdata(dev);
if (pdata->irq <= 0)
return -EINVAL;
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index f25dabe..c5908cf 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) STMicroelectronics SA 2017
- * Author: Amelie Delaunay <amelie.delaunay@st.com> for STMicroelectronics.
- * License terms: GNU General Public License (GPL), version 2
+ * Copyright (C) STMicroelectronics 2017
+ * Author: Amelie Delaunay <amelie.delaunay@st.com>
*/
#include <linux/bcd.h>
@@ -11,20 +11,12 @@
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/pm_wakeirq.h>
#include <linux/regmap.h>
#include <linux/rtc.h>
#define DRIVER_NAME "stm32_rtc"
-/* STM32 RTC registers */
-#define STM32_RTC_TR 0x00
-#define STM32_RTC_DR 0x04
-#define STM32_RTC_CR 0x08
-#define STM32_RTC_ISR 0x0C
-#define STM32_RTC_PRER 0x10
-#define STM32_RTC_ALRMAR 0x1C
-#define STM32_RTC_WPR 0x24
-
/* STM32_RTC_TR bit fields */
#define STM32_RTC_TR_SEC_SHIFT 0
#define STM32_RTC_TR_SEC GENMASK(6, 0)
@@ -48,7 +40,7 @@
#define STM32_RTC_CR_ALRAE BIT(8)
#define STM32_RTC_CR_ALRAIE BIT(12)
-/* STM32_RTC_ISR bit fields */
+/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */
#define STM32_RTC_ISR_ALRAWF BIT(0)
#define STM32_RTC_ISR_INITS BIT(4)
#define STM32_RTC_ISR_RSF BIT(5)
@@ -80,52 +72,87 @@
#define STM32_RTC_ALRMXR_WDAY GENMASK(27, 24)
#define STM32_RTC_ALRMXR_DATE_MASK BIT(31)
+/* STM32_RTC_SR/_SCR bit fields */
+#define STM32_RTC_SR_ALRA BIT(0)
+
+/* STM32_RTC_VERR bit fields */
+#define STM32_RTC_VERR_MINREV_SHIFT 0
+#define STM32_RTC_VERR_MINREV GENMASK(3, 0)
+#define STM32_RTC_VERR_MAJREV_SHIFT 4
+#define STM32_RTC_VERR_MAJREV GENMASK(7, 4)
+
/* STM32_RTC_WPR key constants */
#define RTC_WPR_1ST_KEY 0xCA
#define RTC_WPR_2ND_KEY 0x53
#define RTC_WPR_WRONG_KEY 0xFF
-/*
- * RTC registers are protected against parasitic write access.
- * PWR_CR_DBP bit must be set to enable write access to RTC registers.
- */
-/* STM32_PWR_CR */
-#define PWR_CR 0x00
-/* STM32_PWR_CR bit field */
-#define PWR_CR_DBP BIT(8)
+/* Max STM32 RTC register offset is 0x3FC */
+#define UNDEF_REG 0xFFFF
+
+struct stm32_rtc;
+
+struct stm32_rtc_registers {
+ u16 tr;
+ u16 dr;
+ u16 cr;
+ u16 isr;
+ u16 prer;
+ u16 alrmar;
+ u16 wpr;
+ u16 sr;
+ u16 scr;
+ u16 verr;
+};
+
+struct stm32_rtc_events {
+ u32 alra;
+};
struct stm32_rtc_data {
+ const struct stm32_rtc_registers regs;
+ const struct stm32_rtc_events events;
+ void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags);
bool has_pclk;
+ bool need_dbp;
+ bool has_wakeirq;
};
struct stm32_rtc {
struct rtc_device *rtc_dev;
void __iomem *base;
struct regmap *dbp;
- struct stm32_rtc_data *data;
+ unsigned int dbp_reg;
+ unsigned int dbp_mask;
struct clk *pclk;
struct clk *rtc_ck;
+ const struct stm32_rtc_data *data;
int irq_alarm;
+ int wakeirq_alarm;
};
static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
{
- writel_relaxed(RTC_WPR_1ST_KEY, rtc->base + STM32_RTC_WPR);
- writel_relaxed(RTC_WPR_2ND_KEY, rtc->base + STM32_RTC_WPR);
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
+
+ writel_relaxed(RTC_WPR_1ST_KEY, rtc->base + regs->wpr);
+ writel_relaxed(RTC_WPR_2ND_KEY, rtc->base + regs->wpr);
}
static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc)
{
- writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + STM32_RTC_WPR);
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
+
+ writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + regs->wpr);
}
static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
{
- unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
+ unsigned int isr = readl_relaxed(rtc->base + regs->isr);
if (!(isr & STM32_RTC_ISR_INITF)) {
isr |= STM32_RTC_ISR_INIT;
- writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+ writel_relaxed(isr, rtc->base + regs->isr);
/*
* It takes around 2 rtc_ck clock cycles to enter in
@@ -134,7 +161,7 @@ static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
* 1MHz, we poll every 10 us with a timeout of 100ms.
*/
return readl_relaxed_poll_timeout_atomic(
- rtc->base + STM32_RTC_ISR,
+ rtc->base + regs->isr,
isr, (isr & STM32_RTC_ISR_INITF),
10, 100000);
}
@@ -144,40 +171,50 @@ static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
static void stm32_rtc_exit_init_mode(struct stm32_rtc *rtc)
{
- unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
+ unsigned int isr = readl_relaxed(rtc->base + regs->isr);
isr &= ~STM32_RTC_ISR_INIT;
- writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+ writel_relaxed(isr, rtc->base + regs->isr);
}
static int stm32_rtc_wait_sync(struct stm32_rtc *rtc)
{
- unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
+ unsigned int isr = readl_relaxed(rtc->base + regs->isr);
isr &= ~STM32_RTC_ISR_RSF;
- writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+ writel_relaxed(isr, rtc->base + regs->isr);
/*
* Wait for RSF to be set to ensure the calendar registers are
* synchronised, it takes around 2 rtc_ck clock cycles
*/
- return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
+ return readl_relaxed_poll_timeout_atomic(rtc->base + regs->isr,
isr,
(isr & STM32_RTC_ISR_RSF),
10, 100000);
}
+static void stm32_rtc_clear_event_flags(struct stm32_rtc *rtc,
+ unsigned int flags)
+{
+ rtc->data->clear_events(rtc, flags);
+}
+
static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id)
{
struct stm32_rtc *rtc = (struct stm32_rtc *)dev_id;
- unsigned int isr, cr;
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
+ const struct stm32_rtc_events *evts = &rtc->data->events;
+ unsigned int status, cr;
mutex_lock(&rtc->rtc_dev->ops_lock);
- isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
- cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+ status = readl_relaxed(rtc->base + regs->sr);
+ cr = readl_relaxed(rtc->base + regs->cr);
- if ((isr & STM32_RTC_ISR_ALRAF) &&
+ if ((status & evts->alra) &&
(cr & STM32_RTC_CR_ALRAIE)) {
/* Alarm A flag - Alarm interrupt */
dev_dbg(&rtc->rtc_dev->dev, "Alarm occurred\n");
@@ -185,9 +222,8 @@ static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id)
/* Pass event to the kernel */
rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
- /* Clear event flag, otherwise new events won't be received */
- writel_relaxed(isr & ~STM32_RTC_ISR_ALRAF,
- rtc->base + STM32_RTC_ISR);
+ /* Clear event flags, otherwise new events won't be received */
+ stm32_rtc_clear_event_flags(rtc, evts->alra);
}
mutex_unlock(&rtc->rtc_dev->ops_lock);
@@ -234,11 +270,12 @@ static void bcd2tm(struct rtc_time *tm)
static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
unsigned int tr, dr;
/* Time and Date in BCD format */
- tr = readl_relaxed(rtc->base + STM32_RTC_TR);
- dr = readl_relaxed(rtc->base + STM32_RTC_DR);
+ tr = readl_relaxed(rtc->base + regs->tr);
+ dr = readl_relaxed(rtc->base + regs->dr);
tm->tm_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
tm->tm_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
@@ -259,6 +296,7 @@ static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
unsigned int tr, dr;
int ret = 0;
@@ -283,8 +321,8 @@ static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm)
goto end;
}
- writel_relaxed(tr, rtc->base + STM32_RTC_TR);
- writel_relaxed(dr, rtc->base + STM32_RTC_DR);
+ writel_relaxed(tr, rtc->base + regs->tr);
+ writel_relaxed(dr, rtc->base + regs->dr);
stm32_rtc_exit_init_mode(rtc);
@@ -298,12 +336,14 @@ end:
static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
+ const struct stm32_rtc_events *evts = &rtc->data->events;
struct rtc_time *tm = &alrm->time;
- unsigned int alrmar, cr, isr;
+ unsigned int alrmar, cr, status;
- alrmar = readl_relaxed(rtc->base + STM32_RTC_ALRMAR);
- cr = readl_relaxed(rtc->base + STM32_RTC_CR);
- isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+ alrmar = readl_relaxed(rtc->base + regs->alrmar);
+ cr = readl_relaxed(rtc->base + regs->cr);
+ status = readl_relaxed(rtc->base + regs->sr);
if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) {
/*
@@ -356,7 +396,7 @@ static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
bcd2tm(tm);
alrm->enabled = (cr & STM32_RTC_CR_ALRAE) ? 1 : 0;
- alrm->pending = (isr & STM32_RTC_ISR_ALRAF) ? 1 : 0;
+ alrm->pending = (status & evts->alra) ? 1 : 0;
return 0;
}
@@ -364,9 +404,11 @@ static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct stm32_rtc *rtc = dev_get_drvdata(dev);
- unsigned int isr, cr;
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
+ const struct stm32_rtc_events *evts = &rtc->data->events;
+ unsigned int cr;
- cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+ cr = readl_relaxed(rtc->base + regs->cr);
stm32_rtc_wpr_unlock(rtc);
@@ -375,12 +417,10 @@ static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
cr |= (STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
else
cr &= ~(STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
- writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+ writel_relaxed(cr, rtc->base + regs->cr);
- /* Clear event flag, otherwise new events won't be received */
- isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
- isr &= ~STM32_RTC_ISR_ALRAF;
- writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+ /* Clear event flags, otherwise new events won't be received */
+ stm32_rtc_clear_event_flags(rtc, evts->alra);
stm32_rtc_wpr_lock(rtc);
@@ -389,9 +429,10 @@ static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm)
{
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
int cur_day, cur_mon, cur_year, cur_hour, cur_min, cur_sec;
- unsigned int dr = readl_relaxed(rtc->base + STM32_RTC_DR);
- unsigned int tr = readl_relaxed(rtc->base + STM32_RTC_TR);
+ unsigned int dr = readl_relaxed(rtc->base + regs->dr);
+ unsigned int tr = readl_relaxed(rtc->base + regs->tr);
cur_day = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
cur_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
@@ -425,6 +466,7 @@ static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm)
static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
struct rtc_time *tm = &alrm->time;
unsigned int cr, isr, alrmar;
int ret = 0;
@@ -456,15 +498,15 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
stm32_rtc_wpr_unlock(rtc);
/* Disable Alarm */
- cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+ cr = readl_relaxed(rtc->base + regs->cr);
cr &= ~STM32_RTC_CR_ALRAE;
- writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+ writel_relaxed(cr, rtc->base + regs->cr);
/*
* Poll Alarm write flag to be sure that Alarm update is allowed: it
* takes around 2 rtc_ck clock cycles
*/
- ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
+ ret = readl_relaxed_poll_timeout_atomic(rtc->base + regs->isr,
isr,
(isr & STM32_RTC_ISR_ALRAWF),
10, 100000);
@@ -475,7 +517,7 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
/* Write to Alarm register */
- writel_relaxed(alrmar, rtc->base + STM32_RTC_ALRMAR);
+ writel_relaxed(alrmar, rtc->base + regs->alrmar);
if (alrm->enabled)
stm32_rtc_alarm_irq_enable(dev, 1);
@@ -496,17 +538,95 @@ static const struct rtc_class_ops stm32_rtc_ops = {
.alarm_irq_enable = stm32_rtc_alarm_irq_enable,
};
+static void stm32_rtc_clear_events(struct stm32_rtc *rtc,
+ unsigned int flags)
+{
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
+
+ /* Flags are cleared by writing 0 in RTC_ISR */
+ writel_relaxed(readl_relaxed(rtc->base + regs->isr) & ~flags,
+ rtc->base + regs->isr);
+}
+
static const struct stm32_rtc_data stm32_rtc_data = {
.has_pclk = false,
+ .need_dbp = true,
+ .has_wakeirq = false,
+ .regs = {
+ .tr = 0x00,
+ .dr = 0x04,
+ .cr = 0x08,
+ .isr = 0x0C,
+ .prer = 0x10,
+ .alrmar = 0x1C,
+ .wpr = 0x24,
+ .sr = 0x0C, /* set to ISR offset to ease alarm management */
+ .scr = UNDEF_REG,
+ .verr = UNDEF_REG,
+ },
+ .events = {
+ .alra = STM32_RTC_ISR_ALRAF,
+ },
+ .clear_events = stm32_rtc_clear_events,
};
static const struct stm32_rtc_data stm32h7_rtc_data = {
.has_pclk = true,
+ .need_dbp = true,
+ .has_wakeirq = false,
+ .regs = {
+ .tr = 0x00,
+ .dr = 0x04,
+ .cr = 0x08,
+ .isr = 0x0C,
+ .prer = 0x10,
+ .alrmar = 0x1C,
+ .wpr = 0x24,
+ .sr = 0x0C, /* set to ISR offset to ease alarm management */
+ .scr = UNDEF_REG,
+ .verr = UNDEF_REG,
+ },
+ .events = {
+ .alra = STM32_RTC_ISR_ALRAF,
+ },
+ .clear_events = stm32_rtc_clear_events,
+};
+
+static void stm32mp1_rtc_clear_events(struct stm32_rtc *rtc,
+ unsigned int flags)
+{
+ struct stm32_rtc_registers regs = rtc->data->regs;
+
+ /* Flags are cleared by writing 1 in RTC_SCR */
+ writel_relaxed(flags, rtc->base + regs.scr);
+}
+
+static const struct stm32_rtc_data stm32mp1_data = {
+ .has_pclk = true,
+ .need_dbp = false,
+ .has_wakeirq = true,
+ .regs = {
+ .tr = 0x00,
+ .dr = 0x04,
+ .cr = 0x18,
+ .isr = 0x0C, /* named RTC_ICSR on stm32mp1 */
+ .prer = 0x10,
+ .alrmar = 0x40,
+ .wpr = 0x24,
+ .sr = 0x50,
+ .scr = 0x5C,
+ .verr = 0x3F4,
+ },
+ .events = {
+ .alra = STM32_RTC_SR_ALRA,
+ },
+ .clear_events = stm32mp1_rtc_clear_events,
};
static const struct of_device_id stm32_rtc_of_match[] = {
{ .compatible = "st,stm32-rtc", .data = &stm32_rtc_data },
{ .compatible = "st,stm32h7-rtc", .data = &stm32h7_rtc_data },
+ { .compatible = "st,stm32mp1-rtc", .data = &stm32mp1_data },
{}
};
MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
@@ -514,6 +634,7 @@ MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
static int stm32_rtc_init(struct platform_device *pdev,
struct stm32_rtc *rtc)
{
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
unsigned int rate;
int ret = 0;
@@ -554,14 +675,14 @@ static int stm32_rtc_init(struct platform_device *pdev,
}
prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S;
- writel_relaxed(prer, rtc->base + STM32_RTC_PRER);
+ writel_relaxed(prer, rtc->base + regs->prer);
prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
- writel_relaxed(prer, rtc->base + STM32_RTC_PRER);
+ writel_relaxed(prer, rtc->base + regs->prer);
/* Force 24h time format */
- cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+ cr = readl_relaxed(rtc->base + regs->cr);
cr &= ~STM32_RTC_CR_FMT;
- writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+ writel_relaxed(cr, rtc->base + regs->cr);
stm32_rtc_exit_init_mode(rtc);
@@ -575,8 +696,8 @@ end:
static int stm32_rtc_probe(struct platform_device *pdev)
{
struct stm32_rtc *rtc;
+ const struct stm32_rtc_registers *regs;
struct resource *res;
- const struct of_device_id *match;
int ret;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
@@ -588,15 +709,32 @@ static int stm32_rtc_probe(struct platform_device *pdev)
if (IS_ERR(rtc->base))
return PTR_ERR(rtc->base);
- rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
- "st,syscfg");
- if (IS_ERR(rtc->dbp)) {
- dev_err(&pdev->dev, "no st,syscfg\n");
- return PTR_ERR(rtc->dbp);
- }
+ rtc->data = (struct stm32_rtc_data *)
+ of_device_get_match_data(&pdev->dev);
+ regs = &rtc->data->regs;
+
+ if (rtc->data->need_dbp) {
+ rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "st,syscfg");
+ if (IS_ERR(rtc->dbp)) {
+ dev_err(&pdev->dev, "no st,syscfg\n");
+ return PTR_ERR(rtc->dbp);
+ }
+
+ ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg",
+ 1, &rtc->dbp_reg);
+ if (ret) {
+ dev_err(&pdev->dev, "can't read DBP register offset\n");
+ return ret;
+ }
- match = of_match_device(stm32_rtc_of_match, &pdev->dev);
- rtc->data = (struct stm32_rtc_data *)match->data;
+ ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg",
+ 2, &rtc->dbp_mask);
+ if (ret) {
+ dev_err(&pdev->dev, "can't read DBP register mask\n");
+ return ret;
+ }
+ }
if (!rtc->data->has_pclk) {
rtc->pclk = NULL;
@@ -624,11 +762,13 @@ static int stm32_rtc_probe(struct platform_device *pdev)
if (ret)
goto err;
- regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
+ if (rtc->data->need_dbp)
+ regmap_update_bits(rtc->dbp, rtc->dbp_reg,
+ rtc->dbp_mask, rtc->dbp_mask);
/*
* After a system reset, RTC_ISR.INITS flag can be read to check if
- * the calendar has been initalized or not. INITS flag is reset by a
+ * the calendar has been initialized or not. INITS flag is reset by a
* power-on reset (no vbat, no power-supply). It is not reset if
* rtc_ck parent clock has changed (so RTC prescalers need to be
* changed). That's why we cannot rely on this flag to know if RTC
@@ -645,15 +785,22 @@ static int stm32_rtc_probe(struct platform_device *pdev)
goto err;
}
- platform_set_drvdata(pdev, rtc);
-
ret = device_init_wakeup(&pdev->dev, true);
+ if (rtc->data->has_wakeirq) {
+ rtc->wakeirq_alarm = platform_get_irq(pdev, 1);
+ if (rtc->wakeirq_alarm <= 0)
+ ret = rtc->wakeirq_alarm;
+ else
+ ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
+ rtc->wakeirq_alarm);
+ }
if (ret)
- dev_warn(&pdev->dev,
- "alarm won't be able to wake up the system");
+ dev_warn(&pdev->dev, "alarm can't wake up the system: %d", ret);
+
+ platform_set_drvdata(pdev, rtc);
rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
- &stm32_rtc_ops, THIS_MODULE);
+ &stm32_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc_dev)) {
ret = PTR_ERR(rtc->rtc_dev);
dev_err(&pdev->dev, "rtc device registration failed, err=%d\n",
@@ -663,8 +810,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
/* Handle RTC alarm interrupts */
ret = devm_request_threaded_irq(&pdev->dev, rtc->irq_alarm, NULL,
- stm32_rtc_alarm_irq,
- IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ stm32_rtc_alarm_irq, IRQF_ONESHOT,
pdev->name, rtc);
if (ret) {
dev_err(&pdev->dev, "IRQ%d (alarm interrupt) already claimed\n",
@@ -676,17 +822,27 @@ static int stm32_rtc_probe(struct platform_device *pdev)
* If INITS flag is reset (calendar year field set to 0x00), calendar
* must be initialized
*/
- if (!(readl_relaxed(rtc->base + STM32_RTC_ISR) & STM32_RTC_ISR_INITS))
+ if (!(readl_relaxed(rtc->base + regs->isr) & STM32_RTC_ISR_INITS))
dev_warn(&pdev->dev, "Date/Time must be initialized\n");
+ if (regs->verr != UNDEF_REG) {
+ u32 ver = readl_relaxed(rtc->base + regs->verr);
+
+ dev_info(&pdev->dev, "registered rev:%d.%d\n",
+ (ver >> STM32_RTC_VERR_MAJREV_SHIFT) & 0xF,
+ (ver >> STM32_RTC_VERR_MINREV_SHIFT) & 0xF);
+ }
+
return 0;
err:
if (rtc->data->has_pclk)
clk_disable_unprepare(rtc->pclk);
clk_disable_unprepare(rtc->rtc_ck);
- regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
+ if (rtc->data->need_dbp)
+ regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
+ dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
return ret;
@@ -695,22 +851,25 @@ err:
static int stm32_rtc_remove(struct platform_device *pdev)
{
struct stm32_rtc *rtc = platform_get_drvdata(pdev);
+ const struct stm32_rtc_registers *regs = &rtc->data->regs;
unsigned int cr;
/* Disable interrupts */
stm32_rtc_wpr_unlock(rtc);
- cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+ cr = readl_relaxed(rtc->base + regs->cr);
cr &= ~STM32_RTC_CR_ALRAIE;
- writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+ writel_relaxed(cr, rtc->base + regs->cr);
stm32_rtc_wpr_lock(rtc);
clk_disable_unprepare(rtc->rtc_ck);
if (rtc->data->has_pclk)
clk_disable_unprepare(rtc->pclk);
- /* Enable backup domain write protection */
- regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
+ /* Enable backup domain write protection if needed */
+ if (rtc->data->need_dbp)
+ regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
+ dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
return 0;
diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c
index 2e6fb27..2cd5a7b 100644
--- a/drivers/rtc/rtc-sun6i.c
+++ b/drivers/rtc/rtc-sun6i.c
@@ -74,7 +74,7 @@
#define SUN6I_ALARM_CONFIG_WAKEUP BIT(0)
#define SUN6I_LOSC_OUT_GATING 0x0060
-#define SUN6I_LOSC_OUT_GATING_EN BIT(0)
+#define SUN6I_LOSC_OUT_GATING_EN_OFFSET 0
/*
* Get date values
@@ -255,7 +255,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node)
&clkout_name);
rtc->ext_losc = clk_register_gate(NULL, clkout_name, rtc->hw.init->name,
0, rtc->base + SUN6I_LOSC_OUT_GATING,
- SUN6I_LOSC_OUT_GATING_EN, 0,
+ SUN6I_LOSC_OUT_GATING_EN_OFFSET, 0,
&rtc->lock);
if (IS_ERR(rtc->ext_losc)) {
pr_crit("Couldn't register the LOSC external gate\n");
diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c
index dadbf8b..21865d3 100644
--- a/drivers/rtc/rtc-sunxi.c
+++ b/drivers/rtc/rtc-sunxi.c
@@ -445,6 +445,10 @@ static int sunxi_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, chip);
chip->dev = &pdev->dev;
+ chip->rtc = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(chip->rtc))
+ return PTR_ERR(chip->rtc);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
chip->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(chip->base))
@@ -481,11 +485,12 @@ static int sunxi_rtc_probe(struct platform_device *pdev)
writel(SUNXI_ALRM_IRQ_STA_CNT_IRQ_PEND, chip->base +
SUNXI_ALRM_IRQ_STA);
- chip->rtc = rtc_device_register("rtc-sunxi", &pdev->dev,
- &sunxi_rtc_ops, THIS_MODULE);
- if (IS_ERR(chip->rtc)) {
+ chip->rtc->ops = &sunxi_rtc_ops;
+
+ ret = rtc_register_device(chip->rtc);
+ if (ret) {
dev_err(&pdev->dev, "unable to register device\n");
- return PTR_ERR(chip->rtc);
+ return ret;
}
dev_info(&pdev->dev, "RTC enabled\n");
@@ -493,18 +498,8 @@ static int sunxi_rtc_probe(struct platform_device *pdev)
return 0;
}
-static int sunxi_rtc_remove(struct platform_device *pdev)
-{
- struct sunxi_rtc_dev *chip = platform_get_drvdata(pdev);
-
- rtc_device_unregister(chip->rtc);
-
- return 0;
-}
-
static struct platform_driver sunxi_rtc_driver = {
.probe = sunxi_rtc_probe,
- .remove = sunxi_rtc_remove,
.driver = {
.name = "sunxi-rtc",
.of_match_table = sunxi_rtc_dt_ids,
diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c
index 3a2da4c..8469256 100644
--- a/drivers/rtc/rtc-test.c
+++ b/drivers/rtc/rtc-test.c
@@ -13,135 +13,139 @@
#include <linux/rtc.h>
#include <linux/platform_device.h>
-static int test_mmss64;
-module_param(test_mmss64, int, 0644);
-MODULE_PARM_DESC(test_mmss64, "Test struct rtc_class_ops.set_mmss64().");
+#define MAX_RTC_TEST 3
-static struct platform_device *test0 = NULL, *test1 = NULL;
+struct rtc_test_data {
+ struct rtc_device *rtc;
+ time64_t offset;
+ struct timer_list alarm;
+ bool alarm_en;
+};
-static int test_rtc_read_alarm(struct device *dev,
- struct rtc_wkalrm *alrm)
-{
- return 0;
-}
+struct platform_device *pdev[MAX_RTC_TEST];
-static int test_rtc_set_alarm(struct device *dev,
- struct rtc_wkalrm *alrm)
+static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- return 0;
-}
+ struct rtc_test_data *rtd = dev_get_drvdata(dev);
+ time64_t alarm;
+
+ alarm = (rtd->alarm.expires - jiffies) / HZ;
+ alarm += ktime_get_real_seconds() + rtd->offset;
+
+ rtc_time64_to_tm(alarm, &alrm->time);
+ alrm->enabled = rtd->alarm_en;
-static int test_rtc_read_time(struct device *dev,
- struct rtc_time *tm)
-{
- rtc_time64_to_tm(ktime_get_real_seconds(), tm);
return 0;
}
-static int test_rtc_set_mmss64(struct device *dev, time64_t secs)
+static int test_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- dev_info(dev, "%s, secs = %lld\n", __func__, (long long)secs);
+ struct rtc_test_data *rtd = dev_get_drvdata(dev);
+ ktime_t timeout;
+ u64 expires;
+
+ timeout = rtc_tm_to_time64(&alrm->time) - ktime_get_real_seconds();
+ timeout -= rtd->offset;
+
+ del_timer(&rtd->alarm);
+
+ expires = jiffies + timeout * HZ;
+ if (expires > U32_MAX)
+ expires = U32_MAX;
+
+ pr_err("ABE: %s +%d %s\n", __FILE__, __LINE__, __func__);
+ rtd->alarm.expires = expires;
+
+ if (alrm->enabled)
+ add_timer(&rtd->alarm);
+
+ rtd->alarm_en = alrm->enabled;
+
return 0;
}
-static int test_rtc_set_mmss(struct device *dev, unsigned long secs)
+static int test_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- dev_info(dev, "%s, secs = %lu\n", __func__, secs);
+ struct rtc_test_data *rtd = dev_get_drvdata(dev);
+
+ rtc_time64_to_tm(ktime_get_real_seconds() + rtd->offset, tm);
+
return 0;
}
-static int test_rtc_proc(struct device *dev, struct seq_file *seq)
+static int test_rtc_set_mmss64(struct device *dev, time64_t secs)
{
- struct platform_device *plat_dev = to_platform_device(dev);
+ struct rtc_test_data *rtd = dev_get_drvdata(dev);
- seq_printf(seq, "test\t\t: yes\n");
- seq_printf(seq, "id\t\t: %d\n", plat_dev->id);
+ rtd->offset = secs - ktime_get_real_seconds();
return 0;
}
static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
{
+ struct rtc_test_data *rtd = dev_get_drvdata(dev);
+
+ rtd->alarm_en = enable;
+ if (enable)
+ add_timer(&rtd->alarm);
+ else
+ del_timer(&rtd->alarm);
+
return 0;
}
-static struct rtc_class_ops test_rtc_ops = {
- .proc = test_rtc_proc,
+static const struct rtc_class_ops test_rtc_ops_noalm = {
+ .read_time = test_rtc_read_time,
+ .set_mmss64 = test_rtc_set_mmss64,
+ .alarm_irq_enable = test_rtc_alarm_irq_enable,
+};
+
+static const struct rtc_class_ops test_rtc_ops = {
.read_time = test_rtc_read_time,
.read_alarm = test_rtc_read_alarm,
.set_alarm = test_rtc_set_alarm,
- .set_mmss = test_rtc_set_mmss,
+ .set_mmss64 = test_rtc_set_mmss64,
.alarm_irq_enable = test_rtc_alarm_irq_enable,
};
-static ssize_t test_irq_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static void test_rtc_alarm_handler(struct timer_list *t)
{
- return sprintf(buf, "%d\n", 42);
-}
-static ssize_t test_irq_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int retval;
- struct platform_device *plat_dev = to_platform_device(dev);
- struct rtc_device *rtc = platform_get_drvdata(plat_dev);
-
- retval = count;
- if (strncmp(buf, "tick", 4) == 0 && rtc->pie_enabled)
- rtc_update_irq(rtc, 1, RTC_PF | RTC_IRQF);
- else if (strncmp(buf, "alarm", 5) == 0) {
- struct rtc_wkalrm alrm;
- int err = rtc_read_alarm(rtc, &alrm);
-
- if (!err && alrm.enabled)
- rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
-
- } else if (strncmp(buf, "update", 6) == 0 && rtc->uie_rtctimer.enabled)
- rtc_update_irq(rtc, 1, RTC_UF | RTC_IRQF);
- else
- retval = -EINVAL;
+ struct rtc_test_data *rtd = from_timer(rtd, t, alarm);
- return retval;
+ rtc_update_irq(rtd->rtc, 1, RTC_AF | RTC_IRQF);
}
-static DEVICE_ATTR(irq, S_IRUGO | S_IWUSR, test_irq_show, test_irq_store);
static int test_probe(struct platform_device *plat_dev)
{
- int err;
- struct rtc_device *rtc;
-
- if (test_mmss64) {
- test_rtc_ops.set_mmss64 = test_rtc_set_mmss64;
- test_rtc_ops.set_mmss = NULL;
- }
+ struct rtc_test_data *rtd;
- rtc = devm_rtc_device_register(&plat_dev->dev, "test",
- &test_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc)) {
- return PTR_ERR(rtc);
- }
+ rtd = devm_kzalloc(&plat_dev->dev, sizeof(*rtd), GFP_KERNEL);
+ if (!rtd)
+ return -ENOMEM;
- err = device_create_file(&plat_dev->dev, &dev_attr_irq);
- if (err)
- dev_err(&plat_dev->dev, "Unable to create sysfs entry: %s\n",
- dev_attr_irq.attr.name);
+ platform_set_drvdata(plat_dev, rtd);
- platform_set_drvdata(plat_dev, rtc);
+ rtd->rtc = devm_rtc_allocate_device(&plat_dev->dev);
+ if (IS_ERR(rtd->rtc))
+ return PTR_ERR(rtd->rtc);
- return 0;
-}
+ switch (plat_dev->id) {
+ case 0:
+ rtd->rtc->ops = &test_rtc_ops_noalm;
+ break;
+ default:
+ rtd->rtc->ops = &test_rtc_ops;
+ }
-static int test_remove(struct platform_device *plat_dev)
-{
- device_remove_file(&plat_dev->dev, &dev_attr_irq);
+ timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0);
+ rtd->alarm.expires = 0;
- return 0;
+ return rtc_register_device(rtd->rtc);
}
static struct platform_driver test_driver = {
.probe = test_probe,
- .remove = test_remove,
.driver = {
.name = "rtc-test",
},
@@ -149,47 +153,45 @@ static struct platform_driver test_driver = {
static int __init test_init(void)
{
- int err;
+ int i, err;
if ((err = platform_driver_register(&test_driver)))
return err;
- if ((test0 = platform_device_alloc("rtc-test", 0)) == NULL) {
- err = -ENOMEM;
- goto exit_driver_unregister;
+ err = -ENOMEM;
+ for (i = 0; i < MAX_RTC_TEST; i++) {
+ pdev[i] = platform_device_alloc("rtc-test", i);
+ if (!pdev[i])
+ goto exit_free_mem;
}
- if ((test1 = platform_device_alloc("rtc-test", 1)) == NULL) {
- err = -ENOMEM;
- goto exit_put_test0;
+ for (i = 0; i < MAX_RTC_TEST; i++) {
+ err = platform_device_add(pdev[i]);
+ if (err)
+ goto exit_device_del;
}
- if ((err = platform_device_add(test0)))
- goto exit_put_test1;
-
- if ((err = platform_device_add(test1)))
- goto exit_del_test0;
-
return 0;
-exit_del_test0:
- platform_device_del(test0);
-
-exit_put_test1:
- platform_device_put(test1);
+exit_device_del:
+ for (; i > 0; i--)
+ platform_device_del(pdev[i - 1]);
-exit_put_test0:
- platform_device_put(test0);
+exit_free_mem:
+ for (i = 0; i < MAX_RTC_TEST; i++)
+ platform_device_put(pdev[i]);
-exit_driver_unregister:
platform_driver_unregister(&test_driver);
return err;
}
static void __exit test_exit(void)
{
- platform_device_unregister(test0);
- platform_device_unregister(test1);
+ int i;
+
+ for (i = 0; i < MAX_RTC_TEST; i++)
+ platform_device_unregister(pdev[i]);
+
platform_driver_unregister(&test_driver);
}
diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c
index d7785ae..d6434e5 100644
--- a/drivers/rtc/rtc-tps6586x.c
+++ b/drivers/rtc/rtc-tps6586x.c
@@ -58,7 +58,6 @@ struct tps6586x_rtc {
struct rtc_device *rtc;
int irq;
bool irq_en;
- unsigned long long epoch_start;
};
static inline struct device *to_tps6586x_dev(struct device *dev)
@@ -68,10 +67,9 @@ static inline struct device *to_tps6586x_dev(struct device *dev)
static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
struct device *tps_dev = to_tps6586x_dev(dev);
unsigned long long ticks = 0;
- unsigned long seconds;
+ time64_t seconds;
u8 buff[6];
int ret;
int i;
@@ -88,26 +86,20 @@ static int tps6586x_rtc_read_time(struct device *dev, struct rtc_time *tm)
}
seconds = ticks >> 10;
- seconds += rtc->epoch_start;
- rtc_time_to_tm(seconds, tm);
+ rtc_time64_to_tm(seconds, tm);
+
return 0;
}
static int tps6586x_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
struct device *tps_dev = to_tps6586x_dev(dev);
unsigned long long ticks;
- unsigned long seconds;
+ time64_t seconds;
u8 buff[5];
int ret;
- rtc_tm_to_time(tm, &seconds);
- if (seconds < rtc->epoch_start) {
- dev_err(dev, "requested time unsupported\n");
- return -EINVAL;
- }
- seconds -= rtc->epoch_start;
+ seconds = rtc_tm_to_time64(tm);
ticks = (unsigned long long)seconds << 10;
buff[0] = (ticks >> 32) & 0xff;
@@ -155,9 +147,8 @@ static int tps6586x_rtc_alarm_irq_enable(struct device *dev,
static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
struct device *tps_dev = to_tps6586x_dev(dev);
- unsigned long seconds;
+ time64_t seconds;
unsigned long ticks;
unsigned long rtc_current_time;
unsigned long long rticks = 0;
@@ -166,12 +157,7 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
int ret;
int i;
- rtc_tm_to_time(&alrm->time, &seconds);
-
- if (alrm->enabled && (seconds < rtc->epoch_start)) {
- dev_err(dev, "can't set alarm to requested time\n");
- return -EINVAL;
- }
+ seconds = rtc_tm_to_time64(&alrm->time);
ret = tps6586x_rtc_alarm_irq_enable(dev, alrm->enabled);
if (ret < 0) {
@@ -179,7 +165,6 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret;
}
- seconds -= rtc->epoch_start;
ret = tps6586x_reads(tps_dev, RTC_COUNT4_DUMMYREAD,
sizeof(rbuff), rbuff);
if (ret < 0) {
@@ -210,10 +195,9 @@ static int tps6586x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct tps6586x_rtc *rtc = dev_get_drvdata(dev);
struct device *tps_dev = to_tps6586x_dev(dev);
unsigned long ticks;
- unsigned long seconds;
+ time64_t seconds;
u8 buff[3];
int ret;
@@ -225,9 +209,8 @@ static int tps6586x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
ticks = (buff[0] << 16) | (buff[1] << 8) | buff[2];
seconds = ticks >> 10;
- seconds += rtc->epoch_start;
- rtc_time_to_tm(seconds, &alrm->time);
+ rtc_time64_to_tm(seconds, &alrm->time);
return 0;
}
@@ -260,9 +243,6 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
rtc->dev = &pdev->dev;
rtc->irq = platform_get_irq(pdev, 0);
- /* Set epoch start as 00:00:00:01:01:2009 */
- rtc->epoch_start = mktime(2009, 1, 1, 0, 0, 0);
-
/* 1 kHz tick mode, enable tick counting */
ret = tps6586x_update(tps_dev, RTC_CTRL,
RTC_ENABLE | OSC_SRC_SEL |
@@ -276,14 +256,18 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1);
platform_set_drvdata(pdev, rtc);
- rtc->rtc = devm_rtc_device_register(&pdev->dev, dev_name(&pdev->dev),
- &tps6586x_rtc_ops, THIS_MODULE);
+ rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc->rtc)) {
ret = PTR_ERR(rtc->rtc);
- dev_err(&pdev->dev, "RTC device register: ret %d\n", ret);
+ dev_err(&pdev->dev, "RTC allocate device: ret %d\n", ret);
goto fail_rtc_register;
}
+ rtc->rtc->ops = &tps6586x_rtc_ops;
+ rtc->rtc->range_max = (1ULL << 30) - 1; /* 30-bit seconds */
+ rtc->rtc->start_secs = mktime64(2009, 1, 1, 0, 0, 0);
+ rtc->rtc->set_start_time = true;
+
ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
tps6586x_rtc_irq,
IRQF_ONESHOT,
@@ -294,6 +278,13 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
goto fail_rtc_register;
}
disable_irq(rtc->irq);
+
+ ret = rtc_register_device(rtc->rtc);
+ if (ret) {
+ dev_err(&pdev->dev, "RTC device register: ret %d\n", ret);
+ goto fail_rtc_register;
+ }
+
return 0;
fail_rtc_register:
diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c
index d0244d7..a9bbd022 100644
--- a/drivers/rtc/rtc-tps65910.c
+++ b/drivers/rtc/rtc-tps65910.c
@@ -380,6 +380,10 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
if (!tps_rtc)
return -ENOMEM;
+ tps_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(tps_rtc->rtc))
+ return PTR_ERR(tps_rtc->rtc);
+
/* Clear pending interrupts */
ret = regmap_read(tps65910->regmap, TPS65910_RTC_STATUS, &rtc_reg);
if (ret < 0)
@@ -421,10 +425,12 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
tps_rtc->irq = irq;
device_set_wakeup_capable(&pdev->dev, 1);
- tps_rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
- &tps65910_rtc_ops, THIS_MODULE);
- if (IS_ERR(tps_rtc->rtc)) {
- ret = PTR_ERR(tps_rtc->rtc);
+ tps_rtc->rtc->ops = &tps65910_rtc_ops;
+ tps_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ tps_rtc->rtc->range_max = RTC_TIMESTAMP_END_2099;
+
+ ret = rtc_register_device(tps_rtc->rtc);
+ if (ret) {
dev_err(&pdev->dev, "RTC device register: err %d\n", ret);
return ret;
}
@@ -432,17 +438,6 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
return 0;
}
-/*
- * Disable tps65910 RTC interrupts.
- * Sets status flag to free.
- */
-static int tps65910_rtc_remove(struct platform_device *pdev)
-{
- tps65910_rtc_alarm_irq_enable(&pdev->dev, 0);
-
- return 0;
-}
-
#ifdef CONFIG_PM_SLEEP
static int tps65910_rtc_suspend(struct device *dev)
{
@@ -468,7 +463,6 @@ static SIMPLE_DEV_PM_OPS(tps65910_rtc_pm_ops, tps65910_rtc_suspend,
static struct platform_driver tps65910_rtc_driver = {
.probe = tps65910_rtc_probe,
- .remove = tps65910_rtc_remove,
.driver = {
.name = "tps65910-rtc",
.pm = &tps65910_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c
index 7ce2296..70f013e 100644
--- a/drivers/rtc/rtc-vr41xx.c
+++ b/drivers/rtc/rtc-vr41xx.c
@@ -88,7 +88,7 @@ static unsigned int alarm_enabled;
static int aie_irq;
static int pie_irq;
-static inline unsigned long read_elapsed_second(void)
+static inline time64_t read_elapsed_second(void)
{
unsigned long first_low, first_mid, first_high;
@@ -105,10 +105,10 @@ static inline unsigned long read_elapsed_second(void)
} while (first_low != second_low || first_mid != second_mid ||
first_high != second_high);
- return (first_high << 17) | (first_mid << 1) | (first_low >> 15);
+ return ((u64)first_high << 17) | (first_mid << 1) | (first_low >> 15);
}
-static inline void write_elapsed_second(unsigned long sec)
+static inline void write_elapsed_second(time64_t sec)
{
spin_lock_irq(&rtc_lock);
@@ -121,22 +121,22 @@ static inline void write_elapsed_second(unsigned long sec)
static int vr41xx_rtc_read_time(struct device *dev, struct rtc_time *time)
{
- unsigned long epoch_sec, elapsed_sec;
+ time64_t epoch_sec, elapsed_sec;
- epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
+ epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0);
elapsed_sec = read_elapsed_second();
- rtc_time_to_tm(epoch_sec + elapsed_sec, time);
+ rtc_time64_to_tm(epoch_sec + elapsed_sec, time);
return 0;
}
static int vr41xx_rtc_set_time(struct device *dev, struct rtc_time *time)
{
- unsigned long epoch_sec, current_sec;
+ time64_t epoch_sec, current_sec;
- epoch_sec = mktime(epoch, 1, 1, 0, 0, 0);
- current_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+ epoch_sec = mktime64(epoch, 1, 1, 0, 0, 0);
+ current_sec = mktime64(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
time->tm_hour, time->tm_min, time->tm_sec);
write_elapsed_second(current_sec - epoch_sec);
@@ -165,11 +165,11 @@ static int vr41xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
static int vr41xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
{
- unsigned long alarm_sec;
+ time64_t alarm_sec;
struct rtc_time *time = &wkalrm->time;
- alarm_sec = mktime(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
- time->tm_hour, time->tm_min, time->tm_sec);
+ alarm_sec = mktime64(time->tm_year + 1900, time->tm_mon + 1, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
spin_lock_irq(&rtc_lock);
@@ -292,13 +292,16 @@ static int rtc_probe(struct platform_device *pdev)
goto err_rtc1_iounmap;
}
- rtc = devm_rtc_device_register(&pdev->dev, rtc_name, &vr41xx_rtc_ops,
- THIS_MODULE);
+ rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc)) {
retval = PTR_ERR(rtc);
goto err_iounmap_all;
}
+ rtc->ops = &vr41xx_rtc_ops;
+
+ /* 48-bit counter at 32.768 kHz */
+ rtc->range_max = (1ULL << 33) - 1;
rtc->max_user_freq = MAX_PERIODIC_RATE;
spin_lock_irq(&rtc_lock);
@@ -340,6 +343,10 @@ static int rtc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "Real Time Clock of NEC VR4100 series\n");
+ retval = rtc_register_device(rtc);
+ if (retval)
+ goto err_iounmap_all;
+
return 0;
err_iounmap_all:
diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
index fba994d..c532bd1 100644
--- a/drivers/rtc/rtc-zynqmp.c
+++ b/drivers/rtc/rtc-zynqmp.c
@@ -278,10 +278,9 @@ static int xlnx_rtc_remove(struct platform_device *pdev)
static int __maybe_unused xlnx_rtc_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct xlnx_rtc_dev *xrtcdev = platform_get_drvdata(pdev);
+ struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
- if (device_may_wakeup(&pdev->dev))
+ if (device_may_wakeup(dev))
enable_irq_wake(xrtcdev->alarm_irq);
else
xlnx_rtc_alarm_irq_enable(dev, 0);
@@ -291,10 +290,9 @@ static int __maybe_unused xlnx_rtc_suspend(struct device *dev)
static int __maybe_unused xlnx_rtc_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct xlnx_rtc_dev *xrtcdev = platform_get_drvdata(pdev);
+ struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
- if (device_may_wakeup(&pdev->dev))
+ if (device_may_wakeup(dev))
disable_irq_wake(xrtcdev->alarm_irq);
else
xlnx_rtc_alarm_irq_enable(dev, 1);
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index 73cce3e..d3a38c4 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1222,80 +1222,37 @@ static void dasd_hosts_init(struct dentry *base_dentry,
device->hosts_dentry = pde;
}
-/*
- * Allocate memory for a channel program with 'cplength' channel
- * command words and 'datasize' additional space. There are two
- * variantes: 1) dasd_kmalloc_request uses kmalloc to get the needed
- * memory and 2) dasd_smalloc_request uses the static ccw memory
- * that gets allocated for each device.
- */
-struct dasd_ccw_req *dasd_kmalloc_request(int magic, int cplength,
- int datasize,
- struct dasd_device *device)
-{
- struct dasd_ccw_req *cqr;
-
- /* Sanity checks */
- BUG_ON(datasize > PAGE_SIZE ||
- (cplength*sizeof(struct ccw1)) > PAGE_SIZE);
-
- cqr = kzalloc(sizeof(struct dasd_ccw_req), GFP_ATOMIC);
- if (cqr == NULL)
- return ERR_PTR(-ENOMEM);
- cqr->cpaddr = NULL;
- if (cplength > 0) {
- cqr->cpaddr = kcalloc(cplength, sizeof(struct ccw1),
- GFP_ATOMIC | GFP_DMA);
- if (cqr->cpaddr == NULL) {
- kfree(cqr);
- return ERR_PTR(-ENOMEM);
- }
- }
- cqr->data = NULL;
- if (datasize > 0) {
- cqr->data = kzalloc(datasize, GFP_ATOMIC | GFP_DMA);
- if (cqr->data == NULL) {
- kfree(cqr->cpaddr);
- kfree(cqr);
- return ERR_PTR(-ENOMEM);
- }
- }
- cqr->magic = magic;
- set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
- dasd_get_device(device);
- return cqr;
-}
-EXPORT_SYMBOL(dasd_kmalloc_request);
-
-struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength,
- int datasize,
- struct dasd_device *device)
+struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength, int datasize,
+ struct dasd_device *device,
+ struct dasd_ccw_req *cqr)
{
unsigned long flags;
- struct dasd_ccw_req *cqr;
- char *data;
- int size;
+ char *data, *chunk;
+ int size = 0;
- size = (sizeof(struct dasd_ccw_req) + 7L) & -8L;
if (cplength > 0)
size += cplength * sizeof(struct ccw1);
if (datasize > 0)
size += datasize;
+ if (!cqr)
+ size += (sizeof(*cqr) + 7L) & -8L;
+
spin_lock_irqsave(&device->mem_lock, flags);
- cqr = (struct dasd_ccw_req *)
- dasd_alloc_chunk(&device->ccw_chunks, size);
+ data = chunk = dasd_alloc_chunk(&device->ccw_chunks, size);
spin_unlock_irqrestore(&device->mem_lock, flags);
- if (cqr == NULL)
+ if (!chunk)
return ERR_PTR(-ENOMEM);
- memset(cqr, 0, sizeof(struct dasd_ccw_req));
- data = (char *) cqr + ((sizeof(struct dasd_ccw_req) + 7L) & -8L);
- cqr->cpaddr = NULL;
+ if (!cqr) {
+ cqr = (void *) data;
+ data += (sizeof(*cqr) + 7L) & -8L;
+ }
+ memset(cqr, 0, sizeof(*cqr));
+ cqr->mem_chunk = chunk;
if (cplength > 0) {
- cqr->cpaddr = (struct ccw1 *) data;
- data += cplength*sizeof(struct ccw1);
- memset(cqr->cpaddr, 0, cplength*sizeof(struct ccw1));
+ cqr->cpaddr = data;
+ data += cplength * sizeof(struct ccw1);
+ memset(cqr->cpaddr, 0, cplength * sizeof(struct ccw1));
}
- cqr->data = NULL;
if (datasize > 0) {
cqr->data = data;
memset(cqr->data, 0, datasize);
@@ -1307,33 +1264,12 @@ struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength,
}
EXPORT_SYMBOL(dasd_smalloc_request);
-/*
- * Free memory of a channel program. This function needs to free all the
- * idal lists that might have been created by dasd_set_cda and the
- * struct dasd_ccw_req itself.
- */
-void dasd_kfree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
-{
- struct ccw1 *ccw;
-
- /* Clear any idals used for the request. */
- ccw = cqr->cpaddr;
- do {
- clear_normalized_cda(ccw);
- } while (ccw++->flags & (CCW_FLAG_CC | CCW_FLAG_DC));
- kfree(cqr->cpaddr);
- kfree(cqr->data);
- kfree(cqr);
- dasd_put_device(device);
-}
-EXPORT_SYMBOL(dasd_kfree_request);
-
void dasd_sfree_request(struct dasd_ccw_req *cqr, struct dasd_device *device)
{
unsigned long flags;
spin_lock_irqsave(&device->mem_lock, flags);
- dasd_free_chunk(&device->ccw_chunks, cqr);
+ dasd_free_chunk(&device->ccw_chunks, cqr->mem_chunk);
spin_unlock_irqrestore(&device->mem_lock, flags);
dasd_put_device(device);
}
@@ -1885,6 +1821,33 @@ static void __dasd_device_process_ccw_queue(struct dasd_device *device,
}
}
+static void __dasd_process_cqr(struct dasd_device *device,
+ struct dasd_ccw_req *cqr)
+{
+ char errorstring[ERRORLENGTH];
+
+ switch (cqr->status) {
+ case DASD_CQR_SUCCESS:
+ cqr->status = DASD_CQR_DONE;
+ break;
+ case DASD_CQR_ERROR:
+ cqr->status = DASD_CQR_NEED_ERP;
+ break;
+ case DASD_CQR_CLEARED:
+ cqr->status = DASD_CQR_TERMINATED;
+ break;
+ default:
+ /* internal error 12 - wrong cqr status*/
+ snprintf(errorstring, ERRORLENGTH, "12 %p %x02", cqr, cqr->status);
+ dev_err(&device->cdev->dev,
+ "An error occurred in the DASD device driver, "
+ "reason=%s\n", errorstring);
+ BUG();
+ }
+ if (cqr->callback)
+ cqr->callback(cqr, cqr->callback_data);
+}
+
/*
* the cqrs from the final queue are returned to the upper layer
* by setting a dasd_block state and calling the callback function
@@ -1895,40 +1858,18 @@ static void __dasd_device_process_final_queue(struct dasd_device *device,
struct list_head *l, *n;
struct dasd_ccw_req *cqr;
struct dasd_block *block;
- void (*callback)(struct dasd_ccw_req *, void *data);
- void *callback_data;
- char errorstring[ERRORLENGTH];
list_for_each_safe(l, n, final_queue) {
cqr = list_entry(l, struct dasd_ccw_req, devlist);
list_del_init(&cqr->devlist);
block = cqr->block;
- callback = cqr->callback;
- callback_data = cqr->callback_data;
- if (block)
+ if (!block) {
+ __dasd_process_cqr(device, cqr);
+ } else {
spin_lock_bh(&block->queue_lock);
- switch (cqr->status) {
- case DASD_CQR_SUCCESS:
- cqr->status = DASD_CQR_DONE;
- break;
- case DASD_CQR_ERROR:
- cqr->status = DASD_CQR_NEED_ERP;
- break;
- case DASD_CQR_CLEARED:
- cqr->status = DASD_CQR_TERMINATED;
- break;
- default:
- /* internal error 12 - wrong cqr status*/
- snprintf(errorstring, ERRORLENGTH, "12 %p %x02", cqr, cqr->status);
- dev_err(&device->cdev->dev,
- "An error occurred in the DASD device driver, "
- "reason=%s\n", errorstring);
- BUG();
- }
- if (cqr->callback != NULL)
- (callback)(cqr, callback_data);
- if (block)
+ __dasd_process_cqr(device, cqr);
spin_unlock_bh(&block->queue_lock);
+ }
}
}
@@ -3041,7 +2982,6 @@ static blk_status_t do_dasd_request(struct blk_mq_hw_ctx *hctx,
cqr->callback_data = req;
cqr->status = DASD_CQR_FILLED;
cqr->dq = dq;
- *((struct dasd_ccw_req **) blk_mq_rq_to_pdu(req)) = cqr;
blk_mq_start_request(req);
spin_lock(&block->queue_lock);
@@ -3072,7 +3012,7 @@ enum blk_eh_timer_return dasd_times_out(struct request *req, bool reserved)
unsigned long flags;
int rc = 0;
- cqr = *((struct dasd_ccw_req **) blk_mq_rq_to_pdu(req));
+ cqr = blk_mq_rq_to_pdu(req);
if (!cqr)
return BLK_EH_DONE;
@@ -3174,7 +3114,7 @@ static int dasd_alloc_queue(struct dasd_block *block)
int rc;
block->tag_set.ops = &dasd_mq_ops;
- block->tag_set.cmd_size = sizeof(struct dasd_ccw_req *);
+ block->tag_set.cmd_size = sizeof(struct dasd_ccw_req);
block->tag_set.nr_hw_queues = DASD_NR_HW_QUEUES;
block->tag_set.queue_depth = DASD_MAX_LCU_DEV * DASD_REQ_PER_DEV;
block->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
@@ -4038,7 +3978,8 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
struct ccw1 *ccw;
unsigned long *idaw;
- cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device);
+ cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device,
+ NULL);
if (IS_ERR(cqr)) {
/* internal error 13 - Allocating the RDC request failed*/
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c
index 5e963fe..e36a114 100644
--- a/drivers/s390/block/dasd_alias.c
+++ b/drivers/s390/block/dasd_alias.c
@@ -407,9 +407,9 @@ static int read_unit_address_configuration(struct dasd_device *device,
int rc;
unsigned long flags;
- cqr = dasd_kmalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
(sizeof(struct dasd_psf_prssd_data)),
- device);
+ device, NULL);
if (IS_ERR(cqr))
return PTR_ERR(cqr);
cqr->startdev = device;
@@ -457,7 +457,7 @@ static int read_unit_address_configuration(struct dasd_device *device,
lcu->flags |= NEED_UAC_UPDATE;
spin_unlock_irqrestore(&lcu->lock, flags);
}
- dasd_kfree_request(cqr, cqr->memdev);
+ dasd_sfree_request(cqr, cqr->memdev);
return rc;
}
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 131f198..e1fe024 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -536,7 +536,8 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
/* Build the request */
datasize = sizeof(struct dasd_diag_req) +
count*sizeof(struct dasd_diag_bio);
- cqr = dasd_smalloc_request(DASD_DIAG_MAGIC, 0, datasize, memdev);
+ cqr = dasd_smalloc_request(DASD_DIAG_MAGIC, 0, datasize, memdev,
+ blk_mq_rq_to_pdu(req));
if (IS_ERR(cqr))
return cqr;
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index be208e7..bbf95b7 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -886,7 +886,7 @@ static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
}
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* RCD */,
0, /* use rcd_buf as data ara */
- device);
+ device, NULL);
if (IS_ERR(cqr)) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"Could not allocate RCD request");
@@ -1442,7 +1442,7 @@ static int dasd_eckd_read_features(struct dasd_device *device)
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
(sizeof(struct dasd_psf_prssd_data) +
sizeof(struct dasd_rssd_features)),
- device);
+ device, NULL);
if (IS_ERR(cqr)) {
DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", "Could not "
"allocate initialization request");
@@ -1504,7 +1504,7 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device,
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ ,
sizeof(struct dasd_psf_ssc_data),
- device);
+ device, NULL);
if (IS_ERR(cqr)) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
@@ -1815,7 +1815,8 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
cplength = 8;
datasize = sizeof(struct DE_eckd_data) + 2*sizeof(struct LO_eckd_data);
- cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, device,
+ NULL);
if (IS_ERR(cqr))
return cqr;
ccw = cqr->cpaddr;
@@ -2092,7 +2093,8 @@ dasd_eckd_build_check_tcw(struct dasd_device *base, struct format_data_t *fdata,
*/
itcw_size = itcw_calc_size(0, count, 0);
- cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 0, itcw_size, startdev);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 0, itcw_size, startdev,
+ NULL);
if (IS_ERR(cqr))
return cqr;
@@ -2186,7 +2188,7 @@ dasd_eckd_build_check(struct dasd_device *base, struct format_data_t *fdata,
cplength += count;
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize,
- startdev);
+ startdev, NULL);
if (IS_ERR(cqr))
return cqr;
@@ -2332,7 +2334,7 @@ dasd_eckd_build_format(struct dasd_device *base,
}
/* Allocate the format ccw request. */
fcp = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength,
- datasize, startdev);
+ datasize, startdev, NULL);
if (IS_ERR(fcp))
return fcp;
@@ -3103,7 +3105,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
}
/* Allocate the ccw request. */
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize,
- startdev);
+ startdev, blk_mq_rq_to_pdu(req));
if (IS_ERR(cqr))
return cqr;
ccw = cqr->cpaddr;
@@ -3262,7 +3264,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
/* Allocate the ccw request. */
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize,
- startdev);
+ startdev, blk_mq_rq_to_pdu(req));
if (IS_ERR(cqr))
return cqr;
ccw = cqr->cpaddr;
@@ -3595,7 +3597,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
/* Allocate the ccw request. */
itcw_size = itcw_calc_size(0, ctidaw, 0);
- cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 0, itcw_size, startdev);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 0, itcw_size, startdev,
+ blk_mq_rq_to_pdu(req));
if (IS_ERR(cqr))
return cqr;
@@ -3862,7 +3865,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_raw(struct dasd_device *startdev,
/* Allocate the ccw request. */
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength,
- datasize, startdev);
+ datasize, startdev, blk_mq_rq_to_pdu(req));
if (IS_ERR(cqr))
return cqr;
@@ -4102,7 +4105,7 @@ dasd_eckd_release(struct dasd_device *device)
return -EACCES;
useglobal = 0;
- cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device, NULL);
if (IS_ERR(cqr)) {
mutex_lock(&dasd_reserve_mutex);
useglobal = 1;
@@ -4157,7 +4160,7 @@ dasd_eckd_reserve(struct dasd_device *device)
return -EACCES;
useglobal = 0;
- cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device, NULL);
if (IS_ERR(cqr)) {
mutex_lock(&dasd_reserve_mutex);
useglobal = 1;
@@ -4211,7 +4214,7 @@ dasd_eckd_steal_lock(struct dasd_device *device)
return -EACCES;
useglobal = 0;
- cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device, NULL);
if (IS_ERR(cqr)) {
mutex_lock(&dasd_reserve_mutex);
useglobal = 1;
@@ -4271,7 +4274,8 @@ static int dasd_eckd_snid(struct dasd_device *device,
useglobal = 0;
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1,
- sizeof(struct dasd_snid_data), device);
+ sizeof(struct dasd_snid_data), device,
+ NULL);
if (IS_ERR(cqr)) {
mutex_lock(&dasd_reserve_mutex);
useglobal = 1;
@@ -4331,7 +4335,7 @@ dasd_eckd_performance(struct dasd_device *device, void __user *argp)
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
(sizeof(struct dasd_psf_prssd_data) +
sizeof(struct dasd_rssd_perf_stats_t)),
- device);
+ device, NULL);
if (IS_ERR(cqr)) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"Could not allocate initialization request");
@@ -4477,7 +4481,7 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
psf1 = psf_data[1];
/* setup CCWs for PSF + RSSD */
- cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 , 0, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2, 0, device, NULL);
if (IS_ERR(cqr)) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
"Could not allocate initialization request");
@@ -5037,7 +5041,7 @@ static int dasd_eckd_read_message_buffer(struct dasd_device *device,
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
(sizeof(struct dasd_psf_prssd_data) +
sizeof(struct dasd_rssd_messages)),
- device);
+ device, NULL);
if (IS_ERR(cqr)) {
DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
"Could not allocate read message buffer request");
@@ -5126,7 +5130,7 @@ static int dasd_eckd_query_host_access(struct dasd_device *device,
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */,
sizeof(struct dasd_psf_prssd_data) + 1,
- device);
+ device, NULL);
if (IS_ERR(cqr)) {
DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s",
"Could not allocate read message buffer request");
@@ -5284,8 +5288,8 @@ dasd_eckd_psf_cuir_response(struct dasd_device *device, int response,
int rc;
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ ,
- sizeof(struct dasd_psf_cuir_response),
- device);
+ sizeof(struct dasd_psf_cuir_response),
+ device, NULL);
if (IS_ERR(cqr)) {
DBF_DEV_EVENT(DBF_WARNING, device, "%s",
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c
index fb2c359..6ef8714 100644
--- a/drivers/s390/block/dasd_eer.c
+++ b/drivers/s390/block/dasd_eer.c
@@ -447,7 +447,7 @@ static void dasd_eer_snss_cb(struct dasd_ccw_req *cqr, void *data)
* is a new ccw in device->eer_cqr. Free the "old"
* snss request now.
*/
- dasd_kfree_request(cqr, device);
+ dasd_sfree_request(cqr, device);
}
/*
@@ -472,8 +472,8 @@ int dasd_eer_enable(struct dasd_device *device)
if (rc)
goto out;
- cqr = dasd_kmalloc_request(DASD_ECKD_MAGIC, 1 /* SNSS */,
- SNSS_DATA_SIZE, device);
+ cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* SNSS */,
+ SNSS_DATA_SIZE, device, NULL);
if (IS_ERR(cqr)) {
rc = -ENOMEM;
cqr = NULL;
@@ -505,7 +505,7 @@ out:
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
if (cqr)
- dasd_kfree_request(cqr, device);
+ dasd_sfree_request(cqr, device);
return rc;
}
@@ -528,7 +528,7 @@ void dasd_eer_disable(struct dasd_device *device)
in_use = test_and_clear_bit(DASD_FLAG_EER_IN_USE, &device->flags);
spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
if (cqr && !in_use)
- dasd_kfree_request(cqr, device);
+ dasd_sfree_request(cqr, device);
}
/*
@@ -561,8 +561,8 @@ static int dasd_eer_open(struct inode *inp, struct file *filp)
return -EINVAL;
}
eerb->buffersize = eerb->buffer_page_count * PAGE_SIZE;
- eerb->buffer = kmalloc(eerb->buffer_page_count * sizeof(char *),
- GFP_KERNEL);
+ eerb->buffer = kmalloc_array(eerb->buffer_page_count, sizeof(char *),
+ GFP_KERNEL);
if (!eerb->buffer) {
kfree(eerb);
return -ENOMEM;
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index a6b132f..56007a3 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -356,7 +356,8 @@ static struct dasd_ccw_req *dasd_fba_build_cp_discard(
datasize = sizeof(struct DE_fba_data) +
nr_ccws * (sizeof(struct LO_fba_data) + sizeof(struct ccw1));
- cqr = dasd_smalloc_request(DASD_FBA_MAGIC, cplength, datasize, memdev);
+ cqr = dasd_smalloc_request(DASD_FBA_MAGIC, cplength, datasize, memdev,
+ blk_mq_rq_to_pdu(req));
if (IS_ERR(cqr))
return cqr;
@@ -490,7 +491,8 @@ static struct dasd_ccw_req *dasd_fba_build_cp_regular(
datasize += (count - 1)*sizeof(struct LO_fba_data);
}
/* Allocate the ccw request. */
- cqr = dasd_smalloc_request(DASD_FBA_MAGIC, cplength, datasize, memdev);
+ cqr = dasd_smalloc_request(DASD_FBA_MAGIC, cplength, datasize, memdev,
+ blk_mq_rq_to_pdu(req));
if (IS_ERR(cqr))
return cqr;
ccw = cqr->cpaddr;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 96709b1..976b6bd 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -158,40 +158,33 @@ do { \
struct dasd_ccw_req {
unsigned int magic; /* Eye catcher */
+ int intrc; /* internal error, e.g. from start_IO */
struct list_head devlist; /* for dasd_device request queue */
struct list_head blocklist; /* for dasd_block request queue */
-
- /* Where to execute what... */
struct dasd_block *block; /* the originating block device */
struct dasd_device *memdev; /* the device used to allocate this */
struct dasd_device *startdev; /* device the request is started on */
struct dasd_device *basedev; /* base device if no block->base */
void *cpaddr; /* address of ccw or tcw */
+ short retries; /* A retry counter */
unsigned char cpmode; /* 0 = cmd mode, 1 = itcw */
char status; /* status of this request */
- short retries; /* A retry counter */
+ char lpm; /* logical path mask */
unsigned long flags; /* flags of this request */
struct dasd_queue *dq;
-
- /* ... and how */
unsigned long starttime; /* jiffies time of request start */
unsigned long expires; /* expiration period in jiffies */
- char lpm; /* logical path mask */
void *data; /* pointer to data area */
-
- /* these are important for recovering erroneous requests */
- int intrc; /* internal error, e.g. from start_IO */
struct irb irb; /* device status in case of an error */
struct dasd_ccw_req *refers; /* ERP-chain queueing. */
void *function; /* originating ERP action */
+ void *mem_chunk;
- /* these are for statistics only */
unsigned long buildclk; /* TOD-clock of request generation */
unsigned long startclk; /* TOD-clock of request start */
unsigned long stopclk; /* TOD-clock of request interrupt */
unsigned long endclk; /* TOD-clock of request termination */
- /* Callback that is called after reaching final status. */
void (*callback)(struct dasd_ccw_req *, void *data);
void *callback_data;
};
@@ -714,19 +707,10 @@ extern const struct block_device_operations dasd_device_operations;
extern struct kmem_cache *dasd_page_cache;
struct dasd_ccw_req *
-dasd_kmalloc_request(int , int, int, struct dasd_device *);
-struct dasd_ccw_req *
-dasd_smalloc_request(int , int, int, struct dasd_device *);
-void dasd_kfree_request(struct dasd_ccw_req *, struct dasd_device *);
+dasd_smalloc_request(int, int, int, struct dasd_device *, struct dasd_ccw_req *);
void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *);
void dasd_wakeup_cb(struct dasd_ccw_req *, void *);
-static inline int
-dasd_kmalloc_set_cda(struct ccw1 *ccw, void *cda, struct dasd_device *device)
-{
- return set_normalized_cda(ccw, cda);
-}
-
struct dasd_device *dasd_alloc_device(void);
void dasd_free_device(struct dasd_device *);
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
index 2902449..ed60728 100644
--- a/drivers/s390/block/dcssblk.c
+++ b/drivers/s390/block/dcssblk.c
@@ -238,9 +238,9 @@ dcssblk_is_continuous(struct dcssblk_dev_info *dev_info)
if (dev_info->num_of_segments <= 1)
return 0;
- sort_list = kzalloc(
- sizeof(struct segment_info) * dev_info->num_of_segments,
- GFP_KERNEL);
+ sort_list = kcalloc(dev_info->num_of_segments,
+ sizeof(struct segment_info),
+ GFP_KERNEL);
if (sort_list == NULL)
return -ENOMEM;
i = 0;
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
index db1fbf9..79eb609 100644
--- a/drivers/s390/char/keyboard.c
+++ b/drivers/s390/char/keyboard.c
@@ -78,7 +78,7 @@ kbd_alloc(void) {
}
}
kbd->fn_handler =
- kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL);
+ kcalloc(NR_FN_HANDLER, sizeof(fn_handler_fn *), GFP_KERNEL);
if (!kbd->fn_handler)
goto out_func;
kbd->accent_table = kmemdup(ebc_accent_table,
diff --git a/drivers/s390/char/sclp_sd.c b/drivers/s390/char/sclp_sd.c
index 99f41db..1e244f7 100644
--- a/drivers/s390/char/sclp_sd.c
+++ b/drivers/s390/char/sclp_sd.c
@@ -300,7 +300,7 @@ static int sclp_sd_store_data(struct sclp_sd_data *result, u8 di)
goto out_result;
/* Allocate memory */
- data = vzalloc((size_t) dsize * PAGE_SIZE);
+ data = vzalloc(array_size((size_t)dsize, PAGE_SIZE));
if (!data) {
rc = -ENOMEM;
goto out;
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index 1c98023..5b8af27 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -719,7 +719,8 @@ tty3270_alloc_view(void)
if (!tp)
goto out_err;
tp->freemem_pages =
- kmalloc(sizeof(void *) * TTY3270_STRING_PAGES, GFP_KERNEL);
+ kmalloc_array(TTY3270_STRING_PAGES, sizeof(void *),
+ GFP_KERNEL);
if (!tp->freemem_pages)
goto out_tp;
INIT_LIST_HEAD(&tp->freemem);
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 52aa894..cbde65a 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -242,7 +242,7 @@ static struct ccw1 *alloc_chan_prog(const char __user *ubuf, int rec_count,
* That means we allocate room for CCWs to cover count/reclen
* records plus a NOP.
*/
- cpa = kzalloc((rec_count + 1) * sizeof(struct ccw1),
+ cpa = kcalloc(rec_count + 1, sizeof(struct ccw1),
GFP_KERNEL | GFP_DMA);
if (!cpa)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 4369662..76d3c50 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -152,7 +152,7 @@ static int zcore_memmap_open(struct inode *inode, struct file *filp)
char *buf;
int i = 0;
- buf = kzalloc(memblock.memory.cnt * CHUNK_INFO_SIZE, GFP_KERNEL);
+ buf = kcalloc(memblock.memory.cnt, CHUNK_INFO_SIZE, GFP_KERNEL);
if (!buf) {
return -ENOMEM;
}
diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile
index a070ef0..f230516 100644
--- a/drivers/s390/cio/Makefile
+++ b/drivers/s390/cio/Makefile
@@ -5,6 +5,7 @@
# The following is required for define_trace.h to find ./trace.h
CFLAGS_trace.o := -I$(src)
+CFLAGS_vfio_ccw_fsm.o := -I$(src)
obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o \
fcx.o itcw.o crw.o ccwreq.o trace.o ioasm.o
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 4c14ce4..78f1be4 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -536,7 +536,7 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
int qdio_enable_async_operation(struct qdio_output_q *outq)
{
- outq->aobs = kzalloc(sizeof(struct qaob *) * QDIO_MAX_BUFFERS_PER_Q,
+ outq->aobs = kcalloc(QDIO_MAX_BUFFERS_PER_Q, sizeof(struct qaob *),
GFP_ATOMIC);
if (!outq->aobs) {
outq->use_cq = 0;
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index 0787b58..07dea60 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -241,8 +241,9 @@ out:
/* allocate non-shared indicators and shared indicator */
int __init tiqdio_allocate_memory(void)
{
- q_indicators = kzalloc(sizeof(struct indicator_t) * TIQDIO_NR_INDICATORS,
- GFP_KERNEL);
+ q_indicators = kcalloc(TIQDIO_NR_INDICATORS,
+ sizeof(struct indicator_t),
+ GFP_KERNEL);
if (!q_indicators)
return -ENOMEM;
return 0;
diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index dce92b2..dbe7c7a 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -23,9 +23,13 @@
#define CCWCHAIN_LEN_MAX 256
struct pfn_array {
+ /* Starting guest physical I/O address. */
unsigned long pa_iova;
+ /* Array that stores PFNs of the pages need to pin. */
unsigned long *pa_iova_pfn;
+ /* Array that receives PFNs of the pages pinned. */
unsigned long *pa_pfn;
+ /* Number of pages pinned from @pa_iova. */
int pa_nr;
};
@@ -46,70 +50,33 @@ struct ccwchain {
};
/*
- * pfn_array_pin() - pin user pages in memory
+ * pfn_array_alloc_pin() - alloc memory for PFNs, then pin user pages in memory
* @pa: pfn_array on which to perform the operation
* @mdev: the mediated device to perform pin/unpin operations
+ * @iova: target guest physical address
+ * @len: number of bytes that should be pinned from @iova
*
- * Attempt to pin user pages in memory.
+ * Attempt to allocate memory for PFNs, and pin user pages in memory.
*
* Usage of pfn_array:
- * @pa->pa_iova starting guest physical I/O address. Assigned by caller.
- * @pa->pa_iova_pfn array that stores PFNs of the pages need to pin. Allocated
- * by caller.
- * @pa->pa_pfn array that receives PFNs of the pages pinned. Allocated by
- * caller.
- * @pa->pa_nr number of pages from @pa->pa_iova to pin. Assigned by
- * caller.
- * number of pages pinned. Assigned by callee.
+ * We expect (pa_nr == 0) and (pa_iova_pfn == NULL), any field in
+ * this structure will be filled in by this function.
*
* Returns:
* Number of pages pinned on success.
- * If @pa->pa_nr is 0 or negative, returns 0.
+ * If @pa->pa_nr is not 0, or @pa->pa_iova_pfn is not NULL initially,
+ * returns -EINVAL.
* If no pages were pinned, returns -errno.
*/
-static int pfn_array_pin(struct pfn_array *pa, struct device *mdev)
-{
- int i, ret;
-
- if (pa->pa_nr <= 0) {
- pa->pa_nr = 0;
- return 0;
- }
-
- pa->pa_iova_pfn[0] = pa->pa_iova >> PAGE_SHIFT;
- for (i = 1; i < pa->pa_nr; i++)
- pa->pa_iova_pfn[i] = pa->pa_iova_pfn[i - 1] + 1;
-
- ret = vfio_pin_pages(mdev, pa->pa_iova_pfn, pa->pa_nr,
- IOMMU_READ | IOMMU_WRITE, pa->pa_pfn);
-
- if (ret > 0 && ret != pa->pa_nr) {
- vfio_unpin_pages(mdev, pa->pa_iova_pfn, ret);
- pa->pa_nr = 0;
- return 0;
- }
-
- return ret;
-}
-
-/* Unpin the pages before releasing the memory. */
-static void pfn_array_unpin_free(struct pfn_array *pa, struct device *mdev)
-{
- vfio_unpin_pages(mdev, pa->pa_iova_pfn, pa->pa_nr);
- pa->pa_nr = 0;
- kfree(pa->pa_iova_pfn);
-}
-
-/* Alloc memory for PFNs, then pin pages with them. */
static int pfn_array_alloc_pin(struct pfn_array *pa, struct device *mdev,
u64 iova, unsigned int len)
{
- int ret = 0;
+ int i, ret = 0;
if (!len)
return 0;
- if (pa->pa_nr)
+ if (pa->pa_nr || pa->pa_iova_pfn)
return -EINVAL;
pa->pa_iova = iova;
@@ -126,18 +93,39 @@ static int pfn_array_alloc_pin(struct pfn_array *pa, struct device *mdev,
return -ENOMEM;
pa->pa_pfn = pa->pa_iova_pfn + pa->pa_nr;
- ret = pfn_array_pin(pa, mdev);
+ pa->pa_iova_pfn[0] = pa->pa_iova >> PAGE_SHIFT;
+ for (i = 1; i < pa->pa_nr; i++)
+ pa->pa_iova_pfn[i] = pa->pa_iova_pfn[i - 1] + 1;
- if (ret > 0)
- return ret;
- else if (!ret)
+ ret = vfio_pin_pages(mdev, pa->pa_iova_pfn, pa->pa_nr,
+ IOMMU_READ | IOMMU_WRITE, pa->pa_pfn);
+
+ if (ret < 0) {
+ goto err_out;
+ } else if (ret > 0 && ret != pa->pa_nr) {
+ vfio_unpin_pages(mdev, pa->pa_iova_pfn, ret);
ret = -EINVAL;
+ goto err_out;
+ }
+ return ret;
+
+err_out:
+ pa->pa_nr = 0;
kfree(pa->pa_iova_pfn);
+ pa->pa_iova_pfn = NULL;
return ret;
}
+/* Unpin the pages before releasing the memory. */
+static void pfn_array_unpin_free(struct pfn_array *pa, struct device *mdev)
+{
+ vfio_unpin_pages(mdev, pa->pa_iova_pfn, pa->pa_nr);
+ pa->pa_nr = 0;
+ kfree(pa->pa_iova_pfn);
+}
+
static int pfn_array_table_init(struct pfn_array_table *pat, int nr)
{
pat->pat_pa = kcalloc(nr, sizeof(*pat->pat_pa), GFP_KERNEL);
@@ -365,6 +353,9 @@ static void cp_unpin_free(struct channel_program *cp)
* This is the chain length not considering any TICs.
* You need to do a new round for each TIC target.
*
+ * The program is also validated for absence of not yet supported
+ * indirect data addressing scenarios.
+ *
* Returns: the length of the ccw chain or -errno.
*/
static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
@@ -391,6 +382,14 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
do {
cnt++;
+ /*
+ * As we don't want to fail direct addressing even if the
+ * orb specified one of the unsupported formats, we defer
+ * checking for IDAWs in unsupported formats to here.
+ */
+ if ((!cp->orb.cmd.c64 || cp->orb.cmd.i2k) && ccw_is_idal(ccw))
+ return -EOPNOTSUPP;
+
if ((!ccw_is_chain(ccw)) && (!ccw_is_tic(ccw)))
break;
@@ -503,7 +502,7 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
struct ccw1 *ccw;
struct pfn_array_table *pat;
unsigned long *idaws;
- int idaw_nr;
+ int ret;
ccw = chain->ch_ccw + idx;
@@ -523,18 +522,19 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
* needed when translating a direct ccw to a idal ccw.
*/
pat = chain->ch_pat + idx;
- if (pfn_array_table_init(pat, 1))
- return -ENOMEM;
- idaw_nr = pfn_array_alloc_pin(pat->pat_pa, cp->mdev,
- ccw->cda, ccw->count);
- if (idaw_nr < 0)
- return idaw_nr;
+ ret = pfn_array_table_init(pat, 1);
+ if (ret)
+ goto out_init;
+
+ ret = pfn_array_alloc_pin(pat->pat_pa, cp->mdev, ccw->cda, ccw->count);
+ if (ret < 0)
+ goto out_init;
/* Translate this direct ccw to a idal ccw. */
- idaws = kcalloc(idaw_nr, sizeof(*idaws), GFP_DMA | GFP_KERNEL);
+ idaws = kcalloc(ret, sizeof(*idaws), GFP_DMA | GFP_KERNEL);
if (!idaws) {
- pfn_array_table_unpin_free(pat, cp->mdev);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto out_unpin;
}
ccw->cda = (__u32) virt_to_phys(idaws);
ccw->flags |= CCW_FLAG_IDA;
@@ -542,6 +542,12 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
pfn_array_table_idal_create_words(pat, idaws);
return 0;
+
+out_unpin:
+ pfn_array_table_unpin_free(pat, cp->mdev);
+out_init:
+ ccw->cda = 0;
+ return ret;
}
static int ccwchain_fetch_idal(struct ccwchain *chain,
@@ -571,7 +577,7 @@ static int ccwchain_fetch_idal(struct ccwchain *chain,
pat = chain->ch_pat + idx;
ret = pfn_array_table_init(pat, idaw_nr);
if (ret)
- return ret;
+ goto out_init;
/* Translate idal ccw to use new allocated idaws. */
idaws = kzalloc(idaw_len, GFP_DMA | GFP_KERNEL);
@@ -603,6 +609,8 @@ out_free_idaws:
kfree(idaws);
out_unpin:
pfn_array_table_unpin_free(pat, cp->mdev);
+out_init:
+ ccw->cda = 0;
return ret;
}
@@ -656,10 +664,8 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
/*
* XXX:
* Only support prefetch enable mode now.
- * Only support 64bit addressing idal.
- * Only support 4k IDAW.
*/
- if (!orb->cmd.pfch || !orb->cmd.c64 || orb->cmd.i2k)
+ if (!orb->cmd.pfch)
return -EOPNOTSUPP;
INIT_LIST_HEAD(&cp->ccwchain_list);
@@ -688,6 +694,10 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
ret = ccwchain_loop_tic(chain, cp);
if (ret)
cp_unpin_free(cp);
+ /* It is safe to force: if not set but idals used
+ * ccwchain_calc_length returns an error.
+ */
+ cp->orb.cmd.c64 = 1;
return ret;
}
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index ea6a2d0..770fa9c 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -177,6 +177,7 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process)
{
struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
unsigned long flags;
+ int rc = -EAGAIN;
spin_lock_irqsave(sch->lock, flags);
if (!device_is_registered(&sch->dev))
@@ -187,6 +188,7 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process)
if (cio_update_schib(sch)) {
vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_NOT_OPER);
+ rc = 0;
goto out_unlock;
}
@@ -195,11 +197,12 @@ static int vfio_ccw_sch_event(struct subchannel *sch, int process)
private->state = private->mdev ? VFIO_CCW_STATE_IDLE :
VFIO_CCW_STATE_STANDBY;
}
+ rc = 0;
out_unlock:
spin_unlock_irqrestore(sch->lock, flags);
- return 0;
+ return rc;
}
static struct css_device_id vfio_ccw_sch_ids[] = {
diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c
index 3c80064..797a827 100644
--- a/drivers/s390/cio/vfio_ccw_fsm.c
+++ b/drivers/s390/cio/vfio_ccw_fsm.c
@@ -13,6 +13,9 @@
#include "ioasm.h"
#include "vfio_ccw_private.h"
+#define CREATE_TRACE_POINTS
+#include "vfio_ccw_trace.h"
+
static int fsm_io_helper(struct vfio_ccw_private *private)
{
struct subchannel *sch;
@@ -110,6 +113,10 @@ static void fsm_disabled_irq(struct vfio_ccw_private *private,
*/
cio_disable_subchannel(sch);
}
+inline struct subchannel_id get_schid(struct vfio_ccw_private *p)
+{
+ return p->sch->schid;
+}
/*
* Deal with the ccw command request from the userspace.
@@ -121,6 +128,7 @@ static void fsm_io_request(struct vfio_ccw_private *private,
union scsw *scsw = &private->scsw;
struct ccw_io_region *io_region = &private->io_region;
struct mdev_device *mdev = private->mdev;
+ char *errstr = "request";
private->state = VFIO_CCW_STATE_BOXED;
@@ -132,15 +140,19 @@ static void fsm_io_request(struct vfio_ccw_private *private,
/* Don't try to build a cp if transport mode is specified. */
if (orb->tm.b) {
io_region->ret_code = -EOPNOTSUPP;
+ errstr = "transport mode";
goto err_out;
}
io_region->ret_code = cp_init(&private->cp, mdev_dev(mdev),
orb);
- if (io_region->ret_code)
+ if (io_region->ret_code) {
+ errstr = "cp init";
goto err_out;
+ }
io_region->ret_code = cp_prefetch(&private->cp);
if (io_region->ret_code) {
+ errstr = "cp prefetch";
cp_free(&private->cp);
goto err_out;
}
@@ -148,6 +160,7 @@ static void fsm_io_request(struct vfio_ccw_private *private,
/* Start channel program and wait for I/O interrupt. */
io_region->ret_code = fsm_io_helper(private);
if (io_region->ret_code) {
+ errstr = "cp fsm_io_helper";
cp_free(&private->cp);
goto err_out;
}
@@ -164,6 +177,8 @@ static void fsm_io_request(struct vfio_ccw_private *private,
err_out:
private->state = VFIO_CCW_STATE_IDLE;
+ trace_vfio_ccw_io_fctl(scsw->cmd.fctl, get_schid(private),
+ io_region->ret_code, errstr);
}
/*
diff --git a/drivers/s390/cio/vfio_ccw_trace.h b/drivers/s390/cio/vfio_ccw_trace.h
new file mode 100644
index 0000000..b1da53d
--- /dev/null
+++ b/drivers/s390/cio/vfio_ccw_trace.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Tracepoints for vfio_ccw driver
+ *
+ * Copyright IBM Corp. 2018
+ *
+ * Author(s): Dong Jia Shi <bjsdjshi@linux.vnet.ibm.com>
+ * Halil Pasic <pasic@linux.vnet.ibm.com>
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM vfio_ccw
+
+#if !defined(_VFIO_CCW_TRACE_) || defined(TRACE_HEADER_MULTI_READ)
+#define _VFIO_CCW_TRACE_
+
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(vfio_ccw_io_fctl,
+ TP_PROTO(int fctl, struct subchannel_id schid, int errno, char *errstr),
+ TP_ARGS(fctl, schid, errno, errstr),
+
+ TP_STRUCT__entry(
+ __field(int, fctl)
+ __field_struct(struct subchannel_id, schid)
+ __field(int, errno)
+ __field(char*, errstr)
+ ),
+
+ TP_fast_assign(
+ __entry->fctl = fctl;
+ __entry->schid = schid;
+ __entry->errno = errno;
+ __entry->errstr = errstr;
+ ),
+
+ TP_printk("schid=%x.%x.%04x fctl=%x errno=%d info=%s",
+ __entry->schid.cssid,
+ __entry->schid.ssid,
+ __entry->schid.sch_no,
+ __entry->fctl,
+ __entry->errno,
+ __entry->errstr)
+);
+
+#endif /* _VFIO_CCW_TRACE_ */
+
+/* This part must be outside protection */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE vfio_ccw_trace
+
+#include <trace/define_trace.h>
diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c
index ed80d00..3929c8b 100644
--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -121,7 +121,7 @@ static int alloc_and_prep_cprbmem(size_t paramblen,
* allocate consecutive memory for request CPRB, request param
* block, reply CPRB and reply param block
*/
- cprbmem = kzalloc(2 * cprbplusparamblen, GFP_KERNEL);
+ cprbmem = kcalloc(2, cprbplusparamblen, GFP_KERNEL);
if (!cprbmem)
return -ENOMEM;
@@ -899,9 +899,9 @@ int pkey_findcard(const struct pkey_seckey *seckey,
return -EINVAL;
/* fetch status of all crypto cards */
- device_status = kmalloc(MAX_ZDEV_ENTRIES_EXT
- * sizeof(struct zcrypt_device_status_ext),
- GFP_KERNEL);
+ device_status = kmalloc_array(MAX_ZDEV_ENTRIES_EXT,
+ sizeof(struct zcrypt_device_status_ext),
+ GFP_KERNEL);
if (!device_status)
return -ENOMEM;
zcrypt_device_status_mask_ext(device_status);
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 7ce98b7..7617d21 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1379,7 +1379,7 @@ static int add_channel(struct ccw_device *cdev, enum ctcm_channel_types type,
} else
ccw_num = 8;
- ch->ccw = kzalloc(ccw_num * sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
+ ch->ccw = kcalloc(ccw_num, sizeof(struct ccw1), GFP_KERNEL | GFP_DMA);
if (ch->ccw == NULL)
goto nomem_return;
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 9f28b6f..8e1474f 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -374,9 +374,10 @@ static int qeth_alloc_cq(struct qeth_card *card)
}
card->qdio.no_in_queues = 2;
card->qdio.out_bufstates =
- kzalloc(card->qdio.no_out_queues *
- QDIO_MAX_BUFFERS_PER_Q *
- sizeof(struct qdio_outbuf_state), GFP_KERNEL);
+ kcalloc(card->qdio.no_out_queues *
+ QDIO_MAX_BUFFERS_PER_Q,
+ sizeof(struct qdio_outbuf_state),
+ GFP_KERNEL);
outbuf_states = card->qdio.out_bufstates;
if (outbuf_states == NULL) {
rc = -1;
@@ -2538,8 +2539,9 @@ static int qeth_alloc_qdio_buffers(struct qeth_card *card)
/* outbound */
card->qdio.out_qs =
- kzalloc(card->qdio.no_out_queues *
- sizeof(struct qeth_qdio_out_q *), GFP_KERNEL);
+ kcalloc(card->qdio.no_out_queues,
+ sizeof(struct qeth_qdio_out_q *),
+ GFP_KERNEL);
if (!card->qdio.out_qs)
goto out_freepool;
for (i = 0; i < card->qdio.no_out_queues; ++i) {
@@ -4963,8 +4965,8 @@ static int qeth_qdio_establish(struct qeth_card *card)
QETH_DBF_TEXT(SETUP, 2, "qdioest");
- qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q * sizeof(char),
- GFP_KERNEL);
+ qib_param_field = kzalloc(QDIO_MAX_BUFFERS_PER_Q,
+ GFP_KERNEL);
if (!qib_param_field) {
rc = -ENOMEM;
goto out_free_nothing;
@@ -4973,8 +4975,8 @@ static int qeth_qdio_establish(struct qeth_card *card)
qeth_create_qib_param_field(card, qib_param_field);
qeth_create_qib_param_field_blkt(card, qib_param_field);
- in_sbal_ptrs = kzalloc(card->qdio.no_in_queues *
- QDIO_MAX_BUFFERS_PER_Q * sizeof(void *),
+ in_sbal_ptrs = kcalloc(card->qdio.no_in_queues * QDIO_MAX_BUFFERS_PER_Q,
+ sizeof(void *),
GFP_KERNEL);
if (!in_sbal_ptrs) {
rc = -ENOMEM;
@@ -4985,7 +4987,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
virt_to_phys(card->qdio.in_q->bufs[i].buffer);
}
- queue_start_poll = kzalloc(sizeof(void *) * card->qdio.no_in_queues,
+ queue_start_poll = kcalloc(card->qdio.no_in_queues, sizeof(void *),
GFP_KERNEL);
if (!queue_start_poll) {
rc = -ENOMEM;
@@ -4997,8 +4999,9 @@ static int qeth_qdio_establish(struct qeth_card *card)
qeth_qdio_establish_cq(card, in_sbal_ptrs, queue_start_poll);
out_sbal_ptrs =
- kzalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q *
- sizeof(void *), GFP_KERNEL);
+ kcalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q,
+ sizeof(void *),
+ GFP_KERNEL);
if (!out_sbal_ptrs) {
rc = -ENOMEM;
goto out_free_queue_start_poll;
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 18c4f93..3b368fc 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -285,6 +285,8 @@ void zfcp_dbf_rec_trig(char *tag, struct zfcp_adapter *adapter,
struct list_head *entry;
unsigned long flags;
+ lockdep_assert_held(&adapter->erp_lock);
+
if (unlikely(!debug_level_enabled(dbf->rec, level)))
return;
@@ -599,16 +601,18 @@ void zfcp_dbf_san_in_els(char *tag, struct zfcp_fsf_req *fsf)
}
/**
- * zfcp_dbf_scsi - trace event for scsi commands
- * @tag: identifier for event
- * @sc: pointer to struct scsi_cmnd
- * @fsf: pointer to struct zfcp_fsf_req
+ * zfcp_dbf_scsi_common() - Common trace event helper for scsi.
+ * @tag: Identifier for event.
+ * @level: trace level of event.
+ * @sdev: Pointer to SCSI device as context for this event.
+ * @sc: Pointer to SCSI command, or NULL with task management function (TMF).
+ * @fsf: Pointer to FSF request, or NULL.
*/
-void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc,
- struct zfcp_fsf_req *fsf)
+void zfcp_dbf_scsi_common(char *tag, int level, struct scsi_device *sdev,
+ struct scsi_cmnd *sc, struct zfcp_fsf_req *fsf)
{
struct zfcp_adapter *adapter =
- (struct zfcp_adapter *) sc->device->host->hostdata[0];
+ (struct zfcp_adapter *) sdev->host->hostdata[0];
struct zfcp_dbf *dbf = adapter->dbf;
struct zfcp_dbf_scsi *rec = &dbf->scsi_buf;
struct fcp_resp_with_ext *fcp_rsp;
@@ -620,16 +624,28 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc,
memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
rec->id = ZFCP_DBF_SCSI_CMND;
- rec->scsi_result = sc->result;
- rec->scsi_retries = sc->retries;
- rec->scsi_allowed = sc->allowed;
- rec->scsi_id = sc->device->id;
- rec->scsi_lun = (u32)sc->device->lun;
- rec->scsi_lun_64_hi = (u32)(sc->device->lun >> 32);
- rec->host_scribble = (unsigned long)sc->host_scribble;
-
- memcpy(rec->scsi_opcode, sc->cmnd,
- min((int)sc->cmd_len, ZFCP_DBF_SCSI_OPCODE));
+ if (sc) {
+ rec->scsi_result = sc->result;
+ rec->scsi_retries = sc->retries;
+ rec->scsi_allowed = sc->allowed;
+ rec->scsi_id = sc->device->id;
+ rec->scsi_lun = (u32)sc->device->lun;
+ rec->scsi_lun_64_hi = (u32)(sc->device->lun >> 32);
+ rec->host_scribble = (unsigned long)sc->host_scribble;
+
+ memcpy(rec->scsi_opcode, sc->cmnd,
+ min_t(int, sc->cmd_len, ZFCP_DBF_SCSI_OPCODE));
+ } else {
+ rec->scsi_result = ~0;
+ rec->scsi_retries = ~0;
+ rec->scsi_allowed = ~0;
+ rec->scsi_id = sdev->id;
+ rec->scsi_lun = (u32)sdev->lun;
+ rec->scsi_lun_64_hi = (u32)(sdev->lun >> 32);
+ rec->host_scribble = ~0;
+
+ memset(rec->scsi_opcode, 0xff, ZFCP_DBF_SCSI_OPCODE);
+ }
if (fsf) {
rec->fsf_req_id = fsf->req_id;
@@ -664,6 +680,46 @@ void zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *sc,
spin_unlock_irqrestore(&dbf->scsi_lock, flags);
}
+/**
+ * zfcp_dbf_scsi_eh() - Trace event for special cases of scsi_eh callbacks.
+ * @tag: Identifier for event.
+ * @adapter: Pointer to zfcp adapter as context for this event.
+ * @scsi_id: SCSI ID/target to indicate scope of task management function (TMF).
+ * @ret: Return value of calling function.
+ *
+ * This SCSI trace variant does not depend on any of:
+ * scsi_cmnd, zfcp_fsf_req, scsi_device.
+ */
+void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter,
+ unsigned int scsi_id, int ret)
+{
+ struct zfcp_dbf *dbf = adapter->dbf;
+ struct zfcp_dbf_scsi *rec = &dbf->scsi_buf;
+ unsigned long flags;
+ static int const level = 1;
+
+ if (unlikely(!debug_level_enabled(adapter->dbf->scsi, level)))
+ return;
+
+ spin_lock_irqsave(&dbf->scsi_lock, flags);
+ memset(rec, 0, sizeof(*rec));
+
+ memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
+ rec->id = ZFCP_DBF_SCSI_CMND;
+ rec->scsi_result = ret; /* re-use field, int is 4 bytes and fits */
+ rec->scsi_retries = ~0;
+ rec->scsi_allowed = ~0;
+ rec->fcp_rsp_info = ~0;
+ rec->scsi_id = scsi_id;
+ rec->scsi_lun = (u32)ZFCP_DBF_INVALID_LUN;
+ rec->scsi_lun_64_hi = (u32)(ZFCP_DBF_INVALID_LUN >> 32);
+ rec->host_scribble = ~0;
+ memset(rec->scsi_opcode, 0xff, ZFCP_DBF_SCSI_OPCODE);
+
+ debug_event(dbf->scsi, level, rec, sizeof(*rec));
+ spin_unlock_irqrestore(&dbf->scsi_lock, flags);
+}
+
static debug_info_t *zfcp_dbf_reg(const char *name, int size, int rec_size)
{
struct debug_info *d;
diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h
index e2a973c..d116c07 100644
--- a/drivers/s390/scsi/zfcp_dbf.h
+++ b/drivers/s390/scsi/zfcp_dbf.h
@@ -359,7 +359,7 @@ void _zfcp_dbf_scsi(char *tag, int level, struct scsi_cmnd *scmd,
scmd->device->host->hostdata[0];
if (debug_level_enabled(adapter->dbf->scsi, level))
- zfcp_dbf_scsi(tag, level, scmd, req);
+ zfcp_dbf_scsi_common(tag, level, scmd->device, scmd, req);
}
/**
@@ -402,16 +402,23 @@ void zfcp_dbf_scsi_abort(char *tag, struct scsi_cmnd *scmd,
}
/**
- * zfcp_dbf_scsi_devreset - trace event for Logical Unit or Target Reset
- * @tag: tag indicating success or failure of reset operation
- * @scmnd: SCSI command which caused this error recovery
- * @flag: indicates type of reset (Target Reset, Logical Unit Reset)
+ * zfcp_dbf_scsi_devreset() - Trace event for Logical Unit or Target Reset.
+ * @tag: Tag indicating success or failure of reset operation.
+ * @sdev: Pointer to SCSI device as context for this event.
+ * @flag: Indicates type of reset (Target Reset, Logical Unit Reset).
+ * @fsf_req: Pointer to FSF request representing the TMF, or NULL.
*/
static inline
-void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag,
+void zfcp_dbf_scsi_devreset(char *tag, struct scsi_device *sdev, u8 flag,
struct zfcp_fsf_req *fsf_req)
{
+ struct zfcp_adapter *adapter = (struct zfcp_adapter *)
+ sdev->host->hostdata[0];
char tmp_tag[ZFCP_DBF_TAG_LEN];
+ static int const level = 1;
+
+ if (unlikely(!debug_level_enabled(adapter->dbf->scsi, level)))
+ return;
if (flag == FCP_TMF_TGT_RESET)
memcpy(tmp_tag, "tr_", 3);
@@ -419,7 +426,7 @@ void zfcp_dbf_scsi_devreset(char *tag, struct scsi_cmnd *scmnd, u8 flag,
memcpy(tmp_tag, "lr_", 3);
memcpy(&tmp_tag[3], tag, 4);
- _zfcp_dbf_scsi(tmp_tag, 1, scmnd, fsf_req);
+ zfcp_dbf_scsi_common(tmp_tag, level, sdev, NULL, fsf_req);
}
/**
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 1d91a32..e7e6b63 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -19,7 +19,6 @@
enum zfcp_erp_act_flags {
ZFCP_STATUS_ERP_TIMEDOUT = 0x10000000,
ZFCP_STATUS_ERP_CLOSE_ONLY = 0x01000000,
- ZFCP_STATUS_ERP_DISMISSING = 0x00100000,
ZFCP_STATUS_ERP_DISMISSED = 0x00200000,
ZFCP_STATUS_ERP_LOWMEM = 0x00400000,
ZFCP_STATUS_ERP_NO_REF = 0x00800000,
@@ -27,7 +26,6 @@ enum zfcp_erp_act_flags {
enum zfcp_erp_steps {
ZFCP_ERP_STEP_UNINITIALIZED = 0x0000,
- ZFCP_ERP_STEP_FSF_XCONFIG = 0x0001,
ZFCP_ERP_STEP_PHYS_PORT_CLOSING = 0x0010,
ZFCP_ERP_STEP_PORT_CLOSING = 0x0100,
ZFCP_ERP_STEP_PORT_OPENING = 0x0800,
@@ -35,16 +33,28 @@ enum zfcp_erp_steps {
ZFCP_ERP_STEP_LUN_OPENING = 0x2000,
};
+/**
+ * enum zfcp_erp_act_type - Type of ERP action object.
+ * @ZFCP_ERP_ACTION_REOPEN_LUN: LUN recovery.
+ * @ZFCP_ERP_ACTION_REOPEN_PORT: Port recovery.
+ * @ZFCP_ERP_ACTION_REOPEN_PORT_FORCED: Forced port recovery.
+ * @ZFCP_ERP_ACTION_REOPEN_ADAPTER: Adapter recovery.
+ * @ZFCP_ERP_ACTION_NONE: Eyecatcher pseudo flag to bitwise or-combine with
+ * either of the first four enum values.
+ * Used to indicate that an ERP action could not be
+ * set up despite a detected need for some recovery.
+ * @ZFCP_ERP_ACTION_FAILED: Eyecatcher pseudo flag to bitwise or-combine with
+ * either of the first four enum values.
+ * Used to indicate that ERP not needed because
+ * the object has ZFCP_STATUS_COMMON_ERP_FAILED.
+ */
enum zfcp_erp_act_type {
ZFCP_ERP_ACTION_REOPEN_LUN = 1,
ZFCP_ERP_ACTION_REOPEN_PORT = 2,
ZFCP_ERP_ACTION_REOPEN_PORT_FORCED = 3,
ZFCP_ERP_ACTION_REOPEN_ADAPTER = 4,
-};
-
-enum zfcp_erp_act_state {
- ZFCP_ERP_ACTION_RUNNING = 1,
- ZFCP_ERP_ACTION_READY = 2,
+ ZFCP_ERP_ACTION_NONE = 0xc0,
+ ZFCP_ERP_ACTION_FAILED = 0xe0,
};
enum zfcp_erp_act_result {
@@ -62,14 +72,14 @@ static void zfcp_erp_adapter_block(struct zfcp_adapter *adapter, int mask)
ZFCP_STATUS_COMMON_UNBLOCKED | mask);
}
-static int zfcp_erp_action_exists(struct zfcp_erp_action *act)
+static bool zfcp_erp_action_is_running(struct zfcp_erp_action *act)
{
struct zfcp_erp_action *curr_act;
list_for_each_entry(curr_act, &act->adapter->erp_running_head, list)
if (act == curr_act)
- return ZFCP_ERP_ACTION_RUNNING;
- return 0;
+ return true;
+ return false;
}
static void zfcp_erp_action_ready(struct zfcp_erp_action *act)
@@ -85,7 +95,7 @@ static void zfcp_erp_action_ready(struct zfcp_erp_action *act)
static void zfcp_erp_action_dismiss(struct zfcp_erp_action *act)
{
act->status |= ZFCP_STATUS_ERP_DISMISSED;
- if (zfcp_erp_action_exists(act) == ZFCP_ERP_ACTION_RUNNING)
+ if (zfcp_erp_action_is_running(act))
zfcp_erp_action_ready(act);
}
@@ -126,6 +136,49 @@ static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter)
}
}
+static int zfcp_erp_handle_failed(int want, struct zfcp_adapter *adapter,
+ struct zfcp_port *port,
+ struct scsi_device *sdev)
+{
+ int need = want;
+ struct zfcp_scsi_dev *zsdev;
+
+ switch (want) {
+ case ZFCP_ERP_ACTION_REOPEN_LUN:
+ zsdev = sdev_to_zfcp(sdev);
+ if (atomic_read(&zsdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
+ need = 0;
+ break;
+ case ZFCP_ERP_ACTION_REOPEN_PORT_FORCED:
+ if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
+ need = 0;
+ break;
+ case ZFCP_ERP_ACTION_REOPEN_PORT:
+ if (atomic_read(&port->status) &
+ ZFCP_STATUS_COMMON_ERP_FAILED) {
+ need = 0;
+ /* ensure propagation of failed status to new devices */
+ zfcp_erp_set_port_status(
+ port, ZFCP_STATUS_COMMON_ERP_FAILED);
+ }
+ break;
+ case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
+ if (atomic_read(&adapter->status) &
+ ZFCP_STATUS_COMMON_ERP_FAILED) {
+ need = 0;
+ /* ensure propagation of failed status to new devices */
+ zfcp_erp_set_adapter_status(
+ adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
+ }
+ break;
+ default:
+ need = 0;
+ break;
+ }
+
+ return need;
+}
+
static int zfcp_erp_required_act(int want, struct zfcp_adapter *adapter,
struct zfcp_port *port,
struct scsi_device *sdev)
@@ -241,48 +294,70 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
return erp_action;
}
-static int zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
- struct zfcp_port *port,
- struct scsi_device *sdev,
- char *id, u32 act_status)
+static void zfcp_erp_action_enqueue(int want, struct zfcp_adapter *adapter,
+ struct zfcp_port *port,
+ struct scsi_device *sdev,
+ char *id, u32 act_status)
{
- int retval = 1, need;
+ int need;
struct zfcp_erp_action *act;
- if (!adapter->erp_thread)
- return -EIO;
+ need = zfcp_erp_handle_failed(want, adapter, port, sdev);
+ if (!need) {
+ need = ZFCP_ERP_ACTION_FAILED; /* marker for trace */
+ goto out;
+ }
+
+ if (!adapter->erp_thread) {
+ need = ZFCP_ERP_ACTION_NONE; /* marker for trace */
+ goto out;
+ }
need = zfcp_erp_required_act(want, adapter, port, sdev);
if (!need)
goto out;
act = zfcp_erp_setup_act(need, act_status, adapter, port, sdev);
- if (!act)
+ if (!act) {
+ need |= ZFCP_ERP_ACTION_NONE; /* marker for trace */
goto out;
+ }
atomic_or(ZFCP_STATUS_ADAPTER_ERP_PENDING, &adapter->status);
++adapter->erp_total_count;
list_add_tail(&act->list, &adapter->erp_ready_head);
wake_up(&adapter->erp_ready_wq);
- retval = 0;
out:
zfcp_dbf_rec_trig(id, adapter, port, sdev, want, need);
- return retval;
}
-static int _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter,
+void zfcp_erp_port_forced_no_port_dbf(char *id, struct zfcp_adapter *adapter,
+ u64 port_name, u32 port_id)
+{
+ unsigned long flags;
+ static /* don't waste stack */ struct zfcp_port tmpport;
+
+ write_lock_irqsave(&adapter->erp_lock, flags);
+ /* Stand-in zfcp port with fields just good enough for
+ * zfcp_dbf_rec_trig() and zfcp_dbf_set_common().
+ * Under lock because tmpport is static.
+ */
+ atomic_set(&tmpport.status, -1); /* unknown */
+ tmpport.wwpn = port_name;
+ tmpport.d_id = port_id;
+ zfcp_dbf_rec_trig(id, adapter, &tmpport, NULL,
+ ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
+ ZFCP_ERP_ACTION_NONE);
+ write_unlock_irqrestore(&adapter->erp_lock, flags);
+}
+
+static void _zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter,
int clear_mask, char *id)
{
zfcp_erp_adapter_block(adapter, clear_mask);
zfcp_scsi_schedule_rports_block(adapter);
- /* ensure propagation of failed status to new devices */
- if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
- zfcp_erp_set_adapter_status(adapter,
- ZFCP_STATUS_COMMON_ERP_FAILED);
- return -EIO;
- }
- return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
- adapter, NULL, NULL, id, 0);
+ zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER,
+ adapter, NULL, NULL, id, 0);
}
/**
@@ -299,12 +374,8 @@ void zfcp_erp_adapter_reopen(struct zfcp_adapter *adapter, int clear, char *id)
zfcp_scsi_schedule_rports_block(adapter);
write_lock_irqsave(&adapter->erp_lock, flags);
- if (atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
- zfcp_erp_set_adapter_status(adapter,
- ZFCP_STATUS_COMMON_ERP_FAILED);
- else
- zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
- NULL, NULL, id, 0);
+ zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_ADAPTER, adapter,
+ NULL, NULL, id, 0);
write_unlock_irqrestore(&adapter->erp_lock, flags);
}
@@ -345,9 +416,6 @@ static void _zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear,
zfcp_erp_port_block(port, clear);
zfcp_scsi_schedule_rport_block(port);
- if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
- return;
-
zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT_FORCED,
port->adapter, port, NULL, id, 0);
}
@@ -368,19 +436,13 @@ void zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear, char *id)
write_unlock_irqrestore(&adapter->erp_lock, flags);
}
-static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
+static void _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
{
zfcp_erp_port_block(port, clear);
zfcp_scsi_schedule_rport_block(port);
- if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_FAILED) {
- /* ensure propagation of failed status to new devices */
- zfcp_erp_set_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED);
- return -EIO;
- }
-
- return zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
- port->adapter, port, NULL, id, 0);
+ zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_PORT,
+ port->adapter, port, NULL, id, 0);
}
/**
@@ -388,20 +450,15 @@ static int _zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
* @port: port to recover
* @clear_mask: flags in port status to be cleared
* @id: Id for debug trace event.
- *
- * Returns 0 if recovery has been triggered, < 0 if not.
*/
-int zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
+void zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id)
{
- int retval;
unsigned long flags;
struct zfcp_adapter *adapter = port->adapter;
write_lock_irqsave(&adapter->erp_lock, flags);
- retval = _zfcp_erp_port_reopen(port, clear, id);
+ _zfcp_erp_port_reopen(port, clear, id);
write_unlock_irqrestore(&adapter->erp_lock, flags);
-
- return retval;
}
static void zfcp_erp_lun_block(struct scsi_device *sdev, int clear_mask)
@@ -418,9 +475,6 @@ static void _zfcp_erp_lun_reopen(struct scsi_device *sdev, int clear, char *id,
zfcp_erp_lun_block(sdev, clear);
- if (atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_ERP_FAILED)
- return;
-
zfcp_erp_action_enqueue(ZFCP_ERP_ACTION_REOPEN_LUN, adapter,
zfcp_sdev->port, sdev, id, act_status);
}
@@ -482,21 +536,23 @@ void zfcp_erp_lun_shutdown_wait(struct scsi_device *sdev, char *id)
zfcp_erp_wait(adapter);
}
-static int status_change_set(unsigned long mask, atomic_t *status)
+static int zfcp_erp_status_change_set(unsigned long mask, atomic_t *status)
{
return (atomic_read(status) ^ mask) & mask;
}
static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter)
{
- if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status))
+ if (zfcp_erp_status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED,
+ &adapter->status))
zfcp_dbf_rec_run("eraubl1", &adapter->erp_action);
atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &adapter->status);
}
static void zfcp_erp_port_unblock(struct zfcp_port *port)
{
- if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status))
+ if (zfcp_erp_status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED,
+ &port->status))
zfcp_dbf_rec_run("erpubl1", &port->erp_action);
atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &port->status);
}
@@ -505,7 +561,8 @@ static void zfcp_erp_lun_unblock(struct scsi_device *sdev)
{
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
- if (status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status))
+ if (zfcp_erp_status_change_set(ZFCP_STATUS_COMMON_UNBLOCKED,
+ &zfcp_sdev->status))
zfcp_dbf_rec_run("erlubl1", &sdev_to_zfcp(sdev)->erp_action);
atomic_or(ZFCP_STATUS_COMMON_UNBLOCKED, &zfcp_sdev->status);
}
@@ -553,7 +610,7 @@ void zfcp_erp_notify(struct zfcp_erp_action *erp_action, unsigned long set_mask)
unsigned long flags;
write_lock_irqsave(&adapter->erp_lock, flags);
- if (zfcp_erp_action_exists(erp_action) == ZFCP_ERP_ACTION_RUNNING) {
+ if (zfcp_erp_action_is_running(erp_action)) {
erp_action->status |= set_mask;
zfcp_erp_action_ready(erp_action);
}
@@ -1634,3 +1691,14 @@ void zfcp_erp_clear_lun_status(struct scsi_device *sdev, u32 mask)
atomic_set(&zfcp_sdev->erp_counter, 0);
}
+/**
+ * zfcp_erp_adapter_reset_sync() - Really reopen adapter and wait.
+ * @adapter: Pointer to zfcp_adapter to reopen.
+ * @id: Trace tag string of length %ZFCP_DBF_TAG_LEN.
+ */
+void zfcp_erp_adapter_reset_sync(struct zfcp_adapter *adapter, char *id)
+{
+ zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
+ zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, id);
+ zfcp_erp_wait(adapter);
+}
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index e5eed8a..bd0c5a9 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -50,17 +50,23 @@ extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *);
extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *);
-extern void zfcp_dbf_scsi(char *, int, struct scsi_cmnd *,
- struct zfcp_fsf_req *);
+extern void zfcp_dbf_scsi_common(char *tag, int level, struct scsi_device *sdev,
+ struct scsi_cmnd *sc,
+ struct zfcp_fsf_req *fsf);
+extern void zfcp_dbf_scsi_eh(char *tag, struct zfcp_adapter *adapter,
+ unsigned int scsi_id, int ret);
/* zfcp_erp.c */
extern void zfcp_erp_set_adapter_status(struct zfcp_adapter *, u32);
extern void zfcp_erp_clear_adapter_status(struct zfcp_adapter *, u32);
+extern void zfcp_erp_port_forced_no_port_dbf(char *id,
+ struct zfcp_adapter *adapter,
+ u64 port_name, u32 port_id);
extern void zfcp_erp_adapter_reopen(struct zfcp_adapter *, int, char *);
extern void zfcp_erp_adapter_shutdown(struct zfcp_adapter *, int, char *);
extern void zfcp_erp_set_port_status(struct zfcp_port *, u32);
extern void zfcp_erp_clear_port_status(struct zfcp_port *, u32);
-extern int zfcp_erp_port_reopen(struct zfcp_port *, int, char *);
+extern void zfcp_erp_port_reopen(struct zfcp_port *port, int clear, char *id);
extern void zfcp_erp_port_shutdown(struct zfcp_port *, int, char *);
extern void zfcp_erp_port_forced_reopen(struct zfcp_port *, int, char *);
extern void zfcp_erp_set_lun_status(struct scsi_device *, u32);
@@ -73,6 +79,7 @@ extern void zfcp_erp_thread_kill(struct zfcp_adapter *);
extern void zfcp_erp_wait(struct zfcp_adapter *);
extern void zfcp_erp_notify(struct zfcp_erp_action *, unsigned long);
extern void zfcp_erp_timeout_handler(struct timer_list *t);
+extern void zfcp_erp_adapter_reset_sync(struct zfcp_adapter *adapter, char *id);
/* zfcp_fc.c */
extern struct kmem_cache *zfcp_fc_req_cache;
@@ -120,7 +127,8 @@ extern int zfcp_fsf_send_els(struct zfcp_adapter *, u32,
struct zfcp_fsf_ct_els *, unsigned int);
extern int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *);
extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
-extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *, u8);
+extern struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_device *sdev,
+ u8 tm_flags);
extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_cmnd(struct scsi_cmnd *);
extern void zfcp_fsf_reqid_check(struct zfcp_qdio *, int);
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 6162cf5..f6c415d 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -111,11 +111,10 @@ void zfcp_fc_post_event(struct work_struct *work)
list_for_each_entry_safe(event, tmp, &tmp_lh, list) {
fc_host_post_event(adapter->scsi_host, fc_get_event_number(),
- event->code, event->data);
+ event->code, event->data);
list_del(&event->list);
kfree(event);
}
-
}
/**
@@ -126,7 +125,7 @@ void zfcp_fc_post_event(struct work_struct *work)
* @event_data: The event data (e.g. n_port page in case of els)
*/
void zfcp_fc_enqueue_event(struct zfcp_adapter *adapter,
- enum fc_host_event_code event_code, u32 event_data)
+ enum fc_host_event_code event_code, u32 event_data)
{
struct zfcp_fc_event *event;
@@ -425,6 +424,7 @@ void zfcp_fc_port_did_lookup(struct work_struct *work)
struct zfcp_port *port = container_of(work, struct zfcp_port,
gid_pn_work);
+ set_worker_desc("zgidpn%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */
ret = zfcp_fc_ns_gid_pn(port);
if (ret) {
/* could not issue gid_pn for some reason */
@@ -559,6 +559,7 @@ void zfcp_fc_link_test_work(struct work_struct *work)
container_of(work, struct zfcp_port, test_link_work);
int retval;
+ set_worker_desc("zadisc%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */
get_device(&port->dev);
port->rport_task = RPORT_DEL;
zfcp_scsi_rport_work(&port->rport_work);
@@ -596,7 +597,7 @@ void zfcp_fc_test_link(struct zfcp_port *port)
put_device(&port->dev);
}
-static struct zfcp_fc_req *zfcp_alloc_sg_env(int buf_num)
+static struct zfcp_fc_req *zfcp_fc_alloc_sg_env(int buf_num)
{
struct zfcp_fc_req *fc_req;
@@ -748,7 +749,7 @@ void zfcp_fc_scan_ports(struct work_struct *work)
if (zfcp_fc_wka_port_get(&adapter->gs->ds))
return;
- fc_req = zfcp_alloc_sg_env(buf_num);
+ fc_req = zfcp_fc_alloc_sg_env(buf_num);
if (!fc_req)
goto out;
diff --git a/drivers/s390/scsi/zfcp_fc.h b/drivers/s390/scsi/zfcp_fc.h
index 6a397dd..3cd7472 100644
--- a/drivers/s390/scsi/zfcp_fc.h
+++ b/drivers/s390/scsi/zfcp_fc.h
@@ -207,21 +207,14 @@ struct zfcp_fc_wka_ports {
* zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd
* @fcp: fcp_cmnd to setup
* @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB
- * @tm: task management flags to setup task management command
*/
static inline
-void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi,
- u8 tm_flags)
+void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi)
{
u32 datalen;
int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun);
- if (unlikely(tm_flags)) {
- fcp->fc_tm_flags = tm_flags;
- return;
- }
-
fcp->fc_pri_ta = FCP_PTA_SIMPLE;
if (scsi->sc_data_direction == DMA_FROM_DEVICE)
@@ -241,6 +234,19 @@ void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi,
}
/**
+ * zfcp_fc_fcp_tm() - Setup FCP command as task management command.
+ * @fcp: Pointer to FCP_CMND IU to set up.
+ * @dev: Pointer to SCSI_device where to send the task management command.
+ * @tm_flags: Task management flags to setup tm command.
+ */
+static inline
+void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags)
+{
+ int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun);
+ fcp->fc_tm_flags = tm_flags;
+}
+
+/**
* zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly
* @fcp_rsp: FCP RSP IU to evaluate
* @scsi: SCSI command where to update status and sense buffer
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index b12cb81..3c86e27 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -4,7 +4,7 @@
*
* Implementation of FSF commands.
*
- * Copyright IBM Corp. 2002, 2017
+ * Copyright IBM Corp. 2002, 2018
*/
#define KMSG_COMPONENT "zfcp"
@@ -437,6 +437,9 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
#define ZFCP_FSF_PORTSPEED_10GBIT (1 << 3)
#define ZFCP_FSF_PORTSPEED_8GBIT (1 << 4)
#define ZFCP_FSF_PORTSPEED_16GBIT (1 << 5)
+#define ZFCP_FSF_PORTSPEED_32GBIT (1 << 6)
+#define ZFCP_FSF_PORTSPEED_64GBIT (1 << 7)
+#define ZFCP_FSF_PORTSPEED_128GBIT (1 << 8)
#define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15)
static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed)
@@ -454,6 +457,12 @@ static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed)
fdmi_speed |= FC_PORTSPEED_8GBIT;
if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT)
fdmi_speed |= FC_PORTSPEED_16GBIT;
+ if (fsf_speed & ZFCP_FSF_PORTSPEED_32GBIT)
+ fdmi_speed |= FC_PORTSPEED_32GBIT;
+ if (fsf_speed & ZFCP_FSF_PORTSPEED_64GBIT)
+ fdmi_speed |= FC_PORTSPEED_64GBIT;
+ if (fsf_speed & ZFCP_FSF_PORTSPEED_128GBIT)
+ fdmi_speed |= FC_PORTSPEED_128GBIT;
if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED)
fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED;
return fdmi_speed;
@@ -662,7 +671,7 @@ static struct zfcp_fsf_req *zfcp_fsf_alloc(mempool_t *pool)
return req;
}
-static struct fsf_qtcb *zfcp_qtcb_alloc(mempool_t *pool)
+static struct fsf_qtcb *zfcp_fsf_qtcb_alloc(mempool_t *pool)
{
struct fsf_qtcb *qtcb;
@@ -701,9 +710,10 @@ static struct zfcp_fsf_req *zfcp_fsf_req_create(struct zfcp_qdio *qdio,
if (likely(fsf_cmd != FSF_QTCB_UNSOLICITED_STATUS)) {
if (likely(pool))
- req->qtcb = zfcp_qtcb_alloc(adapter->pool.qtcb_pool);
+ req->qtcb = zfcp_fsf_qtcb_alloc(
+ adapter->pool.qtcb_pool);
else
- req->qtcb = zfcp_qtcb_alloc(NULL);
+ req->qtcb = zfcp_fsf_qtcb_alloc(NULL);
if (unlikely(!req->qtcb)) {
zfcp_fsf_req_free(req);
@@ -2036,10 +2046,14 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
sizeof(blktrc));
}
-static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
+/**
+ * zfcp_fsf_fcp_handler_common() - FCP response handler common to I/O and TMF.
+ * @req: Pointer to FSF request.
+ * @sdev: Pointer to SCSI device as request context.
+ */
+static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req,
+ struct scsi_device *sdev)
{
- struct scsi_cmnd *scmnd = req->data;
- struct scsi_device *sdev = scmnd->device;
struct zfcp_scsi_dev *zfcp_sdev;
struct fsf_qtcb_header *header = &req->qtcb->header;
@@ -2051,7 +2065,7 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
switch (header->fsf_status) {
case FSF_HANDLE_MISMATCH:
case FSF_PORT_HANDLE_NOT_VALID:
- zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fssfch1");
+ zfcp_erp_adapter_reopen(req->adapter, 0, "fssfch1");
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_FCPLUN_NOT_VALID:
@@ -2069,8 +2083,7 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
req->qtcb->bottom.io.data_direction,
(unsigned long long)zfcp_scsi_dev_lun(sdev),
(unsigned long long)zfcp_sdev->port->wwpn);
- zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
- "fssfch3");
+ zfcp_erp_adapter_shutdown(req->adapter, 0, "fssfch3");
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_CMND_LENGTH_NOT_VALID:
@@ -2080,8 +2093,7 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
req->qtcb->bottom.io.fcp_cmnd_length,
(unsigned long long)zfcp_scsi_dev_lun(sdev),
(unsigned long long)zfcp_sdev->port->wwpn);
- zfcp_erp_adapter_shutdown(zfcp_sdev->port->adapter, 0,
- "fssfch4");
+ zfcp_erp_adapter_shutdown(req->adapter, 0, "fssfch4");
req->status |= ZFCP_STATUS_FSFREQ_ERROR;
break;
case FSF_PORT_BOXED:
@@ -2120,7 +2132,7 @@ static void zfcp_fsf_fcp_cmnd_handler(struct zfcp_fsf_req *req)
return;
}
- zfcp_fsf_fcp_handler_common(req);
+ zfcp_fsf_fcp_handler_common(req, scpnt->device);
if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
set_host_byte(scpnt, DID_TRANSPORT_DISRUPTED);
@@ -2258,7 +2270,7 @@ int zfcp_fsf_fcp_cmnd(struct scsi_cmnd *scsi_cmnd)
BUILD_BUG_ON(sizeof(struct fcp_cmnd) > FSF_FCP_CMND_SIZE);
fcp_cmnd = &req->qtcb->bottom.io.fcp_cmnd.iu;
- zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0);
+ zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
if ((scsi_get_prot_op(scsi_cmnd) != SCSI_PROT_NORMAL) &&
scsi_prot_sg_count(scsi_cmnd)) {
@@ -2297,10 +2309,11 @@ out:
static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req)
{
+ struct scsi_device *sdev = req->data;
struct fcp_resp_with_ext *fcp_rsp;
struct fcp_resp_rsp_info *rsp_info;
- zfcp_fsf_fcp_handler_common(req);
+ zfcp_fsf_fcp_handler_common(req, sdev);
fcp_rsp = &req->qtcb->bottom.io.fcp_rsp.iu;
rsp_info = (struct fcp_resp_rsp_info *) &fcp_rsp[1];
@@ -2311,17 +2324,18 @@ static void zfcp_fsf_fcp_task_mgmt_handler(struct zfcp_fsf_req *req)
}
/**
- * zfcp_fsf_fcp_task_mgmt - send SCSI task management command
- * @scmnd: SCSI command to send the task management command for
- * @tm_flags: unsigned byte for task management flags
- * Returns: on success pointer to struct fsf_req, NULL otherwise
+ * zfcp_fsf_fcp_task_mgmt() - Send SCSI task management command (TMF).
+ * @sdev: Pointer to SCSI device to send the task management command to.
+ * @tm_flags: Unsigned byte for task management flags.
+ *
+ * Return: On success pointer to struct zfcp_fsf_req, %NULL otherwise.
*/
-struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
+struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_device *sdev,
u8 tm_flags)
{
struct zfcp_fsf_req *req = NULL;
struct fcp_cmnd *fcp_cmnd;
- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scmnd->device);
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
struct zfcp_qdio *qdio = zfcp_sdev->port->adapter->qdio;
if (unlikely(!(atomic_read(&zfcp_sdev->status) &
@@ -2341,7 +2355,8 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
goto out;
}
- req->data = scmnd;
+ req->data = sdev;
+
req->handler = zfcp_fsf_fcp_task_mgmt_handler;
req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
req->qtcb->header.port_handle = zfcp_sdev->port->handle;
@@ -2352,7 +2367,7 @@ struct zfcp_fsf_req *zfcp_fsf_fcp_task_mgmt(struct scsi_cmnd *scmnd,
zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
fcp_cmnd = &req->qtcb->bottom.io.fcp_cmnd.iu;
- zfcp_fc_scsi_to_fcp(fcp_cmnd, scmnd, tm_flags);
+ zfcp_fc_fcp_tm(fcp_cmnd, sdev, tm_flags);
zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
if (!zfcp_fsf_req_send(req))
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 4baca67..535628b 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -4,7 +4,7 @@
*
* Interface to the FSF support functions.
*
- * Copyright IBM Corp. 2002, 2017
+ * Copyright IBM Corp. 2002, 2018
*/
#ifndef FSF_H
@@ -356,7 +356,7 @@ struct fsf_qtcb_bottom_config {
u32 adapter_features;
u32 connection_features;
u32 fc_topology;
- u32 fc_link_speed;
+ u32 fc_link_speed; /* one of ZFCP_FSF_PORTSPEED_* */
u32 adapter_type;
u8 res0;
u8 peer_d_id[3];
@@ -382,7 +382,7 @@ struct fsf_qtcb_bottom_port {
u32 class_of_service; /* should be 0x00000006 for class 2 and 3 */
u8 supported_fc4_types[32]; /* should be 0x00000100 for scsi fcp */
u8 active_fc4_types[32];
- u32 supported_speed; /* 0x0001 for 1 GBit/s or 0x0002 for 2 GBit/s */
+ u32 supported_speed; /* any combination of ZFCP_FSF_PORTSPEED_* */
u32 maximum_frame_size; /* fixed value of 2112 */
u64 seconds_since_last_reset;
u64 tx_frames;
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 22f9562..a8efcb3 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -181,6 +181,7 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
if (abrt_req)
break;
+ zfcp_dbf_scsi_abort("abrt_wt", scpnt, NULL);
zfcp_erp_wait(adapter);
ret = fc_block_scsi_eh(scpnt);
if (ret) {
@@ -264,44 +265,52 @@ static void zfcp_scsi_forget_cmnds(struct zfcp_scsi_dev *zsdev, u8 tm_flags)
write_unlock_irqrestore(&adapter->abort_lock, flags);
}
-static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
+/**
+ * zfcp_scsi_task_mgmt_function() - Send a task management function (sync).
+ * @sdev: Pointer to SCSI device to send the task management command to.
+ * @tm_flags: Task management flags,
+ * here we only handle %FCP_TMF_TGT_RESET or %FCP_TMF_LUN_RESET.
+ */
+static int zfcp_scsi_task_mgmt_function(struct scsi_device *sdev, u8 tm_flags)
{
- struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
+ struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
+ struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
struct zfcp_fsf_req *fsf_req = NULL;
int retval = SUCCESS, ret;
int retry = 3;
while (retry--) {
- fsf_req = zfcp_fsf_fcp_task_mgmt(scpnt, tm_flags);
+ fsf_req = zfcp_fsf_fcp_task_mgmt(sdev, tm_flags);
if (fsf_req)
break;
+ zfcp_dbf_scsi_devreset("wait", sdev, tm_flags, NULL);
zfcp_erp_wait(adapter);
- ret = fc_block_scsi_eh(scpnt);
+ ret = fc_block_rport(rport);
if (ret) {
- zfcp_dbf_scsi_devreset("fiof", scpnt, tm_flags, NULL);
+ zfcp_dbf_scsi_devreset("fiof", sdev, tm_flags, NULL);
return ret;
}
if (!(atomic_read(&adapter->status) &
ZFCP_STATUS_COMMON_RUNNING)) {
- zfcp_dbf_scsi_devreset("nres", scpnt, tm_flags, NULL);
+ zfcp_dbf_scsi_devreset("nres", sdev, tm_flags, NULL);
return SUCCESS;
}
}
if (!fsf_req) {
- zfcp_dbf_scsi_devreset("reqf", scpnt, tm_flags, NULL);
+ zfcp_dbf_scsi_devreset("reqf", sdev, tm_flags, NULL);
return FAILED;
}
wait_for_completion(&fsf_req->completion);
if (fsf_req->status & ZFCP_STATUS_FSFREQ_TMFUNCFAILED) {
- zfcp_dbf_scsi_devreset("fail", scpnt, tm_flags, fsf_req);
+ zfcp_dbf_scsi_devreset("fail", sdev, tm_flags, fsf_req);
retval = FAILED;
} else {
- zfcp_dbf_scsi_devreset("okay", scpnt, tm_flags, fsf_req);
+ zfcp_dbf_scsi_devreset("okay", sdev, tm_flags, fsf_req);
zfcp_scsi_forget_cmnds(zfcp_sdev, tm_flags);
}
@@ -311,27 +320,81 @@ static int zfcp_task_mgmt_function(struct scsi_cmnd *scpnt, u8 tm_flags)
static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
{
- return zfcp_task_mgmt_function(scpnt, FCP_TMF_LUN_RESET);
+ struct scsi_device *sdev = scpnt->device;
+
+ return zfcp_scsi_task_mgmt_function(sdev, FCP_TMF_LUN_RESET);
}
static int zfcp_scsi_eh_target_reset_handler(struct scsi_cmnd *scpnt)
{
- return zfcp_task_mgmt_function(scpnt, FCP_TMF_TGT_RESET);
+ struct scsi_target *starget = scsi_target(scpnt->device);
+ struct fc_rport *rport = starget_to_rport(starget);
+ struct Scsi_Host *shost = rport_to_shost(rport);
+ struct scsi_device *sdev = NULL, *tmp_sdev;
+ struct zfcp_adapter *adapter =
+ (struct zfcp_adapter *)shost->hostdata[0];
+ int ret;
+
+ shost_for_each_device(tmp_sdev, shost) {
+ if (tmp_sdev->id == starget->id) {
+ sdev = tmp_sdev;
+ break;
+ }
+ }
+ if (!sdev) {
+ ret = FAILED;
+ zfcp_dbf_scsi_eh("tr_nosd", adapter, starget->id, ret);
+ return ret;
+ }
+
+ ret = zfcp_scsi_task_mgmt_function(sdev, FCP_TMF_TGT_RESET);
+
+ /* release reference from above shost_for_each_device */
+ if (sdev)
+ scsi_device_put(tmp_sdev);
+
+ return ret;
}
static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
{
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scpnt->device);
struct zfcp_adapter *adapter = zfcp_sdev->port->adapter;
- int ret;
+ int ret = SUCCESS, fc_ret;
zfcp_erp_adapter_reopen(adapter, 0, "schrh_1");
zfcp_erp_wait(adapter);
- ret = fc_block_scsi_eh(scpnt);
- if (ret)
+ fc_ret = fc_block_scsi_eh(scpnt);
+ if (fc_ret)
+ ret = fc_ret;
+
+ zfcp_dbf_scsi_eh("schrh_r", adapter, ~0, ret);
+ return ret;
+}
+
+/**
+ * zfcp_scsi_sysfs_host_reset() - Support scsi_host sysfs attribute host_reset.
+ * @shost: Pointer to Scsi_Host to perform action on.
+ * @reset_type: We support %SCSI_ADAPTER_RESET but not %SCSI_FIRMWARE_RESET.
+ *
+ * Return: 0 on %SCSI_ADAPTER_RESET, -%EOPNOTSUPP otherwise.
+ *
+ * This is similar to zfcp_sysfs_adapter_failed_store().
+ */
+static int zfcp_scsi_sysfs_host_reset(struct Scsi_Host *shost, int reset_type)
+{
+ struct zfcp_adapter *adapter =
+ (struct zfcp_adapter *)shost->hostdata[0];
+ int ret = 0;
+
+ if (reset_type != SCSI_ADAPTER_RESET) {
+ ret = -EOPNOTSUPP;
+ zfcp_dbf_scsi_eh("scshr_n", adapter, ~0, ret);
return ret;
+ }
- return SUCCESS;
+ zfcp_erp_adapter_reset_sync(adapter, "scshr_y");
+ return ret;
}
struct scsi_transport_template *zfcp_scsi_transport_template;
@@ -349,6 +412,7 @@ static struct scsi_host_template zfcp_scsi_host_template = {
.slave_configure = zfcp_scsi_slave_configure,
.slave_destroy = zfcp_scsi_slave_destroy,
.change_queue_depth = scsi_change_queue_depth,
+ .host_reset = zfcp_scsi_sysfs_host_reset,
.proc_name = "zfcp",
.can_queue = 4096,
.this_id = -1,
@@ -363,6 +427,7 @@ static struct scsi_host_template zfcp_scsi_host_template = {
.shost_attrs = zfcp_sysfs_shost_attrs,
.sdev_attrs = zfcp_sysfs_sdev_attrs,
.track_queue_depth = 1,
+ .supported_mode = MODE_INITIATOR,
};
/**
@@ -430,7 +495,7 @@ void zfcp_scsi_adapter_unregister(struct zfcp_adapter *adapter)
}
static struct fc_host_statistics*
-zfcp_init_fc_host_stats(struct zfcp_adapter *adapter)
+zfcp_scsi_init_fc_host_stats(struct zfcp_adapter *adapter)
{
struct fc_host_statistics *fc_stats;
@@ -444,9 +509,9 @@ zfcp_init_fc_host_stats(struct zfcp_adapter *adapter)
return adapter->fc_stats;
}
-static void zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
- struct fsf_qtcb_bottom_port *data,
- struct fsf_qtcb_bottom_port *old)
+static void zfcp_scsi_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
+ struct fsf_qtcb_bottom_port *data,
+ struct fsf_qtcb_bottom_port *old)
{
fc_stats->seconds_since_last_reset =
data->seconds_since_last_reset - old->seconds_since_last_reset;
@@ -477,8 +542,8 @@ static void zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb;
}
-static void zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats,
- struct fsf_qtcb_bottom_port *data)
+static void zfcp_scsi_set_fc_host_stats(struct fc_host_statistics *fc_stats,
+ struct fsf_qtcb_bottom_port *data)
{
fc_stats->seconds_since_last_reset = data->seconds_since_last_reset;
fc_stats->tx_frames = data->tx_frames;
@@ -502,7 +567,8 @@ static void zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats,
fc_stats->fcp_output_megabytes = data->output_mb;
}
-static struct fc_host_statistics *zfcp_get_fc_host_stats(struct Scsi_Host *host)
+static struct fc_host_statistics *
+zfcp_scsi_get_fc_host_stats(struct Scsi_Host *host)
{
struct zfcp_adapter *adapter;
struct fc_host_statistics *fc_stats;
@@ -510,7 +576,7 @@ static struct fc_host_statistics *zfcp_get_fc_host_stats(struct Scsi_Host *host)
int ret;
adapter = (struct zfcp_adapter *)host->hostdata[0];
- fc_stats = zfcp_init_fc_host_stats(adapter);
+ fc_stats = zfcp_scsi_init_fc_host_stats(adapter);
if (!fc_stats)
return NULL;
@@ -527,16 +593,16 @@ static struct fc_host_statistics *zfcp_get_fc_host_stats(struct Scsi_Host *host)
if (adapter->stats_reset &&
((jiffies/HZ - adapter->stats_reset) <
data->seconds_since_last_reset))
- zfcp_adjust_fc_host_stats(fc_stats, data,
- adapter->stats_reset_data);
+ zfcp_scsi_adjust_fc_host_stats(fc_stats, data,
+ adapter->stats_reset_data);
else
- zfcp_set_fc_host_stats(fc_stats, data);
+ zfcp_scsi_set_fc_host_stats(fc_stats, data);
kfree(data);
return fc_stats;
}
-static void zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
+static void zfcp_scsi_reset_fc_host_stats(struct Scsi_Host *shost)
{
struct zfcp_adapter *adapter;
struct fsf_qtcb_bottom_port *data;
@@ -558,7 +624,7 @@ static void zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
}
}
-static void zfcp_get_host_port_state(struct Scsi_Host *shost)
+static void zfcp_scsi_get_host_port_state(struct Scsi_Host *shost)
{
struct zfcp_adapter *adapter =
(struct zfcp_adapter *)shost->hostdata[0];
@@ -575,7 +641,8 @@ static void zfcp_get_host_port_state(struct Scsi_Host *shost)
fc_host_port_state(shost) = FC_PORTSTATE_UNKNOWN;
}
-static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
+static void zfcp_scsi_set_rport_dev_loss_tmo(struct fc_rport *rport,
+ u32 timeout)
{
rport->dev_loss_tmo = timeout;
}
@@ -602,6 +669,11 @@ static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
if (port) {
zfcp_erp_port_forced_reopen(port, 0, "sctrpi1");
put_device(&port->dev);
+ } else {
+ zfcp_erp_port_forced_no_port_dbf(
+ "sctrpin", adapter,
+ rport->port_name /* zfcp_scsi_rport_register */,
+ rport->port_id /* zfcp_scsi_rport_register */);
}
}
@@ -687,6 +759,9 @@ void zfcp_scsi_rport_work(struct work_struct *work)
struct zfcp_port *port = container_of(work, struct zfcp_port,
rport_work);
+ set_worker_desc("zrp%c-%16llx",
+ (port->rport_task == RPORT_ADD) ? 'a' : 'd',
+ port->wwpn); /* < WORKER_DESC_LEN=24 */
while (port->rport_task) {
if (port->rport_task == RPORT_ADD) {
port->rport_task = RPORT_NONE;
@@ -761,10 +836,10 @@ struct fc_function_template zfcp_transport_functions = {
.show_host_supported_speeds = 1,
.show_host_maxframe_size = 1,
.show_host_serial_number = 1,
- .get_fc_host_stats = zfcp_get_fc_host_stats,
- .reset_fc_host_stats = zfcp_reset_fc_host_stats,
- .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
- .get_host_port_state = zfcp_get_host_port_state,
+ .get_fc_host_stats = zfcp_scsi_get_fc_host_stats,
+ .reset_fc_host_stats = zfcp_scsi_reset_fc_host_stats,
+ .set_rport_dev_loss_tmo = zfcp_scsi_set_rport_dev_loss_tmo,
+ .get_host_port_state = zfcp_scsi_get_host_port_state,
.terminate_rport_io = zfcp_scsi_terminate_rport_io,
.show_host_port_state = 1,
.show_host_active_fc4s = 1,
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 3ac823f..b277be6 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -200,10 +200,7 @@ static ssize_t zfcp_sysfs_adapter_failed_store(struct device *dev,
goto out;
}
- zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
- zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
- "syafai2");
- zfcp_erp_wait(adapter);
+ zfcp_erp_adapter_reset_sync(adapter, "syafai2");
out:
zfcp_ccw_adapter_put(adapter);
return retval ? retval : (ssize_t) count;
diff --git a/drivers/sbus/char/oradax.c b/drivers/sbus/char/oradax.c
index 1754f55..524f9ea 100644
--- a/drivers/sbus/char/oradax.c
+++ b/drivers/sbus/char/oradax.c
@@ -30,7 +30,7 @@
* the recommended way for applications to use the coprocessor, and
* the driver interface is not intended for general use.
*
- * See Documentation/sparc/oradax/oracle_dax.txt for more details.
+ * See Documentation/sparc/oradax/oracle-dax.txt for more details.
*/
#include <linux/uaccess.h>
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index b42c9c4..99ba4a7 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -882,6 +882,11 @@ static int twa_chrdev_open(struct inode *inode, struct file *file)
unsigned int minor_number;
int retval = TW_IOCTL_ERROR_OS_ENODEV;
+ if (!capable(CAP_SYS_ADMIN)) {
+ retval = -EACCES;
+ goto out;
+ }
+
minor_number = iminor(inode);
if (minor_number >= twa_device_extension_count)
goto out;
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 33261b6..f6179e3 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -1033,6 +1033,9 @@ static int tw_chrdev_open(struct inode *inode, struct file *file)
dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n");
+ if (!capable(CAP_SYS_ADMIN))
+ return -EACCES;
+
minor_number = iminor(inode);
if (minor_number >= tw_device_extension_count)
return -ENODEV;
diff --git a/drivers/scsi/BusLogic.c b/drivers/scsi/BusLogic.c
index 35380a5..0d4ffe0 100644
--- a/drivers/scsi/BusLogic.c
+++ b/drivers/scsi/BusLogic.c
@@ -2366,7 +2366,7 @@ static int __init blogic_init(void)
if (blogic_probe_options.noprobe)
return -ENODEV;
blogic_probeinfo_list =
- kzalloc(BLOGIC_MAX_ADAPTERS * sizeof(struct blogic_probeinfo),
+ kcalloc(BLOGIC_MAX_ADAPTERS, sizeof(struct blogic_probeinfo),
GFP_KERNEL);
if (blogic_probeinfo_list == NULL) {
blogic_err("BusLogic: Unable to allocate Probe Info List\n",
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 11e89e5..35c909b 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1351,6 +1351,20 @@ config SCSI_ZORRO7XX
accelerator card for the Amiga 1200,
- the SCSI controller on the GVP Turbo 040/060 accelerator.
+config SCSI_ZORRO_ESP
+ tristate "Zorro ESP SCSI support"
+ depends on ZORRO && SCSI
+ select SCSI_SPI_ATTRS
+ help
+ Support for various NCR53C9x (ESP) based SCSI controllers on Zorro
+ expansion boards for the Amiga.
+ This includes:
+ - the Phase5 Blizzard 1230 II and IV SCSI controllers,
+ - the Phase5 Blizzard 2060 SCSI controller,
+ - the Phase5 Blizzard Cyberstorm and Cyberstorm II SCSI
+ controllers,
+ - the Fastlane Zorro III SCSI controller.
+
config ATARI_SCSI
tristate "Atari native SCSI support"
depends on ATARI && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 56c9403..80aca24 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -48,6 +48,7 @@ obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o
obj-$(CONFIG_ISCSI_BOOT_SYSFS) += iscsi_boot_sysfs.o
obj-$(CONFIG_SCSI_A4000T) += 53c700.o a4000t.o
obj-$(CONFIG_SCSI_ZORRO7XX) += 53c700.o zorro7xx.o
+obj-$(CONFIG_SCSI_ZORRO_ESP) += esp_scsi.o zorro_esp.o
obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o
obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o
obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o
@@ -189,7 +190,7 @@ $(obj)/53c700.o $(MODVERDIR)/$(obj)/53c700.ver: $(obj)/53c700_d.h
$(obj)/scsi_sysfs.o: $(obj)/scsi_devinfo_tbl.c
quiet_cmd_bflags = GEN $@
- cmd_bflags = sed -n 's/.*BLIST_\([A-Z0-9_]*\) *.*/BLIST_FLAG_NAME(\1),/p' $< > $@
+ cmd_bflags = sed -n 's/.*define *BLIST_\([A-Z0-9_]*\) *.*/BLIST_FLAG_NAME(\1),/p' $< > $@
$(obj)/scsi_devinfo_tbl.c: include/scsi/scsi_devinfo.h
$(call if_changed,bflags)
diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c
index 8086bd0..b2942ec 100644
--- a/drivers/scsi/a100u2w.c
+++ b/drivers/scsi/a100u2w.c
@@ -1222,19 +1222,8 @@ static struct pci_driver inia100_pci_driver = {
.remove = inia100_remove_one,
};
-static int __init inia100_init(void)
-{
- return pci_register_driver(&inia100_pci_driver);
-}
-
-static void __exit inia100_exit(void)
-{
- pci_unregister_driver(&inia100_pci_driver);
-}
+module_pci_driver(inia100_pci_driver);
MODULE_DESCRIPTION("Initio A100U2W SCSI driver");
MODULE_AUTHOR("Initio Corporation");
MODULE_LICENSE("Dual BSD/GPL");
-
-module_init(inia100_init);
-module_exit(inia100_exit);
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index e7961cb..a9831bd 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -4132,7 +4132,7 @@ static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int
if (aac_convert_sgl == 0)
return 0;
- sge = kmalloc(nseg_new * sizeof(struct sge_ieee1212), GFP_ATOMIC);
+ sge = kmalloc_array(nseg_new, sizeof(struct sge_ieee1212), GFP_ATOMIC);
if (sge == NULL)
return -ENOMEM;
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index a2b3430..25f6600 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -845,7 +845,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -EINVAL;
goto cleanup;
}
- p = kmalloc(sg_count[i], GFP_KERNEL|GFP_DMA32);
+ p = kmalloc(sg_count[i], GFP_KERNEL);
if (!p) {
dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
sg_count[i], i, usg->count));
@@ -886,7 +886,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -EINVAL;
goto cleanup;
}
- p = kmalloc(sg_count[i], GFP_KERNEL|GFP_DMA32);
+ p = kmalloc(sg_count[i], GFP_KERNEL);
if (!p) {
dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
sg_count[i], i, upsg->count));
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index f24fb94..0444357 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -1681,7 +1681,9 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (aac_reset_devices || reset_devices)
aac->init_reset = true;
- aac->fibs = kzalloc(sizeof(struct fib) * (shost->can_queue + AAC_NUM_MGT_FIB), GFP_KERNEL);
+ aac->fibs = kcalloc(shost->can_queue + AAC_NUM_MGT_FIB,
+ sizeof(struct fib),
+ GFP_KERNEL);
if (!aac->fibs)
goto out_free_host;
spin_lock_init(&aac->fib_lock);
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c
index 1242179..41add33 100644
--- a/drivers/scsi/aha1542.c
+++ b/drivers/scsi/aha1542.c
@@ -400,7 +400,8 @@ static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd)
#endif
if (bufflen) { /* allocate memory before taking host_lock */
sg_count = scsi_sg_count(cmd);
- cptr = kmalloc(sizeof(*cptr) * sg_count, GFP_KERNEL | GFP_DMA);
+ cptr = kmalloc_array(sg_count, sizeof(*cptr),
+ GFP_KERNEL | GFP_DMA);
if (!cptr)
return SCSI_MLQUEUE_HOST_BUSY;
} else {
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index 034f4ee..2d82ec8 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -6112,10 +6112,6 @@ ahd_alloc(void *platform_arg, char *name)
ahd->int_coalescing_stop_threshold =
AHD_INT_COALESCING_STOP_THRESHOLD_DEFAULT;
- if (ahd_platform_alloc(ahd, platform_arg) != 0) {
- ahd_free(ahd);
- ahd = NULL;
- }
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_MEMORY) != 0) {
printk("%s: scb size = 0x%x, hscb size = 0x%x\n",
@@ -6123,6 +6119,10 @@ ahd_alloc(void *platform_arg, char *name)
(u_int)sizeof(struct hardware_scb));
}
#endif
+ if (ahd_platform_alloc(ahd, platform_arg) != 0) {
+ ahd_free(ahd);
+ ahd = NULL;
+ }
return (ahd);
}
@@ -7063,7 +7063,8 @@ ahd_init(struct ahd_softc *ahd)
AHD_ASSERT_MODES(ahd, AHD_MODE_SCSI_MSK, AHD_MODE_SCSI_MSK);
ahd->stack_size = ahd_probe_stack_size(ahd);
- ahd->saved_stack = kmalloc(ahd->stack_size * sizeof(uint16_t), GFP_ATOMIC);
+ ahd->saved_stack = kmalloc_array(ahd->stack_size, sizeof(uint16_t),
+ GFP_ATOMIC);
if (ahd->saved_stack == NULL)
return (ENOMEM);
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c
index e97ecea..915a34f 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_core.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_core.c
@@ -4779,8 +4779,8 @@ ahc_init_scbdata(struct ahc_softc *ahc)
SLIST_INIT(&scb_data->sg_maps);
/* Allocate SCB resources */
- scb_data->scbarray = kzalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC,
- GFP_ATOMIC);
+ scb_data->scbarray = kcalloc(AHC_SCB_MAX_ALLOC, sizeof(struct scb),
+ GFP_ATOMIC);
if (scb_data->scbarray == NULL)
return (ENOMEM);
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.c b/drivers/scsi/aic94xx/aic94xx_hwi.c
index 2dbc833..3b8ad55 100644
--- a/drivers/scsi/aic94xx/aic94xx_hwi.c
+++ b/drivers/scsi/aic94xx/aic94xx_hwi.c
@@ -220,8 +220,9 @@ static int asd_init_scbs(struct asd_ha_struct *asd_ha)
/* allocate the index array and bitmap */
asd_ha->seq.tc_index_bitmap_bits = asd_ha->hw_prof.max_scbs;
- asd_ha->seq.tc_index_array = kzalloc(asd_ha->seq.tc_index_bitmap_bits*
- sizeof(void *), GFP_KERNEL);
+ asd_ha->seq.tc_index_array = kcalloc(asd_ha->seq.tc_index_bitmap_bits,
+ sizeof(void *),
+ GFP_KERNEL);
if (!asd_ha->seq.tc_index_array)
return -ENOMEM;
@@ -291,7 +292,8 @@ static int asd_alloc_edbs(struct asd_ha_struct *asd_ha, gfp_t gfp_flags)
struct asd_seq_data *seq = &asd_ha->seq;
int i;
- seq->edb_arr = kmalloc(seq->num_edbs*sizeof(*seq->edb_arr), gfp_flags);
+ seq->edb_arr = kmalloc_array(seq->num_edbs, sizeof(*seq->edb_arr),
+ gfp_flags);
if (!seq->edb_arr)
return -ENOMEM;
@@ -323,8 +325,8 @@ static int asd_alloc_escbs(struct asd_ha_struct *asd_ha,
struct asd_ascb *escb;
int i, escbs;
- seq->escb_arr = kmalloc(seq->num_escbs*sizeof(*seq->escb_arr),
- gfp_flags);
+ seq->escb_arr = kmalloc_array(seq->num_escbs, sizeof(*seq->escb_arr),
+ gfp_flags);
if (!seq->escb_arr)
return -ENOMEM;
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 6c83886..80e5b28 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -350,7 +350,7 @@ static ssize_t asd_store_update_bios(struct device *dev,
int flash_command = FLASH_CMD_NONE;
int err = 0;
- cmd_ptr = kzalloc(count*2, GFP_KERNEL);
+ cmd_ptr = kcalloc(count, 2, GFP_KERNEL);
if (!cmd_ptr) {
err = FAIL_OUT_MEMORY;
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
index beea30e..d81ca66 100644
--- a/drivers/scsi/am53c974.c
+++ b/drivers/scsi/am53c974.c
@@ -556,15 +556,7 @@ static struct pci_driver am53c974_driver = {
.remove = pci_esp_remove_one,
};
-static int __init am53c974_module_init(void)
-{
- return pci_register_driver(&am53c974_driver);
-}
-
-static void __exit am53c974_module_exit(void)
-{
- pci_unregister_driver(&am53c974_driver);
-}
+module_pci_driver(am53c974_driver);
MODULE_DESCRIPTION("AM53C974 SCSI driver");
MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
@@ -577,6 +569,3 @@ MODULE_PARM_DESC(am53c974_debug, "Enable debugging");
module_param(am53c974_fenab, bool, 0444);
MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
-
-module_init(am53c974_module_init);
-module_exit(am53c974_module_exit);
diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c
index 3441ce3..996dfe9 100644
--- a/drivers/scsi/arm/queue.c
+++ b/drivers/scsi/arm/queue.c
@@ -70,7 +70,7 @@ int queue_initialise (Queue_t *queue)
* need to keep free lists or allocate this
* memory.
*/
- queue->alloc = q = kmalloc(sizeof(QE_t) * nqueues, GFP_KERNEL);
+ queue->alloc = q = kmalloc_array(nqueues, sizeof(QE_t), GFP_KERNEL);
if (q) {
for (; nqueues; q++, nqueues--) {
SET_MAGIC(q, QUEUE_MAGIC_FREE);
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c
index b3cfdd5..818d185 100644
--- a/drivers/scsi/be2iscsi/be_main.c
+++ b/drivers/scsi/be2iscsi/be_main.c
@@ -2467,8 +2467,8 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
/* Allocate memory for wrb_context */
phwi_ctrlr = phba->phwi_ctrlr;
- phwi_ctrlr->wrb_context = kzalloc(sizeof(struct hwi_wrb_context) *
- phba->params.cxns_per_ctrl,
+ phwi_ctrlr->wrb_context = kcalloc(phba->params.cxns_per_ctrl,
+ sizeof(struct hwi_wrb_context),
GFP_KERNEL);
if (!phwi_ctrlr->wrb_context) {
kfree(phba->phwi_ctrlr);
@@ -2483,8 +2483,9 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
return -ENOMEM;
}
- mem_arr_orig = kmalloc(sizeof(*mem_arr_orig) * BEISCSI_MAX_FRAGS_INIT,
- GFP_KERNEL);
+ mem_arr_orig = kmalloc_array(BEISCSI_MAX_FRAGS_INIT,
+ sizeof(*mem_arr_orig),
+ GFP_KERNEL);
if (!mem_arr_orig) {
kfree(phba->init_mem);
kfree(phwi_ctrlr->wrb_context);
@@ -2533,8 +2534,8 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba)
} while (alloc_size);
mem_descr->num_elements = j;
mem_descr->size_in_bytes = phba->mem_req[i];
- mem_descr->mem_array = kmalloc(sizeof(*mem_arr) * j,
- GFP_KERNEL);
+ mem_descr->mem_array = kmalloc_array(j, sizeof(*mem_arr),
+ GFP_KERNEL);
if (!mem_descr->mem_array)
goto free_mem;
@@ -2620,8 +2621,8 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
/* Allocate memory for WRBQ */
phwi_ctxt = phwi_ctrlr->phwi_ctxt;
- phwi_ctxt->be_wrbq = kzalloc(sizeof(struct be_queue_info) *
- phba->params.cxns_per_ctrl,
+ phwi_ctxt->be_wrbq = kcalloc(phba->params.cxns_per_ctrl,
+ sizeof(struct be_queue_info),
GFP_KERNEL);
if (!phwi_ctxt->be_wrbq) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
@@ -2632,16 +2633,18 @@ static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)
for (index = 0; index < phba->params.cxns_per_ctrl; index++) {
pwrb_context = &phwi_ctrlr->wrb_context[index];
pwrb_context->pwrb_handle_base =
- kzalloc(sizeof(struct wrb_handle *) *
- phba->params.wrbs_per_cxn, GFP_KERNEL);
+ kcalloc(phba->params.wrbs_per_cxn,
+ sizeof(struct wrb_handle *),
+ GFP_KERNEL);
if (!pwrb_context->pwrb_handle_base) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Mem Alloc Failed. Failing to load\n");
goto init_wrb_hndl_failed;
}
pwrb_context->pwrb_handle_basestd =
- kzalloc(sizeof(struct wrb_handle *) *
- phba->params.wrbs_per_cxn, GFP_KERNEL);
+ kcalloc(phba->params.wrbs_per_cxn,
+ sizeof(struct wrb_handle *),
+ GFP_KERNEL);
if (!pwrb_context->pwrb_handle_basestd) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Mem Alloc Failed. Failing to load\n");
@@ -3353,8 +3356,9 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,
idx = 0;
mem_descr = phba->init_mem;
mem_descr += HWI_MEM_WRB;
- pwrb_arr = kmalloc(sizeof(*pwrb_arr) * phba->params.cxns_per_ctrl,
- GFP_KERNEL);
+ pwrb_arr = kmalloc_array(phba->params.cxns_per_ctrl,
+ sizeof(*pwrb_arr),
+ GFP_KERNEL);
if (!pwrb_arr) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Memory alloc failed in create wrb ring.\n");
@@ -3894,18 +3898,18 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)
mem_descr_sglh = phba->init_mem;
mem_descr_sglh += HWI_MEM_SGLH;
if (1 == mem_descr_sglh->num_elements) {
- phba->io_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) *
- phba->params.ios_per_ctrl,
+ phba->io_sgl_hndl_base = kcalloc(phba->params.ios_per_ctrl,
+ sizeof(struct sgl_handle *),
GFP_KERNEL);
if (!phba->io_sgl_hndl_base) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Mem Alloc Failed. Failing to load\n");
return -ENOMEM;
}
- phba->eh_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) *
- (phba->params.icds_per_ctrl -
- phba->params.ios_per_ctrl),
- GFP_KERNEL);
+ phba->eh_sgl_hndl_base =
+ kcalloc(phba->params.icds_per_ctrl -
+ phba->params.ios_per_ctrl,
+ sizeof(struct sgl_handle *), GFP_KERNEL);
if (!phba->eh_sgl_hndl_base) {
kfree(phba->io_sgl_hndl_base);
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
@@ -4032,8 +4036,9 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
phba->cid_array_info[ulp_num] = ptr_cid_info;
}
}
- phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) *
- phba->params.cxns_per_ctrl, GFP_KERNEL);
+ phba->ep_array = kcalloc(phba->params.cxns_per_ctrl,
+ sizeof(struct iscsi_endpoint *),
+ GFP_KERNEL);
if (!phba->ep_array) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Failed to allocate memory in "
@@ -4043,8 +4048,9 @@ static int hba_setup_cid_tbls(struct beiscsi_hba *phba)
goto free_memory;
}
- phba->conn_table = kzalloc(sizeof(struct beiscsi_conn *) *
- phba->params.cxns_per_ctrl, GFP_KERNEL);
+ phba->conn_table = kcalloc(phba->params.cxns_per_ctrl,
+ sizeof(struct beiscsi_conn *),
+ GFP_KERNEL);
if (!phba->conn_table) {
beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
"BM_%d : Failed to allocate memory in"
diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c
index d4d276c..26b0fa4 100644
--- a/drivers/scsi/bfa/bfad_attr.c
+++ b/drivers/scsi/bfa/bfad_attr.c
@@ -927,7 +927,7 @@ bfad_im_num_of_discovered_ports_show(struct device *dev,
struct bfa_rport_qualifier_s *rports = NULL;
unsigned long flags;
- rports = kzalloc(sizeof(struct bfa_rport_qualifier_s) * nrports,
+ rports = kcalloc(nrports, sizeof(struct bfa_rport_qualifier_s),
GFP_ATOMIC);
if (rports == NULL)
return snprintf(buf, PAGE_SIZE, "Failed\n");
diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c
index 7c884f8..5d163ca 100644
--- a/drivers/scsi/bfa/bfad_bsg.c
+++ b/drivers/scsi/bfa/bfad_bsg.c
@@ -3252,8 +3252,9 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
struct bfa_sge_s *sg_table;
int sge_num = 1;
- buf_base = kzalloc((sizeof(struct bfad_buf_info) +
- sizeof(struct bfa_sge_s)) * sge_num, GFP_KERNEL);
+ buf_base = kcalloc(sizeof(struct bfad_buf_info) +
+ sizeof(struct bfa_sge_s),
+ sge_num, GFP_KERNEL);
if (!buf_base)
return NULL;
diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
index 65de1d0..f000458 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
@@ -1397,7 +1397,7 @@ static struct bnx2fc_hba *bnx2fc_hba_create(struct cnic_dev *cnic)
hba->next_conn_id = 0;
hba->tgt_ofld_list =
- kzalloc(sizeof(struct bnx2fc_rport *) * BNX2FC_NUM_MAX_SESS,
+ kcalloc(BNX2FC_NUM_MAX_SESS, sizeof(struct bnx2fc_rport *),
GFP_KERNEL);
if (!hba->tgt_ofld_list) {
printk(KERN_ERR PFX "Unable to allocate tgt offload list\n");
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index 5a645b8..350257c 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -240,15 +240,15 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
return NULL;
}
- cmgr->free_list = kzalloc(sizeof(*cmgr->free_list) *
- arr_sz, GFP_KERNEL);
+ cmgr->free_list = kcalloc(arr_sz, sizeof(*cmgr->free_list),
+ GFP_KERNEL);
if (!cmgr->free_list) {
printk(KERN_ERR PFX "failed to alloc free_list\n");
goto mem_err;
}
- cmgr->free_list_lock = kzalloc(sizeof(*cmgr->free_list_lock) *
- arr_sz, GFP_KERNEL);
+ cmgr->free_list_lock = kcalloc(arr_sz, sizeof(*cmgr->free_list_lock),
+ GFP_KERNEL);
if (!cmgr->free_list_lock) {
printk(KERN_ERR PFX "failed to alloc free_list_lock\n");
kfree(cmgr->free_list);
diff --git a/drivers/scsi/csiostor/csio_wr.c b/drivers/scsi/csiostor/csio_wr.c
index c0a1778..faa357b 100644
--- a/drivers/scsi/csiostor/csio_wr.c
+++ b/drivers/scsi/csiostor/csio_wr.c
@@ -276,7 +276,7 @@ csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize,
q->un.iq.flq_idx = flq_idx;
flq = wrm->q_arr[q->un.iq.flq_idx];
- flq->un.fl.bufs = kzalloc(flq->credits *
+ flq->un.fl.bufs = kcalloc(flq->credits,
sizeof(struct csio_dma_buf),
GFP_KERNEL);
if (!flq->un.fl.bufs) {
@@ -1579,7 +1579,7 @@ csio_wrm_init(struct csio_wrm *wrm, struct csio_hw *hw)
return -EINVAL;
}
- wrm->q_arr = kzalloc(sizeof(struct csio_q *) * wrm->num_q, GFP_KERNEL);
+ wrm->q_arr = kcalloc(wrm->num_q, sizeof(struct csio_q *), GFP_KERNEL);
if (!wrm->q_arr)
goto err;
diff --git a/drivers/scsi/cxlflash/Kconfig b/drivers/scsi/cxlflash/Kconfig
index a011c5d..f1b17e3 100644
--- a/drivers/scsi/cxlflash/Kconfig
+++ b/drivers/scsi/cxlflash/Kconfig
@@ -4,7 +4,7 @@
config CXLFLASH
tristate "Support for IBM CAPI Flash"
- depends on PCI && SCSI && CXL && EEH
+ depends on PCI && SCSI && (CXL || OCXL) && EEH
select IRQ_POLL
default m
help
diff --git a/drivers/scsi/cxlflash/Makefile b/drivers/scsi/cxlflash/Makefile
index 7ec3f6b..283377d 100644
--- a/drivers/scsi/cxlflash/Makefile
+++ b/drivers/scsi/cxlflash/Makefile
@@ -1,2 +1,4 @@
obj-$(CONFIG_CXLFLASH) += cxlflash.o
-cxlflash-y += main.o superpipe.o lunmgt.o vlun.o cxl_hw.o
+cxlflash-y += main.o superpipe.o lunmgt.o vlun.o
+cxlflash-$(CONFIG_CXL) += cxl_hw.o
+cxlflash-$(CONFIG_OCXL) += ocxl_hw.o
diff --git a/drivers/scsi/cxlflash/backend.h b/drivers/scsi/cxlflash/backend.h
index 339e42b..55638d1 100644
--- a/drivers/scsi/cxlflash/backend.h
+++ b/drivers/scsi/cxlflash/backend.h
@@ -12,30 +12,41 @@
* 2 of the License, or (at your option) any later version.
*/
+#ifndef _CXLFLASH_BACKEND_H
+#define _CXLFLASH_BACKEND_H
+
extern const struct cxlflash_backend_ops cxlflash_cxl_ops;
+extern const struct cxlflash_backend_ops cxlflash_ocxl_ops;
struct cxlflash_backend_ops {
struct module *module;
- void __iomem * (*psa_map)(void *);
- void (*psa_unmap)(void __iomem *);
- int (*process_element)(void *);
- int (*map_afu_irq)(void *, int, irq_handler_t, void *, char *);
- void (*unmap_afu_irq)(void *, int, void *);
- int (*start_context)(void *);
- int (*stop_context)(void *);
- int (*afu_reset)(void *);
- void (*set_master)(void *);
- void * (*get_context)(struct pci_dev *, void *);
- void * (*dev_context_init)(struct pci_dev *, void *);
- int (*release_context)(void *);
- void (*perst_reloads_same_image)(void *, bool);
- ssize_t (*read_adapter_vpd)(struct pci_dev *, void *, size_t);
- int (*allocate_afu_irqs)(void *, int);
- void (*free_afu_irqs)(void *);
- void * (*create_afu)(struct pci_dev *);
- struct file * (*get_fd)(void *, struct file_operations *, int *);
- void * (*fops_get_context)(struct file *);
- int (*start_work)(void *, u64);
- int (*fd_mmap)(struct file *, struct vm_area_struct *);
- int (*fd_release)(struct inode *, struct file *);
+ void __iomem * (*psa_map)(void *ctx_cookie);
+ void (*psa_unmap)(void __iomem *addr);
+ int (*process_element)(void *ctx_cookie);
+ int (*map_afu_irq)(void *ctx_cookie, int num, irq_handler_t handler,
+ void *cookie, char *name);
+ void (*unmap_afu_irq)(void *ctx_cookie, int num, void *cookie);
+ u64 (*get_irq_objhndl)(void *ctx_cookie, int irq);
+ int (*start_context)(void *ctx_cookie);
+ int (*stop_context)(void *ctx_cookie);
+ int (*afu_reset)(void *ctx_cookie);
+ void (*set_master)(void *ctx_cookie);
+ void * (*get_context)(struct pci_dev *dev, void *afu_cookie);
+ void * (*dev_context_init)(struct pci_dev *dev, void *afu_cookie);
+ int (*release_context)(void *ctx_cookie);
+ void (*perst_reloads_same_image)(void *afu_cookie, bool image);
+ ssize_t (*read_adapter_vpd)(struct pci_dev *dev, void *buf,
+ size_t count);
+ int (*allocate_afu_irqs)(void *ctx_cookie, int num);
+ void (*free_afu_irqs)(void *ctx_cookie);
+ void * (*create_afu)(struct pci_dev *dev);
+ void (*destroy_afu)(void *afu_cookie);
+ struct file * (*get_fd)(void *ctx_cookie, struct file_operations *fops,
+ int *fd);
+ void * (*fops_get_context)(struct file *file);
+ int (*start_work)(void *ctx_cookie, u64 irqs);
+ int (*fd_mmap)(struct file *file, struct vm_area_struct *vm);
+ int (*fd_release)(struct inode *inode, struct file *file);
};
+
+#endif /* _CXLFLASH_BACKEND_H */
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 102fd26..8908a20 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -211,6 +211,7 @@ struct hwq {
struct sisl_ctrl_map __iomem *ctrl_map; /* MC control map */
ctx_hndl_t ctx_hndl; /* master's context handle */
u32 index; /* Index of this hwq */
+ int num_irqs; /* Number of interrupts requested for context */
struct list_head pending_cmds; /* Commands pending completion */
atomic_t hsq_credits;
@@ -223,6 +224,7 @@ struct hwq {
u64 *hrrq_end;
u64 *hrrq_curr;
bool toggle;
+ bool hrrq_online;
s64 room;
@@ -231,13 +233,14 @@ struct hwq {
struct afu {
struct hwq hwqs[CXLFLASH_MAX_HWQS];
- int (*send_cmd)(struct afu *, struct afu_cmd *);
- int (*context_reset)(struct hwq *);
+ int (*send_cmd)(struct afu *afu, struct afu_cmd *cmd);
+ int (*context_reset)(struct hwq *hwq);
/* AFU HW */
struct cxlflash_afu_map __iomem *afu_map; /* entire MMIO map */
atomic_t cmds_active; /* Number of currently active AFU commands */
+ struct mutex sync_active; /* Mutex to serialize AFU commands */
u64 hb;
u32 internal_lun; /* User-desired LUN mode for this AFU */
@@ -272,6 +275,11 @@ static inline bool afu_has_cap(struct afu *afu, u64 cap)
return afu_cap & cap;
}
+static inline bool afu_is_ocxl_lisn(struct afu *afu)
+{
+ return afu_has_cap(afu, SISL_INTVER_CAP_OCXL_LISN);
+}
+
static inline bool afu_is_afu_debug(struct afu *afu)
{
return afu_has_cap(afu, SISL_INTVER_CAP_AFU_DEBUG);
diff --git a/drivers/scsi/cxlflash/cxl_hw.c b/drivers/scsi/cxlflash/cxl_hw.c
index db1cada..b42da88 100644
--- a/drivers/scsi/cxlflash/cxl_hw.c
+++ b/drivers/scsi/cxlflash/cxl_hw.c
@@ -49,6 +49,12 @@ static void cxlflash_unmap_afu_irq(void *ctx_cookie, int num, void *cookie)
cxl_unmap_afu_irq(ctx_cookie, num, cookie);
}
+static u64 cxlflash_get_irq_objhndl(void *ctx_cookie, int irq)
+{
+ /* Dummy fop for cxl */
+ return 0;
+}
+
static int cxlflash_start_context(void *ctx_cookie)
{
return cxl_start_context(ctx_cookie, 0, NULL);
@@ -110,6 +116,11 @@ static void *cxlflash_create_afu(struct pci_dev *dev)
return cxl_pci_to_afu(dev);
}
+static void cxlflash_destroy_afu(void *afu)
+{
+ /* Dummy fop for cxl */
+}
+
static struct file *cxlflash_get_fd(void *ctx_cookie,
struct file_operations *fops, int *fd)
{
@@ -148,6 +159,7 @@ const struct cxlflash_backend_ops cxlflash_cxl_ops = {
.process_element = cxlflash_process_element,
.map_afu_irq = cxlflash_map_afu_irq,
.unmap_afu_irq = cxlflash_unmap_afu_irq,
+ .get_irq_objhndl = cxlflash_get_irq_objhndl,
.start_context = cxlflash_start_context,
.stop_context = cxlflash_stop_context,
.afu_reset = cxlflash_afu_reset,
@@ -160,6 +172,7 @@ const struct cxlflash_backend_ops cxlflash_cxl_ops = {
.allocate_afu_irqs = cxlflash_allocate_afu_irqs,
.free_afu_irqs = cxlflash_free_afu_irqs,
.create_afu = cxlflash_create_afu,
+ .destroy_afu = cxlflash_destroy_afu,
.get_fd = cxlflash_get_fd,
.fops_get_context = cxlflash_fops_get_context,
.start_work = cxlflash_start_work,
diff --git a/drivers/scsi/cxlflash/lunmgt.c b/drivers/scsi/cxlflash/lunmgt.c
index 4d232e2..edea125 100644
--- a/drivers/scsi/cxlflash/lunmgt.c
+++ b/drivers/scsi/cxlflash/lunmgt.c
@@ -12,9 +12,11 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <misc/cxl.h>
#include <asm/unaligned.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+
#include <scsi/scsi_host.h>
#include <uapi/scsi/cxlflash_ioctl.h>
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index d8fe7ab8..6637116 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -19,8 +19,6 @@
#include <asm/unaligned.h>
-#include <misc/cxl.h>
-
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
#include <uapi/scsi/cxlflash_ioctl.h>
@@ -339,8 +337,8 @@ static int send_cmd_ioarrin(struct afu *afu, struct afu_cmd *cmd)
writeq_be((u64)&cmd->rcb, &hwq->host_map->ioarrin);
out:
spin_unlock_irqrestore(&hwq->hsq_slock, lock_flags);
- dev_dbg(dev, "%s: cmd=%p len=%u ea=%016llx rc=%d\n", __func__,
- cmd, cmd->rcb.data_len, cmd->rcb.data_ea, rc);
+ dev_dbg_ratelimited(dev, "%s: cmd=%p len=%u ea=%016llx rc=%d\n",
+ __func__, cmd, cmd->rcb.data_len, cmd->rcb.data_ea, rc);
return rc;
}
@@ -473,6 +471,7 @@ static int send_tmf(struct cxlflash_cfg *cfg, struct scsi_device *sdev,
struct afu_cmd *cmd = NULL;
struct device *dev = &cfg->dev->dev;
struct hwq *hwq = get_hwq(afu, PRIMARY_HWQ);
+ bool needs_deletion = false;
char *buf = NULL;
ulong lock_flags;
int rc = 0;
@@ -527,6 +526,7 @@ static int send_tmf(struct cxlflash_cfg *cfg, struct scsi_device *sdev,
if (!to) {
dev_err(dev, "%s: TMF timed out\n", __func__);
rc = -ETIMEDOUT;
+ needs_deletion = true;
} else if (cmd->cmd_aborted) {
dev_err(dev, "%s: TMF aborted\n", __func__);
rc = -EAGAIN;
@@ -537,6 +537,12 @@ static int send_tmf(struct cxlflash_cfg *cfg, struct scsi_device *sdev,
}
cfg->tmf_active = false;
spin_unlock_irqrestore(&cfg->tmf_slock, lock_flags);
+
+ if (needs_deletion) {
+ spin_lock_irqsave(&hwq->hsq_slock, lock_flags);
+ list_del(&cmd->list);
+ spin_unlock_irqrestore(&hwq->hsq_slock, lock_flags);
+ }
out:
kfree(buf);
return rc;
@@ -608,6 +614,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
rc = 0;
goto out;
default:
+ atomic_inc(&afu->cmds_active);
break;
}
@@ -633,6 +640,7 @@ static int cxlflash_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scp)
memcpy(cmd->rcb.cdb, scp->cmnd, sizeof(cmd->rcb.cdb));
rc = afu->send_cmd(afu, cmd);
+ atomic_dec(&afu->cmds_active);
out:
return rc;
}
@@ -793,6 +801,10 @@ static void term_mc(struct cxlflash_cfg *cfg, u32 index)
WARN_ON(cfg->ops->release_context(hwq->ctx_cookie));
hwq->ctx_cookie = NULL;
+ spin_lock_irqsave(&hwq->hrrq_slock, lock_flags);
+ hwq->hrrq_online = false;
+ spin_unlock_irqrestore(&hwq->hrrq_slock, lock_flags);
+
spin_lock_irqsave(&hwq->hsq_slock, lock_flags);
flush_pending_cmds(hwq);
spin_unlock_irqrestore(&hwq->hsq_slock, lock_flags);
@@ -946,9 +958,9 @@ static void cxlflash_remove(struct pci_dev *pdev)
return;
}
- /* If a Task Management Function is active, wait for it to complete
- * before continuing with remove.
- */
+ /* Yield to running recovery threads before continuing with remove */
+ wait_event(cfg->reset_waitq, cfg->state != STATE_RESET &&
+ cfg->state != STATE_PROBING);
spin_lock_irqsave(&cfg->tmf_slock, lock_flags);
if (cfg->tmf_active)
wait_event_interruptible_lock_irq(cfg->tmf_waitq,
@@ -971,6 +983,7 @@ static void cxlflash_remove(struct pci_dev *pdev)
case INIT_STATE_AFU:
term_afu(cfg);
case INIT_STATE_PCI:
+ cfg->ops->destroy_afu(cfg->afu_cookie);
pci_disable_device(pdev);
case INIT_STATE_NONE:
free_mem(cfg);
@@ -1303,7 +1316,10 @@ static void afu_err_intr_init(struct afu *afu)
for (i = 0; i < afu->num_hwqs; i++) {
hwq = get_hwq(afu, i);
- writeq_be(SISL_MSI_SYNC_ERROR, &hwq->host_map->ctx_ctrl);
+ reg = readq_be(&hwq->host_map->ctx_ctrl);
+ WARN_ON((reg & SISL_CTX_CTRL_LISN_MASK) != 0);
+ reg |= SISL_MSI_SYNC_ERROR;
+ writeq_be(reg, &hwq->host_map->ctx_ctrl);
writeq_be(SISL_ISTATUS_MASK, &hwq->host_map->intr_mask);
}
}
@@ -1463,6 +1479,12 @@ static irqreturn_t cxlflash_rrq_irq(int irq, void *data)
spin_lock_irqsave(&hwq->hrrq_slock, hrrq_flags);
+ /* Silently drop spurious interrupts when queue is not online */
+ if (!hwq->hrrq_online) {
+ spin_unlock_irqrestore(&hwq->hrrq_slock, hrrq_flags);
+ return IRQ_HANDLED;
+ }
+
if (afu_is_irqpoll_enabled(afu)) {
irq_poll_sched(&hwq->irqpoll);
spin_unlock_irqrestore(&hwq->hrrq_slock, hrrq_flags);
@@ -1752,6 +1774,8 @@ static int init_global(struct cxlflash_cfg *cfg)
u64 wwpn[MAX_FC_PORTS]; /* wwpn of AFU ports */
int i = 0, num_ports = 0;
int rc = 0;
+ int j;
+ void *ctx;
u64 reg;
rc = read_vpd(cfg, &wwpn[0]);
@@ -1767,6 +1791,7 @@ static int init_global(struct cxlflash_cfg *cfg)
writeq_be((u64) hwq->hrrq_start, &hmap->rrq_start);
writeq_be((u64) hwq->hrrq_end, &hmap->rrq_end);
+ hwq->hrrq_online = true;
if (afu_is_sq_cmd_mode(afu)) {
writeq_be((u64)hwq->hsq_start, &hmap->sq_start);
@@ -1812,6 +1837,25 @@ static int init_global(struct cxlflash_cfg *cfg)
msleep(100);
}
+ if (afu_is_ocxl_lisn(afu)) {
+ /* Set up the LISN effective address for each master */
+ for (i = 0; i < afu->num_hwqs; i++) {
+ hwq = get_hwq(afu, i);
+ ctx = hwq->ctx_cookie;
+
+ for (j = 0; j < hwq->num_irqs; j++) {
+ reg = cfg->ops->get_irq_objhndl(ctx, j);
+ writeq_be(reg, &hwq->ctrl_map->lisn_ea[j]);
+ }
+
+ reg = hwq->ctx_hndl;
+ writeq_be(SISL_LISN_PASID(reg, reg),
+ &hwq->ctrl_map->lisn_pasid[0]);
+ writeq_be(SISL_LISN_PASID(0UL, reg),
+ &hwq->ctrl_map->lisn_pasid[1]);
+ }
+ }
+
/* Set up master's own CTX_CAP to allow real mode, host translation */
/* tables, afu cmds and read/write GSCSI cmds. */
/* First, unlock ctx_cap write by reading mbox */
@@ -1911,7 +1955,7 @@ static enum undo_level init_intr(struct cxlflash_cfg *cfg,
int rc = 0;
enum undo_level level = UNDO_NOOP;
bool is_primary_hwq = (hwq->index == PRIMARY_HWQ);
- int num_irqs = is_primary_hwq ? 3 : 2;
+ int num_irqs = hwq->num_irqs;
rc = cfg->ops->allocate_afu_irqs(ctx, num_irqs);
if (unlikely(rc)) {
@@ -1965,16 +2009,20 @@ static int init_mc(struct cxlflash_cfg *cfg, u32 index)
struct device *dev = &cfg->dev->dev;
struct hwq *hwq = get_hwq(cfg->afu, index);
int rc = 0;
+ int num_irqs;
enum undo_level level;
hwq->afu = cfg->afu;
hwq->index = index;
INIT_LIST_HEAD(&hwq->pending_cmds);
- if (index == PRIMARY_HWQ)
+ if (index == PRIMARY_HWQ) {
ctx = cfg->ops->get_context(cfg->dev, cfg->afu_cookie);
- else
+ num_irqs = 3;
+ } else {
ctx = cfg->ops->dev_context_init(cfg->dev, cfg->afu_cookie);
+ num_irqs = 2;
+ }
if (IS_ERR_OR_NULL(ctx)) {
rc = -ENOMEM;
goto err1;
@@ -1982,6 +2030,7 @@ static int init_mc(struct cxlflash_cfg *cfg, u32 index)
WARN_ON(hwq->ctx_cookie);
hwq->ctx_cookie = ctx;
+ hwq->num_irqs = num_irqs;
/* Set it up as a master with the CXL */
cfg->ops->set_master(ctx);
@@ -2075,6 +2124,7 @@ static int init_afu(struct cxlflash_cfg *cfg)
cfg->ops->perst_reloads_same_image(cfg->afu_cookie, true);
+ mutex_init(&afu->sync_active);
afu->num_hwqs = afu->desired_hwqs;
for (i = 0; i < afu->num_hwqs; i++) {
rc = init_mc(cfg, i);
@@ -2254,10 +2304,10 @@ static int send_afu_cmd(struct afu *afu, struct sisl_ioarcb *rcb)
struct device *dev = &cfg->dev->dev;
struct afu_cmd *cmd = NULL;
struct hwq *hwq = get_hwq(afu, PRIMARY_HWQ);
+ ulong lock_flags;
char *buf = NULL;
int rc = 0;
int nretry = 0;
- static DEFINE_MUTEX(sync_active);
if (cfg->state != STATE_NORMAL) {
dev_dbg(dev, "%s: Sync not required state=%u\n",
@@ -2265,7 +2315,7 @@ static int send_afu_cmd(struct afu *afu, struct sisl_ioarcb *rcb)
return 0;
}
- mutex_lock(&sync_active);
+ mutex_lock(&afu->sync_active);
atomic_inc(&afu->cmds_active);
buf = kmalloc(sizeof(*cmd) + __alignof__(*cmd) - 1, GFP_KERNEL);
if (unlikely(!buf)) {
@@ -2299,6 +2349,11 @@ retry:
case -ETIMEDOUT:
rc = afu->context_reset(hwq);
if (rc) {
+ /* Delete the command from pending_cmds list */
+ spin_lock_irqsave(&hwq->hsq_slock, lock_flags);
+ list_del(&cmd->list);
+ spin_unlock_irqrestore(&hwq->hsq_slock, lock_flags);
+
cxlflash_schedule_async_reset(cfg);
break;
}
@@ -2315,7 +2370,7 @@ retry:
*rcb->ioasa = cmd->sa;
out:
atomic_dec(&afu->cmds_active);
- mutex_unlock(&sync_active);
+ mutex_unlock(&afu->sync_active);
kfree(buf);
dev_dbg(dev, "%s: returning rc=%d\n", __func__, rc);
return rc;
@@ -3138,7 +3193,8 @@ static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS,
static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS,
CXLFLASH_NOTIFY_SHUTDOWN };
static struct dev_dependent_vals dev_briard_vals = { CXLFLASH_MAX_SECTORS,
- CXLFLASH_NOTIFY_SHUTDOWN };
+ (CXLFLASH_NOTIFY_SHUTDOWN |
+ CXLFLASH_OCXL_DEV) };
/*
* PCI device binding table
@@ -3649,8 +3705,9 @@ static int cxlflash_probe(struct pci_dev *pdev,
cfg->init_state = INIT_STATE_NONE;
cfg->dev = pdev;
- cfg->ops = &cxlflash_cxl_ops;
cfg->cxl_fops = cxlflash_cxl_fops;
+ cfg->ops = cxlflash_assign_ops(ddv);
+ WARN_ON_ONCE(!cfg->ops);
/*
* Promoted LUNs move to the top of the LUN table. The rest stay on
@@ -3681,8 +3738,6 @@ static int cxlflash_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, cfg);
- cfg->afu_cookie = cfg->ops->create_afu(pdev);
-
rc = init_pci(cfg);
if (rc) {
dev_err(dev, "%s: init_pci failed rc=%d\n", __func__, rc);
@@ -3690,6 +3745,12 @@ static int cxlflash_probe(struct pci_dev *pdev,
}
cfg->init_state = INIT_STATE_PCI;
+ cfg->afu_cookie = cfg->ops->create_afu(pdev);
+ if (unlikely(!cfg->afu_cookie)) {
+ dev_err(dev, "%s: create_afu failed\n", __func__);
+ goto out_remove;
+ }
+
rc = init_afu(cfg);
if (rc && !wq_has_sleeper(&cfg->reset_waitq)) {
dev_err(dev, "%s: init_afu failed rc=%d\n", __func__, rc);
diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h
index ba0108a..2a39778 100644
--- a/drivers/scsi/cxlflash/main.h
+++ b/drivers/scsi/cxlflash/main.h
@@ -20,6 +20,8 @@
#include <scsi/scsi.h>
#include <scsi/scsi_device.h>
+#include "backend.h"
+
#define CXLFLASH_NAME "cxlflash"
#define CXLFLASH_ADAPTER_NAME "IBM POWER CXL Flash Adapter"
#define CXLFLASH_MAX_ADAPTERS 32
@@ -97,8 +99,27 @@ struct dev_dependent_vals {
u64 flags;
#define CXLFLASH_NOTIFY_SHUTDOWN 0x0000000000000001ULL
#define CXLFLASH_WWPN_VPD_REQUIRED 0x0000000000000002ULL
+#define CXLFLASH_OCXL_DEV 0x0000000000000004ULL
};
+static inline const struct cxlflash_backend_ops *
+cxlflash_assign_ops(struct dev_dependent_vals *ddv)
+{
+ const struct cxlflash_backend_ops *ops = NULL;
+
+#ifdef CONFIG_OCXL
+ if (ddv->flags & CXLFLASH_OCXL_DEV)
+ ops = &cxlflash_ocxl_ops;
+#endif
+
+#ifdef CONFIG_CXL
+ if (!(ddv->flags & CXLFLASH_OCXL_DEV))
+ ops = &cxlflash_cxl_ops;
+#endif
+
+ return ops;
+}
+
struct asyc_intr_info {
u64 status;
char *desc;
diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
new file mode 100644
index 0000000..0a95b5f
--- /dev/null
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -0,0 +1,1436 @@
+/*
+ * CXL Flash Device Driver
+ *
+ * Written by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>, IBM Corporation
+ * Uma Krishnan <ukrishn@linux.vnet.ibm.com>, IBM Corporation
+ *
+ * Copyright (C) 2018 IBM 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.
+ */
+
+#include <linux/file.h>
+#include <linux/idr.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/poll.h>
+#include <linux/sched/signal.h>
+
+#include <misc/ocxl.h>
+
+#include <uapi/misc/cxl.h>
+
+#include "backend.h"
+#include "ocxl_hw.h"
+
+/*
+ * Pseudo-filesystem to allocate inodes.
+ */
+
+#define OCXLFLASH_FS_MAGIC 0x1697698f
+
+static int ocxlflash_fs_cnt;
+static struct vfsmount *ocxlflash_vfs_mount;
+
+static const struct dentry_operations ocxlflash_fs_dops = {
+ .d_dname = simple_dname,
+};
+
+/*
+ * ocxlflash_fs_mount() - mount the pseudo-filesystem
+ * @fs_type: File system type.
+ * @flags: Flags for the filesystem.
+ * @dev_name: Device name associated with the filesystem.
+ * @data: Data pointer.
+ *
+ * Return: pointer to the directory entry structure
+ */
+static struct dentry *ocxlflash_fs_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+ void *data)
+{
+ return mount_pseudo(fs_type, "ocxlflash:", NULL, &ocxlflash_fs_dops,
+ OCXLFLASH_FS_MAGIC);
+}
+
+static struct file_system_type ocxlflash_fs_type = {
+ .name = "ocxlflash",
+ .owner = THIS_MODULE,
+ .mount = ocxlflash_fs_mount,
+ .kill_sb = kill_anon_super,
+};
+
+/*
+ * ocxlflash_release_mapping() - release the memory mapping
+ * @ctx: Context whose mapping is to be released.
+ */
+static void ocxlflash_release_mapping(struct ocxlflash_context *ctx)
+{
+ if (ctx->mapping)
+ simple_release_fs(&ocxlflash_vfs_mount, &ocxlflash_fs_cnt);
+ ctx->mapping = NULL;
+}
+
+/*
+ * ocxlflash_getfile() - allocate pseudo filesystem, inode, and the file
+ * @dev: Generic device of the host.
+ * @name: Name of the pseudo filesystem.
+ * @fops: File operations.
+ * @priv: Private data.
+ * @flags: Flags for the file.
+ *
+ * Return: pointer to the file on success, ERR_PTR on failure
+ */
+static struct file *ocxlflash_getfile(struct device *dev, const char *name,
+ const struct file_operations *fops,
+ void *priv, int flags)
+{
+ struct qstr this;
+ struct path path;
+ struct file *file;
+ struct inode *inode = NULL;
+ int rc;
+
+ if (fops->owner && !try_module_get(fops->owner)) {
+ dev_err(dev, "%s: Owner does not exist\n", __func__);
+ rc = -ENOENT;
+ goto err1;
+ }
+
+ rc = simple_pin_fs(&ocxlflash_fs_type, &ocxlflash_vfs_mount,
+ &ocxlflash_fs_cnt);
+ if (unlikely(rc < 0)) {
+ dev_err(dev, "%s: Cannot mount ocxlflash pseudofs rc=%d\n",
+ __func__, rc);
+ goto err2;
+ }
+
+ inode = alloc_anon_inode(ocxlflash_vfs_mount->mnt_sb);
+ if (IS_ERR(inode)) {
+ rc = PTR_ERR(inode);
+ dev_err(dev, "%s: alloc_anon_inode failed rc=%d\n",
+ __func__, rc);
+ goto err3;
+ }
+
+ this.name = name;
+ this.len = strlen(name);
+ this.hash = 0;
+ path.dentry = d_alloc_pseudo(ocxlflash_vfs_mount->mnt_sb, &this);
+ if (!path.dentry) {
+ dev_err(dev, "%s: d_alloc_pseudo failed\n", __func__);
+ rc = -ENOMEM;
+ goto err4;
+ }
+
+ path.mnt = mntget(ocxlflash_vfs_mount);
+ d_instantiate(path.dentry, inode);
+
+ file = alloc_file(&path, OPEN_FMODE(flags), fops);
+ if (IS_ERR(file)) {
+ rc = PTR_ERR(file);
+ dev_err(dev, "%s: alloc_file failed rc=%d\n",
+ __func__, rc);
+ goto err5;
+ }
+
+ file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
+ file->private_data = priv;
+out:
+ return file;
+err5:
+ path_put(&path);
+err4:
+ iput(inode);
+err3:
+ simple_release_fs(&ocxlflash_vfs_mount, &ocxlflash_fs_cnt);
+err2:
+ module_put(fops->owner);
+err1:
+ file = ERR_PTR(rc);
+ goto out;
+}
+
+/**
+ * ocxlflash_psa_map() - map the process specific MMIO space
+ * @ctx_cookie: Adapter context for which the mapping needs to be done.
+ *
+ * Return: MMIO pointer of the mapped region
+ */
+static void __iomem *ocxlflash_psa_map(void *ctx_cookie)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+ struct device *dev = ctx->hw_afu->dev;
+
+ mutex_lock(&ctx->state_mutex);
+ if (ctx->state != STARTED) {
+ dev_err(dev, "%s: Context not started, state=%d\n", __func__,
+ ctx->state);
+ mutex_unlock(&ctx->state_mutex);
+ return NULL;
+ }
+ mutex_unlock(&ctx->state_mutex);
+
+ return ioremap(ctx->psn_phys, ctx->psn_size);
+}
+
+/**
+ * ocxlflash_psa_unmap() - unmap the process specific MMIO space
+ * @addr: MMIO pointer to unmap.
+ */
+static void ocxlflash_psa_unmap(void __iomem *addr)
+{
+ iounmap(addr);
+}
+
+/**
+ * ocxlflash_process_element() - get process element of the adapter context
+ * @ctx_cookie: Adapter context associated with the process element.
+ *
+ * Return: process element of the adapter context
+ */
+static int ocxlflash_process_element(void *ctx_cookie)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+
+ return ctx->pe;
+}
+
+/**
+ * afu_map_irq() - map the interrupt of the adapter context
+ * @flags: Flags.
+ * @ctx: Adapter context.
+ * @num: Per-context AFU interrupt number.
+ * @handler: Interrupt handler to register.
+ * @cookie: Interrupt handler private data.
+ * @name: Name of the interrupt.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int afu_map_irq(u64 flags, struct ocxlflash_context *ctx, int num,
+ irq_handler_t handler, void *cookie, char *name)
+{
+ struct ocxl_hw_afu *afu = ctx->hw_afu;
+ struct device *dev = afu->dev;
+ struct ocxlflash_irqs *irq;
+ void __iomem *vtrig;
+ u32 virq;
+ int rc = 0;
+
+ if (num < 0 || num >= ctx->num_irqs) {
+ dev_err(dev, "%s: Interrupt %d not allocated\n", __func__, num);
+ rc = -ENOENT;
+ goto out;
+ }
+
+ irq = &ctx->irqs[num];
+ virq = irq_create_mapping(NULL, irq->hwirq);
+ if (unlikely(!virq)) {
+ dev_err(dev, "%s: irq_create_mapping failed\n", __func__);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ rc = request_irq(virq, handler, 0, name, cookie);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: request_irq failed rc=%d\n", __func__, rc);
+ goto err1;
+ }
+
+ vtrig = ioremap(irq->ptrig, PAGE_SIZE);
+ if (unlikely(!vtrig)) {
+ dev_err(dev, "%s: Trigger page mapping failed\n", __func__);
+ rc = -ENOMEM;
+ goto err2;
+ }
+
+ irq->virq = virq;
+ irq->vtrig = vtrig;
+out:
+ return rc;
+err2:
+ free_irq(virq, cookie);
+err1:
+ irq_dispose_mapping(virq);
+ goto out;
+}
+
+/**
+ * ocxlflash_map_afu_irq() - map the interrupt of the adapter context
+ * @ctx_cookie: Adapter context.
+ * @num: Per-context AFU interrupt number.
+ * @handler: Interrupt handler to register.
+ * @cookie: Interrupt handler private data.
+ * @name: Name of the interrupt.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_map_afu_irq(void *ctx_cookie, int num,
+ irq_handler_t handler, void *cookie,
+ char *name)
+{
+ return afu_map_irq(0, ctx_cookie, num, handler, cookie, name);
+}
+
+/**
+ * afu_unmap_irq() - unmap the interrupt
+ * @flags: Flags.
+ * @ctx: Adapter context.
+ * @num: Per-context AFU interrupt number.
+ * @cookie: Interrupt handler private data.
+ */
+static void afu_unmap_irq(u64 flags, struct ocxlflash_context *ctx, int num,
+ void *cookie)
+{
+ struct ocxl_hw_afu *afu = ctx->hw_afu;
+ struct device *dev = afu->dev;
+ struct ocxlflash_irqs *irq;
+
+ if (num < 0 || num >= ctx->num_irqs) {
+ dev_err(dev, "%s: Interrupt %d not allocated\n", __func__, num);
+ return;
+ }
+
+ irq = &ctx->irqs[num];
+ if (irq->vtrig)
+ iounmap(irq->vtrig);
+
+ if (irq_find_mapping(NULL, irq->hwirq)) {
+ free_irq(irq->virq, cookie);
+ irq_dispose_mapping(irq->virq);
+ }
+
+ memset(irq, 0, sizeof(*irq));
+}
+
+/**
+ * ocxlflash_unmap_afu_irq() - unmap the interrupt
+ * @ctx_cookie: Adapter context.
+ * @num: Per-context AFU interrupt number.
+ * @cookie: Interrupt handler private data.
+ */
+static void ocxlflash_unmap_afu_irq(void *ctx_cookie, int num, void *cookie)
+{
+ return afu_unmap_irq(0, ctx_cookie, num, cookie);
+}
+
+/**
+ * ocxlflash_get_irq_objhndl() - get the object handle for an interrupt
+ * @ctx_cookie: Context associated with the interrupt.
+ * @irq: Interrupt number.
+ *
+ * Return: effective address of the mapped region
+ */
+static u64 ocxlflash_get_irq_objhndl(void *ctx_cookie, int irq)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+
+ if (irq < 0 || irq >= ctx->num_irqs)
+ return 0;
+
+ return (__force u64)ctx->irqs[irq].vtrig;
+}
+
+/**
+ * ocxlflash_xsl_fault() - callback when translation error is triggered
+ * @data: Private data provided at callback registration, the context.
+ * @addr: Address that triggered the error.
+ * @dsisr: Value of dsisr register.
+ */
+static void ocxlflash_xsl_fault(void *data, u64 addr, u64 dsisr)
+{
+ struct ocxlflash_context *ctx = data;
+
+ spin_lock(&ctx->slock);
+ ctx->fault_addr = addr;
+ ctx->fault_dsisr = dsisr;
+ ctx->pending_fault = true;
+ spin_unlock(&ctx->slock);
+
+ wake_up_all(&ctx->wq);
+}
+
+/**
+ * start_context() - local routine to start a context
+ * @ctx: Adapter context to be started.
+ *
+ * Assign the context specific MMIO space, add and enable the PE.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int start_context(struct ocxlflash_context *ctx)
+{
+ struct ocxl_hw_afu *afu = ctx->hw_afu;
+ struct ocxl_afu_config *acfg = &afu->acfg;
+ void *link_token = afu->link_token;
+ struct device *dev = afu->dev;
+ bool master = ctx->master;
+ struct mm_struct *mm;
+ int rc = 0;
+ u32 pid;
+
+ mutex_lock(&ctx->state_mutex);
+ if (ctx->state != OPENED) {
+ dev_err(dev, "%s: Context state invalid, state=%d\n",
+ __func__, ctx->state);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (master) {
+ ctx->psn_size = acfg->global_mmio_size;
+ ctx->psn_phys = afu->gmmio_phys;
+ } else {
+ ctx->psn_size = acfg->pp_mmio_stride;
+ ctx->psn_phys = afu->ppmmio_phys + (ctx->pe * ctx->psn_size);
+ }
+
+ /* pid and mm not set for master contexts */
+ if (master) {
+ pid = 0;
+ mm = NULL;
+ } else {
+ pid = current->mm->context.id;
+ mm = current->mm;
+ }
+
+ rc = ocxl_link_add_pe(link_token, ctx->pe, pid, 0, 0, mm,
+ ocxlflash_xsl_fault, ctx);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: ocxl_link_add_pe failed rc=%d\n",
+ __func__, rc);
+ goto out;
+ }
+
+ ctx->state = STARTED;
+out:
+ mutex_unlock(&ctx->state_mutex);
+ return rc;
+}
+
+/**
+ * ocxlflash_start_context() - start a kernel context
+ * @ctx_cookie: Adapter context to be started.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_start_context(void *ctx_cookie)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+
+ return start_context(ctx);
+}
+
+/**
+ * ocxlflash_stop_context() - stop a context
+ * @ctx_cookie: Adapter context to be stopped.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_stop_context(void *ctx_cookie)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+ struct ocxl_hw_afu *afu = ctx->hw_afu;
+ struct ocxl_afu_config *acfg = &afu->acfg;
+ struct pci_dev *pdev = afu->pdev;
+ struct device *dev = afu->dev;
+ enum ocxlflash_ctx_state state;
+ int rc = 0;
+
+ mutex_lock(&ctx->state_mutex);
+ state = ctx->state;
+ ctx->state = CLOSED;
+ mutex_unlock(&ctx->state_mutex);
+ if (state != STARTED)
+ goto out;
+
+ rc = ocxl_config_terminate_pasid(pdev, acfg->dvsec_afu_control_pos,
+ ctx->pe);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: ocxl_config_terminate_pasid failed rc=%d\n",
+ __func__, rc);
+ /* If EBUSY, PE could be referenced in future by the AFU */
+ if (rc == -EBUSY)
+ goto out;
+ }
+
+ rc = ocxl_link_remove_pe(afu->link_token, ctx->pe);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: ocxl_link_remove_pe failed rc=%d\n",
+ __func__, rc);
+ goto out;
+ }
+out:
+ return rc;
+}
+
+/**
+ * ocxlflash_afu_reset() - reset the AFU
+ * @ctx_cookie: Adapter context.
+ */
+static int ocxlflash_afu_reset(void *ctx_cookie)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+ struct device *dev = ctx->hw_afu->dev;
+
+ /* Pending implementation from OCXL transport services */
+ dev_err_once(dev, "%s: afu_reset() fop not supported\n", __func__);
+
+ /* Silently return success until it is implemented */
+ return 0;
+}
+
+/**
+ * ocxlflash_set_master() - sets the context as master
+ * @ctx_cookie: Adapter context to set as master.
+ */
+static void ocxlflash_set_master(void *ctx_cookie)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+
+ ctx->master = true;
+}
+
+/**
+ * ocxlflash_get_context() - obtains the context associated with the host
+ * @pdev: PCI device associated with the host.
+ * @afu_cookie: Hardware AFU associated with the host.
+ *
+ * Return: returns the pointer to host adapter context
+ */
+static void *ocxlflash_get_context(struct pci_dev *pdev, void *afu_cookie)
+{
+ struct ocxl_hw_afu *afu = afu_cookie;
+
+ return afu->ocxl_ctx;
+}
+
+/**
+ * ocxlflash_dev_context_init() - allocate and initialize an adapter context
+ * @pdev: PCI device associated with the host.
+ * @afu_cookie: Hardware AFU associated with the host.
+ *
+ * Return: returns the adapter context on success, ERR_PTR on failure
+ */
+static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
+{
+ struct ocxl_hw_afu *afu = afu_cookie;
+ struct device *dev = afu->dev;
+ struct ocxlflash_context *ctx;
+ int rc;
+
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (unlikely(!ctx)) {
+ dev_err(dev, "%s: Context allocation failed\n", __func__);
+ rc = -ENOMEM;
+ goto err1;
+ }
+
+ idr_preload(GFP_KERNEL);
+ rc = idr_alloc(&afu->idr, ctx, 0, afu->max_pasid, GFP_NOWAIT);
+ idr_preload_end();
+ if (unlikely(rc < 0)) {
+ dev_err(dev, "%s: idr_alloc failed rc=%d\n", __func__, rc);
+ goto err2;
+ }
+
+ spin_lock_init(&ctx->slock);
+ init_waitqueue_head(&ctx->wq);
+ mutex_init(&ctx->state_mutex);
+
+ ctx->state = OPENED;
+ ctx->pe = rc;
+ ctx->master = false;
+ ctx->mapping = NULL;
+ ctx->hw_afu = afu;
+ ctx->irq_bitmap = 0;
+ ctx->pending_irq = false;
+ ctx->pending_fault = false;
+out:
+ return ctx;
+err2:
+ kfree(ctx);
+err1:
+ ctx = ERR_PTR(rc);
+ goto out;
+}
+
+/**
+ * ocxlflash_release_context() - releases an adapter context
+ * @ctx_cookie: Adapter context to be released.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_release_context(void *ctx_cookie)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+ struct device *dev;
+ int rc = 0;
+
+ if (!ctx)
+ goto out;
+
+ dev = ctx->hw_afu->dev;
+ mutex_lock(&ctx->state_mutex);
+ if (ctx->state >= STARTED) {
+ dev_err(dev, "%s: Context in use, state=%d\n", __func__,
+ ctx->state);
+ mutex_unlock(&ctx->state_mutex);
+ rc = -EBUSY;
+ goto out;
+ }
+ mutex_unlock(&ctx->state_mutex);
+
+ idr_remove(&ctx->hw_afu->idr, ctx->pe);
+ ocxlflash_release_mapping(ctx);
+ kfree(ctx);
+out:
+ return rc;
+}
+
+/**
+ * ocxlflash_perst_reloads_same_image() - sets the image reload policy
+ * @afu_cookie: Hardware AFU associated with the host.
+ * @image: Whether to load the same image on PERST.
+ */
+static void ocxlflash_perst_reloads_same_image(void *afu_cookie, bool image)
+{
+ struct ocxl_hw_afu *afu = afu_cookie;
+
+ afu->perst_same_image = image;
+}
+
+/**
+ * ocxlflash_read_adapter_vpd() - reads the adapter VPD
+ * @pdev: PCI device associated with the host.
+ * @buf: Buffer to get the VPD data.
+ * @count: Size of buffer (maximum bytes that can be read).
+ *
+ * Return: size of VPD on success, -errno on failure
+ */
+static ssize_t ocxlflash_read_adapter_vpd(struct pci_dev *pdev, void *buf,
+ size_t count)
+{
+ return pci_read_vpd(pdev, 0, count, buf);
+}
+
+/**
+ * free_afu_irqs() - internal service to free interrupts
+ * @ctx: Adapter context.
+ */
+static void free_afu_irqs(struct ocxlflash_context *ctx)
+{
+ struct ocxl_hw_afu *afu = ctx->hw_afu;
+ struct device *dev = afu->dev;
+ int i;
+
+ if (!ctx->irqs) {
+ dev_err(dev, "%s: Interrupts not allocated\n", __func__);
+ return;
+ }
+
+ for (i = ctx->num_irqs; i >= 0; i--)
+ ocxl_link_free_irq(afu->link_token, ctx->irqs[i].hwirq);
+
+ kfree(ctx->irqs);
+ ctx->irqs = NULL;
+}
+
+/**
+ * alloc_afu_irqs() - internal service to allocate interrupts
+ * @ctx: Context associated with the request.
+ * @num: Number of interrupts requested.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int alloc_afu_irqs(struct ocxlflash_context *ctx, int num)
+{
+ struct ocxl_hw_afu *afu = ctx->hw_afu;
+ struct device *dev = afu->dev;
+ struct ocxlflash_irqs *irqs;
+ u64 addr;
+ int rc = 0;
+ int hwirq;
+ int i;
+
+ if (ctx->irqs) {
+ dev_err(dev, "%s: Interrupts already allocated\n", __func__);
+ rc = -EEXIST;
+ goto out;
+ }
+
+ if (num > OCXL_MAX_IRQS) {
+ dev_err(dev, "%s: Too many interrupts num=%d\n", __func__, num);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ irqs = kcalloc(num, sizeof(*irqs), GFP_KERNEL);
+ if (unlikely(!irqs)) {
+ dev_err(dev, "%s: Context irqs allocation failed\n", __func__);
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ for (i = 0; i < num; i++) {
+ rc = ocxl_link_irq_alloc(afu->link_token, &hwirq, &addr);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: ocxl_link_irq_alloc failed rc=%d\n",
+ __func__, rc);
+ goto err;
+ }
+
+ irqs[i].hwirq = hwirq;
+ irqs[i].ptrig = addr;
+ }
+
+ ctx->irqs = irqs;
+ ctx->num_irqs = num;
+out:
+ return rc;
+err:
+ for (i = i-1; i >= 0; i--)
+ ocxl_link_free_irq(afu->link_token, irqs[i].hwirq);
+ kfree(irqs);
+ goto out;
+}
+
+/**
+ * ocxlflash_allocate_afu_irqs() - allocates the requested number of interrupts
+ * @ctx_cookie: Context associated with the request.
+ * @num: Number of interrupts requested.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_allocate_afu_irqs(void *ctx_cookie, int num)
+{
+ return alloc_afu_irqs(ctx_cookie, num);
+}
+
+/**
+ * ocxlflash_free_afu_irqs() - frees the interrupts of an adapter context
+ * @ctx_cookie: Adapter context.
+ */
+static void ocxlflash_free_afu_irqs(void *ctx_cookie)
+{
+ free_afu_irqs(ctx_cookie);
+}
+
+/**
+ * ocxlflash_unconfig_afu() - unconfigure the AFU
+ * @afu: AFU associated with the host.
+ */
+static void ocxlflash_unconfig_afu(struct ocxl_hw_afu *afu)
+{
+ if (afu->gmmio_virt) {
+ iounmap(afu->gmmio_virt);
+ afu->gmmio_virt = NULL;
+ }
+}
+
+/**
+ * ocxlflash_destroy_afu() - destroy the AFU structure
+ * @afu_cookie: AFU to be freed.
+ */
+static void ocxlflash_destroy_afu(void *afu_cookie)
+{
+ struct ocxl_hw_afu *afu = afu_cookie;
+ int pos;
+
+ if (!afu)
+ return;
+
+ ocxlflash_release_context(afu->ocxl_ctx);
+ idr_destroy(&afu->idr);
+
+ /* Disable the AFU */
+ pos = afu->acfg.dvsec_afu_control_pos;
+ ocxl_config_set_afu_state(afu->pdev, pos, 0);
+
+ ocxlflash_unconfig_afu(afu);
+ kfree(afu);
+}
+
+/**
+ * ocxlflash_config_fn() - configure the host function
+ * @pdev: PCI device associated with the host.
+ * @afu: AFU associated with the host.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_config_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
+{
+ struct ocxl_fn_config *fcfg = &afu->fcfg;
+ struct device *dev = &pdev->dev;
+ u16 base, enabled, supported;
+ int rc = 0;
+
+ /* Read DVSEC config of the function */
+ rc = ocxl_config_read_function(pdev, fcfg);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: ocxl_config_read_function failed rc=%d\n",
+ __func__, rc);
+ goto out;
+ }
+
+ /* Check if function has AFUs defined, only 1 per function supported */
+ if (fcfg->max_afu_index >= 0) {
+ afu->is_present = true;
+ if (fcfg->max_afu_index != 0)
+ dev_warn(dev, "%s: Unexpected AFU index value %d\n",
+ __func__, fcfg->max_afu_index);
+ }
+
+ rc = ocxl_config_get_actag_info(pdev, &base, &enabled, &supported);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: ocxl_config_get_actag_info failed rc=%d\n",
+ __func__, rc);
+ goto out;
+ }
+
+ afu->fn_actag_base = base;
+ afu->fn_actag_enabled = enabled;
+
+ ocxl_config_set_actag(pdev, fcfg->dvsec_function_pos, base, enabled);
+ dev_dbg(dev, "%s: Function acTag range base=%u enabled=%u\n",
+ __func__, base, enabled);
+
+ rc = ocxl_link_setup(pdev, 0, &afu->link_token);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: ocxl_link_setup failed rc=%d\n",
+ __func__, rc);
+ goto out;
+ }
+
+ rc = ocxl_config_set_TL(pdev, fcfg->dvsec_tl_pos);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: ocxl_config_set_TL failed rc=%d\n",
+ __func__, rc);
+ goto err;
+ }
+out:
+ return rc;
+err:
+ ocxl_link_release(pdev, afu->link_token);
+ goto out;
+}
+
+/**
+ * ocxlflash_unconfig_fn() - unconfigure the host function
+ * @pdev: PCI device associated with the host.
+ * @afu: AFU associated with the host.
+ */
+static void ocxlflash_unconfig_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
+{
+ ocxl_link_release(pdev, afu->link_token);
+}
+
+/**
+ * ocxlflash_map_mmio() - map the AFU MMIO space
+ * @afu: AFU associated with the host.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_map_mmio(struct ocxl_hw_afu *afu)
+{
+ struct ocxl_afu_config *acfg = &afu->acfg;
+ struct pci_dev *pdev = afu->pdev;
+ struct device *dev = afu->dev;
+ phys_addr_t gmmio, ppmmio;
+ int rc = 0;
+
+ rc = pci_request_region(pdev, acfg->global_mmio_bar, "ocxlflash");
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: pci_request_region for global failed rc=%d\n",
+ __func__, rc);
+ goto out;
+ }
+ gmmio = pci_resource_start(pdev, acfg->global_mmio_bar);
+ gmmio += acfg->global_mmio_offset;
+
+ rc = pci_request_region(pdev, acfg->pp_mmio_bar, "ocxlflash");
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: pci_request_region for pp bar failed rc=%d\n",
+ __func__, rc);
+ goto err1;
+ }
+ ppmmio = pci_resource_start(pdev, acfg->pp_mmio_bar);
+ ppmmio += acfg->pp_mmio_offset;
+
+ afu->gmmio_virt = ioremap(gmmio, acfg->global_mmio_size);
+ if (unlikely(!afu->gmmio_virt)) {
+ dev_err(dev, "%s: MMIO mapping failed\n", __func__);
+ rc = -ENOMEM;
+ goto err2;
+ }
+
+ afu->gmmio_phys = gmmio;
+ afu->ppmmio_phys = ppmmio;
+out:
+ return rc;
+err2:
+ pci_release_region(pdev, acfg->pp_mmio_bar);
+err1:
+ pci_release_region(pdev, acfg->global_mmio_bar);
+ goto out;
+}
+
+/**
+ * ocxlflash_config_afu() - configure the host AFU
+ * @pdev: PCI device associated with the host.
+ * @afu: AFU associated with the host.
+ *
+ * Must be called _after_ host function configuration.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_config_afu(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
+{
+ struct ocxl_afu_config *acfg = &afu->acfg;
+ struct ocxl_fn_config *fcfg = &afu->fcfg;
+ struct device *dev = &pdev->dev;
+ int count;
+ int base;
+ int pos;
+ int rc = 0;
+
+ /* This HW AFU function does not have any AFUs defined */
+ if (!afu->is_present)
+ goto out;
+
+ /* Read AFU config at index 0 */
+ rc = ocxl_config_read_afu(pdev, fcfg, acfg, 0);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: ocxl_config_read_afu failed rc=%d\n",
+ __func__, rc);
+ goto out;
+ }
+
+ /* Only one AFU per function is supported, so actag_base is same */
+ base = afu->fn_actag_base;
+ count = min_t(int, acfg->actag_supported, afu->fn_actag_enabled);
+ pos = acfg->dvsec_afu_control_pos;
+
+ ocxl_config_set_afu_actag(pdev, pos, base, count);
+ dev_dbg(dev, "%s: acTag base=%d enabled=%d\n", __func__, base, count);
+ afu->afu_actag_base = base;
+ afu->afu_actag_enabled = count;
+ afu->max_pasid = 1 << acfg->pasid_supported_log;
+
+ ocxl_config_set_afu_pasid(pdev, pos, 0, acfg->pasid_supported_log);
+
+ rc = ocxlflash_map_mmio(afu);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: ocxlflash_map_mmio failed rc=%d\n",
+ __func__, rc);
+ goto out;
+ }
+
+ /* Enable the AFU */
+ ocxl_config_set_afu_state(pdev, acfg->dvsec_afu_control_pos, 1);
+out:
+ return rc;
+}
+
+/**
+ * ocxlflash_create_afu() - create the AFU for OCXL
+ * @pdev: PCI device associated with the host.
+ *
+ * Return: AFU on success, NULL on failure
+ */
+static void *ocxlflash_create_afu(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ocxlflash_context *ctx;
+ struct ocxl_hw_afu *afu;
+ int rc;
+
+ afu = kzalloc(sizeof(*afu), GFP_KERNEL);
+ if (unlikely(!afu)) {
+ dev_err(dev, "%s: HW AFU allocation failed\n", __func__);
+ goto out;
+ }
+
+ afu->pdev = pdev;
+ afu->dev = dev;
+ idr_init(&afu->idr);
+
+ rc = ocxlflash_config_fn(pdev, afu);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: Function configuration failed rc=%d\n",
+ __func__, rc);
+ goto err1;
+ }
+
+ rc = ocxlflash_config_afu(pdev, afu);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: AFU configuration failed rc=%d\n",
+ __func__, rc);
+ goto err2;
+ }
+
+ ctx = ocxlflash_dev_context_init(pdev, afu);
+ if (IS_ERR(ctx)) {
+ rc = PTR_ERR(ctx);
+ dev_err(dev, "%s: ocxlflash_dev_context_init failed rc=%d\n",
+ __func__, rc);
+ goto err3;
+ }
+
+ afu->ocxl_ctx = ctx;
+out:
+ return afu;
+err3:
+ ocxlflash_unconfig_afu(afu);
+err2:
+ ocxlflash_unconfig_fn(pdev, afu);
+err1:
+ idr_destroy(&afu->idr);
+ kfree(afu);
+ afu = NULL;
+ goto out;
+}
+
+/**
+ * ctx_event_pending() - check for any event pending on the context
+ * @ctx: Context to be checked.
+ *
+ * Return: true if there is an event pending, false if none pending
+ */
+static inline bool ctx_event_pending(struct ocxlflash_context *ctx)
+{
+ if (ctx->pending_irq || ctx->pending_fault)
+ return true;
+
+ return false;
+}
+
+/**
+ * afu_poll() - poll the AFU for events on the context
+ * @file: File associated with the adapter context.
+ * @poll: Poll structure from the user.
+ *
+ * Return: poll mask
+ */
+static unsigned int afu_poll(struct file *file, struct poll_table_struct *poll)
+{
+ struct ocxlflash_context *ctx = file->private_data;
+ struct device *dev = ctx->hw_afu->dev;
+ ulong lock_flags;
+ int mask = 0;
+
+ poll_wait(file, &ctx->wq, poll);
+
+ spin_lock_irqsave(&ctx->slock, lock_flags);
+ if (ctx_event_pending(ctx))
+ mask |= POLLIN | POLLRDNORM;
+ else if (ctx->state == CLOSED)
+ mask |= POLLERR;
+ spin_unlock_irqrestore(&ctx->slock, lock_flags);
+
+ dev_dbg(dev, "%s: Poll wait completed for pe %i mask %i\n",
+ __func__, ctx->pe, mask);
+
+ return mask;
+}
+
+/**
+ * afu_read() - perform a read on the context for any event
+ * @file: File associated with the adapter context.
+ * @buf: Buffer to receive the data.
+ * @count: Size of buffer (maximum bytes that can be read).
+ * @off: Offset.
+ *
+ * Return: size of the data read on success, -errno on failure
+ */
+static ssize_t afu_read(struct file *file, char __user *buf, size_t count,
+ loff_t *off)
+{
+ struct ocxlflash_context *ctx = file->private_data;
+ struct device *dev = ctx->hw_afu->dev;
+ struct cxl_event event;
+ ulong lock_flags;
+ ssize_t esize;
+ ssize_t rc;
+ int bit;
+ DEFINE_WAIT(event_wait);
+
+ if (*off != 0) {
+ dev_err(dev, "%s: Non-zero offset not supported, off=%lld\n",
+ __func__, *off);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ spin_lock_irqsave(&ctx->slock, lock_flags);
+
+ for (;;) {
+ prepare_to_wait(&ctx->wq, &event_wait, TASK_INTERRUPTIBLE);
+
+ if (ctx_event_pending(ctx) || (ctx->state == CLOSED))
+ break;
+
+ if (file->f_flags & O_NONBLOCK) {
+ dev_err(dev, "%s: File cannot be blocked on I/O\n",
+ __func__);
+ rc = -EAGAIN;
+ goto err;
+ }
+
+ if (signal_pending(current)) {
+ dev_err(dev, "%s: Signal pending on the process\n",
+ __func__);
+ rc = -ERESTARTSYS;
+ goto err;
+ }
+
+ spin_unlock_irqrestore(&ctx->slock, lock_flags);
+ schedule();
+ spin_lock_irqsave(&ctx->slock, lock_flags);
+ }
+
+ finish_wait(&ctx->wq, &event_wait);
+
+ memset(&event, 0, sizeof(event));
+ event.header.process_element = ctx->pe;
+ event.header.size = sizeof(struct cxl_event_header);
+ if (ctx->pending_irq) {
+ esize = sizeof(struct cxl_event_afu_interrupt);
+ event.header.size += esize;
+ event.header.type = CXL_EVENT_AFU_INTERRUPT;
+
+ bit = find_first_bit(&ctx->irq_bitmap, ctx->num_irqs);
+ clear_bit(bit, &ctx->irq_bitmap);
+ event.irq.irq = bit + 1;
+ if (bitmap_empty(&ctx->irq_bitmap, ctx->num_irqs))
+ ctx->pending_irq = false;
+ } else if (ctx->pending_fault) {
+ event.header.size += sizeof(struct cxl_event_data_storage);
+ event.header.type = CXL_EVENT_DATA_STORAGE;
+ event.fault.addr = ctx->fault_addr;
+ event.fault.dsisr = ctx->fault_dsisr;
+ ctx->pending_fault = false;
+ }
+
+ spin_unlock_irqrestore(&ctx->slock, lock_flags);
+
+ if (copy_to_user(buf, &event, event.header.size)) {
+ dev_err(dev, "%s: copy_to_user failed\n", __func__);
+ rc = -EFAULT;
+ goto out;
+ }
+
+ rc = event.header.size;
+out:
+ return rc;
+err:
+ finish_wait(&ctx->wq, &event_wait);
+ spin_unlock_irqrestore(&ctx->slock, lock_flags);
+ goto out;
+}
+
+/**
+ * afu_release() - release and free the context
+ * @inode: File inode pointer.
+ * @file: File associated with the context.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int afu_release(struct inode *inode, struct file *file)
+{
+ struct ocxlflash_context *ctx = file->private_data;
+ int i;
+
+ /* Unmap and free the interrupts associated with the context */
+ for (i = ctx->num_irqs; i >= 0; i--)
+ afu_unmap_irq(0, ctx, i, ctx);
+ free_afu_irqs(ctx);
+
+ return ocxlflash_release_context(ctx);
+}
+
+/**
+ * ocxlflash_mmap_fault() - mmap fault handler
+ * @vmf: VM fault associated with current fault.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_mmap_fault(struct vm_fault *vmf)
+{
+ struct vm_area_struct *vma = vmf->vma;
+ struct ocxlflash_context *ctx = vma->vm_file->private_data;
+ struct device *dev = ctx->hw_afu->dev;
+ u64 mmio_area, offset;
+
+ offset = vmf->pgoff << PAGE_SHIFT;
+ if (offset >= ctx->psn_size)
+ return VM_FAULT_SIGBUS;
+
+ mutex_lock(&ctx->state_mutex);
+ if (ctx->state != STARTED) {
+ dev_err(dev, "%s: Context not started, state=%d\n",
+ __func__, ctx->state);
+ mutex_unlock(&ctx->state_mutex);
+ return VM_FAULT_SIGBUS;
+ }
+ mutex_unlock(&ctx->state_mutex);
+
+ mmio_area = ctx->psn_phys;
+ mmio_area += offset;
+
+ vm_insert_pfn(vma, vmf->address, mmio_area >> PAGE_SHIFT);
+ return VM_FAULT_NOPAGE;
+}
+
+static const struct vm_operations_struct ocxlflash_vmops = {
+ .fault = ocxlflash_mmap_fault,
+};
+
+/**
+ * afu_mmap() - map the fault handler operations
+ * @file: File associated with the context.
+ * @vma: VM area associated with mapping.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int afu_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct ocxlflash_context *ctx = file->private_data;
+
+ if ((vma_pages(vma) + vma->vm_pgoff) >
+ (ctx->psn_size >> PAGE_SHIFT))
+ return -EINVAL;
+
+ vma->vm_flags |= VM_IO | VM_PFNMAP;
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_ops = &ocxlflash_vmops;
+ return 0;
+}
+
+static const struct file_operations ocxl_afu_fops = {
+ .owner = THIS_MODULE,
+ .poll = afu_poll,
+ .read = afu_read,
+ .release = afu_release,
+ .mmap = afu_mmap,
+};
+
+#define PATCH_FOPS(NAME) \
+ do { if (!fops->NAME) fops->NAME = ocxl_afu_fops.NAME; } while (0)
+
+/**
+ * ocxlflash_get_fd() - get file descriptor for an adapter context
+ * @ctx_cookie: Adapter context.
+ * @fops: File operations to be associated.
+ * @fd: File descriptor to be returned back.
+ *
+ * Return: pointer to the file on success, ERR_PTR on failure
+ */
+static struct file *ocxlflash_get_fd(void *ctx_cookie,
+ struct file_operations *fops, int *fd)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+ struct device *dev = ctx->hw_afu->dev;
+ struct file *file;
+ int flags, fdtmp;
+ int rc = 0;
+ char *name = NULL;
+
+ /* Only allow one fd per context */
+ if (ctx->mapping) {
+ dev_err(dev, "%s: Context is already mapped to an fd\n",
+ __func__);
+ rc = -EEXIST;
+ goto err1;
+ }
+
+ flags = O_RDWR | O_CLOEXEC;
+
+ /* This code is similar to anon_inode_getfd() */
+ rc = get_unused_fd_flags(flags);
+ if (unlikely(rc < 0)) {
+ dev_err(dev, "%s: get_unused_fd_flags failed rc=%d\n",
+ __func__, rc);
+ goto err1;
+ }
+ fdtmp = rc;
+
+ /* Patch the file ops that are not defined */
+ if (fops) {
+ PATCH_FOPS(poll);
+ PATCH_FOPS(read);
+ PATCH_FOPS(release);
+ PATCH_FOPS(mmap);
+ } else /* Use default ops */
+ fops = (struct file_operations *)&ocxl_afu_fops;
+
+ name = kasprintf(GFP_KERNEL, "ocxlflash:%d", ctx->pe);
+ file = ocxlflash_getfile(dev, name, fops, ctx, flags);
+ kfree(name);
+ if (IS_ERR(file)) {
+ rc = PTR_ERR(file);
+ dev_err(dev, "%s: ocxlflash_getfile failed rc=%d\n",
+ __func__, rc);
+ goto err2;
+ }
+
+ ctx->mapping = file->f_mapping;
+ *fd = fdtmp;
+out:
+ return file;
+err2:
+ put_unused_fd(fdtmp);
+err1:
+ file = ERR_PTR(rc);
+ goto out;
+}
+
+/**
+ * ocxlflash_fops_get_context() - get the context associated with the file
+ * @file: File associated with the adapter context.
+ *
+ * Return: pointer to the context
+ */
+static void *ocxlflash_fops_get_context(struct file *file)
+{
+ return file->private_data;
+}
+
+/**
+ * ocxlflash_afu_irq() - interrupt handler for user contexts
+ * @irq: Interrupt number.
+ * @data: Private data provided at interrupt registration, the context.
+ *
+ * Return: Always return IRQ_HANDLED.
+ */
+static irqreturn_t ocxlflash_afu_irq(int irq, void *data)
+{
+ struct ocxlflash_context *ctx = data;
+ struct device *dev = ctx->hw_afu->dev;
+ int i;
+
+ dev_dbg(dev, "%s: Interrupt raised for pe %i virq %i\n",
+ __func__, ctx->pe, irq);
+
+ for (i = 0; i < ctx->num_irqs; i++) {
+ if (ctx->irqs[i].virq == irq)
+ break;
+ }
+ if (unlikely(i >= ctx->num_irqs)) {
+ dev_err(dev, "%s: Received AFU IRQ out of range\n", __func__);
+ goto out;
+ }
+
+ spin_lock(&ctx->slock);
+ set_bit(i - 1, &ctx->irq_bitmap);
+ ctx->pending_irq = true;
+ spin_unlock(&ctx->slock);
+
+ wake_up_all(&ctx->wq);
+out:
+ return IRQ_HANDLED;
+}
+
+/**
+ * ocxlflash_start_work() - start a user context
+ * @ctx_cookie: Context to be started.
+ * @num_irqs: Number of interrupts requested.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_start_work(void *ctx_cookie, u64 num_irqs)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+ struct ocxl_hw_afu *afu = ctx->hw_afu;
+ struct device *dev = afu->dev;
+ char *name;
+ int rc = 0;
+ int i;
+
+ rc = alloc_afu_irqs(ctx, num_irqs);
+ if (unlikely(rc < 0)) {
+ dev_err(dev, "%s: alloc_afu_irqs failed rc=%d\n", __func__, rc);
+ goto out;
+ }
+
+ for (i = 0; i < num_irqs; i++) {
+ name = kasprintf(GFP_KERNEL, "ocxlflash-%s-pe%i-%i",
+ dev_name(dev), ctx->pe, i);
+ rc = afu_map_irq(0, ctx, i, ocxlflash_afu_irq, ctx, name);
+ kfree(name);
+ if (unlikely(rc < 0)) {
+ dev_err(dev, "%s: afu_map_irq failed rc=%d\n",
+ __func__, rc);
+ goto err;
+ }
+ }
+
+ rc = start_context(ctx);
+ if (unlikely(rc)) {
+ dev_err(dev, "%s: start_context failed rc=%d\n", __func__, rc);
+ goto err;
+ }
+out:
+ return rc;
+err:
+ for (i = i-1; i >= 0; i--)
+ afu_unmap_irq(0, ctx, i, ctx);
+ free_afu_irqs(ctx);
+ goto out;
+};
+
+/**
+ * ocxlflash_fd_mmap() - mmap handler for adapter file descriptor
+ * @file: File installed with adapter file descriptor.
+ * @vma: VM area associated with mapping.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_fd_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ return afu_mmap(file, vma);
+}
+
+/**
+ * ocxlflash_fd_release() - release the context associated with the file
+ * @inode: File inode pointer.
+ * @file: File associated with the adapter context.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_fd_release(struct inode *inode, struct file *file)
+{
+ return afu_release(inode, file);
+}
+
+/* Backend ops to ocxlflash services */
+const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
+ .module = THIS_MODULE,
+ .psa_map = ocxlflash_psa_map,
+ .psa_unmap = ocxlflash_psa_unmap,
+ .process_element = ocxlflash_process_element,
+ .map_afu_irq = ocxlflash_map_afu_irq,
+ .unmap_afu_irq = ocxlflash_unmap_afu_irq,
+ .get_irq_objhndl = ocxlflash_get_irq_objhndl,
+ .start_context = ocxlflash_start_context,
+ .stop_context = ocxlflash_stop_context,
+ .afu_reset = ocxlflash_afu_reset,
+ .set_master = ocxlflash_set_master,
+ .get_context = ocxlflash_get_context,
+ .dev_context_init = ocxlflash_dev_context_init,
+ .release_context = ocxlflash_release_context,
+ .perst_reloads_same_image = ocxlflash_perst_reloads_same_image,
+ .read_adapter_vpd = ocxlflash_read_adapter_vpd,
+ .allocate_afu_irqs = ocxlflash_allocate_afu_irqs,
+ .free_afu_irqs = ocxlflash_free_afu_irqs,
+ .create_afu = ocxlflash_create_afu,
+ .destroy_afu = ocxlflash_destroy_afu,
+ .get_fd = ocxlflash_get_fd,
+ .fops_get_context = ocxlflash_fops_get_context,
+ .start_work = ocxlflash_start_work,
+ .fd_mmap = ocxlflash_fd_mmap,
+ .fd_release = ocxlflash_fd_release,
+};
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
new file mode 100644
index 0000000..9270d35
--- /dev/null
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -0,0 +1,77 @@
+/*
+ * CXL Flash Device Driver
+ *
+ * Written by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>, IBM Corporation
+ * Uma Krishnan <ukrishn@linux.vnet.ibm.com>, IBM Corporation
+ *
+ * Copyright (C) 2018 IBM 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.
+ */
+
+#define OCXL_MAX_IRQS 4 /* Max interrupts per process */
+
+struct ocxlflash_irqs {
+ int hwirq;
+ u32 virq;
+ u64 ptrig;
+ void __iomem *vtrig;
+};
+
+/* OCXL hardware AFU associated with the host */
+struct ocxl_hw_afu {
+ struct ocxlflash_context *ocxl_ctx; /* Host context */
+ struct pci_dev *pdev; /* PCI device */
+ struct device *dev; /* Generic device */
+ bool perst_same_image; /* Same image loaded on perst */
+
+ struct ocxl_fn_config fcfg; /* DVSEC config of the function */
+ struct ocxl_afu_config acfg; /* AFU configuration data */
+
+ int fn_actag_base; /* Function acTag base */
+ int fn_actag_enabled; /* Function acTag number enabled */
+ int afu_actag_base; /* AFU acTag base */
+ int afu_actag_enabled; /* AFU acTag number enabled */
+
+ phys_addr_t ppmmio_phys; /* Per process MMIO space */
+ phys_addr_t gmmio_phys; /* Global AFU MMIO space */
+ void __iomem *gmmio_virt; /* Global MMIO map */
+
+ void *link_token; /* Link token for the SPA */
+ struct idr idr; /* IDR to manage contexts */
+ int max_pasid; /* Maximum number of contexts */
+ bool is_present; /* Function has AFUs defined */
+};
+
+enum ocxlflash_ctx_state {
+ CLOSED,
+ OPENED,
+ STARTED
+};
+
+struct ocxlflash_context {
+ struct ocxl_hw_afu *hw_afu; /* HW AFU back pointer */
+ struct address_space *mapping; /* Mapping for pseudo filesystem */
+ bool master; /* Whether this is a master context */
+ int pe; /* Process element */
+
+ phys_addr_t psn_phys; /* Process mapping */
+ u64 psn_size; /* Process mapping size */
+
+ spinlock_t slock; /* Protects irq/fault/event updates */
+ wait_queue_head_t wq; /* Wait queue for poll and interrupts */
+ struct mutex state_mutex; /* Mutex to update context state */
+ enum ocxlflash_ctx_state state; /* Context state */
+
+ struct ocxlflash_irqs *irqs; /* Pointer to array of structures */
+ int num_irqs; /* Number of interrupts */
+ bool pending_irq; /* Pending interrupt on the context */
+ ulong irq_bitmap; /* Bits indicating pending irq num */
+
+ u64 fault_addr; /* Address that triggered the fault */
+ u64 fault_dsisr; /* Value of dsisr register at fault */
+ bool pending_fault; /* Pending translation fault */
+};
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index bedf1ce..874abce 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -258,23 +258,30 @@ struct sisl_host_map {
* exit since there is no way to tell which
* command caused the error.
*/
-#define SISL_ISTATUS_PERM_ERR_CMDROOM 0x0010ULL /* b59, user error */
-#define SISL_ISTATUS_PERM_ERR_RCB_READ 0x0008ULL /* b60, user error */
-#define SISL_ISTATUS_PERM_ERR_SA_WRITE 0x0004ULL /* b61, user error */
-#define SISL_ISTATUS_PERM_ERR_RRQ_WRITE 0x0002ULL /* b62, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_3_EA 0x0400ULL /* b53, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_2_EA 0x0200ULL /* b54, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_1_EA 0x0100ULL /* b55, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_3_PASID 0x0080ULL /* b56, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_2_PASID 0x0040ULL /* b57, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_1_PASID 0x0020ULL /* b58, user error */
+#define SISL_ISTATUS_PERM_ERR_CMDROOM 0x0010ULL /* b59, user error */
+#define SISL_ISTATUS_PERM_ERR_RCB_READ 0x0008ULL /* b60, user error */
+#define SISL_ISTATUS_PERM_ERR_SA_WRITE 0x0004ULL /* b61, user error */
+#define SISL_ISTATUS_PERM_ERR_RRQ_WRITE 0x0002ULL /* b62, user error */
/* Page in wait accessing RCB/IOASA/RRQ is reported in b63.
* Same error in data/LXT/RHT access is reported via IOASA.
*/
-#define SISL_ISTATUS_TEMP_ERR_PAGEIN 0x0001ULL /* b63, can be generated
- * only when AFU auto
- * retry is disabled.
- * If user can determine
- * the command that
- * caused the error, it
- * can be retried.
- */
-#define SISL_ISTATUS_UNMASK (0x001FULL) /* 1 means unmasked */
-#define SISL_ISTATUS_MASK ~(SISL_ISTATUS_UNMASK) /* 1 means masked */
+#define SISL_ISTATUS_TEMP_ERR_PAGEIN 0x0001ULL /* b63, can only be
+ * generated when AFU
+ * auto retry is
+ * disabled. If user
+ * can determine the
+ * command that caused
+ * the error, it can
+ * be retried.
+ */
+#define SISL_ISTATUS_UNMASK (0x07FFULL) /* 1 means unmasked */
+#define SISL_ISTATUS_MASK ~(SISL_ISTATUS_UNMASK) /* 1 means masked */
__be64 intr_clear;
__be64 intr_mask;
@@ -284,6 +291,7 @@ struct sisl_host_map {
__be64 cmd_room;
__be64 ctx_ctrl; /* least significant byte or b56:63 is LISN# */
#define SISL_CTX_CTRL_UNMAP_SECTOR 0x8000000000000000ULL /* b0 */
+#define SISL_CTX_CTRL_LISN_MASK (0xFFULL)
__be64 mbox_w; /* restricted use */
__be64 sq_start; /* Submission Queue (R/W): write sequence and */
__be64 sq_end; /* inclusion semantics are the same as RRQ */
@@ -309,6 +317,10 @@ struct sisl_ctrl_map {
#define SISL_CTX_CAP_WRITE_CMD 0x0000000000000002ULL /* afu_rc 0x21 */
#define SISL_CTX_CAP_READ_CMD 0x0000000000000001ULL /* afu_rc 0x21 */
__be64 mbox_r;
+ __be64 lisn_pasid[2];
+ /* pasid _a arg must be ULL */
+#define SISL_LISN_PASID(_a, _b) (((_a) << 32) | (_b))
+ __be64 lisn_ea[3];
};
/* single copy global regs */
@@ -415,6 +427,7 @@ struct sisl_global_regs {
#define SISL_INTVER_CAP_RESERVED_CMD_MODE_B 0x100000000000ULL
#define SISL_INTVER_CAP_LUN_PROVISION 0x080000000000ULL
#define SISL_INTVER_CAP_AFU_DEBUG 0x040000000000ULL
+#define SISL_INTVER_CAP_OCXL_LISN 0x020000000000ULL
};
#define CXLFLASH_NUM_FC_PORTS_PER_BANK 2 /* fixed # of ports per bank */
diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c
index 2fe79df..e489d89 100644
--- a/drivers/scsi/cxlflash/superpipe.c
+++ b/drivers/scsi/cxlflash/superpipe.c
@@ -14,8 +14,9 @@
#include <linux/delay.h>
#include <linux/file.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
#include <linux/syscalls.h>
-#include <misc/cxl.h>
#include <asm/unaligned.h>
#include <scsi/scsi.h>
@@ -269,6 +270,7 @@ static int afu_attach(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
int rc = 0;
struct hwq *hwq = get_hwq(afu, PRIMARY_HWQ);
u64 val;
+ int i;
/* Unlock cap and restrict user to read/write cmds in translated mode */
readq_be(&ctrl_map->mbox_r);
@@ -282,6 +284,19 @@ static int afu_attach(struct cxlflash_cfg *cfg, struct ctx_info *ctxi)
goto out;
}
+ if (afu_is_ocxl_lisn(afu)) {
+ /* Set up the LISN effective address for each interrupt */
+ for (i = 0; i < ctxi->irqs; i++) {
+ val = cfg->ops->get_irq_objhndl(ctxi->ctx, i);
+ writeq_be(val, &ctrl_map->lisn_ea[i]);
+ }
+
+ /* Use primary HWQ PASID as identifier for all interrupts */
+ val = hwq->ctx_hndl;
+ writeq_be(SISL_LISN_PASID(val, val), &ctrl_map->lisn_pasid[0]);
+ writeq_be(SISL_LISN_PASID(0UL, val), &ctrl_map->lisn_pasid[1]);
+ }
+
/* Set up MMIO registers pointing to the RHT */
writeq_be((u64)ctxi->rht_start, &ctrl_map->rht_start);
val = SISL_RHT_CNT_ID((u64)MAX_RHT_PER_CONTEXT, (u64)(hwq->ctx_hndl));
@@ -974,6 +989,10 @@ static int cxlflash_disk_detach(struct scsi_device *sdev,
* theoretically never occur), every call into this routine results
* in a complete freeing of a context.
*
+ * Detaching the LUN is typically an ioctl() operation and the underlying
+ * code assumes that ioctl_rwsem has been acquired as a reader. To support
+ * that design point, the semaphore is acquired and released around detach.
+ *
* Return: 0 on success
*/
static int cxlflash_cxl_release(struct inode *inode, struct file *file)
@@ -1012,9 +1031,11 @@ static int cxlflash_cxl_release(struct inode *inode, struct file *file)
dev_dbg(dev, "%s: close for ctxid=%d\n", __func__, ctxid);
+ down_read(&cfg->ioctl_rwsem);
detach.context_id = ctxi->ctxid;
list_for_each_entry_safe(lun_access, t, &ctxi->luns, list)
_cxlflash_disk_detach(lun_access->sdev, ctxi, &detach);
+ up_read(&cfg->ioctl_rwsem);
out_release:
cfg->ops->fd_release(inode, file);
out:
diff --git a/drivers/scsi/cxlflash/vlun.c b/drivers/scsi/cxlflash/vlun.c
index 5deef57..66e445a 100644
--- a/drivers/scsi/cxlflash/vlun.c
+++ b/drivers/scsi/cxlflash/vlun.c
@@ -12,8 +12,9 @@
* 2 of the License, or (at your option) any later version.
*/
+#include <linux/interrupt.h>
+#include <linux/pci.h>
#include <linux/syscalls.h>
-#include <misc/cxl.h>
#include <asm/unaligned.h>
#include <asm/bitsperlong.h>
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index 5ceea8d..37de8fb 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -1706,7 +1706,7 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
u32 reply_size = 0;
u32 __user *user_msg = arg;
u32 __user * user_reply = NULL;
- void *sg_list[pHba->sg_tablesize];
+ void **sg_list = NULL;
u32 sg_offset = 0;
u32 sg_count = 0;
int sg_index = 0;
@@ -1748,19 +1748,23 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
msg[2] = 0x40000000; // IOCTL context
msg[3] = adpt_ioctl_to_context(pHba, reply);
if (msg[3] == (u32)-1) {
- kfree(reply);
- return -EBUSY;
+ rcode = -EBUSY;
+ goto free;
}
- memset(sg_list,0, sizeof(sg_list[0])*pHba->sg_tablesize);
+ sg_list = kcalloc(pHba->sg_tablesize, sizeof(*sg_list), GFP_KERNEL);
+ if (!sg_list) {
+ rcode = -ENOMEM;
+ goto free;
+ }
if(sg_offset) {
// TODO add 64 bit API
struct sg_simple_element *sg = (struct sg_simple_element*) (msg+sg_offset);
sg_count = (size - sg_offset*4) / sizeof(struct sg_simple_element);
if (sg_count > pHba->sg_tablesize){
printk(KERN_DEBUG"%s:IOCTL SG List too large (%u)\n", pHba->name,sg_count);
- kfree (reply);
- return -EINVAL;
+ rcode = -EINVAL;
+ goto free;
}
for(i = 0; i < sg_count; i++) {
@@ -1879,7 +1883,6 @@ cleanup:
if (rcode != -ETIME && rcode != -EINTR) {
struct sg_simple_element *sg =
(struct sg_simple_element*) (msg +sg_offset);
- kfree (reply);
while(sg_index) {
if(sg_list[--sg_index]) {
dma_free_coherent(&pHba->pDev->dev,
@@ -1889,6 +1892,10 @@ cleanup:
}
}
}
+
+free:
+ kfree(sg_list);
+ kfree(reply);
return rcode;
}
diff --git a/drivers/scsi/esas2r/esas2r_init.c b/drivers/scsi/esas2r/esas2r_init.c
index 9dffcb2..bbe77db 100644
--- a/drivers/scsi/esas2r/esas2r_init.c
+++ b/drivers/scsi/esas2r/esas2r_init.c
@@ -833,7 +833,7 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a,
/* allocate requests for asynchronous events */
a->first_ae_req =
- kzalloc(num_ae_requests * sizeof(struct esas2r_request),
+ kcalloc(num_ae_requests, sizeof(struct esas2r_request),
GFP_KERNEL);
if (a->first_ae_req == NULL) {
@@ -843,8 +843,8 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a,
}
/* allocate the S/G list memory descriptors */
- a->sg_list_mds = kzalloc(
- num_sg_lists * sizeof(struct esas2r_mem_desc), GFP_KERNEL);
+ a->sg_list_mds = kcalloc(num_sg_lists, sizeof(struct esas2r_mem_desc),
+ GFP_KERNEL);
if (a->sg_list_mds == NULL) {
esas2r_log(ESAS2R_LOG_CRIT,
@@ -854,8 +854,9 @@ bool esas2r_init_adapter_struct(struct esas2r_adapter *a,
/* allocate the request table */
a->req_table =
- kzalloc((num_requests + num_ae_requests +
- 1) * sizeof(struct esas2r_request *), GFP_KERNEL);
+ kcalloc(num_requests + num_ae_requests + 1,
+ sizeof(struct esas2r_request *),
+ GFP_KERNEL);
if (a->req_table == NULL) {
esas2r_log(ESAS2R_LOG_CRIT,
@@ -1202,8 +1203,6 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a,
case ESAS2R_INIT_MSG_START:
case ESAS2R_INIT_MSG_REINIT:
{
- struct timeval now;
- do_gettimeofday(&now);
esas2r_hdebug("CFG init");
esas2r_build_cfg_req(a,
rq,
@@ -1212,7 +1211,8 @@ static bool esas2r_format_init_msg(struct esas2r_adapter *a,
NULL);
ci = (struct atto_vda_cfg_init *)&rq->vrq->cfg.data.init;
ci->sgl_page_size = cpu_to_le32(sgl_page_size);
- ci->epoch_time = cpu_to_le32(now.tv_sec);
+ /* firmware interface overflows in y2106 */
+ ci->epoch_time = cpu_to_le32(ktime_get_real_seconds());
rq->flags |= RF_FAILURE_OK;
a->init_msg = ESAS2R_INIT_MSG_INIT;
break;
diff --git a/drivers/scsi/esas2r/esas2r_ioctl.c b/drivers/scsi/esas2r/esas2r_ioctl.c
index 9762300..34bcc8c 100644
--- a/drivers/scsi/esas2r/esas2r_ioctl.c
+++ b/drivers/scsi/esas2r/esas2r_ioctl.c
@@ -1849,7 +1849,7 @@ int esas2r_read_vda(struct esas2r_adapter *a, char *buf, long off, int count)
/* allocate a request */
rq = esas2r_alloc_request(a);
if (rq == NULL) {
- esas2r_debug("esas2r_read_vda: out of requestss");
+ esas2r_debug("esas2r_read_vda: out of requests");
return -EBUSY;
}
diff --git a/drivers/scsi/esas2r/esas2r_main.c b/drivers/scsi/esas2r/esas2r_main.c
index e07eac5..c071186 100644
--- a/drivers/scsi/esas2r/esas2r_main.c
+++ b/drivers/scsi/esas2r/esas2r_main.c
@@ -283,7 +283,7 @@ MODULE_PARM_DESC(num_requests,
int num_ae_requests = 4;
module_param(num_ae_requests, int, 0);
MODULE_PARM_DESC(num_ae_requests,
- "Number of VDA asynchromous event requests. Default 4.");
+ "Number of VDA asynchronous event requests. Default 4.");
int cmd_per_lun = ESAS2R_DEFAULT_CMD_PER_LUN;
module_param(cmd_per_lun, int, 0);
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 097f37d..ea23c8d 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -1390,8 +1390,8 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
*/
num_vlink_desc = rlen / sizeof(*vp);
if (num_vlink_desc)
- vlink_desc_arr = kmalloc(sizeof(vp) * num_vlink_desc,
- GFP_ATOMIC);
+ vlink_desc_arr = kmalloc_array(num_vlink_desc, sizeof(vp),
+ GFP_ATOMIC);
if (!vlink_desc_arr)
return;
num_vlink_desc = 0;
diff --git a/drivers/scsi/fnic/fnic_debugfs.c b/drivers/scsi/fnic/fnic_debugfs.c
index 6d3e1cb..139fffa 100644
--- a/drivers/scsi/fnic/fnic_debugfs.c
+++ b/drivers/scsi/fnic/fnic_debugfs.c
@@ -233,8 +233,8 @@ static int fnic_trace_debugfs_open(struct inode *inode,
return -ENOMEM;
if (*rdata_ptr == fc_trc_flag->fnic_trace) {
- fnic_dbg_prt->buffer = vmalloc(3 *
- (trace_max_pages * PAGE_SIZE));
+ fnic_dbg_prt->buffer = vmalloc(array3_size(3, trace_max_pages,
+ PAGE_SIZE));
if (!fnic_dbg_prt->buffer) {
kfree(fnic_dbg_prt);
return -ENOMEM;
@@ -244,7 +244,8 @@ static int fnic_trace_debugfs_open(struct inode *inode,
fnic_dbg_prt->buffer_len = fnic_get_trace_data(fnic_dbg_prt);
} else {
fnic_dbg_prt->buffer =
- vmalloc(3 * (fnic_fc_trace_max_pages * PAGE_SIZE));
+ vmalloc(array3_size(3, fnic_fc_trace_max_pages,
+ PAGE_SIZE));
if (!fnic_dbg_prt->buffer) {
kfree(fnic_dbg_prt);
return -ENOMEM;
diff --git a/drivers/scsi/fnic/fnic_trace.c b/drivers/scsi/fnic/fnic_trace.c
index 98597b5..8271785 100644
--- a/drivers/scsi/fnic/fnic_trace.c
+++ b/drivers/scsi/fnic/fnic_trace.c
@@ -477,8 +477,9 @@ int fnic_trace_buf_init(void)
}
memset((void *)fnic_trace_buf_p, 0, (trace_max_pages * PAGE_SIZE));
- fnic_trace_entries.page_offset = vmalloc(fnic_max_trace_entries *
- sizeof(unsigned long));
+ fnic_trace_entries.page_offset =
+ vmalloc(array_size(fnic_max_trace_entries,
+ sizeof(unsigned long)));
if (!fnic_trace_entries.page_offset) {
printk(KERN_ERR PFX "Failed to allocate memory for"
" page_offset\n");
@@ -555,8 +556,9 @@ int fnic_fc_trace_init(void)
fc_trace_max_entries = (fnic_fc_trace_max_pages * PAGE_SIZE)/
FC_TRC_SIZE_BYTES;
- fnic_fc_ctlr_trace_buf_p = (unsigned long)vmalloc(
- fnic_fc_trace_max_pages * PAGE_SIZE);
+ fnic_fc_ctlr_trace_buf_p =
+ (unsigned long)vmalloc(array_size(PAGE_SIZE,
+ fnic_fc_trace_max_pages));
if (!fnic_fc_ctlr_trace_buf_p) {
pr_err("fnic: Failed to allocate memory for "
"FC Control Trace Buf\n");
@@ -568,8 +570,9 @@ int fnic_fc_trace_init(void)
fnic_fc_trace_max_pages * PAGE_SIZE);
/* Allocate memory for page offset */
- fc_trace_entries.page_offset = vmalloc(fc_trace_max_entries *
- sizeof(unsigned long));
+ fc_trace_entries.page_offset =
+ vmalloc(array_size(fc_trace_max_entries,
+ sizeof(unsigned long)));
if (!fc_trace_entries.page_offset) {
pr_err("fnic:Failed to allocate memory for page_offset\n");
if (fnic_fc_ctlr_trace_buf_p) {
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index d1153e8..7052a5d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -136,12 +136,14 @@ struct hisi_sas_phy {
struct hisi_sas_port *port;
struct asd_sas_phy sas_phy;
struct sas_identify identify;
+ struct completion *reset_completion;
+ spinlock_t lock;
u64 port_id; /* from hw */
- u64 dev_sas_addr;
u64 frame_rcvd_size;
u8 frame_rcvd[32];
u8 phy_attached;
- u8 reserved[3];
+ u8 in_reset;
+ u8 reserved[2];
u32 phy_type;
enum sas_linkrate minimum_linkrate;
enum sas_linkrate maximum_linkrate;
@@ -162,7 +164,7 @@ struct hisi_sas_cq {
struct hisi_sas_dq {
struct hisi_hba *hisi_hba;
- struct hisi_sas_slot *slot_prep;
+ struct list_head list;
spinlock_t lock;
int wr_point;
int id;
@@ -174,15 +176,22 @@ struct hisi_sas_device {
struct completion *completion;
struct hisi_sas_dq *dq;
struct list_head list;
- u64 attached_phy;
enum sas_device_type dev_type;
int device_id;
int sata_idx;
u8 dev_status;
};
+struct hisi_sas_tmf_task {
+ int force_phy;
+ int phy_id;
+ u8 tmf;
+ u16 tag_of_task_to_be_managed;
+};
+
struct hisi_sas_slot {
struct list_head entry;
+ struct list_head delivery;
struct sas_task *task;
struct hisi_sas_port *port;
u64 n_elem;
@@ -192,17 +201,15 @@ struct hisi_sas_slot {
int cmplt_queue_slot;
int idx;
int abort;
+ int ready;
void *buf;
dma_addr_t buf_dma;
void *cmd_hdr;
dma_addr_t cmd_hdr_dma;
struct work_struct abort_slot;
struct timer_list internal_abort_timer;
-};
-
-struct hisi_sas_tmf_task {
- u8 tmf;
- u16 tag_of_task_to_be_managed;
+ bool is_internal;
+ struct hisi_sas_tmf_task *tmf;
};
struct hisi_sas_hw {
@@ -215,14 +222,13 @@ struct hisi_sas_hw {
void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no);
int (*get_free_slot)(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq);
void (*start_delivery)(struct hisi_sas_dq *dq);
- int (*prep_ssp)(struct hisi_hba *hisi_hba,
- struct hisi_sas_slot *slot, int is_tmf,
- struct hisi_sas_tmf_task *tmf);
- int (*prep_smp)(struct hisi_hba *hisi_hba,
+ void (*prep_ssp)(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot);
+ void (*prep_smp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot);
- int (*prep_stp)(struct hisi_hba *hisi_hba,
+ void (*prep_stp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot);
- int (*prep_abort)(struct hisi_hba *hisi_hba,
+ void (*prep_abort)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot,
int device_id, int abort_flag, int tag_to_abort);
int (*slot_complete)(struct hisi_hba *hisi_hba,
@@ -245,8 +251,11 @@ struct hisi_sas_hw {
u32 (*get_phys_state)(struct hisi_hba *hisi_hba);
int (*write_gpio)(struct hisi_hba *hisi_hba, u8 reg_type,
u8 reg_index, u8 reg_count, u8 *write_data);
+ void (*wait_cmds_complete_timeout)(struct hisi_hba *hisi_hba,
+ int delay_ms, int timeout_ms);
int max_command_entries;
int complete_hdr_size;
+ struct scsi_host_template *sht;
};
struct hisi_hba {
@@ -273,6 +282,8 @@ struct hisi_hba {
struct workqueue_struct *wq;
int slot_index_count;
+ int last_slot_index;
+ int last_dev_id;
unsigned long *slot_index_tags;
unsigned long reject_stp_links_msk;
@@ -411,7 +422,7 @@ struct hisi_sas_command_table_ssp {
union {
struct {
struct ssp_command_iu task;
- u32 prot[6];
+ u32 prot[7];
};
struct ssp_tmf_iu ssp_task;
struct xfer_rdy_iu xfer_rdy;
@@ -437,10 +448,7 @@ struct hisi_sas_slot_buf_table {
};
extern struct scsi_transport_template *hisi_sas_stt;
-extern struct scsi_host_template *hisi_sas_sht;
-
extern void hisi_sas_stop_phys(struct hisi_hba *hisi_hba);
-extern void hisi_sas_init_add(struct hisi_hba *hisi_hba);
extern int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost);
extern void hisi_sas_free(struct hisi_hba *hisi_hba);
extern u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis,
@@ -454,6 +462,11 @@ extern int hisi_sas_probe(struct platform_device *pdev,
const struct hisi_sas_hw *ops);
extern int hisi_sas_remove(struct platform_device *pdev);
+extern int hisi_sas_slave_configure(struct scsi_device *sdev);
+extern int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time);
+extern void hisi_sas_scan_start(struct Scsi_Host *shost);
+extern struct device_attribute *host_attrs[];
+extern int hisi_sas_host_reset(struct Scsi_Host *shost, int reset_type);
extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy);
extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
struct sas_task *task,
@@ -465,4 +478,5 @@ extern void hisi_sas_kill_tasklets(struct hisi_hba *hisi_hba);
extern bool hisi_sas_notify_phy_event(struct hisi_sas_phy *phy,
enum hisi_sas_phy_event event);
extern void hisi_sas_release_tasks(struct hisi_hba *hisi_hba);
+extern u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max);
#endif
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 49c1fa6..6f56297 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -24,6 +24,9 @@ hisi_sas_internal_task_abort(struct hisi_hba *hisi_hba,
static int hisi_sas_softreset_ata_disk(struct domain_device *device);
static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
void *funcdata);
+static void hisi_sas_release_task(struct hisi_hba *hisi_hba,
+ struct domain_device *device);
+static void hisi_sas_dev_gone(struct domain_device *device);
u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
{
@@ -78,22 +81,23 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction)
case ATA_CMD_STANDBYNOW1:
case ATA_CMD_ZAC_MGMT_OUT:
return HISI_SAS_SATA_PROTOCOL_NONDATA;
+
+ case ATA_CMD_SET_MAX:
+ switch (fis->features) {
+ case ATA_SET_MAX_PASSWD:
+ case ATA_SET_MAX_LOCK:
+ return HISI_SAS_SATA_PROTOCOL_PIO;
+
+ case ATA_SET_MAX_PASSWD_DMA:
+ case ATA_SET_MAX_UNLOCK_DMA:
+ return HISI_SAS_SATA_PROTOCOL_DMA;
+
+ default:
+ return HISI_SAS_SATA_PROTOCOL_NONDATA;
+ }
+
default:
{
- if (fis->command == ATA_CMD_SET_MAX) {
- switch (fis->features) {
- case ATA_SET_MAX_PASSWD:
- case ATA_SET_MAX_LOCK:
- return HISI_SAS_SATA_PROTOCOL_PIO;
-
- case ATA_SET_MAX_PASSWD_DMA:
- case ATA_SET_MAX_UNLOCK_DMA:
- return HISI_SAS_SATA_PROTOCOL_DMA;
-
- default:
- return HISI_SAS_SATA_PROTOCOL_NONDATA;
- }
- }
if (direction == DMA_NONE)
return HISI_SAS_SATA_PROTOCOL_NONDATA;
return HISI_SAS_SATA_PROTOCOL_PIO;
@@ -134,6 +138,22 @@ int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag)
}
EXPORT_SYMBOL_GPL(hisi_sas_get_ncq_tag);
+/*
+ * This function assumes linkrate mask fits in 8 bits, which it
+ * does for all HW versions supported.
+ */
+u8 hisi_sas_get_prog_phy_linkrate_mask(enum sas_linkrate max)
+{
+ u16 rate = 0;
+ int i;
+
+ max -= SAS_LINK_RATE_1_5_GBPS;
+ for (i = 0; i <= max; i++)
+ rate |= 1 << (i * 2);
+ return rate;
+}
+EXPORT_SYMBOL_GPL(hisi_sas_get_prog_phy_linkrate_mask);
+
static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
{
return device->port->ha->lldd_ha;
@@ -178,11 +198,18 @@ static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, int *slot_idx)
unsigned int index;
void *bitmap = hisi_hba->slot_index_tags;
- index = find_first_zero_bit(bitmap, hisi_hba->slot_index_count);
- if (index >= hisi_hba->slot_index_count)
- return -SAS_QUEUE_FULL;
+ index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count,
+ hisi_hba->last_slot_index + 1);
+ if (index >= hisi_hba->slot_index_count) {
+ index = find_next_zero_bit(bitmap, hisi_hba->slot_index_count,
+ 0);
+ if (index >= hisi_hba->slot_index_count)
+ return -SAS_QUEUE_FULL;
+ }
hisi_sas_slot_index_set(hisi_hba, index);
*slot_idx = index;
+ hisi_hba->last_slot_index = index;
+
return 0;
}
@@ -197,6 +224,8 @@ static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba)
void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
struct hisi_sas_slot *slot)
{
+ struct hisi_sas_dq *dq = &hisi_hba->dq[slot->dlvry_queue];
+ unsigned long flags;
if (task) {
struct device *dev = hisi_hba->dev;
@@ -216,40 +245,43 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
if (slot->buf)
dma_pool_free(hisi_hba->buffer_pool, slot->buf, slot->buf_dma);
+ spin_lock_irqsave(&dq->lock, flags);
list_del_init(&slot->entry);
+ spin_unlock_irqrestore(&dq->lock, flags);
slot->buf = NULL;
slot->task = NULL;
slot->port = NULL;
+ spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_slot_index_free(hisi_hba, slot->idx);
+ spin_unlock_irqrestore(&hisi_hba->lock, flags);
/* slot memory is fully zeroed when it is reused */
}
EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
-static int hisi_sas_task_prep_smp(struct hisi_hba *hisi_hba,
+static void hisi_sas_task_prep_smp(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot)
{
- return hisi_hba->hw->prep_smp(hisi_hba, slot);
+ hisi_hba->hw->prep_smp(hisi_hba, slot);
}
-static int hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
- struct hisi_sas_slot *slot, int is_tmf,
- struct hisi_sas_tmf_task *tmf)
+static void hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
{
- return hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf);
+ hisi_hba->hw->prep_ssp(hisi_hba, slot);
}
-static int hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
+static void hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot)
{
- return hisi_hba->hw->prep_stp(hisi_hba, slot);
+ hisi_hba->hw->prep_stp(hisi_hba, slot);
}
-static int hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba,
+static void hisi_sas_task_prep_abort(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot,
int device_id, int abort_flag, int tag_to_abort)
{
- return hisi_hba->hw->prep_abort(hisi_hba, slot,
+ hisi_hba->hw->prep_abort(hisi_hba, slot,
device_id, abort_flag, tag_to_abort);
}
@@ -269,7 +301,6 @@ static void hisi_sas_slot_abort(struct work_struct *work)
struct scsi_lun lun;
struct device *dev = hisi_hba->dev;
int tag = abort_slot->idx;
- unsigned long flags;
if (!(task->task_proto & SAS_PROTOCOL_SSP)) {
dev_err(dev, "cannot abort slot for non-ssp task\n");
@@ -283,27 +314,29 @@ static void hisi_sas_slot_abort(struct work_struct *work)
hisi_sas_debug_issue_ssp_tmf(task->dev, lun.scsi_lun, &tmf_task);
out:
/* Do cleanup for this task */
- spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_slot_task_free(hisi_hba, task, abort_slot);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
if (task->task_done)
task->task_done(task);
}
-static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
- *dq, int is_tmf, struct hisi_sas_tmf_task *tmf,
- int *pass)
+static int hisi_sas_task_prep(struct sas_task *task,
+ struct hisi_sas_dq **dq_pointer,
+ bool is_tmf, struct hisi_sas_tmf_task *tmf,
+ int *pass)
{
- struct hisi_hba *hisi_hba = dq->hisi_hba;
struct domain_device *device = task->dev;
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_sas_port *port;
struct hisi_sas_slot *slot;
struct hisi_sas_cmd_hdr *cmd_hdr_base;
struct asd_sas_port *sas_port = device->port;
struct device *dev = hisi_hba->dev;
- int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
- unsigned long flags;
+ int dlvry_queue_slot, dlvry_queue, rc, slot_idx;
+ int n_elem = 0, n_elem_req = 0, n_elem_resp = 0;
+ unsigned long flags, flags_dq;
+ struct hisi_sas_dq *dq;
+ int wr_q_index;
if (!sas_port) {
struct task_status_struct *ts = &task->task_status;
@@ -330,6 +363,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
return -ECOMM;
}
+ *dq_pointer = dq = sas_dev->dq;
+
port = to_hisi_sas_port(sas_port);
if (port && !port->port_attached) {
dev_info(dev, "task prep: %s port%d not attach device\n",
@@ -341,6 +376,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
}
if (!sas_protocol_ata(task->task_proto)) {
+ unsigned int req_len, resp_len;
+
if (task->num_scatter) {
n_elem = dma_map_sg(dev, task->scatter,
task->num_scatter, task->data_dir);
@@ -348,31 +385,74 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
rc = -ENOMEM;
goto prep_out;
}
+ } else if (task->task_proto & SAS_PROTOCOL_SMP) {
+ n_elem_req = dma_map_sg(dev, &task->smp_task.smp_req,
+ 1, DMA_TO_DEVICE);
+ if (!n_elem_req) {
+ rc = -ENOMEM;
+ goto prep_out;
+ }
+ req_len = sg_dma_len(&task->smp_task.smp_req);
+ if (req_len & 0x3) {
+ rc = -EINVAL;
+ goto err_out_dma_unmap;
+ }
+ n_elem_resp = dma_map_sg(dev, &task->smp_task.smp_resp,
+ 1, DMA_FROM_DEVICE);
+ if (!n_elem_resp) {
+ rc = -ENOMEM;
+ goto err_out_dma_unmap;
+ }
+ resp_len = sg_dma_len(&task->smp_task.smp_resp);
+ if (resp_len & 0x3) {
+ rc = -EINVAL;
+ goto err_out_dma_unmap;
+ }
}
} else
n_elem = task->num_scatter;
+ if (n_elem > HISI_SAS_SGE_PAGE_CNT) {
+ dev_err(dev, "task prep: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
+ n_elem);
+ rc = -EINVAL;
+ goto err_out_dma_unmap;
+ }
+
spin_lock_irqsave(&hisi_hba->lock, flags);
if (hisi_hba->hw->slot_index_alloc)
rc = hisi_hba->hw->slot_index_alloc(hisi_hba, &slot_idx,
device);
else
rc = hisi_sas_slot_index_alloc(hisi_hba, &slot_idx);
- if (rc) {
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- goto err_out;
- }
spin_unlock_irqrestore(&hisi_hba->lock, flags);
-
- rc = hisi_hba->hw->get_free_slot(hisi_hba, dq);
if (rc)
- goto err_out_tag;
+ goto err_out_dma_unmap;
- dlvry_queue = dq->id;
- dlvry_queue_slot = dq->wr_point;
slot = &hisi_hba->slot_info[slot_idx];
memset(slot, 0, sizeof(struct hisi_sas_slot));
+ slot->buf = dma_pool_alloc(hisi_hba->buffer_pool,
+ GFP_ATOMIC, &slot->buf_dma);
+ if (!slot->buf) {
+ rc = -ENOMEM;
+ goto err_out_tag;
+ }
+
+ spin_lock_irqsave(&dq->lock, flags_dq);
+ wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq);
+ if (wr_q_index < 0) {
+ spin_unlock_irqrestore(&dq->lock, flags_dq);
+ rc = -EAGAIN;
+ goto err_out_buf;
+ }
+
+ list_add_tail(&slot->delivery, &dq->list);
+ spin_unlock_irqrestore(&dq->lock, flags_dq);
+
+ dlvry_queue = dq->id;
+ dlvry_queue_slot = wr_q_index;
+
slot->idx = slot_idx;
slot->n_elem = n_elem;
slot->dlvry_queue = dlvry_queue;
@@ -381,99 +461,94 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot];
slot->task = task;
slot->port = port;
+ slot->tmf = tmf;
+ slot->is_internal = is_tmf;
task->lldd_task = slot;
INIT_WORK(&slot->abort_slot, hisi_sas_slot_abort);
- slot->buf = dma_pool_alloc(hisi_hba->buffer_pool,
- GFP_ATOMIC, &slot->buf_dma);
- if (!slot->buf) {
- rc = -ENOMEM;
- goto err_out_slot_buf;
- }
memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr));
memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ);
memset(hisi_sas_status_buf_addr_mem(slot), 0, HISI_SAS_STATUS_BUF_SZ);
switch (task->task_proto) {
case SAS_PROTOCOL_SMP:
- rc = hisi_sas_task_prep_smp(hisi_hba, slot);
+ hisi_sas_task_prep_smp(hisi_hba, slot);
break;
case SAS_PROTOCOL_SSP:
- rc = hisi_sas_task_prep_ssp(hisi_hba, slot, is_tmf, tmf);
+ hisi_sas_task_prep_ssp(hisi_hba, slot);
break;
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
- rc = hisi_sas_task_prep_ata(hisi_hba, slot);
+ hisi_sas_task_prep_ata(hisi_hba, slot);
break;
default:
dev_err(dev, "task prep: unknown/unsupported proto (0x%x)\n",
task->task_proto);
- rc = -EINVAL;
break;
}
- if (rc) {
- dev_err(dev, "task prep: rc = 0x%x\n", rc);
- goto err_out_buf;
- }
-
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ spin_lock_irqsave(&dq->lock, flags);
list_add_tail(&slot->entry, &sas_dev->list);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
+ spin_unlock_irqrestore(&dq->lock, flags);
spin_lock_irqsave(&task->task_state_lock, flags);
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(&task->task_state_lock, flags);
- dq->slot_prep = slot;
++(*pass);
+ slot->ready = 1;
return 0;
err_out_buf:
dma_pool_free(hisi_hba->buffer_pool, slot->buf,
- slot->buf_dma);
-err_out_slot_buf:
- /* Nothing to be done */
+ slot->buf_dma);
err_out_tag:
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_slot_index_free(hisi_hba, slot_idx);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
-err_out:
- dev_err(dev, "task prep: failed[%d]!\n", rc);
- if (!sas_protocol_ata(task->task_proto))
- if (n_elem)
- dma_unmap_sg(dev, task->scatter,
- task->num_scatter,
- task->data_dir);
+err_out_dma_unmap:
+ if (!sas_protocol_ata(task->task_proto)) {
+ if (task->num_scatter) {
+ dma_unmap_sg(dev, task->scatter, task->num_scatter,
+ task->data_dir);
+ } else if (task->task_proto & SAS_PROTOCOL_SMP) {
+ if (n_elem_req)
+ dma_unmap_sg(dev, &task->smp_task.smp_req,
+ 1, DMA_TO_DEVICE);
+ if (n_elem_resp)
+ dma_unmap_sg(dev, &task->smp_task.smp_resp,
+ 1, DMA_FROM_DEVICE);
+ }
+ }
prep_out:
+ dev_err(dev, "task prep: failed[%d]!\n", rc);
return rc;
}
static int hisi_sas_task_exec(struct sas_task *task, gfp_t gfp_flags,
- int is_tmf, struct hisi_sas_tmf_task *tmf)
+ bool is_tmf, struct hisi_sas_tmf_task *tmf)
{
u32 rc;
u32 pass = 0;
unsigned long flags;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
struct device *dev = hisi_hba->dev;
- struct domain_device *device = task->dev;
- struct hisi_sas_device *sas_dev = device->lldd_dev;
- struct hisi_sas_dq *dq = sas_dev->dq;
+ struct hisi_sas_dq *dq = NULL;
if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags)))
return -EINVAL;
/* protect task_prep and start_delivery sequence */
- spin_lock_irqsave(&dq->lock, flags);
- rc = hisi_sas_task_prep(task, dq, is_tmf, tmf, &pass);
+ rc = hisi_sas_task_prep(task, &dq, is_tmf, tmf, &pass);
if (rc)
dev_err(dev, "task exec: failed[%d]!\n", rc);
- if (likely(pass))
+ if (likely(pass)) {
+ spin_lock_irqsave(&dq->lock, flags);
hisi_hba->hw->start_delivery(dq);
- spin_unlock_irqrestore(&dq->lock, flags);
+ spin_unlock_irqrestore(&dq->lock, flags);
+ }
return rc;
}
@@ -524,10 +599,12 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct hisi_sas_device *sas_dev = NULL;
unsigned long flags;
+ int last = hisi_hba->last_dev_id;
+ int first = (hisi_hba->last_dev_id + 1) % HISI_SAS_MAX_DEVICES;
int i;
spin_lock_irqsave(&hisi_hba->lock, flags);
- for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
+ for (i = first; i != last; i %= HISI_SAS_MAX_DEVICES) {
if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) {
int queue = i % hisi_hba->queue_count;
struct hisi_sas_dq *dq = &hisi_hba->dq[queue];
@@ -542,18 +619,57 @@ static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
INIT_LIST_HEAD(&hisi_hba->devices[i].list);
break;
}
+ i++;
}
+ hisi_hba->last_dev_id = i;
spin_unlock_irqrestore(&hisi_hba->lock, flags);
return sas_dev;
}
+#define HISI_SAS_SRST_ATA_DISK_CNT 3
+static int hisi_sas_init_device(struct domain_device *device)
+{
+ int rc = TMF_RESP_FUNC_COMPLETE;
+ struct scsi_lun lun;
+ struct hisi_sas_tmf_task tmf_task;
+ int retry = HISI_SAS_SRST_ATA_DISK_CNT;
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+
+ switch (device->dev_type) {
+ case SAS_END_DEVICE:
+ int_to_scsilun(0, &lun);
+
+ tmf_task.tmf = TMF_CLEAR_TASK_SET;
+ rc = hisi_sas_debug_issue_ssp_tmf(device, lun.scsi_lun,
+ &tmf_task);
+ if (rc == TMF_RESP_FUNC_COMPLETE)
+ hisi_sas_release_task(hisi_hba, device);
+ break;
+ case SAS_SATA_DEV:
+ case SAS_SATA_PM:
+ case SAS_SATA_PM_PORT:
+ case SAS_SATA_PENDING:
+ while (retry-- > 0) {
+ rc = hisi_sas_softreset_ata_disk(device);
+ if (!rc)
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
static int hisi_sas_dev_found(struct domain_device *device)
{
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct domain_device *parent_dev = device->parent;
struct hisi_sas_device *sas_dev;
struct device *dev = hisi_hba->dev;
+ int rc;
if (hisi_hba->hw->alloc_dev)
sas_dev = hisi_hba->hw->alloc_dev(device);
@@ -576,10 +692,8 @@ static int hisi_sas_dev_found(struct domain_device *device)
for (phy_no = 0; phy_no < phy_num; phy_no++) {
phy = &parent_dev->ex_dev.ex_phy[phy_no];
if (SAS_ADDR(phy->attached_sas_addr) ==
- SAS_ADDR(device->sas_addr)) {
- sas_dev->attached_phy = phy_no;
+ SAS_ADDR(device->sas_addr))
break;
- }
}
if (phy_no == phy_num) {
@@ -587,17 +701,25 @@ static int hisi_sas_dev_found(struct domain_device *device)
"dev:%016llx at ex:%016llx\n",
SAS_ADDR(device->sas_addr),
SAS_ADDR(parent_dev->sas_addr));
- return -EINVAL;
+ rc = -EINVAL;
+ goto err_out;
}
}
dev_info(dev, "dev[%d:%x] found\n",
sas_dev->device_id, sas_dev->dev_type);
+ rc = hisi_sas_init_device(device);
+ if (rc)
+ goto err_out;
return 0;
+
+err_out:
+ hisi_sas_dev_gone(device);
+ return rc;
}
-static int hisi_sas_slave_configure(struct scsi_device *sdev)
+int hisi_sas_slave_configure(struct scsi_device *sdev)
{
struct domain_device *dev = sdev_to_domain_dev(sdev);
int ret = sas_slave_configure(sdev);
@@ -609,15 +731,17 @@ static int hisi_sas_slave_configure(struct scsi_device *sdev)
return 0;
}
+EXPORT_SYMBOL_GPL(hisi_sas_slave_configure);
-static void hisi_sas_scan_start(struct Scsi_Host *shost)
+void hisi_sas_scan_start(struct Scsi_Host *shost)
{
struct hisi_hba *hisi_hba = shost_priv(shost);
hisi_hba->hw->phys_init(hisi_hba);
}
+EXPORT_SYMBOL_GPL(hisi_sas_scan_start);
-static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
+int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
{
struct hisi_hba *hisi_hba = shost_priv(shost);
struct sas_ha_struct *sha = &hisi_hba->sha;
@@ -629,6 +753,7 @@ static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
sas_drain_work(sha);
return 1;
}
+EXPORT_SYMBOL_GPL(hisi_sas_scan_finished);
static void hisi_sas_phyup_work(struct work_struct *work)
{
@@ -803,6 +928,33 @@ static int hisi_sas_queue_command(struct sas_task *task, gfp_t gfp_flags)
return hisi_sas_task_exec(task, gfp_flags, 0, NULL);
}
+static void hisi_sas_phy_set_linkrate(struct hisi_hba *hisi_hba, int phy_no,
+ struct sas_phy_linkrates *r)
+{
+ struct sas_phy_linkrates _r;
+
+ struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+ enum sas_linkrate min, max;
+
+ if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+ max = sas_phy->phy->maximum_linkrate;
+ min = r->minimum_linkrate;
+ } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) {
+ max = r->maximum_linkrate;
+ min = sas_phy->phy->minimum_linkrate;
+ } else
+ return;
+
+ _r.maximum_linkrate = max;
+ _r.minimum_linkrate = min;
+
+ hisi_hba->hw->phy_disable(hisi_hba, phy_no);
+ msleep(100);
+ hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, &_r);
+ hisi_hba->hw->phy_start(hisi_hba, phy_no);
+}
+
static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
void *funcdata)
{
@@ -826,7 +978,7 @@ static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func func,
break;
case PHY_FUNC_SET_LINK_RATE:
- hisi_hba->hw->phy_set_linkrate(hisi_hba, phy_no, funcdata);
+ hisi_sas_phy_set_linkrate(hisi_hba, phy_no, funcdata);
break;
case PHY_FUNC_GET_EVENTS:
if (hisi_hba->hw->get_events) {
@@ -990,7 +1142,6 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device)
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = hisi_hba->dev;
int s = sizeof(struct host_to_dev_fis);
- unsigned long flags;
ata_for_each_link(link, ap, EDGE) {
int pmp = sata_srst_pmp(link);
@@ -1015,11 +1166,8 @@ static int hisi_sas_softreset_ata_disk(struct domain_device *device)
dev_err(dev, "ata disk reset failed\n");
}
- if (rc == TMF_RESP_FUNC_COMPLETE) {
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ if (rc == TMF_RESP_FUNC_COMPLETE)
hisi_sas_release_task(hisi_hba, device);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- }
return rc;
}
@@ -1111,12 +1259,103 @@ static void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, u32 old_state,
}
}
+static void hisi_sas_reset_init_all_devices(struct hisi_hba *hisi_hba)
+{
+ struct hisi_sas_device *sas_dev;
+ struct domain_device *device;
+ int i;
+
+ for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
+ sas_dev = &hisi_hba->devices[i];
+ device = sas_dev->sas_device;
+
+ if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device)
+ continue;
+
+ hisi_sas_init_device(device);
+ }
+}
+
+static void hisi_sas_send_ata_reset_each_phy(struct hisi_hba *hisi_hba,
+ struct asd_sas_port *sas_port,
+ struct domain_device *device)
+{
+ struct hisi_sas_tmf_task tmf_task = { .force_phy = 1 };
+ struct ata_port *ap = device->sata_dev.ap;
+ struct device *dev = hisi_hba->dev;
+ int s = sizeof(struct host_to_dev_fis);
+ int rc = TMF_RESP_FUNC_FAILED;
+ struct asd_sas_phy *sas_phy;
+ struct ata_link *link;
+ u8 fis[20] = {0};
+ u32 state;
+
+ state = hisi_hba->hw->get_phys_state(hisi_hba);
+ list_for_each_entry(sas_phy, &sas_port->phy_list, port_phy_el) {
+ if (!(state & BIT(sas_phy->id)))
+ continue;
+
+ ata_for_each_link(link, ap, EDGE) {
+ int pmp = sata_srst_pmp(link);
+
+ tmf_task.phy_id = sas_phy->id;
+ hisi_sas_fill_ata_reset_cmd(link->device, 1, pmp, fis);
+ rc = hisi_sas_exec_internal_tmf_task(device, fis, s,
+ &tmf_task);
+ if (rc != TMF_RESP_FUNC_COMPLETE) {
+ dev_err(dev, "phy%d ata reset failed rc=%d\n",
+ sas_phy->id, rc);
+ break;
+ }
+ }
+ }
+}
+
+static void hisi_sas_terminate_stp_reject(struct hisi_hba *hisi_hba)
+{
+ struct device *dev = hisi_hba->dev;
+ int port_no, rc, i;
+
+ for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
+ struct hisi_sas_device *sas_dev = &hisi_hba->devices[i];
+ struct domain_device *device = sas_dev->sas_device;
+
+ if ((sas_dev->dev_type == SAS_PHY_UNUSED) || !device)
+ continue;
+
+ rc = hisi_sas_internal_task_abort(hisi_hba, device,
+ HISI_SAS_INT_ABT_DEV, 0);
+ if (rc < 0)
+ dev_err(dev, "STP reject: abort dev failed %d\n", rc);
+ }
+
+ for (port_no = 0; port_no < hisi_hba->n_phy; port_no++) {
+ struct hisi_sas_port *port = &hisi_hba->port[port_no];
+ struct asd_sas_port *sas_port = &port->sas_port;
+ struct domain_device *port_dev = sas_port->port_dev;
+ struct domain_device *device;
+
+ if (!port_dev || !DEV_IS_EXPANDER(port_dev->dev_type))
+ continue;
+
+ /* Try to find a SATA device */
+ list_for_each_entry(device, &sas_port->dev_list,
+ dev_list_node) {
+ if (dev_is_sata(device)) {
+ hisi_sas_send_ata_reset_each_phy(hisi_hba,
+ sas_port,
+ device);
+ break;
+ }
+ }
+ }
+}
+
static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
struct Scsi_Host *shost = hisi_hba->shost;
u32 old_state, state;
- unsigned long flags;
int rc;
if (!hisi_hba->hw->soft_reset)
@@ -1129,6 +1368,11 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
old_state = hisi_hba->hw->get_phys_state(hisi_hba);
scsi_block_requests(shost);
+ hisi_hba->hw->wait_cmds_complete_timeout(hisi_hba, 100, 5000);
+
+ if (timer_pending(&hisi_hba->timer))
+ del_timer_sync(&hisi_hba->timer);
+
set_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
rc = hisi_hba->hw->soft_reset(hisi_hba);
if (rc) {
@@ -1137,9 +1381,6 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
scsi_unblock_requests(shost);
goto out;
}
- spin_lock_irqsave(&hisi_hba->lock, flags);
- hisi_sas_release_tasks(hisi_hba);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
@@ -1147,6 +1388,10 @@ static int hisi_sas_controller_reset(struct hisi_hba *hisi_hba)
hisi_hba->hw->phys_init(hisi_hba);
msleep(1000);
hisi_sas_refresh_port_id(hisi_hba);
+
+ if (hisi_hba->reject_stp_links_msk)
+ hisi_sas_terminate_stp_reject(hisi_hba);
+ hisi_sas_reset_init_all_devices(hisi_hba);
scsi_unblock_requests(shost);
state = hisi_hba->hw->get_phys_state(hisi_hba);
@@ -1165,20 +1410,25 @@ static int hisi_sas_abort_task(struct sas_task *task)
struct hisi_sas_tmf_task tmf_task;
struct domain_device *device = task->dev;
struct hisi_sas_device *sas_dev = device->lldd_dev;
- struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
- struct device *dev = hisi_hba->dev;
+ struct hisi_hba *hisi_hba;
+ struct device *dev;
int rc = TMF_RESP_FUNC_FAILED;
unsigned long flags;
- if (!sas_dev) {
- dev_warn(dev, "Device has been removed\n");
+ if (!sas_dev)
return TMF_RESP_FUNC_FAILED;
- }
+ hisi_hba = dev_to_hisi_hba(task->dev);
+ dev = hisi_hba->dev;
+
+ spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
rc = TMF_RESP_FUNC_COMPLETE;
goto out;
}
+ task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
sas_dev->dev_status = HISI_SAS_DEV_EH;
if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
@@ -1209,11 +1459,8 @@ static int hisi_sas_abort_task(struct sas_task *task)
* will have already been completed
*/
if (rc == TMF_RESP_FUNC_COMPLETE && rc2 != TMF_RESP_FUNC_SUCC) {
- if (task->lldd_task) {
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ if (task->lldd_task)
hisi_sas_do_release_task(hisi_hba, task, slot);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- }
}
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
task->task_proto & SAS_PROTOCOL_STP) {
@@ -1235,11 +1482,8 @@ static int hisi_sas_abort_task(struct sas_task *task)
rc = hisi_sas_internal_task_abort(hisi_hba, device,
HISI_SAS_INT_ABT_CMD, tag);
if (((rc < 0) || (rc == TMF_RESP_FUNC_FAILED)) &&
- task->lldd_task) {
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ task->lldd_task)
hisi_sas_do_release_task(hisi_hba, task, slot);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- }
}
out:
@@ -1254,7 +1498,6 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)
struct device *dev = hisi_hba->dev;
struct hisi_sas_tmf_task tmf_task;
int rc = TMF_RESP_FUNC_FAILED;
- unsigned long flags;
rc = hisi_sas_internal_task_abort(hisi_hba, device,
HISI_SAS_INT_ABT_DEV, 0);
@@ -1267,11 +1510,8 @@ static int hisi_sas_abort_task_set(struct domain_device *device, u8 *lun)
tmf_task.tmf = TMF_ABORT_TASK_SET;
rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
- if (rc == TMF_RESP_FUNC_COMPLETE) {
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ if (rc == TMF_RESP_FUNC_COMPLETE)
hisi_sas_release_task(hisi_hba, device);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- }
return rc;
}
@@ -1289,12 +1529,39 @@ static int hisi_sas_clear_aca(struct domain_device *device, u8 *lun)
static int hisi_sas_debug_I_T_nexus_reset(struct domain_device *device)
{
- struct sas_phy *phy = sas_get_local_phy(device);
+ struct sas_phy *local_phy = sas_get_local_phy(device);
int rc, reset_type = (device->dev_type == SAS_SATA_DEV ||
(device->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
- rc = sas_phy_reset(phy, reset_type);
- sas_put_local_phy(phy);
- msleep(2000);
+ struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+ struct sas_ha_struct *sas_ha = &hisi_hba->sha;
+ struct asd_sas_phy *sas_phy = sas_ha->sas_phy[local_phy->number];
+ struct hisi_sas_phy *phy = container_of(sas_phy,
+ struct hisi_sas_phy, sas_phy);
+ DECLARE_COMPLETION_ONSTACK(phyreset);
+
+ if (scsi_is_sas_phy_local(local_phy)) {
+ phy->in_reset = 1;
+ phy->reset_completion = &phyreset;
+ }
+
+ rc = sas_phy_reset(local_phy, reset_type);
+ sas_put_local_phy(local_phy);
+
+ if (scsi_is_sas_phy_local(local_phy)) {
+ int ret = wait_for_completion_timeout(&phyreset, 2 * HZ);
+ unsigned long flags;
+
+ spin_lock_irqsave(&phy->lock, flags);
+ phy->reset_completion = NULL;
+ phy->in_reset = 0;
+ spin_unlock_irqrestore(&phy->lock, flags);
+
+ /* report PHY down if timed out */
+ if (!ret)
+ hisi_sas_phy_down(hisi_hba, sas_phy->id, 0);
+ } else
+ msleep(2000);
+
return rc;
}
@@ -1304,7 +1571,6 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = hisi_hba->dev;
int rc = TMF_RESP_FUNC_FAILED;
- unsigned long flags;
if (sas_dev->dev_status != HISI_SAS_DEV_EH)
return TMF_RESP_FUNC_FAILED;
@@ -1320,11 +1586,9 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device *device)
rc = hisi_sas_debug_I_T_nexus_reset(device);
- if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV)) {
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ if ((rc == TMF_RESP_FUNC_COMPLETE) || (rc == -ENODEV))
hisi_sas_release_task(hisi_hba, device);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- }
+
return rc;
}
@@ -1333,7 +1597,6 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = hisi_hba->dev;
- unsigned long flags;
int rc = TMF_RESP_FUNC_FAILED;
sas_dev->dev_status = HISI_SAS_DEV_EH;
@@ -1353,11 +1616,8 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
rc = sas_phy_reset(phy, 1);
- if (rc == 0) {
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ if (rc == 0)
hisi_sas_release_task(hisi_hba, device);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- }
sas_put_local_phy(phy);
} else {
struct hisi_sas_tmf_task tmf_task = { .tmf = TMF_LU_RESET };
@@ -1371,11 +1631,8 @@ static int hisi_sas_lu_reset(struct domain_device *device, u8 *lun)
hisi_sas_dereg_device(hisi_hba, device);
rc = hisi_sas_debug_issue_ssp_tmf(device, lun, &tmf_task);
- if (rc == TMF_RESP_FUNC_COMPLETE) {
- spin_lock_irqsave(&hisi_hba->lock, flags);
+ if (rc == TMF_RESP_FUNC_COMPLETE)
hisi_sas_release_task(hisi_hba, device);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- }
}
out:
if (rc != TMF_RESP_FUNC_COMPLETE)
@@ -1445,7 +1702,8 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
struct hisi_sas_cmd_hdr *cmd_hdr_base;
struct hisi_sas_dq *dq = sas_dev->dq;
int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
- unsigned long flags, flags_dq;
+ unsigned long flags, flags_dq = 0;
+ int wr_q_index;
if (unlikely(test_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags)))
return -EINVAL;
@@ -1464,16 +1722,28 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
}
spin_unlock_irqrestore(&hisi_hba->lock, flags);
- spin_lock_irqsave(&dq->lock, flags_dq);
- rc = hisi_hba->hw->get_free_slot(hisi_hba, dq);
- if (rc)
+ slot = &hisi_hba->slot_info[slot_idx];
+ memset(slot, 0, sizeof(struct hisi_sas_slot));
+
+ slot->buf = dma_pool_alloc(hisi_hba->buffer_pool,
+ GFP_ATOMIC, &slot->buf_dma);
+ if (!slot->buf) {
+ rc = -ENOMEM;
goto err_out_tag;
+ }
- dlvry_queue = dq->id;
- dlvry_queue_slot = dq->wr_point;
+ spin_lock_irqsave(&dq->lock, flags_dq);
+ wr_q_index = hisi_hba->hw->get_free_slot(hisi_hba, dq);
+ if (wr_q_index < 0) {
+ spin_unlock_irqrestore(&dq->lock, flags_dq);
+ rc = -EAGAIN;
+ goto err_out_buf;
+ }
+ list_add_tail(&slot->delivery, &dq->list);
+ spin_unlock_irqrestore(&dq->lock, flags_dq);
- slot = &hisi_hba->slot_info[slot_idx];
- memset(slot, 0, sizeof(struct hisi_sas_slot));
+ dlvry_queue = dq->id;
+ dlvry_queue_slot = wr_q_index;
slot->idx = slot_idx;
slot->n_elem = n_elem;
@@ -1483,47 +1753,36 @@ hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
slot->cmd_hdr = &cmd_hdr_base[dlvry_queue_slot];
slot->task = task;
slot->port = port;
+ slot->is_internal = true;
task->lldd_task = slot;
- slot->buf = dma_pool_alloc(hisi_hba->buffer_pool,
- GFP_ATOMIC, &slot->buf_dma);
- if (!slot->buf) {
- rc = -ENOMEM;
- goto err_out_tag;
- }
-
memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr));
memset(hisi_sas_cmd_hdr_addr_mem(slot), 0, HISI_SAS_COMMAND_TABLE_SZ);
memset(hisi_sas_status_buf_addr_mem(slot), 0, HISI_SAS_STATUS_BUF_SZ);
- rc = hisi_sas_task_prep_abort(hisi_hba, slot, device_id,
+ hisi_sas_task_prep_abort(hisi_hba, slot, device_id,
abort_flag, task_tag);
- if (rc)
- goto err_out_buf;
- spin_lock_irqsave(&hisi_hba->lock, flags);
- list_add_tail(&slot->entry, &sas_dev->list);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
spin_lock_irqsave(&task->task_state_lock, flags);
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(&task->task_state_lock, flags);
- dq->slot_prep = slot;
-
+ slot->ready = 1;
/* send abort command to the chip */
+ spin_lock_irqsave(&dq->lock, flags);
+ list_add_tail(&slot->entry, &sas_dev->list);
hisi_hba->hw->start_delivery(dq);
- spin_unlock_irqrestore(&dq->lock, flags_dq);
+ spin_unlock_irqrestore(&dq->lock, flags);
return 0;
err_out_buf:
dma_pool_free(hisi_hba->buffer_pool, slot->buf,
- slot->buf_dma);
+ slot->buf_dma);
err_out_tag:
spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_slot_index_free(hisi_hba, slot_idx);
spin_unlock_irqrestore(&hisi_hba->lock, flags);
- spin_unlock_irqrestore(&dq->lock, flags_dq);
err_out:
dev_err(dev, "internal abort task prep: failed[%d]!\n", rc);
@@ -1651,6 +1910,7 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy)
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
struct sas_ha_struct *sas_ha = &hisi_hba->sha;
+ struct device *dev = hisi_hba->dev;
if (rdy) {
/* Phy down but ready */
@@ -1659,6 +1919,10 @@ void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy)
} else {
struct hisi_sas_port *port = phy->port;
+ if (phy->in_reset) {
+ dev_info(dev, "ignore flutter phy%d down\n", phy_no);
+ return;
+ }
/* Phy down and not ready */
sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL);
sas_phy_disconnected(sas_phy);
@@ -1693,34 +1957,11 @@ EXPORT_SYMBOL_GPL(hisi_sas_kill_tasklets);
struct scsi_transport_template *hisi_sas_stt;
EXPORT_SYMBOL_GPL(hisi_sas_stt);
-static struct device_attribute *host_attrs[] = {
+struct device_attribute *host_attrs[] = {
&dev_attr_phy_event_threshold,
NULL,
};
-
-static struct scsi_host_template _hisi_sas_sht = {
- .module = THIS_MODULE,
- .name = DRV_NAME,
- .queuecommand = sas_queuecommand,
- .target_alloc = sas_target_alloc,
- .slave_configure = hisi_sas_slave_configure,
- .scan_finished = hisi_sas_scan_finished,
- .scan_start = hisi_sas_scan_start,
- .change_queue_depth = sas_change_queue_depth,
- .bios_param = sas_bios_param,
- .can_queue = 1,
- .this_id = -1,
- .sg_tablesize = SG_ALL,
- .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
- .use_clustering = ENABLE_CLUSTERING,
- .eh_device_reset_handler = sas_eh_device_reset_handler,
- .eh_target_reset_handler = sas_eh_target_reset_handler,
- .target_destroy = sas_target_destroy,
- .ioctl = sas_ioctl,
- .shost_attrs = host_attrs,
-};
-struct scsi_host_template *hisi_sas_sht = &_hisi_sas_sht;
-EXPORT_SYMBOL_GPL(hisi_sas_sht);
+EXPORT_SYMBOL_GPL(host_attrs);
static struct sas_domain_function_template hisi_sas_transport_ops = {
.lldd_dev_found = hisi_sas_dev_found,
@@ -1798,6 +2039,7 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
/* Delivery queue structure */
spin_lock_init(&dq->lock);
+ INIT_LIST_HEAD(&dq->list);
dq->id = i;
dq->hisi_hba = hisi_hba;
@@ -1822,13 +2064,11 @@ int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
goto err_out;
s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
- hisi_hba->itct = dma_alloc_coherent(dev, s, &hisi_hba->itct_dma,
+ hisi_hba->itct = dma_zalloc_coherent(dev, s, &hisi_hba->itct_dma,
GFP_KERNEL);
if (!hisi_hba->itct)
goto err_out;
- memset(hisi_hba->itct, 0, s);
-
hisi_hba->slot_info = devm_kcalloc(dev, max_command_entries,
sizeof(struct hisi_sas_slot),
GFP_KERNEL);
@@ -2031,7 +2271,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
struct hisi_hba *hisi_hba;
struct device *dev = &pdev->dev;
- shost = scsi_host_alloc(hisi_sas_sht, sizeof(*hisi_hba));
+ shost = scsi_host_alloc(hw->sht, sizeof(*hisi_hba));
if (!shost) {
dev_err(dev, "scsi host alloc failed\n");
return NULL;
@@ -2080,19 +2320,8 @@ err_out:
return NULL;
}
-void hisi_sas_init_add(struct hisi_hba *hisi_hba)
-{
- int i;
-
- for (i = 0; i < hisi_hba->n_phy; i++)
- memcpy(&hisi_hba->phy[i].dev_sas_addr,
- hisi_hba->sas_addr,
- SAS_ADDR_SIZE);
-}
-EXPORT_SYMBOL_GPL(hisi_sas_init_add);
-
int hisi_sas_probe(struct platform_device *pdev,
- const struct hisi_sas_hw *hw)
+ const struct hisi_sas_hw *hw)
{
struct Scsi_Host *shost;
struct hisi_hba *hisi_hba;
@@ -2144,8 +2373,6 @@ int hisi_sas_probe(struct platform_device *pdev,
sha->sas_port[i] = &hisi_hba->port[i].sas_port;
}
- hisi_sas_init_add(hisi_hba);
-
rc = scsi_add_host(shost, &pdev->dev);
if (rc)
goto err_out_ha;
@@ -2177,6 +2404,9 @@ int hisi_sas_remove(struct platform_device *pdev)
struct hisi_hba *hisi_hba = sha->lldd_ha;
struct Scsi_Host *shost = sha->core.shost;
+ if (timer_pending(&hisi_hba->timer))
+ del_timer(&hisi_hba->timer);
+
sas_unregister_ha(sha);
sas_remove_host(sha->core.shost);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 84a0ccc..89ab18c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -855,39 +855,12 @@ static enum sas_linkrate phy_get_max_linkrate_v1_hw(void)
static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no,
struct sas_phy_linkrates *r)
{
- u32 prog_phy_link_rate =
- hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE);
- struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
- struct asd_sas_phy *sas_phy = &phy->sas_phy;
- int i;
- enum sas_linkrate min, max;
- u32 rate_mask = 0;
-
- if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
- max = sas_phy->phy->maximum_linkrate;
- min = r->minimum_linkrate;
- } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) {
- max = r->maximum_linkrate;
- min = sas_phy->phy->minimum_linkrate;
- } else
- return;
-
- sas_phy->phy->maximum_linkrate = max;
- sas_phy->phy->minimum_linkrate = min;
-
- max -= SAS_LINK_RATE_1_5_GBPS;
+ enum sas_linkrate max = r->maximum_linkrate;
+ u32 prog_phy_link_rate = 0x800;
- for (i = 0; i <= max; i++)
- rate_mask |= 1 << (i * 2);
-
- prog_phy_link_rate &= ~0xff;
- prog_phy_link_rate |= rate_mask;
-
- disable_phy_v1_hw(hisi_hba, phy_no);
- msleep(100);
+ prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
- prog_phy_link_rate);
- start_phy_v1_hw(hisi_hba, phy_no);
+ prog_phy_link_rate);
}
static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id)
@@ -921,37 +894,45 @@ get_free_slot_v1_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
return -EAGAIN;
}
- return 0;
+ dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
+
+ return w;
}
+/* DQ lock must be taken here */
static void start_delivery_v1_hw(struct hisi_sas_dq *dq)
{
struct hisi_hba *hisi_hba = dq->hisi_hba;
- int dlvry_queue = dq->slot_prep->dlvry_queue;
- int dlvry_queue_slot = dq->slot_prep->dlvry_queue_slot;
+ struct hisi_sas_slot *s, *s1;
+ struct list_head *dq_list;
+ int dlvry_queue = dq->id;
+ int wp, count = 0;
+
+ dq_list = &dq->list;
+ list_for_each_entry_safe(s, s1, &dq->list, delivery) {
+ if (!s->ready)
+ break;
+ count++;
+ wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
+ list_del(&s->delivery);
+ }
- dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
- hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
- dq->wr_point);
+ if (!count)
+ return;
+
+ hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
}
-static int prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba,
+static void prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot,
struct hisi_sas_cmd_hdr *hdr,
struct scatterlist *scatter,
int n_elem)
{
struct hisi_sas_sge_page *sge_page = hisi_sas_sge_addr_mem(slot);
- struct device *dev = hisi_hba->dev;
struct scatterlist *sg;
int i;
- if (n_elem > HISI_SAS_SGE_PAGE_CNT) {
- dev_err(dev, "prd err: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
- n_elem);
- return -EINVAL;
- }
-
for_each_sg(scatter, sg, n_elem, i) {
struct hisi_sas_sge *entry = &sge_page->sge[i];
@@ -964,48 +945,25 @@ static int prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba,
hdr->prd_table_addr = cpu_to_le64(hisi_sas_sge_addr_dma(slot));
hdr->sg_len = cpu_to_le32(n_elem << CMD_HDR_DATA_SGL_LEN_OFF);
-
- return 0;
}
-static int prep_smp_v1_hw(struct hisi_hba *hisi_hba,
+static void prep_smp_v1_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
struct domain_device *device = task->dev;
- struct device *dev = hisi_hba->dev;
struct hisi_sas_port *port = slot->port;
- struct scatterlist *sg_req, *sg_resp;
+ struct scatterlist *sg_req;
struct hisi_sas_device *sas_dev = device->lldd_dev;
dma_addr_t req_dma_addr;
- unsigned int req_len, resp_len;
- int elem, rc;
+ unsigned int req_len;
- /*
- * DMA-map SMP request, response buffers
- */
/* req */
sg_req = &task->smp_task.smp_req;
- elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE);
- if (!elem)
- return -ENOMEM;
req_len = sg_dma_len(sg_req);
req_dma_addr = sg_dma_address(sg_req);
- /* resp */
- sg_resp = &task->smp_task.smp_resp;
- elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE);
- if (!elem) {
- rc = -ENOMEM;
- goto err_out_req;
- }
- resp_len = sg_dma_len(sg_resp);
- if ((req_len & 0x3) || (resp_len & 0x3)) {
- rc = -EINVAL;
- goto err_out_resp;
- }
-
/* create header */
/* dw0 */
hdr->dw0 = cpu_to_le32((port->id << CMD_HDR_PORT_OFF) |
@@ -1025,21 +983,10 @@ static int prep_smp_v1_hw(struct hisi_hba *hisi_hba,
hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
-
- return 0;
-
-err_out_resp:
- dma_unmap_sg(dev, &slot->task->smp_task.smp_resp, 1,
- DMA_FROM_DEVICE);
-err_out_req:
- dma_unmap_sg(dev, &slot->task->smp_task.smp_req, 1,
- DMA_TO_DEVICE);
- return rc;
}
-static int prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
- struct hisi_sas_slot *slot, int is_tmf,
- struct hisi_sas_tmf_task *tmf)
+static void prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
@@ -1048,7 +995,8 @@ static int prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_port *port = slot->port;
struct sas_ssp_task *ssp_task = &task->ssp_task;
struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
- int has_data = 0, rc, priority = is_tmf;
+ struct hisi_sas_tmf_task *tmf = slot->tmf;
+ int has_data = 0, priority = !!tmf;
u8 *buf_cmd, fburst = 0;
u32 dw1, dw2;
@@ -1062,7 +1010,7 @@ static int prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
dw1 = 1 << CMD_HDR_VERIFY_DTL_OFF;
- if (is_tmf) {
+ if (tmf) {
dw1 |= 3 << CMD_HDR_SSP_FRAME_TYPE_OFF;
} else {
switch (scsi_cmnd->sc_data_direction) {
@@ -1083,7 +1031,7 @@ static int prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
dw1 |= sas_dev->device_id << CMD_HDR_DEVICE_ID_OFF;
hdr->dw1 = cpu_to_le32(dw1);
- if (is_tmf) {
+ if (tmf) {
dw2 = ((sizeof(struct ssp_tmf_iu) +
sizeof(struct ssp_frame_hdr)+3)/4) <<
CMD_HDR_CFL_OFF;
@@ -1097,12 +1045,9 @@ static int prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
hdr->transfer_tags = cpu_to_le32(slot->idx << CMD_HDR_IPTT_OFF);
- if (has_data) {
- rc = prep_prd_sge_v1_hw(hisi_hba, slot, hdr, task->scatter,
+ if (has_data)
+ prep_prd_sge_v1_hw(hisi_hba, slot, hdr, task->scatter,
slot->n_elem);
- if (rc)
- return rc;
- }
hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
@@ -1117,7 +1062,7 @@ static int prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
hdr->dw2 = cpu_to_le32(dw2);
memcpy(buf_cmd, &task->ssp_task.LUN, 8);
- if (!is_tmf) {
+ if (!tmf) {
buf_cmd[9] = fburst | task->ssp_task.task_attr |
(task->ssp_task.task_prio << 3);
memcpy(buf_cmd + 12, task->ssp_task.cmd->cmnd,
@@ -1136,8 +1081,6 @@ static int prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
break;
}
}
-
- return 0;
}
/* by default, task resp is complete */
@@ -1430,6 +1373,7 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p)
u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd;
struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd;
irqreturn_t res = IRQ_HANDLED;
+ unsigned long flags;
irq_value = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2);
if (!(irq_value & CHL_INT2_SL_PHY_ENA_MSK)) {
@@ -1483,6 +1427,13 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p)
SAS_PROTOCOL_SMP;
hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
+ spin_lock_irqsave(&phy->lock, flags);
+ if (phy->reset_completion) {
+ phy->in_reset = 0;
+ complete(phy->reset_completion);
+ }
+ spin_unlock_irqrestore(&phy->lock, flags);
+
end:
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
CHL_INT2_SL_PHY_ENA_MSK);
@@ -1845,6 +1796,28 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba)
return 0;
}
+static struct scsi_host_template sht_v1_hw = {
+ .name = DRV_NAME,
+ .module = THIS_MODULE,
+ .queuecommand = sas_queuecommand,
+ .target_alloc = sas_target_alloc,
+ .slave_configure = hisi_sas_slave_configure,
+ .scan_finished = hisi_sas_scan_finished,
+ .scan_start = hisi_sas_scan_start,
+ .change_queue_depth = sas_change_queue_depth,
+ .bios_param = sas_bios_param,
+ .can_queue = 1,
+ .this_id = -1,
+ .sg_tablesize = SG_ALL,
+ .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
+ .use_clustering = ENABLE_CLUSTERING,
+ .eh_device_reset_handler = sas_eh_device_reset_handler,
+ .eh_target_reset_handler = sas_eh_target_reset_handler,
+ .target_destroy = sas_target_destroy,
+ .ioctl = sas_ioctl,
+ .shost_attrs = host_attrs,
+};
+
static const struct hisi_sas_hw hisi_sas_v1_hw = {
.hw_init = hisi_sas_v1_init,
.setup_itct = setup_itct_v1_hw,
@@ -1864,6 +1837,7 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = {
.get_wideport_bitmap = get_wideport_bitmap_v1_hw,
.max_command_entries = HISI_SAS_COMMAND_ENTRIES_V1_HW,
.complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr),
+ .sht = &sht_v1_hw,
};
static int hisi_sas_v1_probe(struct platform_device *pdev)
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index f89fb9a..213c530 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -144,6 +144,7 @@
#define SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF 19
#define SAS_ECC_INTR_MSK 0x1ec
#define HGC_ERR_STAT_EN 0x238
+#define CQE_SEND_CNT 0x248
#define DLVRY_Q_0_BASE_ADDR_LO 0x260
#define DLVRY_Q_0_BASE_ADDR_HI 0x264
#define DLVRY_Q_0_DEPTH 0x268
@@ -295,6 +296,10 @@
#define CMD_HDR_RESP_REPORT_MSK (0x1 << CMD_HDR_RESP_REPORT_OFF)
#define CMD_HDR_TLR_CTRL_OFF 6
#define CMD_HDR_TLR_CTRL_MSK (0x3 << CMD_HDR_TLR_CTRL_OFF)
+#define CMD_HDR_PHY_ID_OFF 8
+#define CMD_HDR_PHY_ID_MSK (0x1ff << CMD_HDR_PHY_ID_OFF)
+#define CMD_HDR_FORCE_PHY_OFF 17
+#define CMD_HDR_FORCE_PHY_MSK (0x1 << CMD_HDR_FORCE_PHY_OFF)
#define CMD_HDR_PORT_OFF 18
#define CMD_HDR_PORT_MSK (0xf << CMD_HDR_PORT_OFF)
#define CMD_HDR_PRIORITY_OFF 27
@@ -1216,7 +1221,22 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba)
}
for (i = 0; i < hisi_hba->n_phy; i++) {
- hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855);
+ struct hisi_sas_phy *phy = &hisi_hba->phy[i];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+ u32 prog_phy_link_rate = 0x800;
+
+ if (!sas_phy->phy || (sas_phy->phy->maximum_linkrate <
+ SAS_LINK_RATE_1_5_GBPS)) {
+ prog_phy_link_rate = 0x855;
+ } else {
+ enum sas_linkrate max = sas_phy->phy->maximum_linkrate;
+
+ prog_phy_link_rate =
+ hisi_sas_get_prog_phy_linkrate_mask(max) |
+ 0x800;
+ }
+ hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE,
+ prog_phy_link_rate);
hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, sas_phy_ctrl);
hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d);
hisi_sas_phy_write32(hisi_hba, i, SL_CONTROL, 0x0);
@@ -1585,39 +1605,12 @@ static enum sas_linkrate phy_get_max_linkrate_v2_hw(void)
static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no,
struct sas_phy_linkrates *r)
{
- u32 prog_phy_link_rate =
- hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE);
- struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
- struct asd_sas_phy *sas_phy = &phy->sas_phy;
- int i;
- enum sas_linkrate min, max;
- u32 rate_mask = 0;
-
- if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
- max = sas_phy->phy->maximum_linkrate;
- min = r->minimum_linkrate;
- } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) {
- max = r->maximum_linkrate;
- min = sas_phy->phy->minimum_linkrate;
- } else
- return;
-
- sas_phy->phy->maximum_linkrate = max;
- sas_phy->phy->minimum_linkrate = min;
-
- max -= SAS_LINK_RATE_1_5_GBPS;
-
- for (i = 0; i <= max; i++)
- rate_mask |= 1 << (i * 2);
-
- prog_phy_link_rate &= ~0xff;
- prog_phy_link_rate |= rate_mask;
+ enum sas_linkrate max = r->maximum_linkrate;
+ u32 prog_phy_link_rate = 0x800;
- disable_phy_v2_hw(hisi_hba, phy_no);
- msleep(100);
+ prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
- prog_phy_link_rate);
- start_phy_v2_hw(hisi_hba, phy_no);
+ prog_phy_link_rate);
}
static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id)
@@ -1658,42 +1651,50 @@ get_free_slot_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
r = hisi_sas_read32_relaxed(hisi_hba,
DLVRY_Q_0_RD_PTR + (queue * 0x14));
if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
- dev_warn(dev, "full queue=%d r=%d w=%d\n\n",
+ dev_warn(dev, "full queue=%d r=%d w=%d\n",
queue, r, w);
return -EAGAIN;
}
- return 0;
+ dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
+
+ return w;
}
+/* DQ lock must be taken here */
static void start_delivery_v2_hw(struct hisi_sas_dq *dq)
{
struct hisi_hba *hisi_hba = dq->hisi_hba;
- int dlvry_queue = dq->slot_prep->dlvry_queue;
- int dlvry_queue_slot = dq->slot_prep->dlvry_queue_slot;
+ struct hisi_sas_slot *s, *s1;
+ struct list_head *dq_list;
+ int dlvry_queue = dq->id;
+ int wp, count = 0;
+
+ dq_list = &dq->list;
+ list_for_each_entry_safe(s, s1, &dq->list, delivery) {
+ if (!s->ready)
+ break;
+ count++;
+ wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
+ list_del(&s->delivery);
+ }
+
+ if (!count)
+ return;
- dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
- hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
- dq->wr_point);
+ hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
}
-static int prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
+static void prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot,
struct hisi_sas_cmd_hdr *hdr,
struct scatterlist *scatter,
int n_elem)
{
struct hisi_sas_sge_page *sge_page = hisi_sas_sge_addr_mem(slot);
- struct device *dev = hisi_hba->dev;
struct scatterlist *sg;
int i;
- if (n_elem > HISI_SAS_SGE_PAGE_CNT) {
- dev_err(dev, "prd err: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
- n_elem);
- return -EINVAL;
- }
-
for_each_sg(scatter, sg, n_elem, i) {
struct hisi_sas_sge *entry = &sge_page->sge[i];
@@ -1706,47 +1707,24 @@ static int prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
hdr->prd_table_addr = cpu_to_le64(hisi_sas_sge_addr_dma(slot));
hdr->sg_len = cpu_to_le32(n_elem << CMD_HDR_DATA_SGL_LEN_OFF);
-
- return 0;
}
-static int prep_smp_v2_hw(struct hisi_hba *hisi_hba,
+static void prep_smp_v2_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
struct domain_device *device = task->dev;
- struct device *dev = hisi_hba->dev;
struct hisi_sas_port *port = slot->port;
- struct scatterlist *sg_req, *sg_resp;
+ struct scatterlist *sg_req;
struct hisi_sas_device *sas_dev = device->lldd_dev;
dma_addr_t req_dma_addr;
- unsigned int req_len, resp_len;
- int elem, rc;
+ unsigned int req_len;
- /*
- * DMA-map SMP request, response buffers
- */
/* req */
sg_req = &task->smp_task.smp_req;
- elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE);
- if (!elem)
- return -ENOMEM;
- req_len = sg_dma_len(sg_req);
req_dma_addr = sg_dma_address(sg_req);
-
- /* resp */
- sg_resp = &task->smp_task.smp_resp;
- elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE);
- if (!elem) {
- rc = -ENOMEM;
- goto err_out_req;
- }
- resp_len = sg_dma_len(sg_resp);
- if ((req_len & 0x3) || (resp_len & 0x3)) {
- rc = -EINVAL;
- goto err_out_resp;
- }
+ req_len = sg_dma_len(&task->smp_task.smp_req);
/* create header */
/* dw0 */
@@ -1768,21 +1746,10 @@ static int prep_smp_v2_hw(struct hisi_hba *hisi_hba,
hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
-
- return 0;
-
-err_out_resp:
- dma_unmap_sg(dev, &slot->task->smp_task.smp_resp, 1,
- DMA_FROM_DEVICE);
-err_out_req:
- dma_unmap_sg(dev, &slot->task->smp_task.smp_req, 1,
- DMA_TO_DEVICE);
- return rc;
}
-static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
- struct hisi_sas_slot *slot, int is_tmf,
- struct hisi_sas_tmf_task *tmf)
+static void prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
@@ -1791,7 +1758,8 @@ static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_port *port = slot->port;
struct sas_ssp_task *ssp_task = &task->ssp_task;
struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
- int has_data = 0, rc, priority = is_tmf;
+ struct hisi_sas_tmf_task *tmf = slot->tmf;
+ int has_data = 0, priority = !!tmf;
u8 *buf_cmd;
u32 dw1 = 0, dw2 = 0;
@@ -1802,7 +1770,7 @@ static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
(1 << CMD_HDR_CMD_OFF)); /* ssp */
dw1 = 1 << CMD_HDR_VDTL_OFF;
- if (is_tmf) {
+ if (tmf) {
dw1 |= 2 << CMD_HDR_FRAME_TYPE_OFF;
dw1 |= DIR_NO_DATA << CMD_HDR_DIR_OFF;
} else {
@@ -1833,12 +1801,9 @@ static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
hdr->transfer_tags = cpu_to_le32(slot->idx);
- if (has_data) {
- rc = prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
+ if (has_data)
+ prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
slot->n_elem);
- if (rc)
- return rc;
- }
hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
@@ -1848,7 +1813,7 @@ static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
sizeof(struct ssp_frame_hdr);
memcpy(buf_cmd, &task->ssp_task.LUN, 8);
- if (!is_tmf) {
+ if (!tmf) {
buf_cmd[9] = task->ssp_task.task_attr |
(task->ssp_task.task_prio << 3);
memcpy(buf_cmd + 12, task->ssp_task.cmd->cmnd,
@@ -1867,8 +1832,6 @@ static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
break;
}
}
-
- return 0;
}
#define TRANS_TX_ERR 0
@@ -2380,23 +2343,24 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
struct device *dev = hisi_hba->dev;
struct task_status_struct *ts;
struct domain_device *device;
+ struct sas_ha_struct *ha;
enum exec_status sts;
struct hisi_sas_complete_v2_hdr *complete_queue =
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v2_hdr *complete_hdr =
&complete_queue[slot->cmplt_queue_slot];
unsigned long flags;
- int aborted;
+ bool is_internal = slot->is_internal;
if (unlikely(!task || !task->lldd_task || !task->dev))
return -EINVAL;
ts = &task->task_status;
device = task->dev;
+ ha = device->port->ha;
sas_dev = device->lldd_dev;
spin_lock_irqsave(&task->task_state_lock, flags);
- aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED;
task->task_state_flags &=
~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
spin_unlock_irqrestore(&task->task_state_lock, flags);
@@ -2404,15 +2368,6 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
memset(ts, 0, sizeof(*ts));
ts->resp = SAS_TASK_COMPLETE;
- if (unlikely(aborted)) {
- dev_dbg(dev, "slot_complete: task(%p) aborted\n", task);
- ts->stat = SAS_ABORTED_TASK;
- spin_lock_irqsave(&hisi_hba->lock, flags);
- hisi_sas_slot_task_free(hisi_hba, task, slot);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- return ts->stat;
- }
-
if (unlikely(!sas_dev)) {
dev_dbg(dev, "slot complete: port has no device\n");
ts->stat = SAS_PHY_DOWN;
@@ -2459,10 +2414,10 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
slot_err_v2_hw(hisi_hba, task, slot, 2);
if (ts->stat != SAS_DATA_UNDERRUN)
- dev_info(dev, "erroneous completion iptt=%d task=%p "
+ dev_info(dev, "erroneous completion iptt=%d task=%p dev id=%d "
"CQ hdr: 0x%x 0x%x 0x%x 0x%x "
"Error info: 0x%x 0x%x 0x%x 0x%x\n",
- slot->idx, task,
+ slot->idx, task, sas_dev->device_id,
complete_hdr->dw0, complete_hdr->dw1,
complete_hdr->act, complete_hdr->dw3,
error_info[0], error_info[1],
@@ -2523,13 +2478,27 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
}
out:
+ hisi_sas_slot_task_free(hisi_hba, task, slot);
+ sts = ts->stat;
spin_lock_irqsave(&task->task_state_lock, flags);
+ if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+ dev_info(dev, "slot complete: task(%p) aborted\n", task);
+ return SAS_ABORTED_TASK;
+ }
task->task_state_flags |= SAS_TASK_STATE_DONE;
spin_unlock_irqrestore(&task->task_state_lock, flags);
- spin_lock_irqsave(&hisi_hba->lock, flags);
- hisi_sas_slot_task_free(hisi_hba, task, slot);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- sts = ts->stat;
+
+ if (!is_internal && (task->task_proto != SAS_PROTOCOL_SMP)) {
+ spin_lock_irqsave(&device->done_lock, flags);
+ if (test_bit(SAS_HA_FROZEN, &ha->state)) {
+ spin_unlock_irqrestore(&device->done_lock, flags);
+ dev_info(dev, "slot complete: task(%p) ignored\n ",
+ task);
+ return sts;
+ }
+ spin_unlock_irqrestore(&device->done_lock, flags);
+ }
if (task->task_done)
task->task_done(task);
@@ -2537,7 +2506,7 @@ out:
return sts;
}
-static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
+static void prep_ata_v2_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
@@ -2547,8 +2516,9 @@ static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
struct asd_sas_port *sas_port = device->port;
struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
+ struct hisi_sas_tmf_task *tmf = slot->tmf;
u8 *buf_cmd;
- int has_data = 0, rc = 0, hdr_tag = 0;
+ int has_data = 0, hdr_tag = 0;
u32 dw1 = 0, dw2 = 0;
/* create header */
@@ -2559,6 +2529,12 @@ static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
else
hdr->dw0 |= cpu_to_le32(4 << CMD_HDR_CMD_OFF);
+ if (tmf && tmf->force_phy) {
+ hdr->dw0 |= CMD_HDR_FORCE_PHY_MSK;
+ hdr->dw0 |= cpu_to_le32((1 << tmf->phy_id)
+ << CMD_HDR_PHY_ID_OFF);
+ }
+
/* dw1 */
switch (task->data_dir) {
case DMA_TO_DEVICE:
@@ -2596,12 +2572,9 @@ static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
/* dw3 */
hdr->transfer_tags = cpu_to_le32(slot->idx);
- if (has_data) {
- rc = prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
+ if (has_data)
+ prep_prd_sge_v2_hw(hisi_hba, slot, hdr, task->scatter,
slot->n_elem);
- if (rc)
- return rc;
- }
hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
@@ -2613,8 +2586,6 @@ static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */
/* fill in command FIS */
memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis));
-
- return 0;
}
static void hisi_sas_internal_abort_quirk_timeout(struct timer_list *t)
@@ -2651,7 +2622,7 @@ static void hisi_sas_internal_abort_quirk_timeout(struct timer_list *t)
}
}
-static int prep_abort_v2_hw(struct hisi_hba *hisi_hba,
+static void prep_abort_v2_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot,
int device_id, int abort_flag, int tag_to_abort)
{
@@ -2679,8 +2650,6 @@ static int prep_abort_v2_hw(struct hisi_hba *hisi_hba,
/* dw7 */
hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF);
hdr->transfer_tags = cpu_to_le32(slot->idx);
-
- return 0;
}
static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
@@ -2692,6 +2661,7 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
struct device *dev = hisi_hba->dev;
u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd;
struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd;
+ unsigned long flags;
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
@@ -2744,6 +2714,12 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
set_link_timer_quirk(hisi_hba);
}
hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
+ spin_lock_irqsave(&phy->lock, flags);
+ if (phy->reset_completion) {
+ phy->in_reset = 0;
+ complete(phy->reset_completion);
+ }
+ spin_unlock_irqrestore(&phy->lock, flags);
end:
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
@@ -3151,14 +3127,12 @@ static void cq_tasklet_v2_hw(unsigned long val)
struct hisi_sas_complete_v2_hdr *complete_queue;
u32 rd_point = cq->rd_point, wr_point, dev_id;
int queue = cq->id;
- struct hisi_sas_dq *dq = &hisi_hba->dq[queue];
if (unlikely(hisi_hba->reject_stp_links_msk))
phys_try_accept_stp_links_v2_hw(hisi_hba);
complete_queue = hisi_hba->complete_hdr[queue];
- spin_lock(&dq->lock);
wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
(0x14 * queue));
@@ -3208,7 +3182,6 @@ static void cq_tasklet_v2_hw(unsigned long val)
/* update rd_point */
cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
- spin_unlock(&dq->lock);
}
static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
@@ -3235,6 +3208,7 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
u32 ent_tmp, ent_msk, ent_int, port_id, link_rate, hard_phy_linkrate;
irqreturn_t res = IRQ_HANDLED;
u8 attached_sas_addr[SAS_ADDR_SIZE] = {0};
+ unsigned long flags;
int phy_no, offset;
phy_no = sas_phy->id;
@@ -3295,6 +3269,7 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
sas_phy->oob_mode = SATA_OOB_MODE;
/* Make up some unique SAS address */
attached_sas_addr[0] = 0x50;
+ attached_sas_addr[6] = hisi_hba->shost->host_no;
attached_sas_addr[7] = phy_no;
memcpy(sas_phy->attached_sas_addr, attached_sas_addr, SAS_ADDR_SIZE);
memcpy(sas_phy->frame_rcvd, fis, sizeof(struct dev_to_host_fis));
@@ -3308,6 +3283,12 @@ static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
+ spin_lock_irqsave(&phy->lock, flags);
+ if (phy->reset_completion) {
+ phy->in_reset = 0;
+ complete(phy->reset_completion);
+ }
+ spin_unlock_irqrestore(&phy->lock, flags);
end:
hisi_sas_write32(hisi_hba, ENT_INT_SRC1 + offset, ent_tmp);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1 + offset, ent_msk);
@@ -3546,6 +3527,46 @@ static int write_gpio_v2_hw(struct hisi_hba *hisi_hba, u8 reg_type,
return 0;
}
+static void wait_cmds_complete_timeout_v2_hw(struct hisi_hba *hisi_hba,
+ int delay_ms, int timeout_ms)
+{
+ struct device *dev = hisi_hba->dev;
+ int entries, entries_old = 0, time;
+
+ for (time = 0; time < timeout_ms; time += delay_ms) {
+ entries = hisi_sas_read32(hisi_hba, CQE_SEND_CNT);
+ if (entries == entries_old)
+ break;
+
+ entries_old = entries;
+ msleep(delay_ms);
+ }
+
+ dev_dbg(dev, "wait commands complete %dms\n", time);
+}
+
+static struct scsi_host_template sht_v2_hw = {
+ .name = DRV_NAME,
+ .module = THIS_MODULE,
+ .queuecommand = sas_queuecommand,
+ .target_alloc = sas_target_alloc,
+ .slave_configure = hisi_sas_slave_configure,
+ .scan_finished = hisi_sas_scan_finished,
+ .scan_start = hisi_sas_scan_start,
+ .change_queue_depth = sas_change_queue_depth,
+ .bios_param = sas_bios_param,
+ .can_queue = 1,
+ .this_id = -1,
+ .sg_tablesize = SG_ALL,
+ .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
+ .use_clustering = ENABLE_CLUSTERING,
+ .eh_device_reset_handler = sas_eh_device_reset_handler,
+ .eh_target_reset_handler = sas_eh_target_reset_handler,
+ .target_destroy = sas_target_destroy,
+ .ioctl = sas_ioctl,
+ .shost_attrs = host_attrs,
+};
+
static const struct hisi_sas_hw hisi_sas_v2_hw = {
.hw_init = hisi_sas_v2_init,
.setup_itct = setup_itct_v2_hw,
@@ -3574,6 +3595,8 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
.soft_reset = soft_reset_v2_hw,
.get_phys_state = get_phys_state_v2_hw,
.write_gpio = write_gpio_v2_hw,
+ .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v2_hw,
+ .sht = &sht_v2_hw,
};
static int hisi_sas_v2_probe(struct platform_device *pdev)
@@ -3598,9 +3621,6 @@ static int hisi_sas_v2_remove(struct platform_device *pdev)
struct sas_ha_struct *sha = platform_get_drvdata(pdev);
struct hisi_hba *hisi_hba = sha->lldd_ha;
- if (timer_pending(&hisi_hba->timer))
- del_timer(&hisi_hba->timer);
-
hisi_sas_kill_tasklets(hisi_hba);
return hisi_sas_remove(pdev);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 6f3e5ba..9f1e2d0 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -92,6 +92,7 @@
#define SAS_ECC_INTR 0x1e8
#define SAS_ECC_INTR_MSK 0x1ec
#define HGC_ERR_STAT_EN 0x238
+#define CQE_SEND_CNT 0x248
#define DLVRY_Q_0_BASE_ADDR_LO 0x260
#define DLVRY_Q_0_BASE_ADDR_HI 0x264
#define DLVRY_Q_0_DEPTH 0x268
@@ -106,6 +107,11 @@
#define COMPL_Q_0_RD_PTR 0x4f0
#define AWQOS_AWCACHE_CFG 0xc84
#define ARQOS_ARCACHE_CFG 0xc88
+#define HILINK_ERR_DFX 0xe04
+#define SAS_GPIO_CFG_0 0x1000
+#define SAS_GPIO_CFG_1 0x1004
+#define SAS_GPIO_TX_0_1 0x1040
+#define SAS_CFG_DRIVE_VLD 0x1070
/* phy registers requiring init */
#define PORT_BASE (0x2000)
@@ -167,6 +173,7 @@
#define CHL_INT1_DMAC_RX_AXI_RD_ERR_OFF 22
#define CHL_INT2 (PORT_BASE + 0x1bc)
#define CHL_INT2_SL_IDAF_TOUT_CONF_OFF 0
+#define CHL_INT2_RX_INVLD_DW_OFF 30
#define CHL_INT2_STP_LINK_TIMEOUT_OFF 31
#define CHL_INT0_MSK (PORT_BASE + 0x1c0)
#define CHL_INT1_MSK (PORT_BASE + 0x1c4)
@@ -216,6 +223,9 @@
#define SAS_RAS_INTR1 (RAS_BASE + 0x04)
#define SAS_RAS_INTR0_MASK (RAS_BASE + 0x08)
#define SAS_RAS_INTR1_MASK (RAS_BASE + 0x0c)
+#define CFG_SAS_RAS_INTR_MASK (RAS_BASE + 0x1c)
+#define SAS_RAS_INTR2 (RAS_BASE + 0x20)
+#define SAS_RAS_INTR2_MASK (RAS_BASE + 0x24)
/* HW dma structures */
/* Delivery queue header */
@@ -348,10 +358,11 @@ struct hisi_sas_err_record_v3 {
#define DIR_TO_DEVICE 2
#define DIR_RESERVED 3
-#define CMD_IS_UNCONSTRAINT(cmd) \
- ((cmd == ATA_CMD_READ_LOG_EXT) || \
- (cmd == ATA_CMD_READ_LOG_DMA_EXT) || \
- (cmd == ATA_CMD_DEV_RESET))
+#define FIS_CMD_IS_UNCONSTRAINED(fis) \
+ ((fis.command == ATA_CMD_READ_LOG_EXT) || \
+ (fis.command == ATA_CMD_READ_LOG_DMA_EXT) || \
+ ((fis.command == ATA_CMD_DEV_RESET) && \
+ ((fis.control & ATA_SRST) != 0)))
static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
{
@@ -390,8 +401,23 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
return readl(regs);
}
+#define hisi_sas_read32_poll_timeout(off, val, cond, delay_us, \
+ timeout_us) \
+({ \
+ void __iomem *regs = hisi_hba->regs + off; \
+ readl_poll_timeout(regs, val, cond, delay_us, timeout_us); \
+})
+
+#define hisi_sas_read32_poll_timeout_atomic(off, val, cond, delay_us, \
+ timeout_us) \
+({ \
+ void __iomem *regs = hisi_hba->regs + off; \
+ readl_poll_timeout_atomic(regs, val, cond, delay_us, timeout_us);\
+})
+
static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
{
+ struct pci_dev *pdev = hisi_hba->pci_dev;
int i;
/* Global registers init */
@@ -409,7 +435,10 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_write32(hisi_hba, ENT_INT_SRC3, 0xffffffff);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, 0xfefefefe);
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK2, 0xfefefefe);
- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xfffe20ff);
+ if (pdev->revision >= 0x21)
+ hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xffff7fff);
+ else
+ hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, 0xfffe20ff);
hisi_sas_write32(hisi_hba, CHNL_PHYUPDOWN_INT_MSK, 0x0);
hisi_sas_write32(hisi_hba, CHNL_ENT_INT_MSK, 0x0);
hisi_sas_write32(hisi_hba, HGC_COM_INT_MSK, 0x0);
@@ -422,13 +451,33 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1);
for (i = 0; i < hisi_hba->n_phy; i++) {
- hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855);
+ struct hisi_sas_phy *phy = &hisi_hba->phy[i];
+ struct asd_sas_phy *sas_phy = &phy->sas_phy;
+ u32 prog_phy_link_rate = 0x800;
+
+ if (!sas_phy->phy || (sas_phy->phy->maximum_linkrate <
+ SAS_LINK_RATE_1_5_GBPS)) {
+ prog_phy_link_rate = 0x855;
+ } else {
+ enum sas_linkrate max = sas_phy->phy->maximum_linkrate;
+
+ prog_phy_link_rate =
+ hisi_sas_get_prog_phy_linkrate_mask(max) |
+ 0x800;
+ }
+ hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE,
+ prog_phy_link_rate);
hisi_sas_phy_write32(hisi_hba, i, SAS_RX_TRAIN_TIMER, 0x13e80);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT0, 0xffffffff);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT1, 0xffffffff);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2, 0xffffffff);
hisi_sas_phy_write32(hisi_hba, i, RXOP_CHECK_CFG_H, 0x1000);
- hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK, 0xff87ffff);
+ if (pdev->revision >= 0x21)
+ hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK,
+ 0xffffffff);
+ else
+ hisi_sas_phy_write32(hisi_hba, i, CHL_INT1_MSK,
+ 0xff87ffff);
hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0xffffbfe);
hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL_RDY_MSK, 0x0);
hisi_sas_phy_write32(hisi_hba, i, PHYCTRL_NOT_RDY_MSK, 0x0);
@@ -503,6 +552,16 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
/* RAS registers init */
hisi_sas_write32(hisi_hba, SAS_RAS_INTR0_MASK, 0x0);
hisi_sas_write32(hisi_hba, SAS_RAS_INTR1_MASK, 0x0);
+ hisi_sas_write32(hisi_hba, SAS_RAS_INTR2_MASK, 0x0);
+ hisi_sas_write32(hisi_hba, CFG_SAS_RAS_INTR_MASK, 0x0);
+
+ /* LED registers init */
+ hisi_sas_write32(hisi_hba, SAS_CFG_DRIVE_VLD, 0x80000ff);
+ hisi_sas_write32(hisi_hba, SAS_GPIO_TX_0_1, 0x80808080);
+ hisi_sas_write32(hisi_hba, SAS_GPIO_TX_0_1 + 0x4, 0x80808080);
+ /* Configure blink generator rate A to 1Hz and B to 4Hz */
+ hisi_sas_write32(hisi_hba, SAS_GPIO_CFG_1, 0x121700);
+ hisi_sas_write32(hisi_hba, SAS_GPIO_CFG_0, 0x800000);
}
static void config_phy_opt_mode_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
@@ -654,8 +713,8 @@ static int reset_hw_v3_hw(struct hisi_hba *hisi_hba)
udelay(50);
/* Ensure axi bus idle */
- ret = readl_poll_timeout(hisi_hba->regs + AXI_CFG, val, !val,
- 20000, 1000000);
+ ret = hisi_sas_read32_poll_timeout(AXI_CFG, val, !val,
+ 20000, 1000000);
if (ret) {
dev_err(dev, "axi bus is not idle, ret = %d!\n", ret);
return -EIO;
@@ -794,42 +853,49 @@ get_free_slot_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
r = hisi_sas_read32_relaxed(hisi_hba,
DLVRY_Q_0_RD_PTR + (queue * 0x14));
if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
- dev_warn(dev, "full queue=%d r=%d w=%d\n\n",
+ dev_warn(dev, "full queue=%d r=%d w=%d\n",
queue, r, w);
return -EAGAIN;
}
- return 0;
+ dq->wr_point = (dq->wr_point + 1) % HISI_SAS_QUEUE_SLOTS;
+
+ return w;
}
static void start_delivery_v3_hw(struct hisi_sas_dq *dq)
{
struct hisi_hba *hisi_hba = dq->hisi_hba;
- int dlvry_queue = dq->slot_prep->dlvry_queue;
- int dlvry_queue_slot = dq->slot_prep->dlvry_queue_slot;
+ struct hisi_sas_slot *s, *s1;
+ struct list_head *dq_list;
+ int dlvry_queue = dq->id;
+ int wp, count = 0;
+
+ dq_list = &dq->list;
+ list_for_each_entry_safe(s, s1, &dq->list, delivery) {
+ if (!s->ready)
+ break;
+ count++;
+ wp = (s->dlvry_queue_slot + 1) % HISI_SAS_QUEUE_SLOTS;
+ list_del(&s->delivery);
+ }
+
+ if (!count)
+ return;
- dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
- hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
- dq->wr_point);
+ hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14), wp);
}
-static int prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba,
+static void prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot,
struct hisi_sas_cmd_hdr *hdr,
struct scatterlist *scatter,
int n_elem)
{
struct hisi_sas_sge_page *sge_page = hisi_sas_sge_addr_mem(slot);
- struct device *dev = hisi_hba->dev;
struct scatterlist *sg;
int i;
- if (n_elem > HISI_SAS_SGE_PAGE_CNT) {
- dev_err(dev, "prd err: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
- n_elem);
- return -EINVAL;
- }
-
for_each_sg(scatter, sg, n_elem, i) {
struct hisi_sas_sge *entry = &sge_page->sge[i];
@@ -842,13 +908,10 @@ static int prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba,
hdr->prd_table_addr = cpu_to_le64(hisi_sas_sge_addr_dma(slot));
hdr->sg_len = cpu_to_le32(n_elem << CMD_HDR_DATA_SGL_LEN_OFF);
-
- return 0;
}
-static int prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
- struct hisi_sas_slot *slot, int is_tmf,
- struct hisi_sas_tmf_task *tmf)
+static void prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
@@ -857,7 +920,8 @@ static int prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_port *port = slot->port;
struct sas_ssp_task *ssp_task = &task->ssp_task;
struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
- int has_data = 0, rc, priority = is_tmf;
+ struct hisi_sas_tmf_task *tmf = slot->tmf;
+ int has_data = 0, priority = !!tmf;
u8 *buf_cmd;
u32 dw1 = 0, dw2 = 0;
@@ -868,7 +932,7 @@ static int prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
(1 << CMD_HDR_CMD_OFF)); /* ssp */
dw1 = 1 << CMD_HDR_VDTL_OFF;
- if (is_tmf) {
+ if (tmf) {
dw1 |= 2 << CMD_HDR_FRAME_TYPE_OFF;
dw1 |= DIR_NO_DATA << CMD_HDR_DIR_OFF;
} else {
@@ -898,12 +962,9 @@ static int prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
hdr->dw2 = cpu_to_le32(dw2);
hdr->transfer_tags = cpu_to_le32(slot->idx);
- if (has_data) {
- rc = prep_prd_sge_v3_hw(hisi_hba, slot, hdr, task->scatter,
+ if (has_data)
+ prep_prd_sge_v3_hw(hisi_hba, slot, hdr, task->scatter,
slot->n_elem);
- if (rc)
- return rc;
- }
hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
@@ -913,7 +974,7 @@ static int prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
sizeof(struct ssp_frame_hdr);
memcpy(buf_cmd, &task->ssp_task.LUN, 8);
- if (!is_tmf) {
+ if (!tmf) {
buf_cmd[9] = ssp_task->task_attr | (ssp_task->task_prio << 3);
memcpy(buf_cmd + 12, scsi_cmnd->cmnd, scsi_cmnd->cmd_len);
} else {
@@ -930,48 +991,25 @@ static int prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
break;
}
}
-
- return 0;
}
-static int prep_smp_v3_hw(struct hisi_hba *hisi_hba,
+static void prep_smp_v3_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
struct domain_device *device = task->dev;
- struct device *dev = hisi_hba->dev;
struct hisi_sas_port *port = slot->port;
- struct scatterlist *sg_req, *sg_resp;
+ struct scatterlist *sg_req;
struct hisi_sas_device *sas_dev = device->lldd_dev;
dma_addr_t req_dma_addr;
- unsigned int req_len, resp_len;
- int elem, rc;
+ unsigned int req_len;
- /*
- * DMA-map SMP request, response buffers
- */
/* req */
sg_req = &task->smp_task.smp_req;
- elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE);
- if (!elem)
- return -ENOMEM;
req_len = sg_dma_len(sg_req);
req_dma_addr = sg_dma_address(sg_req);
- /* resp */
- sg_resp = &task->smp_task.smp_resp;
- elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE);
- if (!elem) {
- rc = -ENOMEM;
- goto err_out_req;
- }
- resp_len = sg_dma_len(sg_resp);
- if ((req_len & 0x3) || (resp_len & 0x3)) {
- rc = -EINVAL;
- goto err_out_resp;
- }
-
/* create header */
/* dw0 */
hdr->dw0 = cpu_to_le32((port->id << CMD_HDR_PORT_OFF) |
@@ -993,18 +1031,9 @@ static int prep_smp_v3_hw(struct hisi_hba *hisi_hba,
hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
hdr->sts_buffer_addr = cpu_to_le64(hisi_sas_status_buf_addr_dma(slot));
- return 0;
-
-err_out_resp:
- dma_unmap_sg(dev, &slot->task->smp_task.smp_resp, 1,
- DMA_FROM_DEVICE);
-err_out_req:
- dma_unmap_sg(dev, &slot->task->smp_task.smp_req, 1,
- DMA_TO_DEVICE);
- return rc;
}
-static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
+static void prep_ata_v3_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot)
{
struct sas_task *task = slot->task;
@@ -1015,7 +1044,7 @@ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
struct asd_sas_port *sas_port = device->port;
struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
u8 *buf_cmd;
- int has_data = 0, rc = 0, hdr_tag = 0;
+ int has_data = 0, hdr_tag = 0;
u32 dw1 = 0, dw2 = 0;
hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF);
@@ -1046,7 +1075,7 @@ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
<< CMD_HDR_FRAME_TYPE_OFF;
dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
- if (CMD_IS_UNCONSTRAINT(task->ata_task.fis.command))
+ if (FIS_CMD_IS_UNCONSTRAINED(task->ata_task.fis))
dw1 |= 1 << CMD_HDR_UNCON_CMD_OFF;
hdr->dw1 = cpu_to_le32(dw1);
@@ -1064,12 +1093,9 @@ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
/* dw3 */
hdr->transfer_tags = cpu_to_le32(slot->idx);
- if (has_data) {
- rc = prep_prd_sge_v3_hw(hisi_hba, slot, hdr, task->scatter,
+ if (has_data)
+ prep_prd_sge_v3_hw(hisi_hba, slot, hdr, task->scatter,
slot->n_elem);
- if (rc)
- return rc;
- }
hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
hdr->cmd_table_addr = cpu_to_le64(hisi_sas_cmd_hdr_addr_dma(slot));
@@ -1081,11 +1107,9 @@ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */
/* fill in command FIS */
memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis));
-
- return 0;
}
-static int prep_abort_v3_hw(struct hisi_hba *hisi_hba,
+static void prep_abort_v3_hw(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot,
int device_id, int abort_flag, int tag_to_abort)
{
@@ -1110,7 +1134,6 @@ static int prep_abort_v3_hw(struct hisi_hba *hisi_hba,
hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF);
hdr->transfer_tags = cpu_to_le32(slot->idx);
- return 0;
}
static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
@@ -1120,6 +1143,7 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
struct device *dev = hisi_hba->dev;
+ unsigned long flags;
hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
@@ -1188,6 +1212,12 @@ static irqreturn_t phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
phy->phy_attached = 1;
hisi_sas_notify_phy_event(phy, HISI_PHYE_PHY_UP);
res = IRQ_HANDLED;
+ spin_lock_irqsave(&phy->lock, flags);
+ if (phy->reset_completion) {
+ phy->in_reset = 0;
+ complete(phy->reset_completion);
+ }
+ spin_unlock_irqrestore(&phy->lock, flags);
end:
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
CHL_INT0_SL_PHY_ENABLE_MSK);
@@ -1301,14 +1331,10 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
{
struct hisi_hba *hisi_hba = p;
struct device *dev = hisi_hba->dev;
- u32 ent_msk, ent_tmp, irq_msk;
+ struct pci_dev *pci_dev = hisi_hba->pci_dev;
+ u32 irq_msk;
int phy_no = 0;
- ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3);
- ent_tmp = ent_msk;
- ent_msk |= ENT_INT_SRC_MSK3_ENT95_MSK_MSK;
- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, ent_msk);
-
irq_msk = hisi_sas_read32(hisi_hba, CHNL_INT_STATUS)
& 0xeeeeeeee;
@@ -1319,6 +1345,13 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
CHL_INT1);
u32 irq_value2 = hisi_sas_phy_read32(hisi_hba, phy_no,
CHL_INT2);
+ u32 irq_msk1 = hisi_sas_phy_read32(hisi_hba, phy_no,
+ CHL_INT1_MSK);
+ u32 irq_msk2 = hisi_sas_phy_read32(hisi_hba, phy_no,
+ CHL_INT2_MSK);
+
+ irq_value1 &= ~irq_msk1;
+ irq_value2 &= ~irq_msk2;
if ((irq_msk & (4 << (phy_no * 4))) &&
irq_value1) {
@@ -1364,8 +1397,28 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
hisi_sas_phy_write32(hisi_hba, phy_no,
CHL_INT2, irq_value2);
- }
+ if ((irq_value2 & BIT(CHL_INT2_RX_INVLD_DW_OFF)) &&
+ (pci_dev->revision == 0x20)) {
+ u32 reg_value;
+ int rc;
+
+ rc = hisi_sas_read32_poll_timeout_atomic(
+ HILINK_ERR_DFX, reg_value,
+ !((reg_value >> 8) & BIT(phy_no)),
+ 1000, 10000);
+ if (rc) {
+ disable_phy_v3_hw(hisi_hba, phy_no);
+ hisi_sas_phy_write32(hisi_hba, phy_no,
+ CHL_INT2,
+ BIT(CHL_INT2_RX_INVLD_DW_OFF));
+ hisi_sas_phy_read32(hisi_hba, phy_no,
+ ERR_CNT_INVLD_DW);
+ mdelay(1);
+ enable_phy_v3_hw(hisi_hba, phy_no);
+ }
+ }
+ }
if (irq_msk & (2 << (phy_no * 4)) && irq_value0) {
hisi_sas_phy_write32(hisi_hba, phy_no,
@@ -1378,8 +1431,6 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
phy_no++;
}
- hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, ent_tmp);
-
return IRQ_HANDLED;
}
@@ -1448,6 +1499,7 @@ static irqreturn_t fatal_axi_int_v3_hw(int irq_no, void *p)
hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, irq_msk | 0x1df00);
irq_value = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
+ irq_value &= ~irq_msk;
for (i = 0; i < ARRAY_SIZE(fatal_axi_error); i++) {
const struct hisi_sas_hw_error *error = &fatal_axi_error[i];
@@ -1549,37 +1601,30 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
struct device *dev = hisi_hba->dev;
struct task_status_struct *ts;
struct domain_device *device;
+ struct sas_ha_struct *ha;
enum exec_status sts;
struct hisi_sas_complete_v3_hdr *complete_queue =
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v3_hdr *complete_hdr =
&complete_queue[slot->cmplt_queue_slot];
- int aborted;
unsigned long flags;
+ bool is_internal = slot->is_internal;
if (unlikely(!task || !task->lldd_task || !task->dev))
return -EINVAL;
ts = &task->task_status;
device = task->dev;
+ ha = device->port->ha;
sas_dev = device->lldd_dev;
spin_lock_irqsave(&task->task_state_lock, flags);
- aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED;
task->task_state_flags &=
~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
spin_unlock_irqrestore(&task->task_state_lock, flags);
memset(ts, 0, sizeof(*ts));
ts->resp = SAS_TASK_COMPLETE;
- if (unlikely(aborted)) {
- dev_dbg(dev, "slot complete: task(%p) aborted\n", task);
- ts->stat = SAS_ABORTED_TASK;
- spin_lock_irqsave(&hisi_hba->lock, flags);
- hisi_sas_slot_task_free(hisi_hba, task, slot);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- return ts->stat;
- }
if (unlikely(!sas_dev)) {
dev_dbg(dev, "slot complete: port has not device\n");
@@ -1619,10 +1664,10 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
slot_err_v3_hw(hisi_hba, task, slot);
if (ts->stat != SAS_DATA_UNDERRUN)
- dev_info(dev, "erroneous completion iptt=%d task=%p "
+ dev_info(dev, "erroneous completion iptt=%d task=%p dev id=%d "
"CQ hdr: 0x%x 0x%x 0x%x 0x%x "
"Error info: 0x%x 0x%x 0x%x 0x%x\n",
- slot->idx, task,
+ slot->idx, task, sas_dev->device_id,
complete_hdr->dw0, complete_hdr->dw1,
complete_hdr->act, complete_hdr->dw3,
error_info[0], error_info[1],
@@ -1677,13 +1722,27 @@ slot_complete_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot)
}
out:
+ hisi_sas_slot_task_free(hisi_hba, task, slot);
+ sts = ts->stat;
spin_lock_irqsave(&task->task_state_lock, flags);
+ if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+ dev_info(dev, "slot complete: task(%p) aborted\n", task);
+ return SAS_ABORTED_TASK;
+ }
task->task_state_flags |= SAS_TASK_STATE_DONE;
spin_unlock_irqrestore(&task->task_state_lock, flags);
- spin_lock_irqsave(&hisi_hba->lock, flags);
- hisi_sas_slot_task_free(hisi_hba, task, slot);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
- sts = ts->stat;
+
+ if (!is_internal && (task->task_proto != SAS_PROTOCOL_SMP)) {
+ spin_lock_irqsave(&device->done_lock, flags);
+ if (test_bit(SAS_HA_FROZEN, &ha->state)) {
+ spin_unlock_irqrestore(&device->done_lock, flags);
+ dev_info(dev, "slot complete: task(%p) ignored\n ",
+ task);
+ return sts;
+ }
+ spin_unlock_irqrestore(&device->done_lock, flags);
+ }
if (task->task_done)
task->task_done(task);
@@ -1699,25 +1758,27 @@ static void cq_tasklet_v3_hw(unsigned long val)
struct hisi_sas_complete_v3_hdr *complete_queue;
u32 rd_point = cq->rd_point, wr_point;
int queue = cq->id;
- struct hisi_sas_dq *dq = &hisi_hba->dq[queue];
complete_queue = hisi_hba->complete_hdr[queue];
- spin_lock(&dq->lock);
wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
(0x14 * queue));
while (rd_point != wr_point) {
struct hisi_sas_complete_v3_hdr *complete_hdr;
+ struct device *dev = hisi_hba->dev;
int iptt;
complete_hdr = &complete_queue[rd_point];
iptt = (complete_hdr->dw1) & CMPLT_HDR_IPTT_MSK;
- slot = &hisi_hba->slot_info[iptt];
- slot->cmplt_queue_slot = rd_point;
- slot->cmplt_queue = queue;
- slot_complete_v3_hw(hisi_hba, slot);
+ if (likely(iptt < HISI_SAS_COMMAND_ENTRIES_V3_HW)) {
+ slot = &hisi_hba->slot_info[iptt];
+ slot->cmplt_queue_slot = rd_point;
+ slot->cmplt_queue = queue;
+ slot_complete_v3_hw(hisi_hba, slot);
+ } else
+ dev_err(dev, "IPTT %d is invalid, discard it.\n", iptt);
if (++rd_point >= HISI_SAS_QUEUE_SLOTS)
rd_point = 0;
@@ -1726,7 +1787,6 @@ static void cq_tasklet_v3_hw(unsigned long val)
/* update rd_point */
cq->rd_point = rd_point;
hisi_sas_write32(hisi_hba, COMPL_Q_0_RD_PTR + (0x14 * queue), rd_point);
- spin_unlock(&dq->lock);
}
static irqreturn_t cq_interrupt_v3_hw(int irq_no, void *p)
@@ -1839,39 +1899,12 @@ static int hisi_sas_v3_init(struct hisi_hba *hisi_hba)
static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no,
struct sas_phy_linkrates *r)
{
- u32 prog_phy_link_rate =
- hisi_sas_phy_read32(hisi_hba, phy_no, PROG_PHY_LINK_RATE);
- struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
- struct asd_sas_phy *sas_phy = &phy->sas_phy;
- int i;
- enum sas_linkrate min, max;
- u32 rate_mask = 0;
-
- if (r->maximum_linkrate == SAS_LINK_RATE_UNKNOWN) {
- max = sas_phy->phy->maximum_linkrate;
- min = r->minimum_linkrate;
- } else if (r->minimum_linkrate == SAS_LINK_RATE_UNKNOWN) {
- max = r->maximum_linkrate;
- min = sas_phy->phy->minimum_linkrate;
- } else
- return;
-
- sas_phy->phy->maximum_linkrate = max;
- sas_phy->phy->minimum_linkrate = min;
-
- max -= SAS_LINK_RATE_1_5_GBPS;
-
- for (i = 0; i <= max; i++)
- rate_mask |= 1 << (i * 2);
-
- prog_phy_link_rate &= ~0xff;
- prog_phy_link_rate |= rate_mask;
+ enum sas_linkrate max = r->maximum_linkrate;
+ u32 prog_phy_link_rate = 0x800;
- disable_phy_v3_hw(hisi_hba, phy_no);
- msleep(100);
+ prog_phy_link_rate |= hisi_sas_get_prog_phy_linkrate_mask(max);
hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE,
- prog_phy_link_rate);
- start_phy_v3_hw(hisi_hba, phy_no);
+ prog_phy_link_rate);
}
static void interrupt_disable_v3_hw(struct hisi_hba *hisi_hba)
@@ -1948,8 +1981,9 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
hisi_sas_write32(hisi_hba, AXI_MASTER_CFG_BASE + AM_CTRL_GLOBAL, 0x1);
/* wait until bus idle */
- rc = readl_poll_timeout(hisi_hba->regs + AXI_MASTER_CFG_BASE +
- AM_CURR_TRANS_RETURN, status, status == 0x3, 10, 100);
+ rc = hisi_sas_read32_poll_timeout(AXI_MASTER_CFG_BASE +
+ AM_CURR_TRANS_RETURN, status,
+ status == 0x3, 10, 100);
if (rc) {
dev_err(dev, "axi bus is not idle, rc = %d\n", rc);
return rc;
@@ -1960,6 +1994,75 @@ static int soft_reset_v3_hw(struct hisi_hba *hisi_hba)
return hw_init_v3_hw(hisi_hba);
}
+static int write_gpio_v3_hw(struct hisi_hba *hisi_hba, u8 reg_type,
+ u8 reg_index, u8 reg_count, u8 *write_data)
+{
+ struct device *dev = hisi_hba->dev;
+ u32 *data = (u32 *)write_data;
+ int i;
+
+ switch (reg_type) {
+ case SAS_GPIO_REG_TX:
+ if ((reg_index + reg_count) > ((hisi_hba->n_phy + 3) / 4)) {
+ dev_err(dev, "write gpio: invalid reg range[%d, %d]\n",
+ reg_index, reg_index + reg_count - 1);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < reg_count; i++)
+ hisi_sas_write32(hisi_hba,
+ SAS_GPIO_TX_0_1 + (reg_index + i) * 4,
+ data[i]);
+ break;
+ default:
+ dev_err(dev, "write gpio: unsupported or bad reg type %d\n",
+ reg_type);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void wait_cmds_complete_timeout_v3_hw(struct hisi_hba *hisi_hba,
+ int delay_ms, int timeout_ms)
+{
+ struct device *dev = hisi_hba->dev;
+ int entries, entries_old = 0, time;
+
+ for (time = 0; time < timeout_ms; time += delay_ms) {
+ entries = hisi_sas_read32(hisi_hba, CQE_SEND_CNT);
+ if (entries == entries_old)
+ break;
+
+ entries_old = entries;
+ msleep(delay_ms);
+ }
+
+ dev_dbg(dev, "wait commands complete %dms\n", time);
+}
+
+static struct scsi_host_template sht_v3_hw = {
+ .name = DRV_NAME,
+ .module = THIS_MODULE,
+ .queuecommand = sas_queuecommand,
+ .target_alloc = sas_target_alloc,
+ .slave_configure = hisi_sas_slave_configure,
+ .scan_finished = hisi_sas_scan_finished,
+ .scan_start = hisi_sas_scan_start,
+ .change_queue_depth = sas_change_queue_depth,
+ .bios_param = sas_bios_param,
+ .can_queue = 1,
+ .this_id = -1,
+ .sg_tablesize = SG_ALL,
+ .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
+ .use_clustering = ENABLE_CLUSTERING,
+ .eh_device_reset_handler = sas_eh_device_reset_handler,
+ .eh_target_reset_handler = sas_eh_target_reset_handler,
+ .target_destroy = sas_target_destroy,
+ .ioctl = sas_ioctl,
+ .shost_attrs = host_attrs,
+};
+
static const struct hisi_sas_hw hisi_sas_v3_hw = {
.hw_init = hisi_sas_v3_init,
.setup_itct = setup_itct_v3_hw,
@@ -1985,6 +2088,8 @@ static const struct hisi_sas_hw hisi_sas_v3_hw = {
.soft_reset = soft_reset_v3_hw,
.get_phys_state = get_phys_state_v3_hw,
.get_events = phy_get_events_v3_hw,
+ .write_gpio = write_gpio_v3_hw,
+ .wait_cmds_complete_timeout = wait_cmds_complete_timeout_v3_hw,
};
static struct Scsi_Host *
@@ -1994,7 +2099,7 @@ hisi_sas_shost_alloc_pci(struct pci_dev *pdev)
struct hisi_hba *hisi_hba;
struct device *dev = &pdev->dev;
- shost = scsi_host_alloc(hisi_sas_sht, sizeof(*hisi_hba));
+ shost = scsi_host_alloc(&sht_v3_hw, sizeof(*hisi_hba));
if (!shost) {
dev_err(dev, "shost alloc failed\n");
return NULL;
@@ -2108,8 +2213,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
sha->sas_port[i] = &hisi_hba->port[i].sas_port;
}
- hisi_sas_init_add(hisi_hba);
-
rc = scsi_add_host(shost, dev);
if (rc)
goto err_out_ha;
@@ -2161,6 +2264,9 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
struct hisi_hba *hisi_hba = sha->lldd_ha;
struct Scsi_Host *shost = sha->core.shost;
+ if (timer_pending(&hisi_hba->timer))
+ del_timer(&hisi_hba->timer);
+
sas_unregister_ha(sha);
sas_remove_host(sha->core.shost);
@@ -2222,6 +2328,29 @@ static const struct hisi_sas_hw_error sas_ras_intr1_nfe[] = {
{ .irq_msk = BIT(31), .msg = "DMAC7_RX_POISON" },
};
+static const struct hisi_sas_hw_error sas_ras_intr2_nfe[] = {
+ { .irq_msk = BIT(0), .msg = "DMAC0_AXI_BUS_ERR" },
+ { .irq_msk = BIT(1), .msg = "DMAC1_AXI_BUS_ERR" },
+ { .irq_msk = BIT(2), .msg = "DMAC2_AXI_BUS_ERR" },
+ { .irq_msk = BIT(3), .msg = "DMAC3_AXI_BUS_ERR" },
+ { .irq_msk = BIT(4), .msg = "DMAC4_AXI_BUS_ERR" },
+ { .irq_msk = BIT(5), .msg = "DMAC5_AXI_BUS_ERR" },
+ { .irq_msk = BIT(6), .msg = "DMAC6_AXI_BUS_ERR" },
+ { .irq_msk = BIT(7), .msg = "DMAC7_AXI_BUS_ERR" },
+ { .irq_msk = BIT(8), .msg = "DMAC0_FIFO_OMIT_ERR" },
+ { .irq_msk = BIT(9), .msg = "DMAC1_FIFO_OMIT_ERR" },
+ { .irq_msk = BIT(10), .msg = "DMAC2_FIFO_OMIT_ERR" },
+ { .irq_msk = BIT(11), .msg = "DMAC3_FIFO_OMIT_ERR" },
+ { .irq_msk = BIT(12), .msg = "DMAC4_FIFO_OMIT_ERR" },
+ { .irq_msk = BIT(13), .msg = "DMAC5_FIFO_OMIT_ERR" },
+ { .irq_msk = BIT(14), .msg = "DMAC6_FIFO_OMIT_ERR" },
+ { .irq_msk = BIT(15), .msg = "DMAC7_FIFO_OMIT_ERR" },
+ { .irq_msk = BIT(16), .msg = "HGC_RLSE_SLOT_UNMATCH" },
+ { .irq_msk = BIT(17), .msg = "HGC_LM_ADD_FCH_LIST_ERR" },
+ { .irq_msk = BIT(18), .msg = "HGC_AXI_BUS_ERR" },
+ { .irq_msk = BIT(19), .msg = "HGC_FIFO_OMIT_ERR" },
+};
+
static bool process_non_fatal_error_v3_hw(struct hisi_hba *hisi_hba)
{
struct device *dev = hisi_hba->dev;
@@ -2252,6 +2381,17 @@ static bool process_non_fatal_error_v3_hw(struct hisi_hba *hisi_hba)
}
hisi_sas_write32(hisi_hba, SAS_RAS_INTR1, irq_value);
+ irq_value = hisi_sas_read32(hisi_hba, SAS_RAS_INTR2);
+ for (i = 0; i < ARRAY_SIZE(sas_ras_intr2_nfe); i++) {
+ ras_error = &sas_ras_intr2_nfe[i];
+ if (ras_error->irq_msk & irq_value) {
+ dev_warn(dev, "SAS_RAS_INTR2: %s(irq_value=0x%x) found.\n",
+ ras_error->msg, irq_value);
+ need_reset = true;
+ }
+ }
+ hisi_sas_write32(hisi_hba, SAS_RAS_INTR2, irq_value);
+
return need_reset;
}
@@ -2307,7 +2447,6 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
u32 device_state, status;
int rc;
u32 reg_val;
- unsigned long flags;
if (!pdev->pm_cap) {
dev_err(dev, "PCI PM not supported\n");
@@ -2332,8 +2471,9 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
AM_CTRL_GLOBAL, reg_val);
/* wait until bus idle */
- rc = readl_poll_timeout(hisi_hba->regs + AXI_MASTER_CFG_BASE +
- AM_CURR_TRANS_RETURN, status, status == 0x3, 10, 100);
+ rc = hisi_sas_read32_poll_timeout(AXI_MASTER_CFG_BASE +
+ AM_CURR_TRANS_RETURN, status,
+ status == 0x3, 10, 100);
if (rc) {
dev_err(dev, "axi bus is not idle, rc = %d\n", rc);
clear_bit(HISI_SAS_REJECT_CMD_BIT, &hisi_hba->flags);
@@ -2351,9 +2491,7 @@ static int hisi_sas_v3_suspend(struct pci_dev *pdev, pm_message_t state)
pci_disable_device(pdev);
pci_set_power_state(pdev, device_state);
- spin_lock_irqsave(&hisi_hba->lock, flags);
hisi_sas_release_tasks(hisi_hba);
- spin_unlock_irqrestore(&hisi_hba->lock, flags);
sas_suspend_ha(sha);
return 0;
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 3a9eca1..15c7f3b 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1923,8 +1923,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h,
}
spin_unlock_irqrestore(&h->reset_lock, flags);
- added = kzalloc(sizeof(*added) * HPSA_MAX_DEVICES, GFP_KERNEL);
- removed = kzalloc(sizeof(*removed) * HPSA_MAX_DEVICES, GFP_KERNEL);
+ added = kcalloc(HPSA_MAX_DEVICES, sizeof(*added), GFP_KERNEL);
+ removed = kcalloc(HPSA_MAX_DEVICES, sizeof(*removed), GFP_KERNEL);
if (!added || !removed) {
dev_warn(&h->pdev->dev, "out of memory in "
@@ -2171,14 +2171,15 @@ static int hpsa_allocate_ioaccel2_sg_chain_blocks(struct ctlr_info *h)
return 0;
h->ioaccel2_cmd_sg_list =
- kzalloc(sizeof(*h->ioaccel2_cmd_sg_list) * h->nr_cmds,
+ kcalloc(h->nr_cmds, sizeof(*h->ioaccel2_cmd_sg_list),
GFP_KERNEL);
if (!h->ioaccel2_cmd_sg_list)
return -ENOMEM;
for (i = 0; i < h->nr_cmds; i++) {
h->ioaccel2_cmd_sg_list[i] =
- kmalloc(sizeof(*h->ioaccel2_cmd_sg_list[i]) *
- h->maxsgentries, GFP_KERNEL);
+ kmalloc_array(h->maxsgentries,
+ sizeof(*h->ioaccel2_cmd_sg_list[i]),
+ GFP_KERNEL);
if (!h->ioaccel2_cmd_sg_list[i])
goto clean;
}
@@ -2210,14 +2211,15 @@ static int hpsa_alloc_sg_chain_blocks(struct ctlr_info *h)
if (h->chainsize <= 0)
return 0;
- h->cmd_sg_list = kzalloc(sizeof(*h->cmd_sg_list) * h->nr_cmds,
- GFP_KERNEL);
+ h->cmd_sg_list = kcalloc(h->nr_cmds, sizeof(*h->cmd_sg_list),
+ GFP_KERNEL);
if (!h->cmd_sg_list)
return -ENOMEM;
for (i = 0; i < h->nr_cmds; i++) {
- h->cmd_sg_list[i] = kmalloc(sizeof(*h->cmd_sg_list[i]) *
- h->chainsize, GFP_KERNEL);
+ h->cmd_sg_list[i] = kmalloc_array(h->chainsize,
+ sizeof(*h->cmd_sg_list[i]),
+ GFP_KERNEL);
if (!h->cmd_sg_list[i])
goto clean;
@@ -4319,7 +4321,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
bool physical_device;
DECLARE_BITMAP(lunzerobits, MAX_EXT_TARGETS);
- currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_DEVICES, GFP_KERNEL);
+ currentsd = kcalloc(HPSA_MAX_DEVICES, sizeof(*currentsd), GFP_KERNEL);
physdev_list = kzalloc(sizeof(*physdev_list), GFP_KERNEL);
logdev_list = kzalloc(sizeof(*logdev_list), GFP_KERNEL);
tmpdevice = kzalloc(sizeof(*tmpdevice), GFP_KERNEL);
@@ -6402,12 +6404,12 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
status = -EINVAL;
goto cleanup1;
}
- buff = kzalloc(SG_ENTRIES_IN_CMD * sizeof(char *), GFP_KERNEL);
+ buff = kcalloc(SG_ENTRIES_IN_CMD, sizeof(char *), GFP_KERNEL);
if (!buff) {
status = -ENOMEM;
goto cleanup1;
}
- buff_size = kmalloc(SG_ENTRIES_IN_CMD * sizeof(int), GFP_KERNEL);
+ buff_size = kmalloc_array(SG_ENTRIES_IN_CMD, sizeof(int), GFP_KERNEL);
if (!buff_size) {
status = -ENOMEM;
goto cleanup1;
@@ -7151,7 +7153,7 @@ static int controller_reset_failed(struct CfgTable __iomem *cfgtable)
char *driver_ver, *old_driver_ver;
int rc, size = sizeof(cfgtable->driver_version);
- old_driver_ver = kmalloc(2 * size, GFP_KERNEL);
+ old_driver_ver = kmalloc_array(2, size, GFP_KERNEL);
if (!old_driver_ver)
return -ENOMEM;
driver_ver = old_driver_ver + size;
@@ -7931,9 +7933,9 @@ static void hpsa_free_cmd_pool(struct ctlr_info *h)
static int hpsa_alloc_cmd_pool(struct ctlr_info *h)
{
- h->cmd_pool_bits = kzalloc(
- DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG) *
- sizeof(unsigned long), GFP_KERNEL);
+ h->cmd_pool_bits = kcalloc(DIV_ROUND_UP(h->nr_cmds, BITS_PER_LONG),
+ sizeof(unsigned long),
+ GFP_KERNEL);
h->cmd_pool = pci_alloc_consistent(h->pdev,
h->nr_cmds * sizeof(*h->cmd_pool),
&(h->cmd_pool_dhandle));
@@ -8507,7 +8509,7 @@ static struct ctlr_info *hpda_alloc_ctlr_info(void)
if (!h)
return NULL;
- h->reply_map = kzalloc(sizeof(*h->reply_map) * nr_cpu_ids, GFP_KERNEL);
+ h->reply_map = kcalloc(nr_cpu_ids, sizeof(*h->reply_map), GFP_KERNEL);
if (!h->reply_map) {
kfree(h);
return NULL;
@@ -8869,7 +8871,7 @@ out:
kfree(options);
}
-static void hpsa_shutdown(struct pci_dev *pdev)
+static void __hpsa_shutdown(struct pci_dev *pdev)
{
struct ctlr_info *h;
@@ -8884,6 +8886,12 @@ static void hpsa_shutdown(struct pci_dev *pdev)
hpsa_disable_interrupt_mode(h); /* pci_init 2 */
}
+static void hpsa_shutdown(struct pci_dev *pdev)
+{
+ __hpsa_shutdown(pdev);
+ pci_disable_device(pdev);
+}
+
static void hpsa_free_device_info(struct ctlr_info *h)
{
int i;
@@ -8927,7 +8935,7 @@ static void hpsa_remove_one(struct pci_dev *pdev)
scsi_remove_host(h->scsi_host); /* init_one 8 */
/* includes hpsa_free_irqs - init_one 4 */
/* includes hpsa_disable_interrupt_mode - pci_init 2 */
- hpsa_shutdown(pdev);
+ __hpsa_shutdown(pdev);
hpsa_free_device_info(h); /* scan */
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index dda1a64..0a9b8b3 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -435,6 +435,8 @@ struct ipr_error_table_t ipr_error_table[] = {
"4080: IOA exceeded maximum operating temperature"},
{0x060B8000, 0, IPR_DEFAULT_LOG_LEVEL,
"4085: Service required"},
+ {0x060B8100, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4086: SAS Adapter Hardware Configuration Error"},
{0x06288000, 0, IPR_DEFAULT_LOG_LEVEL,
"3140: Device bus not ready to ready transition"},
{0x06290000, 0, IPR_DEFAULT_LOG_LEVEL,
@@ -4329,9 +4331,11 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
}
if (ioa_cfg->sis64)
- ioa_data = vmalloc(IPR_FMT3_MAX_NUM_DUMP_PAGES * sizeof(__be32 *));
+ ioa_data = vmalloc(array_size(IPR_FMT3_MAX_NUM_DUMP_PAGES,
+ sizeof(__be32 *)));
else
- ioa_data = vmalloc(IPR_FMT2_MAX_NUM_DUMP_PAGES * sizeof(__be32 *));
+ ioa_data = vmalloc(array_size(IPR_FMT2_MAX_NUM_DUMP_PAGES,
+ sizeof(__be32 *)));
if (!ioa_data) {
ipr_err("Dump memory allocation failed\n");
@@ -9711,8 +9715,9 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
int i, rc = -ENOMEM;
ENTER;
- ioa_cfg->res_entries = kzalloc(sizeof(struct ipr_resource_entry) *
- ioa_cfg->max_devs_supported, GFP_KERNEL);
+ ioa_cfg->res_entries = kcalloc(ioa_cfg->max_devs_supported,
+ sizeof(struct ipr_resource_entry),
+ GFP_KERNEL);
if (!ioa_cfg->res_entries)
goto out;
@@ -9773,8 +9778,9 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q);
}
- ioa_cfg->trace = kzalloc(sizeof(struct ipr_trace_entry) *
- IPR_NUM_TRACE_ENTRIES, GFP_KERNEL);
+ ioa_cfg->trace = kcalloc(IPR_NUM_TRACE_ENTRIES,
+ sizeof(struct ipr_trace_entry),
+ GFP_KERNEL);
if (!ioa_cfg->trace)
goto out_free_hostrcb_dma;
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index e3c8857..bd6ac6b 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -291,7 +291,7 @@ static void ips_freescb(ips_ha_t *, ips_scb_t *);
static void ips_setup_funclist(ips_ha_t *);
static void ips_statinit(ips_ha_t *);
static void ips_statinit_memio(ips_ha_t *);
-static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t);
+static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time64_t);
static void ips_ffdc_reset(ips_ha_t *, int);
static void ips_ffdc_time(ips_ha_t *);
static uint32_t ips_statupd_copperhead(ips_ha_t *);
@@ -985,10 +985,7 @@ static int __ips_eh_reset(struct scsi_cmnd *SC)
/* FFDC */
if (le32_to_cpu(ha->subsys->param[3]) & 0x300000) {
- struct timeval tv;
-
- do_gettimeofday(&tv);
- ha->last_ffdc = tv.tv_sec;
+ ha->last_ffdc = ktime_get_real_seconds();
ha->reset_count++;
ips_ffdc_reset(ha, IPS_INTR_IORL);
}
@@ -2392,7 +2389,6 @@ static int
ips_hainit(ips_ha_t * ha)
{
int i;
- struct timeval tv;
METHOD_TRACE("ips_hainit", 1);
@@ -2407,8 +2403,7 @@ ips_hainit(ips_ha_t * ha)
/* Send FFDC */
ha->reset_count = 1;
- do_gettimeofday(&tv);
- ha->last_ffdc = tv.tv_sec;
+ ha->last_ffdc = ktime_get_real_seconds();
ips_ffdc_reset(ha, IPS_INTR_IORL);
if (!ips_read_config(ha, IPS_INTR_IORL)) {
@@ -2548,12 +2543,9 @@ ips_next(ips_ha_t * ha, int intr)
if ((ha->subsys->param[3] & 0x300000)
&& (ha->scb_activelist.count == 0)) {
- struct timeval tv;
-
- do_gettimeofday(&tv);
-
- if (tv.tv_sec - ha->last_ffdc > IPS_SECS_8HOURS) {
- ha->last_ffdc = tv.tv_sec;
+ time64_t now = ktime_get_real_seconds();
+ if (now - ha->last_ffdc > IPS_SECS_8HOURS) {
+ ha->last_ffdc = now;
ips_ffdc_time(ha);
}
}
@@ -5988,59 +5980,21 @@ ips_ffdc_time(ips_ha_t * ha)
/* */
/****************************************************************************/
static void
-ips_fix_ffdc_time(ips_ha_t * ha, ips_scb_t * scb, time_t current_time)
+ips_fix_ffdc_time(ips_ha_t * ha, ips_scb_t * scb, time64_t current_time)
{
- long days;
- long rem;
- int i;
- int year;
- int yleap;
- int year_lengths[2] = { IPS_DAYS_NORMAL_YEAR, IPS_DAYS_LEAP_YEAR };
- int month_lengths[12][2] = { {31, 31},
- {28, 29},
- {31, 31},
- {30, 30},
- {31, 31},
- {30, 30},
- {31, 31},
- {31, 31},
- {30, 30},
- {31, 31},
- {30, 30},
- {31, 31}
- };
+ struct tm tm;
METHOD_TRACE("ips_fix_ffdc_time", 1);
- days = current_time / IPS_SECS_DAY;
- rem = current_time % IPS_SECS_DAY;
-
- scb->cmd.ffdc.hour = (rem / IPS_SECS_HOUR);
- rem = rem % IPS_SECS_HOUR;
- scb->cmd.ffdc.minute = (rem / IPS_SECS_MIN);
- scb->cmd.ffdc.second = (rem % IPS_SECS_MIN);
-
- year = IPS_EPOCH_YEAR;
- while (days < 0 || days >= year_lengths[yleap = IPS_IS_LEAP_YEAR(year)]) {
- int newy;
-
- newy = year + (days / IPS_DAYS_NORMAL_YEAR);
- if (days < 0)
- --newy;
- days -= (newy - year) * IPS_DAYS_NORMAL_YEAR +
- IPS_NUM_LEAP_YEARS_THROUGH(newy - 1) -
- IPS_NUM_LEAP_YEARS_THROUGH(year - 1);
- year = newy;
- }
-
- scb->cmd.ffdc.yearH = year / 100;
- scb->cmd.ffdc.yearL = year % 100;
-
- for (i = 0; days >= month_lengths[i][yleap]; ++i)
- days -= month_lengths[i][yleap];
+ time64_to_tm(current_time, 0, &tm);
- scb->cmd.ffdc.month = i + 1;
- scb->cmd.ffdc.day = days + 1;
+ scb->cmd.ffdc.hour = tm.tm_hour;
+ scb->cmd.ffdc.minute = tm.tm_min;
+ scb->cmd.ffdc.second = tm.tm_sec;
+ scb->cmd.ffdc.yearH = (tm.tm_year + 1900) / 100;
+ scb->cmd.ffdc.yearL = tm.tm_year % 100;
+ scb->cmd.ffdc.month = tm.tm_mon + 1;
+ scb->cmd.ffdc.day = tm.tm_mday;
}
/****************************************************************************
diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h
index 366be3b..db54617 100644
--- a/drivers/scsi/ips.h
+++ b/drivers/scsi/ips.h
@@ -402,16 +402,7 @@
#define IPS_BIOS_HEADER 0xC0
/* time oriented stuff */
- #define IPS_IS_LEAP_YEAR(y) (((y % 4 == 0) && ((y % 100 != 0) || (y % 400 == 0))) ? 1 : 0)
- #define IPS_NUM_LEAP_YEARS_THROUGH(y) ((y) / 4 - (y) / 100 + (y) / 400)
-
- #define IPS_SECS_MIN 60
- #define IPS_SECS_HOUR 3600
#define IPS_SECS_8HOURS 28800
- #define IPS_SECS_DAY 86400
- #define IPS_DAYS_NORMAL_YEAR 365
- #define IPS_DAYS_LEAP_YEAR 366
- #define IPS_EPOCH_YEAR 1970
/*
* Scsi_Host Template
@@ -1054,7 +1045,7 @@ typedef struct ips_ha {
uint8_t active;
int ioctl_reset; /* IOCTL Requested Reset Flag */
uint16_t reset_count; /* number of resets */
- time_t last_ffdc; /* last time we sent ffdc info*/
+ time64_t last_ffdc; /* last time we sent ffdc info*/
uint8_t slot_num; /* PCI Slot Number */
int ioctl_len; /* size of ioctl buffer */
dma_addr_t ioctl_busaddr; /* dma address of ioctl buffer*/
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index 922e3e5..08c7b1e 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -232,14 +232,14 @@ static int isci_register_sas_ha(struct isci_host *isci_host)
struct asd_sas_phy **sas_phys;
struct asd_sas_port **sas_ports;
- sas_phys = devm_kzalloc(&isci_host->pdev->dev,
- SCI_MAX_PHYS * sizeof(void *),
+ sas_phys = devm_kcalloc(&isci_host->pdev->dev,
+ SCI_MAX_PHYS, sizeof(void *),
GFP_KERNEL);
if (!sas_phys)
return -ENOMEM;
- sas_ports = devm_kzalloc(&isci_host->pdev->dev,
- SCI_MAX_PORTS * sizeof(void *),
+ sas_ports = devm_kcalloc(&isci_host->pdev->dev,
+ SCI_MAX_PORTS, sizeof(void *),
GFP_KERNEL);
if (!sas_ports)
return -ENOMEM;
@@ -433,9 +433,6 @@ static enum sci_status sci_user_parameters_set(struct isci_host *ihost,
(u->max_speed_generation > SCIC_SDS_PARM_NO_SPEED)))
return SCI_FAILURE_INVALID_PARAMETER_VALUE;
- if (u->in_connection_align_insertion_frequency < 3)
- return SCI_FAILURE_INVALID_PARAMETER_VALUE;
-
if ((u->in_connection_align_insertion_frequency < 3) ||
(u->align_insertion_frequency == 0) ||
(u->notify_enable_spin_up_insertion_frequency == 0))
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 2ba4b68..b025a0b 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -962,7 +962,6 @@ static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev)
if (conn->datadgst_en)
sdev->request_queue->backing_dev_info->capabilities
|= BDI_CAP_STABLE_WRITES;
- blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY);
blk_queue_dma_alignment(sdev->request_queue, 0);
return 0;
}
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 71bdc0b..d609383 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -2576,7 +2576,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
* the array. */
if (items)
num_arrays++;
- q->pool = kvzalloc(num_arrays * max * sizeof(void*), GFP_KERNEL);
+ q->pool = kvcalloc(num_arrays * max, sizeof(void *), GFP_KERNEL);
if (q->pool == NULL)
return -ENOMEM;
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 0cc1567..ff1d612 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -577,6 +577,11 @@ int sas_ata_init(struct domain_device *found_dev)
ata_sas_port_destroy(ap);
return rc;
}
+ rc = ata_sas_tport_add(found_dev->sata_dev.ata_host.dev, ap);
+ if (rc) {
+ ata_sas_port_destroy(ap);
+ return rc;
+ }
found_dev->sata_dev.ap = ap;
return 0;
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index a0fa7ef..1ffca28 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -314,6 +314,7 @@ void sas_free_device(struct kref *kref)
kfree(dev->ex_dev.ex_phy);
if (dev_is_sata(dev) && dev->sata_dev.ap) {
+ ata_sas_tport_delete(dev->sata_dev.ap);
ata_sas_port_destroy(dev->sata_dev.ap);
dev->sata_dev.ap = NULL;
}
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 8b71143..fadc99c 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -443,7 +443,7 @@ static int sas_expander_discover(struct domain_device *dev)
struct expander_device *ex = &dev->ex_dev;
int res = -ENOMEM;
- ex->ex_phy = kzalloc(sizeof(*ex->ex_phy)*ex->num_phys, GFP_KERNEL);
+ ex->ex_phy = kcalloc(ex->num_phys, sizeof(*ex->ex_phy), GFP_KERNEL);
if (!ex->ex_phy)
return -ENOMEM;
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 6c0d351..20b249a 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -64,8 +64,6 @@ struct lpfc_sli2_slim;
#define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */
#define LPFC_Q_RAMP_UP_INTERVAL 120 /* lun q_depth ramp up interval */
#define LPFC_VNAME_LEN 100 /* vport symbolic name length */
-#define LPFC_TGTQ_INTERVAL 40000 /* Min amount of time between tgt
- queue depth change in millisecs */
#define LPFC_TGTQ_RAMPUP_PCENT 5 /* Target queue rampup in percentage */
#define LPFC_MIN_TGT_QDEPTH 10
#define LPFC_MAX_TGT_QDEPTH 0xFFFF
@@ -784,6 +782,7 @@ struct lpfc_hba {
uint32_t cfg_nvme_oas;
uint32_t cfg_nvme_embed_cmd;
uint32_t cfg_nvme_io_channel;
+ uint32_t cfg_nvmet_mrq_post;
uint32_t cfg_nvmet_mrq;
uint32_t cfg_enable_nvmet;
uint32_t cfg_nvme_enable_fb;
@@ -922,12 +921,6 @@ struct lpfc_hba {
atomic_t fc4ScsiOutputRequests;
atomic_t fc4ScsiControlRequests;
atomic_t fc4ScsiIoCmpls;
- atomic_t fc4NvmeInputRequests;
- atomic_t fc4NvmeOutputRequests;
- atomic_t fc4NvmeControlRequests;
- atomic_t fc4NvmeIoCmpls;
- atomic_t fc4NvmeLsRequests;
- atomic_t fc4NvmeLsCmpls;
uint64_t bg_guard_err_cnt;
uint64_t bg_apptag_err_cnt;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 2ac1d21c..729d343 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -2,7 +2,7 @@
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
@@ -149,10 +149,14 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
struct lpfc_nvmet_tgtport *tgtp;
struct nvme_fc_local_port *localport;
struct lpfc_nvme_lport *lport;
+ struct lpfc_nvme_rport *rport;
struct lpfc_nodelist *ndlp;
struct nvme_fc_remote_port *nrport;
- uint64_t data1, data2, data3, tot;
+ struct lpfc_nvme_ctrl_stat *cstat;
+ uint64_t data1, data2, data3;
+ uint64_t totin, totout, tot;
char *statep;
+ int i;
int len = 0;
if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME)) {
@@ -293,6 +297,13 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
len = snprintf(buf, PAGE_SIZE, "NVME Initiator Enabled\n");
spin_lock_irq(shost->host_lock);
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ "XRI Dist lpfc%d Total %d NVME %d SCSI %d ELS %d\n",
+ phba->brd_no,
+ phba->sli4_hba.max_cfg_param.max_xri,
+ phba->sli4_hba.nvme_xri_max,
+ phba->sli4_hba.scsi_xri_max,
+ lpfc_sli4_get_els_iocb_cnt(phba));
/* Port state is only one of two values for now. */
if (localport->port_id)
@@ -309,11 +320,14 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
localport->port_id, statep);
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
- if (!ndlp->nrport)
+ rport = lpfc_ndlp_get_nrport(ndlp);
+ if (!rport)
continue;
/* local short-hand pointer. */
- nrport = ndlp->nrport->remoteport;
+ nrport = rport->remoteport;
+ if (!nrport)
+ continue;
/* Port state is only one of two values for now. */
switch (nrport->port_state) {
@@ -364,11 +378,14 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
}
spin_unlock_irq(shost->host_lock);
+ if (!lport)
+ return len;
+
len += snprintf(buf + len, PAGE_SIZE - len, "\nNVME Statistics\n");
len += snprintf(buf+len, PAGE_SIZE-len,
"LS: Xmt %010x Cmpl %010x Abort %08x\n",
- atomic_read(&phba->fc4NvmeLsRequests),
- atomic_read(&phba->fc4NvmeLsCmpls),
+ atomic_read(&lport->fc4NvmeLsRequests),
+ atomic_read(&lport->fc4NvmeLsCmpls),
atomic_read(&lport->xmt_ls_abort));
len += snprintf(buf + len, PAGE_SIZE - len,
@@ -377,28 +394,33 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
atomic_read(&lport->cmpl_ls_xb),
atomic_read(&lport->cmpl_ls_err));
- tot = atomic_read(&phba->fc4NvmeIoCmpls);
- data1 = atomic_read(&phba->fc4NvmeInputRequests);
- data2 = atomic_read(&phba->fc4NvmeOutputRequests);
- data3 = atomic_read(&phba->fc4NvmeControlRequests);
+ totin = 0;
+ totout = 0;
+ for (i = 0; i < phba->cfg_nvme_io_channel; i++) {
+ cstat = &lport->cstat[i];
+ tot = atomic_read(&cstat->fc4NvmeIoCmpls);
+ totin += tot;
+ data1 = atomic_read(&cstat->fc4NvmeInputRequests);
+ data2 = atomic_read(&cstat->fc4NvmeOutputRequests);
+ data3 = atomic_read(&cstat->fc4NvmeControlRequests);
+ totout += (data1 + data2 + data3);
+ }
len += snprintf(buf+len, PAGE_SIZE-len,
- "FCP: Rd %016llx Wr %016llx IO %016llx\n",
- data1, data2, data3);
+ "Total FCP Cmpl %016llx Issue %016llx "
+ "OutIO %016llx\n",
+ totin, totout, totout - totin);
len += snprintf(buf+len, PAGE_SIZE-len,
- " noxri %08x nondlp %08x qdepth %08x "
- "wqerr %08x\n",
+ " abort %08x noxri %08x nondlp %08x qdepth %08x "
+ "wqerr %08x err %08x\n",
+ atomic_read(&lport->xmt_fcp_abort),
atomic_read(&lport->xmt_fcp_noxri),
atomic_read(&lport->xmt_fcp_bad_ndlp),
atomic_read(&lport->xmt_fcp_qdepth),
+ atomic_read(&lport->xmt_fcp_err),
atomic_read(&lport->xmt_fcp_wqerr));
len += snprintf(buf + len, PAGE_SIZE - len,
- " Cmpl %016llx Outstanding %016llx Abort %08x\n",
- tot, ((data1 + data2 + data3) - tot),
- atomic_read(&lport->xmt_fcp_abort));
-
- len += snprintf(buf + len, PAGE_SIZE - len,
"FCP CMPL: xb %08x Err %08x\n",
atomic_read(&lport->cmpl_fcp_xb),
atomic_read(&lport->cmpl_fcp_err));
@@ -3280,6 +3302,9 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
{
struct Scsi_Host *shost;
struct lpfc_nodelist *ndlp;
+#if (IS_ENABLED(CONFIG_NVME_FC))
+ struct lpfc_nvme_rport *rport;
+#endif
shost = lpfc_shost_from_vport(vport);
spin_lock_irq(shost->host_lock);
@@ -3289,8 +3314,9 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
if (ndlp->rport)
ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo;
#if (IS_ENABLED(CONFIG_NVME_FC))
- if (ndlp->nrport)
- nvme_fc_set_remoteport_devloss(ndlp->nrport->remoteport,
+ rport = lpfc_ndlp_get_nrport(ndlp);
+ if (rport)
+ nvme_fc_set_remoteport_devloss(rport->remoteport,
vport->cfg_devloss_tmo);
#endif
}
@@ -3414,6 +3440,15 @@ LPFC_ATTR_R(nvmet_mrq,
"Specify number of RQ pairs for processing NVMET cmds");
/*
+ * lpfc_nvmet_mrq_post: Specify number of RQ buffer to initially post
+ * to each NVMET RQ. Range 64 to 2048, default is 512.
+ */
+LPFC_ATTR_R(nvmet_mrq_post,
+ LPFC_NVMET_RQE_DEF_POST, LPFC_NVMET_RQE_MIN_POST,
+ LPFC_NVMET_RQE_DEF_COUNT,
+ "Specify number of RQ buffers to initially post");
+
+/*
* lpfc_enable_fc4_type: Defines what FC4 types are supported.
* Supported Values: 1 - register just FCP
* 3 - register both FCP and NVME
@@ -3469,8 +3504,49 @@ LPFC_VPORT_ATTR_R(lun_queue_depth, 30, 1, 512,
# tgt_queue_depth: This parameter is used to limit the number of outstanding
# commands per target port. Value range is [10,65535]. Default value is 65535.
*/
-LPFC_VPORT_ATTR_RW(tgt_queue_depth, 65535, 10, 65535,
- "Max number of FCP commands we can queue to a specific target port");
+static uint lpfc_tgt_queue_depth = LPFC_MAX_TGT_QDEPTH;
+module_param(lpfc_tgt_queue_depth, uint, 0444);
+MODULE_PARM_DESC(lpfc_tgt_queue_depth, "Set max Target queue depth");
+lpfc_vport_param_show(tgt_queue_depth);
+lpfc_vport_param_init(tgt_queue_depth, LPFC_MAX_TGT_QDEPTH,
+ LPFC_MIN_TGT_QDEPTH, LPFC_MAX_TGT_QDEPTH);
+
+/**
+ * lpfc_tgt_queue_depth_store: Sets an attribute value.
+ * @phba: pointer the the adapter structure.
+ * @val: integer attribute value.
+ *
+ * Description: Sets the parameter to the new value.
+ *
+ * Returns:
+ * zero on success
+ * -EINVAL if val is invalid
+ */
+static int
+lpfc_tgt_queue_depth_set(struct lpfc_vport *vport, uint val)
+{
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ struct lpfc_nodelist *ndlp;
+
+ if (!lpfc_rangecheck(val, LPFC_MIN_TGT_QDEPTH, LPFC_MAX_TGT_QDEPTH))
+ return -EINVAL;
+
+ if (val == vport->cfg_tgt_queue_depth)
+ return 0;
+
+ spin_lock_irq(shost->host_lock);
+ vport->cfg_tgt_queue_depth = val;
+
+ /* Next loop thru nodelist and change cmd_qdepth */
+ list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)
+ ndlp->cmd_qdepth = vport->cfg_tgt_queue_depth;
+
+ spin_unlock_irq(shost->host_lock);
+ return 0;
+}
+
+lpfc_vport_param_store(tgt_queue_depth);
+static DEVICE_ATTR_RW(lpfc_tgt_queue_depth);
/*
# hba_queue_depth: This parameter is used to limit the number of outstanding
@@ -5302,6 +5378,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
&dev_attr_lpfc_suppress_rsp,
&dev_attr_lpfc_nvme_io_channel,
&dev_attr_lpfc_nvmet_mrq,
+ &dev_attr_lpfc_nvmet_mrq_post,
&dev_attr_lpfc_nvme_enable_fb,
&dev_attr_lpfc_nvmet_fb_size,
&dev_attr_lpfc_enable_bg,
@@ -6352,6 +6429,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_enable_fc4_type_init(phba, lpfc_enable_fc4_type);
lpfc_nvmet_mrq_init(phba, lpfc_nvmet_mrq);
+ lpfc_nvmet_mrq_post_init(phba, lpfc_nvmet_mrq_post);
/* Initialize first burst. Target vs Initiator are different. */
lpfc_nvme_enable_fb_init(phba, lpfc_nvme_enable_fb);
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 0f174ca..edb1a18 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -3621,7 +3621,7 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
bsg_reply->result = 0;
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
- "2937 SLI_CONFIG ext-buffer maibox command "
+ "2937 SLI_CONFIG ext-buffer mailbox command "
"(x%x/x%x) complete bsg job done, bsize:%d\n",
phba->mbox_ext_buf_ctx.nembType,
phba->mbox_ext_buf_ctx.mboxType, size);
@@ -3632,7 +3632,7 @@ lpfc_bsg_issue_mbox_ext_handle_job(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
phba->mbox_ext_buf_ctx.mbx_dmabuf, 0);
} else {
lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
- "2938 SLI_CONFIG ext-buffer maibox "
+ "2938 SLI_CONFIG ext-buffer mailbox "
"command (x%x/x%x) failure, rc:x%x\n",
phba->mbox_ext_buf_ctx.nembType,
phba->mbox_ext_buf_ctx.mboxType, rc);
@@ -3666,7 +3666,7 @@ lpfc_bsg_issue_read_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
pmboxq->u.mb.mbxStatus = MBXERR_ERROR;
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
- "2939 SLI_CONFIG ext-buffer rd maibox command "
+ "2939 SLI_CONFIG ext-buffer rd mailbox command "
"complete, ctxState:x%x, mbxStatus:x%x\n",
phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus);
@@ -3706,7 +3706,7 @@ lpfc_bsg_issue_write_mbox_ext_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq)
pmboxq->u.mb.mbxStatus = MBXERR_ERROR;
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
- "2940 SLI_CONFIG ext-buffer wr maibox command "
+ "2940 SLI_CONFIG ext-buffer wr mailbox command "
"complete, ctxState:x%x, mbxStatus:x%x\n",
phba->mbox_ext_buf_ctx.state, pmboxq->u.mb.mbxStatus);
@@ -3988,12 +3988,12 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,
if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
"2947 Issued SLI_CONFIG ext-buffer "
- "maibox command, rc:x%x\n", rc);
+ "mailbox command, rc:x%x\n", rc);
return SLI_CONFIG_HANDLED;
}
lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
"2948 Failed to issue SLI_CONFIG ext-buffer "
- "maibox command, rc:x%x\n", rc);
+ "mailbox command, rc:x%x\n", rc);
rc = -EPIPE;
job_error:
@@ -4147,12 +4147,12 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, struct bsg_job *job,
if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
"2955 Issued SLI_CONFIG ext-buffer "
- "maibox command, rc:x%x\n", rc);
+ "mailbox command, rc:x%x\n", rc);
return SLI_CONFIG_HANDLED;
}
lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
"2956 Failed to issue SLI_CONFIG ext-buffer "
- "maibox command, rc:x%x\n", rc);
+ "mailbox command, rc:x%x\n", rc);
rc = -EPIPE;
goto job_error;
}
@@ -4492,12 +4492,12 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job,
if ((rc == MBX_SUCCESS) || (rc == MBX_BUSY)) {
lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC,
"2969 Issued SLI_CONFIG ext-buffer "
- "maibox command, rc:x%x\n", rc);
+ "mailbox command, rc:x%x\n", rc);
return SLI_CONFIG_HANDLED;
}
lpfc_printf_log(phba, KERN_ERR, LOG_LIBDFC,
"2970 Failed to issue SLI_CONFIG ext-buffer "
- "maibox command, rc:x%x\n", rc);
+ "mailbox command, rc:x%x\n", rc);
rc = -EPIPE;
goto job_error;
}
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 0617c8e..d4a200a 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -471,6 +471,11 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type)
"Parse GID_FTrsp: did:x%x flg:x%x x%x",
Did, ndlp->nlp_flag, vport->fc_flag);
+ /* Don't assume the rport is always the previous
+ * FC4 type.
+ */
+ ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);
+
/* By default, the driver expects to support FCP FC4 */
if (fc4_type == FC_TYPE_FCP)
ndlp->nlp_fc4_type |= NLP_FC4_FCP;
@@ -691,6 +696,11 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
vport->fc_flag &= ~FC_RSCN_DEFERRED;
spin_unlock_irq(shost->host_lock);
+ /* This is a GID_FT completing so the gidft_inp counter was
+ * incremented before the GID_FT was issued to the wire.
+ */
+ vport->gidft_inp--;
+
/*
* Skip processing the NS response
* Re-issue the NS cmd
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index fb0dc2a..9df0c05 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -2,7 +2,7 @@
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2007-2015 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
@@ -544,7 +544,7 @@ static int
lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
{
int len = 0;
- int cnt;
+ int i, iocnt, outio, cnt;
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp;
@@ -552,12 +552,15 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
struct nvme_fc_local_port *localport;
struct lpfc_nvmet_tgtport *tgtp;
struct nvme_fc_remote_port *nrport;
+ struct lpfc_nvme_rport *rport;
cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
+ outio = 0;
len += snprintf(buf+len, size-len, "\nFCP Nodelist Entries ...\n");
spin_lock_irq(shost->host_lock);
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+ iocnt = 0;
if (!cnt) {
len += snprintf(buf+len, size-len,
"Missing Nodelist Entries\n");
@@ -585,9 +588,11 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
break;
case NLP_STE_UNMAPPED_NODE:
statep = "UNMAP ";
+ iocnt = 1;
break;
case NLP_STE_MAPPED_NODE:
statep = "MAPPED";
+ iocnt = 1;
break;
case NLP_STE_NPR_NODE:
statep = "NPR ";
@@ -614,8 +619,10 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
len += snprintf(buf+len, size-len, "UNKNOWN_TYPE ");
if (ndlp->nlp_type & NLP_FC_NODE)
len += snprintf(buf+len, size-len, "FC_NODE ");
- if (ndlp->nlp_type & NLP_FABRIC)
+ if (ndlp->nlp_type & NLP_FABRIC) {
len += snprintf(buf+len, size-len, "FABRIC ");
+ iocnt = 0;
+ }
if (ndlp->nlp_type & NLP_FCP_TARGET)
len += snprintf(buf+len, size-len, "FCP_TGT sid:%d ",
ndlp->nlp_sid);
@@ -632,10 +639,20 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
ndlp->nlp_usg_map);
len += snprintf(buf+len, size-len, "refcnt:%x",
kref_read(&ndlp->kref));
+ if (iocnt) {
+ i = atomic_read(&ndlp->cmd_pending);
+ len += snprintf(buf + len, size - len,
+ " OutIO:x%x Qdepth x%x",
+ i, ndlp->cmd_qdepth);
+ outio += i;
+ }
len += snprintf(buf+len, size-len, "\n");
}
spin_unlock_irq(shost->host_lock);
+ len += snprintf(buf + len, size - len,
+ "\nOutstanding IO x%x\n", outio);
+
if (phba->nvmet_support && phba->targetport && (vport == phba->pport)) {
tgtp = (struct lpfc_nvmet_tgtport *)phba->targetport->private;
len += snprintf(buf + len, size - len,
@@ -679,10 +696,13 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
len += snprintf(buf + len, size - len, "\tRport List:\n");
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
/* local short-hand pointer. */
- if (!ndlp->nrport)
+ rport = lpfc_ndlp_get_nrport(ndlp);
+ if (!rport)
continue;
- nrport = ndlp->nrport->remoteport;
+ nrport = rport->remoteport;
+ if (!nrport)
+ continue;
/* Port state is only one of two values for now. */
switch (nrport->port_state) {
@@ -751,10 +771,12 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
struct lpfc_nvmet_tgtport *tgtp;
struct lpfc_nvmet_rcv_ctx *ctxp, *next_ctxp;
struct nvme_fc_local_port *localport;
+ struct lpfc_nvme_ctrl_stat *cstat;
struct lpfc_nvme_lport *lport;
- uint64_t tot, data1, data2, data3;
+ uint64_t data1, data2, data3;
+ uint64_t tot, totin, totout;
+ int cnt, i, maxch;
int len = 0;
- int cnt;
if (phba->nvmet_support) {
if (!phba->targetport)
@@ -880,33 +902,52 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
if (!(phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME))
return len;
+ localport = vport->localport;
+ if (!localport)
+ return len;
+ lport = (struct lpfc_nvme_lport *)localport->private;
+ if (!lport)
+ return len;
+
len += snprintf(buf + len, size - len,
"\nNVME Lport Statistics\n");
len += snprintf(buf + len, size - len,
"LS: Xmt %016x Cmpl %016x\n",
- atomic_read(&phba->fc4NvmeLsRequests),
- atomic_read(&phba->fc4NvmeLsCmpls));
-
- tot = atomic_read(&phba->fc4NvmeIoCmpls);
- data1 = atomic_read(&phba->fc4NvmeInputRequests);
- data2 = atomic_read(&phba->fc4NvmeOutputRequests);
- data3 = atomic_read(&phba->fc4NvmeControlRequests);
+ atomic_read(&lport->fc4NvmeLsRequests),
+ atomic_read(&lport->fc4NvmeLsCmpls));
- len += snprintf(buf + len, size - len,
- "FCP: Rd %016llx Wr %016llx IO %016llx\n",
- data1, data2, data3);
-
- len += snprintf(buf + len, size - len,
- " Cmpl %016llx Outstanding %016llx\n",
- tot, (data1 + data2 + data3) - tot);
+ if (phba->cfg_nvme_io_channel < 32)
+ maxch = phba->cfg_nvme_io_channel;
+ else
+ maxch = 32;
+ totin = 0;
+ totout = 0;
+ for (i = 0; i < phba->cfg_nvme_io_channel; i++) {
+ cstat = &lport->cstat[i];
+ tot = atomic_read(&cstat->fc4NvmeIoCmpls);
+ totin += tot;
+ data1 = atomic_read(&cstat->fc4NvmeInputRequests);
+ data2 = atomic_read(&cstat->fc4NvmeOutputRequests);
+ data3 = atomic_read(&cstat->fc4NvmeControlRequests);
+ totout += (data1 + data2 + data3);
+
+ /* Limit to 32, debugfs display buffer limitation */
+ if (i >= 32)
+ continue;
- localport = vport->localport;
- if (!localport)
- return len;
- lport = (struct lpfc_nvme_lport *)localport->private;
- if (!lport)
- return len;
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ "FCP (%d): Rd %016llx Wr %016llx "
+ "IO %016llx ",
+ i, data1, data2, data3);
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ "Cmpl %016llx OutIO %016llx\n",
+ tot, ((data1 + data2 + data3) - tot));
+ }
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ "Total FCP Cmpl %016llx Issue %016llx "
+ "OutIO %016llx\n",
+ totin, totout, totout - totin);
len += snprintf(buf + len, size - len,
"LS Xmt Err: Abrt %08x Err %08x "
@@ -918,11 +959,12 @@ lpfc_debugfs_nvmestat_data(struct lpfc_vport *vport, char *buf, int size)
len += snprintf(buf + len, size - len,
"FCP Xmt Err: noxri %06x nondlp %06x "
- "qdepth %06x wqerr %06x Abrt %06x\n",
+ "qdepth %06x wqerr %06x err %06x Abrt %06x\n",
atomic_read(&lport->xmt_fcp_noxri),
atomic_read(&lport->xmt_fcp_bad_ndlp),
atomic_read(&lport->xmt_fcp_qdepth),
atomic_read(&lport->xmt_fcp_wqerr),
+ atomic_read(&lport->xmt_fcp_err),
atomic_read(&lport->xmt_fcp_abort));
len += snprintf(buf + len, size - len,
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 74895e6..6d84a10 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -6268,7 +6268,6 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
* flush the RSCN. Otherwise, the outstanding requests
* need to complete.
*/
- vport->gidft_inp = 0;
if (lpfc_issue_gidft(vport) > 0)
return 1;
} else {
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 3e7712c..2fef54f 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -708,8 +708,7 @@ lpfc_work_done(struct lpfc_hba *phba)
HA_RXMASK));
}
}
- if ((phba->sli_rev == LPFC_SLI_REV4) &&
- (!list_empty(&pring->txq)))
+ if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_drain_txq(phba);
/*
* Turn on Ring interrupts
@@ -3876,10 +3875,6 @@ int
lpfc_issue_gidft(struct lpfc_vport *vport)
{
struct lpfc_hba *phba = vport->phba;
- struct lpfc_nodelist *ndlp;
-
- list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp)
- ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME);
/* Good status, issue CT Request to NameServer */
if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) ||
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 98b8055..f43f0ba 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -2,7 +2,7 @@
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2009-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
@@ -566,6 +566,7 @@ struct lpfc_register {
/* The following BAR0 register sets are defined for if_type 0 and 2 UCNAs. */
#define LPFC_SLI_INTF 0x0058
+#define LPFC_SLI_ASIC_VER 0x009C
#define LPFC_CTL_PORT_SEM_OFFSET 0x400
#define lpfc_port_smphr_perr_SHIFT 31
@@ -3912,6 +3913,7 @@ struct lpfc_acqe_link {
#define LPFC_ASYNC_LINK_FAULT_NONE 0x0
#define LPFC_ASYNC_LINK_FAULT_LOCAL 0x1
#define LPFC_ASYNC_LINK_FAULT_REMOTE 0x2
+#define LPFC_ASYNC_LINK_FAULT_LR_LRR 0x3
#define lpfc_acqe_logical_link_speed_SHIFT 16
#define lpfc_acqe_logical_link_speed_MASK 0x0000FFFF
#define lpfc_acqe_logical_link_speed_WORD word1
@@ -4616,6 +4618,9 @@ union lpfc_wqe128 {
struct send_frame_wqe send_frame;
};
+#define MAGIC_NUMER_G6 0xFEAA0003
+#define MAGIC_NUMER_G7 0xFEAA0005
+
struct lpfc_grp_hdr {
uint32_t size;
uint32_t magic_number;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 7887468..52cae87 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2,7 +2,7 @@
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
@@ -1266,6 +1266,9 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
uint64_t tot, data1, data2, data3;
struct lpfc_nvmet_tgtport *tgtp;
struct lpfc_register reg_data;
+ struct nvme_fc_local_port *localport;
+ struct lpfc_nvme_lport *lport;
+ struct lpfc_nvme_ctrl_stat *cstat;
void __iomem *eqdreg = phba->sli4_hba.u.if_type2.EQDregaddr;
vports = lpfc_create_vport_work_array(phba);
@@ -1299,14 +1302,25 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba)
tot += atomic_read(&tgtp->xmt_fcp_release);
tot = atomic_read(&tgtp->rcv_fcp_cmd_in) - tot;
} else {
- tot = atomic_read(&phba->fc4NvmeIoCmpls);
- data1 = atomic_read(
- &phba->fc4NvmeInputRequests);
- data2 = atomic_read(
- &phba->fc4NvmeOutputRequests);
- data3 = atomic_read(
- &phba->fc4NvmeControlRequests);
- tot = (data1 + data2 + data3) - tot;
+ localport = phba->pport->localport;
+ if (!localport || !localport->private)
+ goto skip_eqdelay;
+ lport = (struct lpfc_nvme_lport *)
+ localport->private;
+ tot = 0;
+ for (i = 0;
+ i < phba->cfg_nvme_io_channel; i++) {
+ cstat = &lport->cstat[i];
+ data1 = atomic_read(
+ &cstat->fc4NvmeInputRequests);
+ data2 = atomic_read(
+ &cstat->fc4NvmeOutputRequests);
+ data3 = atomic_read(
+ &cstat->fc4NvmeControlRequests);
+ tot += (data1 + data2 + data3);
+ tot -= atomic_read(
+ &cstat->fc4NvmeIoCmpls);
+ }
}
}
@@ -4265,32 +4279,24 @@ lpfc_sli4_fcf_redisc_wait_tmo(struct timer_list *t)
* @phba: pointer to lpfc hba data structure.
* @acqe_link: pointer to the async link completion queue entry.
*
- * This routine is to parse the SLI4 link-attention link fault code and
- * translate it into the base driver's read link attention mailbox command
- * status.
- *
- * Return: Link-attention status in terms of base driver's coding.
+ * This routine is to parse the SLI4 link-attention link fault code.
**/
-static uint16_t
+static void
lpfc_sli4_parse_latt_fault(struct lpfc_hba *phba,
struct lpfc_acqe_link *acqe_link)
{
- uint16_t latt_fault;
-
switch (bf_get(lpfc_acqe_link_fault, acqe_link)) {
case LPFC_ASYNC_LINK_FAULT_NONE:
case LPFC_ASYNC_LINK_FAULT_LOCAL:
case LPFC_ASYNC_LINK_FAULT_REMOTE:
- latt_fault = 0;
+ case LPFC_ASYNC_LINK_FAULT_LR_LRR:
break;
default:
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
- "0398 Invalid link fault code: x%x\n",
+ "0398 Unknown link fault code: x%x\n",
bf_get(lpfc_acqe_link_fault, acqe_link));
- latt_fault = MBXERR_ERROR;
break;
}
- return latt_fault;
}
/**
@@ -4565,9 +4571,12 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
* the READ_TOPOLOGY completion routine to continue without actually
* sending the READ_TOPOLOGY mailbox command to the port.
*/
- /* Parse and translate status field */
+ /* Initialize completion status */
mb = &pmb->u.mb;
- mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba, acqe_link);
+ mb->mbxStatus = MBX_SUCCESS;
+
+ /* Parse port fault information field */
+ lpfc_sli4_parse_latt_fault(phba, acqe_link);
/* Parse and translate link attention fields */
la = (struct lpfc_mbx_read_top *) &pmb->u.mb.un.varReadTop;
@@ -4695,10 +4704,12 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
break;
}
- /* Parse and translate status field */
+ /* Initialize completion status */
mb = &pmb->u.mb;
- mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba,
- (void *)acqe_fc);
+ mb->mbxStatus = MBX_SUCCESS;
+
+ /* Parse port fault information field */
+ lpfc_sli4_parse_latt_fault(phba, (void *)acqe_fc);
/* Parse and translate link attention fields */
la = (struct lpfc_mbx_read_top *)&pmb->u.mb.un.varReadTop;
@@ -5103,7 +5114,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
LOG_DISCOVERY,
- "2772 Issue FCF rediscover mabilbox "
+ "2772 Issue FCF rediscover mailbox "
"command failed, fail through to FCF "
"dead event\n");
spin_lock_irq(&phba->hbalock);
@@ -5195,7 +5206,7 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
lpfc_printf_log(phba, KERN_ERR, LOG_FIP |
LOG_DISCOVERY,
"2774 Issue FCF rediscover "
- "mabilbox command failed, "
+ "mailbox command failed, "
"through to CVL event\n");
spin_lock_irq(&phba->hbalock);
phba->fcf.fcf_flag &= ~FCF_ACVL_DISC;
@@ -5712,8 +5723,9 @@ lpfc_sli_driver_resource_setup(struct lpfc_hba *phba)
}
if (!phba->sli.sli3_ring)
- phba->sli.sli3_ring = kzalloc(LPFC_SLI3_MAX_RING *
- sizeof(struct lpfc_sli_ring), GFP_KERNEL);
+ phba->sli.sli3_ring = kcalloc(LPFC_SLI3_MAX_RING,
+ sizeof(struct lpfc_sli_ring),
+ GFP_KERNEL);
if (!phba->sli.sli3_ring)
return -ENOMEM;
@@ -5839,6 +5851,8 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
int fof_vectors = 0;
int extra;
uint64_t wwn;
+ u32 if_type;
+ u32 if_fam;
phba->sli4_hba.num_online_cpu = num_online_cpus();
phba->sli4_hba.num_present_cpu = lpfc_present_cpu;
@@ -6160,15 +6174,28 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
*/
rc = lpfc_get_sli4_parameters(phba, mboxq);
if (rc) {
+ if_type = bf_get(lpfc_sli_intf_if_type,
+ &phba->sli4_hba.sli_intf);
+ if_fam = bf_get(lpfc_sli_intf_sli_family,
+ &phba->sli4_hba.sli_intf);
if (phba->sli4_hba.extents_in_use &&
phba->sli4_hba.rpi_hdrs_in_use) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2999 Unsupported SLI4 Parameters "
"Extents and RPI headers enabled.\n");
+ if (if_type == LPFC_SLI_INTF_IF_TYPE_0 &&
+ if_fam == LPFC_SLI_INTF_FAMILY_BE2) {
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ rc = -EIO;
+ goto out_free_bsmbx;
+ }
+ }
+ if (!(if_type == LPFC_SLI_INTF_IF_TYPE_0 &&
+ if_fam == LPFC_SLI_INTF_FAMILY_BE2)) {
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ rc = -EIO;
+ goto out_free_bsmbx;
}
- mempool_free(mboxq, phba->mbox_mem_pool);
- rc = -EIO;
- goto out_free_bsmbx;
}
mempool_free(mboxq, phba->mbox_mem_pool);
@@ -6207,7 +6234,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
/* Allocate eligible FCF bmask memory for FCF roundrobin failover */
longs = (LPFC_SLI4_FCF_TBL_INDX_MAX + BITS_PER_LONG - 1)/BITS_PER_LONG;
- phba->fcf.fcf_rr_bmask = kzalloc(longs * sizeof(unsigned long),
+ phba->fcf.fcf_rr_bmask = kcalloc(longs, sizeof(unsigned long),
GFP_KERNEL);
if (!phba->fcf.fcf_rr_bmask) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -6406,8 +6433,11 @@ lpfc_setup_driver_resource_phase2(struct lpfc_hba *phba)
return error;
}
- /* workqueue for deferred irq use */
- phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM, 0);
+ /* The lpfc_wq workqueue for deferred irq use, is only used for SLI4 */
+ if (phba->sli_rev == LPFC_SLI_REV4)
+ phba->wq = alloc_workqueue("lpfc_wq", WQ_MEM_RECLAIM, 0);
+ else
+ phba->wq = NULL;
return 0;
}
@@ -6430,7 +6460,8 @@ lpfc_unset_driver_resource_phase2(struct lpfc_hba *phba)
}
/* Stop kernel worker thread */
- kthread_stop(phba->worker_thread);
+ if (phba->worker_thread)
+ kthread_stop(phba->worker_thread);
}
/**
@@ -6895,12 +6926,6 @@ lpfc_create_shost(struct lpfc_hba *phba)
atomic_set(&phba->fc4ScsiOutputRequests, 0);
atomic_set(&phba->fc4ScsiControlRequests, 0);
atomic_set(&phba->fc4ScsiIoCmpls, 0);
- atomic_set(&phba->fc4NvmeInputRequests, 0);
- atomic_set(&phba->fc4NvmeOutputRequests, 0);
- atomic_set(&phba->fc4NvmeControlRequests, 0);
- atomic_set(&phba->fc4NvmeIoCmpls, 0);
- atomic_set(&phba->fc4NvmeLsRequests, 0);
- atomic_set(&phba->fc4NvmeLsCmpls, 0);
vport = lpfc_create_port(phba, phba->brd_no, &phba->pcidev->dev);
if (!vport)
return -ENODEV;
@@ -7781,6 +7806,40 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
phba->sli4_hba.max_cfg_param.max_wq,
phba->sli4_hba.max_cfg_param.max_rq);
+ /*
+ * Calculate NVME queue resources based on how
+ * many WQ/CQs are available.
+ */
+ if (phba->cfg_enable_fc4_type & LPFC_ENABLE_NVME) {
+ length = phba->sli4_hba.max_cfg_param.max_wq;
+ if (phba->sli4_hba.max_cfg_param.max_cq <
+ phba->sli4_hba.max_cfg_param.max_wq)
+ length = phba->sli4_hba.max_cfg_param.max_cq;
+
+ /*
+ * Whats left after this can go toward NVME.
+ * The minus 6 accounts for ELS, NVME LS, MBOX
+ * fof plus a couple extra. When configured for
+ * NVMET, FCP io channel WQs are not created.
+ */
+ length -= 6;
+ if (!phba->nvmet_support)
+ length -= phba->cfg_fcp_io_channel;
+
+ if (phba->cfg_nvme_io_channel > length) {
+ lpfc_printf_log(
+ phba, KERN_ERR, LOG_SLI,
+ "2005 Reducing NVME IO channel to %d: "
+ "WQ %d CQ %d NVMEIO %d FCPIO %d\n",
+ length,
+ phba->sli4_hba.max_cfg_param.max_wq,
+ phba->sli4_hba.max_cfg_param.max_cq,
+ phba->cfg_nvme_io_channel,
+ phba->cfg_fcp_io_channel);
+
+ phba->cfg_nvme_io_channel = length;
+ }
+ }
}
if (rc)
@@ -10533,6 +10592,7 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
struct lpfc_pc_sli4_params *sli4_params;
uint32_t mbox_tmo;
int length;
+ bool exp_wqcq_pages = true;
struct lpfc_sli4_parameters *mbx_sli4_parameters;
/*
@@ -10659,8 +10719,15 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
phba->nvme_support, phba->nvme_embed_pbde,
phba->cfg_nvme_embed_cmd, phba->cfg_suppress_rsp);
+ if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_IF_TYPE_2) &&
+ (bf_get(lpfc_sli_intf_sli_family, &phba->sli4_hba.sli_intf) ==
+ LPFC_SLI_INTF_FAMILY_LNCR_A0))
+ exp_wqcq_pages = false;
+
if ((bf_get(cfg_cqpsize, mbx_sli4_parameters) & LPFC_CQ_16K_PAGE_SZ) &&
(bf_get(cfg_wqpsize, mbx_sli4_parameters) & LPFC_WQ_16K_PAGE_SZ) &&
+ exp_wqcq_pages &&
(sli4_params->wqsize & LPFC_WQ_SZ128_SUPPORT))
phba->enab_exp_wqcq_pages = 1;
else
@@ -11322,7 +11389,11 @@ lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset,
uint32_t magic_number, uint32_t ftype, uint32_t fid, uint32_t fsize,
const struct firmware *fw)
{
- if (offset == ADD_STATUS_FW_NOT_SUPPORTED)
+ if ((offset == ADD_STATUS_FW_NOT_SUPPORTED) ||
+ (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G6_FC &&
+ magic_number != MAGIC_NUMER_G6) ||
+ (phba->pcidev->device == PCI_DEVICE_ID_LANCER_G7_FC &&
+ magic_number != MAGIC_NUMER_G7))
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3030 This firmware version is not supported on "
"this HBA model. Device:%x Magic:%x Type:%x "
@@ -11719,6 +11790,7 @@ lpfc_pci_remove_one_s4(struct pci_dev *pdev)
lpfc_nvme_free(phba);
lpfc_free_iocb_list(phba);
+ lpfc_unset_driver_resource_phase2(phba);
lpfc_sli4_driver_resource_unset(phba);
/* Unmap adapter Control and Doorbell registers */
diff --git a/drivers/scsi/lpfc/lpfc_mem.c b/drivers/scsi/lpfc/lpfc_mem.c
index 4136166..0758edb 100644
--- a/drivers/scsi/lpfc/lpfc_mem.c
+++ b/drivers/scsi/lpfc/lpfc_mem.c
@@ -120,8 +120,9 @@ lpfc_mem_alloc(struct lpfc_hba *phba, int align)
if (!phba->lpfc_mbuf_pool)
goto fail_free_dma_buf_pool;
- pool->elements = kmalloc(sizeof(struct lpfc_dmabuf) *
- LPFC_MBUF_POOL_SIZE, GFP_KERNEL);
+ pool->elements = kmalloc_array(LPFC_MBUF_POOL_SIZE,
+ sizeof(struct lpfc_dmabuf),
+ GFP_KERNEL);
if (!pool->elements)
goto fail_free_lpfc_mbuf_pool;
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 0220606..1a80397 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -1936,31 +1936,14 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
goto out;
}
- /* When the rport rejected the FCP PRLI as unsupported.
- * This should only happen in Pt2Pt so an NVME PRLI
- * should be outstanding still.
- */
- if (npr && ndlp->nlp_flag & NLP_FCP_PRLI_RJT) {
+ /* Adjust the nlp_type accordingly if the PRLI failed */
+ if (npr)
ndlp->nlp_fc4_type &= ~NLP_FC4_FCP;
- goto out_err;
- }
-
- /* The LS Req had some error. Don't let this be a
- * target.
- */
- if ((ndlp->fc4_prli_sent == 1) &&
- (ndlp->nlp_state == NLP_STE_PRLI_ISSUE) &&
- (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_FCP_INITIATOR)))
- /* The FCP PRLI completed successfully but
- * the NVME PRLI failed. Since they are sent in
- * succession, allow the FCP to complete.
- */
- goto out_err;
+ if (nvpr)
+ ndlp->nlp_fc4_type &= ~NLP_FC4_NVME;
- ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
- ndlp->nlp_type |= NLP_FCP_INITIATOR;
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
- return ndlp->nlp_state;
+ /* We can't set the DSM state till BOTH PRLIs complete */
+ goto out_err;
}
if (npr && (npr->acceptRspCode == PRLI_REQ_EXECUTED) &&
@@ -1999,6 +1982,12 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (bf_get_be32(prli_disc, nvpr))
ndlp->nlp_type |= NLP_NVME_DISCOVERY;
+ /* This node is an NVME target. Adjust the command
+ * queue depth on this node to not exceed the available
+ * xris.
+ */
+ ndlp->cmd_qdepth = phba->sli4_hba.nvme_xri_max;
+
/*
* If prli_fba is set, the Target supports FirstBurst.
* If prli_fb_sz is 0, the FirstBurst size is unlimited,
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 378dca4..76a5a99 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -2,7 +2,7 @@
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
@@ -334,7 +334,14 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport)
"6146 remoteport delete of remoteport %p\n",
remoteport);
spin_lock_irq(&vport->phba->hbalock);
- ndlp->nrport = NULL;
+
+ /* The register rebind might have occurred before the delete
+ * downcall. Guard against this race.
+ */
+ if (ndlp->upcall_flags & NLP_WAIT_FOR_UNREG) {
+ ndlp->nrport = NULL;
+ ndlp->upcall_flags &= ~NLP_WAIT_FOR_UNREG;
+ }
spin_unlock_irq(&vport->phba->hbalock);
/* Remove original register reference. The host transport
@@ -357,15 +364,19 @@ lpfc_nvme_cmpl_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe,
struct lpfc_dmabuf *buf_ptr;
struct lpfc_nodelist *ndlp;
- atomic_inc(&vport->phba->fc4NvmeLsCmpls);
-
pnvme_lsreq = (struct nvmefc_ls_req *)cmdwqe->context2;
status = bf_get(lpfc_wcqe_c_status, wcqe) & LPFC_IOCB_STATUS_MASK;
- if (status) {
+
+ if (vport->localport) {
lport = (struct lpfc_nvme_lport *)vport->localport->private;
- if (bf_get(lpfc_wcqe_c_xb, wcqe))
- atomic_inc(&lport->cmpl_ls_xb);
- atomic_inc(&lport->cmpl_ls_err);
+ if (lport) {
+ atomic_inc(&lport->fc4NvmeLsCmpls);
+ if (status) {
+ if (bf_get(lpfc_wcqe_c_xb, wcqe))
+ atomic_inc(&lport->cmpl_ls_xb);
+ atomic_inc(&lport->cmpl_ls_err);
+ }
+ }
}
ndlp = (struct lpfc_nodelist *)cmdwqe->context1;
@@ -570,6 +581,9 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
lport = (struct lpfc_nvme_lport *)pnvme_lport->private;
rport = (struct lpfc_nvme_rport *)pnvme_rport->private;
+ if (unlikely(!lport) || unlikely(!rport))
+ return -EINVAL;
+
vport = lport->vport;
if (vport->load_flag & FC_UNLOADING)
@@ -639,7 +653,7 @@ lpfc_nvme_ls_req(struct nvme_fc_local_port *pnvme_lport,
pnvme_lsreq->rsplen, &pnvme_lsreq->rqstdma,
&pnvme_lsreq->rspdma);
- atomic_inc(&vport->phba->fc4NvmeLsRequests);
+ atomic_inc(&lport->fc4NvmeLsRequests);
/* Hardcode the wait to 30 seconds. Connections are failing otherwise.
* This code allows it all to work.
@@ -690,6 +704,8 @@ lpfc_nvme_ls_abort(struct nvme_fc_local_port *pnvme_lport,
struct lpfc_iocbq *wqe, *next_wqe;
lport = (struct lpfc_nvme_lport *)pnvme_lport->private;
+ if (unlikely(!lport))
+ return;
vport = lport->vport;
phba = vport->phba;
@@ -949,28 +965,48 @@ lpfc_nvme_io_cmd_wqe_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pwqeIn,
struct lpfc_nodelist *ndlp;
struct lpfc_nvme_fcpreq_priv *freqpriv;
struct lpfc_nvme_lport *lport;
+ struct lpfc_nvme_ctrl_stat *cstat;
unsigned long flags;
- uint32_t code, status;
+ uint32_t code, status, idx;
uint16_t cid, sqhd, data;
uint32_t *ptr;
/* Sanity check on return of outstanding command */
if (!lpfc_ncmd || !lpfc_ncmd->nvmeCmd || !lpfc_ncmd->nrport) {
+ if (!lpfc_ncmd) {
+ lpfc_printf_vlog(vport, KERN_ERR,
+ LOG_NODE | LOG_NVME_IOERR,
+ "6071 Null lpfc_ncmd pointer. No "
+ "release, skip completion\n");
+ return;
+ }
+
lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
- "6071 Completion pointers bad on wqe %p.\n",
- wcqe);
+ "6066 Missing cmpl ptrs: lpfc_ncmd %p, "
+ "nvmeCmd %p nrport %p\n",
+ lpfc_ncmd, lpfc_ncmd->nvmeCmd,
+ lpfc_ncmd->nrport);
+
+ /* Release the lpfc_ncmd regardless of the missing elements. */
+ lpfc_release_nvme_buf(phba, lpfc_ncmd);
return;
}
- atomic_inc(&phba->fc4NvmeIoCmpls);
-
nCmd = lpfc_ncmd->nvmeCmd;
rport = lpfc_ncmd->nrport;
status = bf_get(lpfc_wcqe_c_status, wcqe);
- if (status) {
+
+ if (vport->localport) {
lport = (struct lpfc_nvme_lport *)vport->localport->private;
- if (bf_get(lpfc_wcqe_c_xb, wcqe))
- atomic_inc(&lport->cmpl_fcp_xb);
- atomic_inc(&lport->cmpl_fcp_err);
+ if (lport) {
+ idx = lpfc_ncmd->cur_iocbq.hba_wqidx;
+ cstat = &lport->cstat[idx];
+ atomic_inc(&cstat->fc4NvmeIoCmpls);
+ if (status) {
+ if (bf_get(lpfc_wcqe_c_xb, wcqe))
+ atomic_inc(&lport->cmpl_fcp_xb);
+ atomic_inc(&lport->cmpl_fcp_err);
+ }
+ }
}
lpfc_nvmeio_data(phba, "NVME FCP CMPL: xri x%x stat x%x parm x%x\n",
@@ -1163,7 +1199,8 @@ out_err:
static int
lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
struct lpfc_nvme_buf *lpfc_ncmd,
- struct lpfc_nodelist *pnode)
+ struct lpfc_nodelist *pnode,
+ struct lpfc_nvme_ctrl_stat *cstat)
{
struct lpfc_hba *phba = vport->phba;
struct nvmefc_fcp_req *nCmd = lpfc_ncmd->nvmeCmd;
@@ -1201,7 +1238,7 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
} else {
wqe->fcp_iwrite.initial_xfer_len = 0;
}
- atomic_inc(&phba->fc4NvmeOutputRequests);
+ atomic_inc(&cstat->fc4NvmeOutputRequests);
} else {
/* From the iread template, initialize words 7 - 11 */
memcpy(&wqe->words[7],
@@ -1214,13 +1251,13 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport,
/* Word 5 */
wqe->fcp_iread.rsrvd5 = 0;
- atomic_inc(&phba->fc4NvmeInputRequests);
+ atomic_inc(&cstat->fc4NvmeInputRequests);
}
} else {
/* From the icmnd template, initialize words 4 - 11 */
memcpy(&wqe->words[4], &lpfc_icmnd_cmd_template.words[4],
sizeof(uint32_t) * 8);
- atomic_inc(&phba->fc4NvmeControlRequests);
+ atomic_inc(&cstat->fc4NvmeControlRequests);
}
/*
* Finish initializing those WQE fields that are independent
@@ -1400,7 +1437,9 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
{
int ret = 0;
int expedite = 0;
+ int idx;
struct lpfc_nvme_lport *lport;
+ struct lpfc_nvme_ctrl_stat *cstat;
struct lpfc_vport *vport;
struct lpfc_hba *phba;
struct lpfc_nodelist *ndlp;
@@ -1425,9 +1464,10 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
vport = lport->vport;
if (unlikely(!hw_queue_handle)) {
- lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_ABTS,
- "6129 Fail Abort, NULL hw_queue_handle\n");
- ret = -EINVAL;
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+ "6117 Fail IO, NULL hw_queue_handle\n");
+ atomic_inc(&lport->xmt_fcp_err);
+ ret = -EBUSY;
goto out_fail;
}
@@ -1439,12 +1479,18 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
}
if (vport->load_flag & FC_UNLOADING) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+ "6124 Fail IO, Driver unload\n");
+ atomic_inc(&lport->xmt_fcp_err);
ret = -ENODEV;
goto out_fail;
}
freqpriv = pnvme_fcreq->private;
if (unlikely(!freqpriv)) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+ "6158 Fail IO, NULL request data\n");
+ atomic_inc(&lport->xmt_fcp_err);
ret = -EINVAL;
goto out_fail;
}
@@ -1462,32 +1508,26 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
*/
ndlp = rport->ndlp;
if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
- "6053 rport %p, ndlp %p, DID x%06x "
- "ndlp not ready.\n",
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_NVME_IOERR,
+ "6053 Fail IO, ndlp not ready: rport %p "
+ "ndlp %p, DID x%06x\n",
rport, ndlp, pnvme_rport->port_id);
-
- ndlp = lpfc_findnode_did(vport, pnvme_rport->port_id);
- if (!ndlp) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
- "6066 Missing node for DID %x\n",
- pnvme_rport->port_id);
- atomic_inc(&lport->xmt_fcp_bad_ndlp);
- ret = -ENODEV;
- goto out_fail;
- }
+ atomic_inc(&lport->xmt_fcp_err);
+ ret = -EBUSY;
+ goto out_fail;
}
/* The remote node has to be a mapped target or it's an error. */
if ((ndlp->nlp_type & NLP_NVME_TARGET) &&
(ndlp->nlp_state != NLP_STE_MAPPED_NODE)) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_NODE | LOG_NVME_IOERR,
- "6036 rport %p, DID x%06x not ready for "
- "IO. State x%x, Type x%x\n",
- rport, pnvme_rport->port_id,
- ndlp->nlp_state, ndlp->nlp_type);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_NVME_IOERR,
+ "6036 Fail IO, DID x%06x not ready for "
+ "IO. State x%x, Type x%x Flg x%x\n",
+ pnvme_rport->port_id,
+ ndlp->nlp_state, ndlp->nlp_type,
+ ndlp->upcall_flags);
atomic_inc(&lport->xmt_fcp_bad_ndlp);
- ret = -ENODEV;
+ ret = -EBUSY;
goto out_fail;
}
@@ -1508,6 +1548,12 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
*/
if ((atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth) &&
!expedite) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+ "6174 Fail IO, ndlp qdepth exceeded: "
+ "idx %d DID %x pend %d qdepth %d\n",
+ lpfc_queue_info->index, ndlp->nlp_DID,
+ atomic_read(&ndlp->cmd_pending),
+ ndlp->cmd_qdepth);
atomic_inc(&lport->xmt_fcp_qdepth);
ret = -EBUSY;
goto out_fail;
@@ -1517,8 +1563,9 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
if (lpfc_ncmd == NULL) {
atomic_inc(&lport->xmt_fcp_noxri);
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
- "6065 driver's buffer pool is empty, "
- "IO failed\n");
+ "6065 Fail IO, driver buffer pool is empty: "
+ "idx %d DID %x\n",
+ lpfc_queue_info->index, ndlp->nlp_DID);
ret = -EBUSY;
goto out_fail;
}
@@ -1543,15 +1590,6 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
lpfc_ncmd->ndlp = ndlp;
lpfc_ncmd->start_time = jiffies;
- lpfc_nvme_prep_io_cmd(vport, lpfc_ncmd, ndlp);
- ret = lpfc_nvme_prep_io_dma(vport, lpfc_ncmd);
- if (ret) {
- ret = -ENOMEM;
- goto out_free_nvme_buf;
- }
-
- atomic_inc(&ndlp->cmd_pending);
-
/*
* Issue the IO on the WQ indicated by index in the hw_queue_handle.
* This identfier was create in our hardware queue create callback
@@ -1560,7 +1598,23 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
* index to use and that they have affinitized a CPU to this hardware
* queue. A hardware queue maps to a driver MSI-X vector/EQ/CQ/WQ.
*/
- lpfc_ncmd->cur_iocbq.hba_wqidx = lpfc_queue_info->index;
+ idx = lpfc_queue_info->index;
+ lpfc_ncmd->cur_iocbq.hba_wqidx = idx;
+ cstat = &lport->cstat[idx];
+
+ lpfc_nvme_prep_io_cmd(vport, lpfc_ncmd, ndlp, cstat);
+ ret = lpfc_nvme_prep_io_dma(vport, lpfc_ncmd);
+ if (ret) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
+ "6175 Fail IO, Prep DMA: "
+ "idx %d DID %x\n",
+ lpfc_queue_info->index, ndlp->nlp_DID);
+ atomic_inc(&lport->xmt_fcp_err);
+ ret = -ENOMEM;
+ goto out_free_nvme_buf;
+ }
+
+ atomic_inc(&ndlp->cmd_pending);
lpfc_nvmeio_data(phba, "NVME FCP XMIT: xri x%x idx %d to %06x\n",
lpfc_ncmd->cur_iocbq.sli4_xritag,
@@ -1571,7 +1625,7 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
atomic_inc(&lport->xmt_fcp_wqerr);
atomic_dec(&ndlp->cmd_pending);
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_IOERR,
- "6113 FCP could not issue WQE err %x "
+ "6113 Fail IO, Could not issue WQE err %x "
"sid: x%x did: x%x oxid: x%x\n",
ret, vport->fc_myDID, ndlp->nlp_DID,
lpfc_ncmd->cur_iocbq.sli4_xritag);
@@ -1605,11 +1659,11 @@ lpfc_nvme_fcp_io_submit(struct nvme_fc_local_port *pnvme_lport,
out_free_nvme_buf:
if (lpfc_ncmd->nvmeCmd->sg_cnt) {
if (lpfc_ncmd->nvmeCmd->io_dir == NVMEFC_FCP_WRITE)
- atomic_dec(&phba->fc4NvmeOutputRequests);
+ atomic_dec(&cstat->fc4NvmeOutputRequests);
else
- atomic_dec(&phba->fc4NvmeInputRequests);
+ atomic_dec(&cstat->fc4NvmeInputRequests);
} else
- atomic_dec(&phba->fc4NvmeControlRequests);
+ atomic_dec(&cstat->fc4NvmeControlRequests);
lpfc_release_nvme_buf(phba, lpfc_ncmd);
out_fail:
return ret;
@@ -2390,7 +2444,8 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
struct nvme_fc_port_info nfcp_info;
struct nvme_fc_local_port *localport;
struct lpfc_nvme_lport *lport;
- int len;
+ struct lpfc_nvme_ctrl_stat *cstat;
+ int len, i;
/* Initialize this localport instance. The vport wwn usage ensures
* that NPIV is accounted for.
@@ -2414,6 +2469,11 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
lpfc_nvme_template.max_sgl_segments = phba->cfg_nvme_seg_cnt + 1;
lpfc_nvme_template.max_hw_queues = phba->cfg_nvme_io_channel;
+ cstat = kmalloc((sizeof(struct lpfc_nvme_ctrl_stat) *
+ phba->cfg_nvme_io_channel), GFP_KERNEL);
+ if (!cstat)
+ return -ENOMEM;
+
/* localport is allocated from the stack, but the registration
* call allocates heap memory as well as the private area.
*/
@@ -2436,11 +2496,13 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
lport = (struct lpfc_nvme_lport *)localport->private;
vport->localport = localport;
lport->vport = vport;
+ lport->cstat = cstat;
vport->nvmei_support = 1;
atomic_set(&lport->xmt_fcp_noxri, 0);
atomic_set(&lport->xmt_fcp_bad_ndlp, 0);
atomic_set(&lport->xmt_fcp_qdepth, 0);
+ atomic_set(&lport->xmt_fcp_err, 0);
atomic_set(&lport->xmt_fcp_wqerr, 0);
atomic_set(&lport->xmt_fcp_abort, 0);
atomic_set(&lport->xmt_ls_abort, 0);
@@ -2449,6 +2511,16 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
atomic_set(&lport->cmpl_fcp_err, 0);
atomic_set(&lport->cmpl_ls_xb, 0);
atomic_set(&lport->cmpl_ls_err, 0);
+ atomic_set(&lport->fc4NvmeLsRequests, 0);
+ atomic_set(&lport->fc4NvmeLsCmpls, 0);
+
+ for (i = 0; i < phba->cfg_nvme_io_channel; i++) {
+ cstat = &lport->cstat[i];
+ atomic_set(&cstat->fc4NvmeInputRequests, 0);
+ atomic_set(&cstat->fc4NvmeOutputRequests, 0);
+ atomic_set(&cstat->fc4NvmeControlRequests, 0);
+ atomic_set(&cstat->fc4NvmeIoCmpls, 0);
+ }
/* Don't post more new bufs if repost already recovered
* the nvme sgls.
@@ -2458,6 +2530,8 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
phba->sli4_hba.nvme_xri_max);
vport->phba->total_nvme_bufs += len;
}
+ } else {
+ kfree(cstat);
}
return ret;
@@ -2520,6 +2594,7 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
#if (IS_ENABLED(CONFIG_NVME_FC))
struct nvme_fc_local_port *localport;
struct lpfc_nvme_lport *lport;
+ struct lpfc_nvme_ctrl_stat *cstat;
int ret;
if (vport->nvmei_support == 0)
@@ -2528,6 +2603,7 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
localport = vport->localport;
vport->localport = NULL;
lport = (struct lpfc_nvme_lport *)localport->private;
+ cstat = lport->cstat;
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME,
"6011 Destroying NVME localport %p\n",
@@ -2543,6 +2619,7 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
* indefinitely or succeeds
*/
lpfc_nvme_lport_unreg_wait(vport, lport);
+ kfree(cstat);
/* Regardless of the unregister upcall response, clear
* nvmei_support. All rports are unregistered and the
@@ -2607,6 +2684,7 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
struct nvme_fc_local_port *localport;
struct lpfc_nvme_lport *lport;
struct lpfc_nvme_rport *rport;
+ struct lpfc_nvme_rport *oldrport;
struct nvme_fc_remote_port *remote_port;
struct nvme_fc_port_info rpinfo;
struct lpfc_nodelist *prev_ndlp;
@@ -2639,7 +2717,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
- if (!ndlp->nrport)
+
+ oldrport = lpfc_ndlp_get_nrport(ndlp);
+ if (!oldrport)
lpfc_nlp_get(ndlp);
ret = nvme_fc_register_remoteport(localport, &rpinfo, &remote_port);
@@ -2648,9 +2728,15 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* a resume of the existing rport. Else this is a
* new rport.
*/
+ /* Guard against an unregister/reregister
+ * race that leaves the WAIT flag set.
+ */
+ spin_lock_irq(&vport->phba->hbalock);
+ ndlp->upcall_flags &= ~NLP_WAIT_FOR_UNREG;
+ spin_unlock_irq(&vport->phba->hbalock);
rport = remote_port->private;
- if (ndlp->nrport) {
- if (ndlp->nrport == remote_port->private) {
+ if (oldrport) {
+ if (oldrport == remote_port->private) {
/* Same remoteport. Just reuse. */
lpfc_printf_vlog(ndlp->vport, KERN_INFO,
LOG_NVME_DISC,
@@ -2674,11 +2760,20 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
*/
spin_lock_irq(&vport->phba->hbalock);
ndlp->nrport = NULL;
+ ndlp->upcall_flags &= ~NLP_WAIT_FOR_UNREG;
spin_unlock_irq(&vport->phba->hbalock);
rport->ndlp = NULL;
rport->remoteport = NULL;
- if (prev_ndlp)
- lpfc_nlp_put(ndlp);
+
+ /* Reference only removed if previous NDLP is no longer
+ * active. It might be just a swap and removing the
+ * reference would cause a premature cleanup.
+ */
+ if (prev_ndlp && prev_ndlp != ndlp) {
+ if ((!NLP_CHK_NODE_ACT(prev_ndlp)) ||
+ (!prev_ndlp->nrport))
+ lpfc_nlp_put(prev_ndlp);
+ }
}
/* Clean bind the rport to the ndlp. */
@@ -2746,7 +2841,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
if (!lport)
goto input_err;
- rport = ndlp->nrport;
+ rport = lpfc_ndlp_get_nrport(ndlp);
if (!rport)
goto input_err;
@@ -2767,6 +2862,15 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* The transport will update it.
*/
ndlp->upcall_flags |= NLP_WAIT_FOR_UNREG;
+
+ /* Don't let the host nvme transport keep sending keep-alives
+ * on this remoteport. Vport is unloading, no recovery. The
+ * return values is ignored. The upcall is a courtesy to the
+ * transport.
+ */
+ if (vport->load_flag & FC_UNLOADING)
+ (void)nvme_fc_set_remoteport_devloss(remoteport, 0);
+
ret = nvme_fc_unregister_remoteport(remoteport);
if (ret != 0) {
lpfc_nlp_put(ndlp);
diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h
index 9216653..04bd463d 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.h
+++ b/drivers/scsi/lpfc/lpfc_nvme.h
@@ -2,7 +2,7 @@
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
@@ -30,21 +30,36 @@
#define LPFC_NVME_FB_SHIFT 9
#define LPFC_NVME_MAX_FB (1 << 20) /* 1M */
+#define lpfc_ndlp_get_nrport(ndlp) \
+ ((!ndlp->nrport || (ndlp->upcall_flags & NLP_WAIT_FOR_UNREG)) \
+ ? NULL : ndlp->nrport)
+
struct lpfc_nvme_qhandle {
uint32_t index; /* WQ index to use */
uint32_t qidx; /* queue index passed to create */
uint32_t cpu_id; /* current cpu id at time of create */
};
+struct lpfc_nvme_ctrl_stat {
+ atomic_t fc4NvmeInputRequests;
+ atomic_t fc4NvmeOutputRequests;
+ atomic_t fc4NvmeControlRequests;
+ atomic_t fc4NvmeIoCmpls;
+};
+
/* Declare nvme-based local and remote port definitions. */
struct lpfc_nvme_lport {
struct lpfc_vport *vport;
struct completion lport_unreg_done;
/* Add stats counters here */
+ struct lpfc_nvme_ctrl_stat *cstat;
+ atomic_t fc4NvmeLsRequests;
+ atomic_t fc4NvmeLsCmpls;
atomic_t xmt_fcp_noxri;
atomic_t xmt_fcp_bad_ndlp;
atomic_t xmt_fcp_qdepth;
atomic_t xmt_fcp_wqerr;
+ atomic_t xmt_fcp_err;
atomic_t xmt_fcp_abort;
atomic_t xmt_ls_abort;
atomic_t xmt_ls_err;
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.h b/drivers/scsi/lpfc/lpfc_nvmet.h
index c1bcef3..81f520a 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.h
+++ b/drivers/scsi/lpfc/lpfc_nvmet.h
@@ -22,8 +22,10 @@
********************************************************************/
#define LPFC_NVMET_DEFAULT_SEGS (64 + 1) /* 256K IOs */
-#define LPFC_NVMET_RQE_DEF_COUNT 512
-#define LPFC_NVMET_SUCCESS_LEN 12
+#define LPFC_NVMET_RQE_MIN_POST 128
+#define LPFC_NVMET_RQE_DEF_POST 512
+#define LPFC_NVMET_RQE_DEF_COUNT 2048
+#define LPFC_NVMET_SUCCESS_LEN 12
#define LPFC_NVMET_MRQ_OFF 0xffff
#define LPFC_NVMET_MRQ_AUTO 0
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 050f044..a94fb9f 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -2,7 +2,7 @@
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
@@ -1021,7 +1021,7 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
if (lpfc_test_rrq_active(phba, ndlp,
lpfc_cmd->cur_iocbq.sli4_lxritag))
continue;
- list_del(&lpfc_cmd->list);
+ list_del_init(&lpfc_cmd->list);
found = 1;
break;
}
@@ -1036,7 +1036,7 @@ lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
if (lpfc_test_rrq_active(
phba, ndlp, lpfc_cmd->cur_iocbq.sli4_lxritag))
continue;
- list_del(&lpfc_cmd->list);
+ list_del_init(&lpfc_cmd->list);
found = 1;
break;
}
@@ -3983,9 +3983,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
}
#endif
- if (pnode && NLP_CHK_NODE_ACT(pnode))
- atomic_dec(&pnode->cmd_pending);
-
if (lpfc_cmd->status) {
if (lpfc_cmd->status == IOSTAT_LOCAL_REJECT &&
(lpfc_cmd->result & IOERR_DRVR_MASK))
@@ -4125,6 +4122,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
spin_lock_irqsave(shost->host_lock, flags);
if (pnode && NLP_CHK_NODE_ACT(pnode)) {
+ atomic_dec(&pnode->cmd_pending);
if (pnode->cmd_qdepth >
atomic_read(&pnode->cmd_pending) &&
(atomic_read(&pnode->cmd_pending) >
@@ -4138,16 +4136,8 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
}
spin_unlock_irqrestore(shost->host_lock, flags);
} else if (pnode && NLP_CHK_NODE_ACT(pnode)) {
- if ((pnode->cmd_qdepth != vport->cfg_tgt_queue_depth) &&
- time_after(jiffies, pnode->last_change_time +
- msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) {
- spin_lock_irqsave(shost->host_lock, flags);
- pnode->cmd_qdepth = vport->cfg_tgt_queue_depth;
- pnode->last_change_time = jiffies;
- spin_unlock_irqrestore(shost->host_lock, flags);
- }
+ atomic_dec(&pnode->cmd_pending);
}
-
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
spin_lock_irqsave(&phba->hbalock, flags);
@@ -4591,6 +4581,8 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
ndlp->nlp_portname.u.wwn[7]);
goto out_tgt_busy;
}
+ atomic_inc(&ndlp->cmd_pending);
+
lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp);
if (lpfc_cmd == NULL) {
lpfc_rampdown_queue_depth(phba);
@@ -4643,11 +4635,9 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
lpfc_scsi_prep_cmnd(vport, lpfc_cmd, ndlp);
- atomic_inc(&ndlp->cmd_pending);
err = lpfc_sli_issue_iocb(phba, LPFC_FCP_RING,
&lpfc_cmd->cur_iocbq, SLI_IOCB_RET_IOCB);
if (err) {
- atomic_dec(&ndlp->cmd_pending);
lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP,
"3376 FCP could not issue IOCB err %x"
"FCP cmd x%x <%d/%llu> "
@@ -4691,6 +4681,7 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
lpfc_release_scsi_buf(phba, lpfc_cmd);
out_host_busy:
+ atomic_dec(&ndlp->cmd_pending);
return SCSI_MLQUEUE_HOST_BUSY;
out_tgt_busy:
@@ -4725,7 +4716,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
int ret = SUCCESS, status = 0;
struct lpfc_sli_ring *pring_s4;
int ret_val;
- unsigned long flags, iflags;
+ unsigned long flags;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(waitq);
status = fc_block_scsi_eh(cmnd);
@@ -4825,16 +4816,16 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
abtsiocb->vport = vport;
if (phba->sli_rev == LPFC_SLI_REV4) {
- pring_s4 = lpfc_sli4_calc_ring(phba, iocb);
+ pring_s4 = lpfc_sli4_calc_ring(phba, abtsiocb);
if (pring_s4 == NULL) {
ret = FAILED;
goto out_unlock;
}
/* Note: both hbalock and ring_lock must be set here */
- spin_lock_irqsave(&pring_s4->ring_lock, iflags);
+ spin_lock(&pring_s4->ring_lock);
ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno,
abtsiocb, 0);
- spin_unlock_irqrestore(&pring_s4->ring_lock, iflags);
+ spin_unlock(&pring_s4->ring_lock);
} else {
ret_val = __lpfc_sli_issue_iocb(phba, LPFC_FCP_RING,
abtsiocb, 0);
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h
index 8e38e02..c38e4da 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.h
+++ b/drivers/scsi/lpfc/lpfc_scsi.h
@@ -2,7 +2,7 @@
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
+ * “Broadcom” refers to Broadcom Inc and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index cb17e2b..6f3c00a 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -2,7 +2,7 @@
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
@@ -96,6 +96,34 @@ lpfc_get_iocb_from_iocbq(struct lpfc_iocbq *iocbq)
return &iocbq->iocb;
}
+#if defined(CONFIG_64BIT) && defined(__LITTLE_ENDIAN)
+/**
+ * lpfc_sli4_pcimem_bcopy - SLI4 memory copy function
+ * @srcp: Source memory pointer.
+ * @destp: Destination memory pointer.
+ * @cnt: Number of words required to be copied.
+ * Must be a multiple of sizeof(uint64_t)
+ *
+ * This function is used for copying data between driver memory
+ * and the SLI WQ. This function also changes the endianness
+ * of each word if native endianness is different from SLI
+ * endianness. This function can be called with or without
+ * lock.
+ **/
+void
+lpfc_sli4_pcimem_bcopy(void *srcp, void *destp, uint32_t cnt)
+{
+ uint64_t *src = srcp;
+ uint64_t *dest = destp;
+ int i;
+
+ for (i = 0; i < (int)cnt; i += sizeof(uint64_t))
+ *dest++ = *src++;
+}
+#else
+#define lpfc_sli4_pcimem_bcopy(a, b, c) lpfc_sli_pcimem_bcopy(a, b, c)
+#endif
+
/**
* lpfc_sli4_wq_put - Put a Work Queue Entry on an Work Queue
* @q: The Work Queue to operate on.
@@ -137,7 +165,7 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe128 *wqe)
bf_set(wqe_wqec, &wqe->generic.wqe_com, 0);
if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED)
bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id);
- lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
+ lpfc_sli4_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
if (q->dpp_enable && q->phba->cfg_enable_dpp) {
/* write to DPP aperture taking advatage of Combined Writes */
tmp = (uint8_t *)temp_wqe;
@@ -240,7 +268,7 @@ lpfc_sli4_mq_put(struct lpfc_queue *q, struct lpfc_mqe *mqe)
/* If the host has not yet processed the next entry then we are done */
if (((q->host_index + 1) % q->entry_count) == q->hba_index)
return -ENOMEM;
- lpfc_sli_pcimem_bcopy(mqe, temp_mqe, q->entry_size);
+ lpfc_sli4_pcimem_bcopy(mqe, temp_mqe, q->entry_size);
/* Save off the mailbox pointer for completion */
q->phba->mbox = (MAILBOX_t *)temp_mqe;
@@ -663,8 +691,8 @@ lpfc_sli4_rq_put(struct lpfc_queue *hq, struct lpfc_queue *dq,
/* If the host has not yet processed the next entry then we are done */
if (((hq_put_index + 1) % hq->entry_count) == hq->hba_index)
return -EBUSY;
- lpfc_sli_pcimem_bcopy(hrqe, temp_hrqe, hq->entry_size);
- lpfc_sli_pcimem_bcopy(drqe, temp_drqe, dq->entry_size);
+ lpfc_sli4_pcimem_bcopy(hrqe, temp_hrqe, hq->entry_size);
+ lpfc_sli4_pcimem_bcopy(drqe, temp_drqe, dq->entry_size);
/* Update the host index to point to the next slot */
hq->host_index = ((hq_put_index + 1) % hq->entry_count);
@@ -1692,7 +1720,7 @@ lpfc_sli_next_iotag(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq)
- LPFC_IOCBQ_LOOKUP_INCREMENT)) {
new_len = psli->iocbq_lookup_len + LPFC_IOCBQ_LOOKUP_INCREMENT;
spin_unlock_irq(&phba->hbalock);
- new_arr = kzalloc(new_len * sizeof (struct lpfc_iocbq *),
+ new_arr = kcalloc(new_len, sizeof(struct lpfc_iocbq *),
GFP_KERNEL);
if (new_arr) {
spin_lock_irq(&phba->hbalock);
@@ -5114,16 +5142,17 @@ lpfc_sli_hba_setup(struct lpfc_hba *phba)
*/
if ((phba->vpi_bmask == NULL) && (phba->vpi_ids == NULL)) {
longs = (phba->max_vpi + BITS_PER_LONG) / BITS_PER_LONG;
- phba->vpi_bmask = kzalloc(longs * sizeof(unsigned long),
+ phba->vpi_bmask = kcalloc(longs,
+ sizeof(unsigned long),
GFP_KERNEL);
if (!phba->vpi_bmask) {
rc = -ENOMEM;
goto lpfc_sli_hba_setup_error;
}
- phba->vpi_ids = kzalloc(
- (phba->max_vpi+1) * sizeof(uint16_t),
- GFP_KERNEL);
+ phba->vpi_ids = kcalloc(phba->max_vpi + 1,
+ sizeof(uint16_t),
+ GFP_KERNEL);
if (!phba->vpi_ids) {
kfree(phba->vpi_bmask);
rc = -ENOMEM;
@@ -5808,14 +5837,14 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type)
length = sizeof(struct lpfc_rsrc_blks);
switch (type) {
case LPFC_RSC_TYPE_FCOE_RPI:
- phba->sli4_hba.rpi_bmask = kzalloc(longs *
+ phba->sli4_hba.rpi_bmask = kcalloc(longs,
sizeof(unsigned long),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.rpi_bmask)) {
rc = -ENOMEM;
goto err_exit;
}
- phba->sli4_hba.rpi_ids = kzalloc(rsrc_id_cnt *
+ phba->sli4_hba.rpi_ids = kcalloc(rsrc_id_cnt,
sizeof(uint16_t),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.rpi_ids)) {
@@ -5837,15 +5866,13 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type)
ext_blk_list = &phba->sli4_hba.lpfc_rpi_blk_list;
break;
case LPFC_RSC_TYPE_FCOE_VPI:
- phba->vpi_bmask = kzalloc(longs *
- sizeof(unsigned long),
+ phba->vpi_bmask = kcalloc(longs, sizeof(unsigned long),
GFP_KERNEL);
if (unlikely(!phba->vpi_bmask)) {
rc = -ENOMEM;
goto err_exit;
}
- phba->vpi_ids = kzalloc(rsrc_id_cnt *
- sizeof(uint16_t),
+ phba->vpi_ids = kcalloc(rsrc_id_cnt, sizeof(uint16_t),
GFP_KERNEL);
if (unlikely(!phba->vpi_ids)) {
kfree(phba->vpi_bmask);
@@ -5859,7 +5886,7 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type)
ext_blk_list = &phba->lpfc_vpi_blk_list;
break;
case LPFC_RSC_TYPE_FCOE_XRI:
- phba->sli4_hba.xri_bmask = kzalloc(longs *
+ phba->sli4_hba.xri_bmask = kcalloc(longs,
sizeof(unsigned long),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.xri_bmask)) {
@@ -5867,7 +5894,7 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type)
goto err_exit;
}
phba->sli4_hba.max_cfg_param.xri_used = 0;
- phba->sli4_hba.xri_ids = kzalloc(rsrc_id_cnt *
+ phba->sli4_hba.xri_ids = kcalloc(rsrc_id_cnt,
sizeof(uint16_t),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.xri_ids)) {
@@ -5882,14 +5909,14 @@ lpfc_sli4_alloc_extent(struct lpfc_hba *phba, uint16_t type)
ext_blk_list = &phba->sli4_hba.lpfc_xri_blk_list;
break;
case LPFC_RSC_TYPE_FCOE_VFI:
- phba->sli4_hba.vfi_bmask = kzalloc(longs *
+ phba->sli4_hba.vfi_bmask = kcalloc(longs,
sizeof(unsigned long),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.vfi_bmask)) {
rc = -ENOMEM;
goto err_exit;
}
- phba->sli4_hba.vfi_ids = kzalloc(rsrc_id_cnt *
+ phba->sli4_hba.vfi_ids = kcalloc(rsrc_id_cnt,
sizeof(uint16_t),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.vfi_ids)) {
@@ -6222,15 +6249,14 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
}
base = phba->sli4_hba.max_cfg_param.rpi_base;
longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG;
- phba->sli4_hba.rpi_bmask = kzalloc(longs *
+ phba->sli4_hba.rpi_bmask = kcalloc(longs,
sizeof(unsigned long),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.rpi_bmask)) {
rc = -ENOMEM;
goto err_exit;
}
- phba->sli4_hba.rpi_ids = kzalloc(count *
- sizeof(uint16_t),
+ phba->sli4_hba.rpi_ids = kcalloc(count, sizeof(uint16_t),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.rpi_ids)) {
rc = -ENOMEM;
@@ -6251,15 +6277,13 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
}
base = phba->sli4_hba.max_cfg_param.vpi_base;
longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG;
- phba->vpi_bmask = kzalloc(longs *
- sizeof(unsigned long),
+ phba->vpi_bmask = kcalloc(longs, sizeof(unsigned long),
GFP_KERNEL);
if (unlikely(!phba->vpi_bmask)) {
rc = -ENOMEM;
goto free_rpi_ids;
}
- phba->vpi_ids = kzalloc(count *
- sizeof(uint16_t),
+ phba->vpi_ids = kcalloc(count, sizeof(uint16_t),
GFP_KERNEL);
if (unlikely(!phba->vpi_ids)) {
rc = -ENOMEM;
@@ -6280,7 +6304,7 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
}
base = phba->sli4_hba.max_cfg_param.xri_base;
longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG;
- phba->sli4_hba.xri_bmask = kzalloc(longs *
+ phba->sli4_hba.xri_bmask = kcalloc(longs,
sizeof(unsigned long),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.xri_bmask)) {
@@ -6288,8 +6312,7 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
goto free_vpi_ids;
}
phba->sli4_hba.max_cfg_param.xri_used = 0;
- phba->sli4_hba.xri_ids = kzalloc(count *
- sizeof(uint16_t),
+ phba->sli4_hba.xri_ids = kcalloc(count, sizeof(uint16_t),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.xri_ids)) {
rc = -ENOMEM;
@@ -6310,15 +6333,14 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba)
}
base = phba->sli4_hba.max_cfg_param.vfi_base;
longs = (count + BITS_PER_LONG - 1) / BITS_PER_LONG;
- phba->sli4_hba.vfi_bmask = kzalloc(longs *
+ phba->sli4_hba.vfi_bmask = kcalloc(longs,
sizeof(unsigned long),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.vfi_bmask)) {
rc = -ENOMEM;
goto free_xri_ids;
}
- phba->sli4_hba.vfi_ids = kzalloc(count *
- sizeof(uint16_t),
+ phba->sli4_hba.vfi_ids = kcalloc(count, sizeof(uint16_t),
GFP_KERNEL);
if (unlikely(!phba->sli4_hba.vfi_ids)) {
rc = -ENOMEM;
@@ -7199,7 +7221,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba)
lpfc_post_rq_buffer(
phba, phba->sli4_hba.nvmet_mrq_hdr[i],
phba->sli4_hba.nvmet_mrq_data[i],
- LPFC_NVMET_RQE_DEF_COUNT, i);
+ phba->cfg_nvmet_mrq_post, i);
}
}
@@ -8185,8 +8207,8 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
*/
mbx_cmnd = bf_get(lpfc_mqe_command, mb);
memset(phba->sli4_hba.bmbx.avirt, 0, sizeof(struct lpfc_bmbx_create));
- lpfc_sli_pcimem_bcopy(mb, phba->sli4_hba.bmbx.avirt,
- sizeof(struct lpfc_mqe));
+ lpfc_sli4_pcimem_bcopy(mb, phba->sli4_hba.bmbx.avirt,
+ sizeof(struct lpfc_mqe));
/* Post the high mailbox dma address to the port and wait for ready. */
dma_address = &phba->sli4_hba.bmbx.dma_address;
@@ -8210,11 +8232,11 @@ lpfc_sli4_post_sync_mbox(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
* If so, update the mailbox status so that the upper layers
* can complete the request normally.
*/
- lpfc_sli_pcimem_bcopy(phba->sli4_hba.bmbx.avirt, mb,
- sizeof(struct lpfc_mqe));
+ lpfc_sli4_pcimem_bcopy(phba->sli4_hba.bmbx.avirt, mb,
+ sizeof(struct lpfc_mqe));
mbox_rgn = (struct lpfc_bmbx_create *) phba->sli4_hba.bmbx.avirt;
- lpfc_sli_pcimem_bcopy(&mbox_rgn->mcqe, &mboxq->mcqe,
- sizeof(struct lpfc_mcqe));
+ lpfc_sli4_pcimem_bcopy(&mbox_rgn->mcqe, &mboxq->mcqe,
+ sizeof(struct lpfc_mcqe));
mcqe_status = bf_get(lpfc_mcqe_status, &mbox_rgn->mcqe);
/*
* When the CQE status indicates a failure and the mailbox status
@@ -11300,11 +11322,11 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
unsigned long iflags;
struct lpfc_sli_ring *pring_s4;
- spin_lock_irq(&phba->hbalock);
+ spin_lock_irqsave(&phba->hbalock, iflags);
/* all I/Os are in process of being flushed */
if (phba->hba_flag & HBA_FCP_IOQ_FLUSH) {
- spin_unlock_irq(&phba->hbalock);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
return 0;
}
sum = 0;
@@ -11366,14 +11388,14 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
iocbq->iocb_flag |= LPFC_DRIVER_ABORTED;
if (phba->sli_rev == LPFC_SLI_REV4) {
- pring_s4 = lpfc_sli4_calc_ring(phba, iocbq);
- if (pring_s4 == NULL)
+ pring_s4 = lpfc_sli4_calc_ring(phba, abtsiocbq);
+ if (!pring_s4)
continue;
/* Note: both hbalock and ring_lock must be set here */
- spin_lock_irqsave(&pring_s4->ring_lock, iflags);
+ spin_lock(&pring_s4->ring_lock);
ret_val = __lpfc_sli_issue_iocb(phba, pring_s4->ringno,
abtsiocbq, 0);
- spin_unlock_irqrestore(&pring_s4->ring_lock, iflags);
+ spin_unlock(&pring_s4->ring_lock);
} else {
ret_val = __lpfc_sli_issue_iocb(phba, pring->ringno,
abtsiocbq, 0);
@@ -11385,7 +11407,7 @@ lpfc_sli_abort_taskmgmt(struct lpfc_vport *vport, struct lpfc_sli_ring *pring,
else
sum++;
}
- spin_unlock_irq(&phba->hbalock);
+ spin_unlock_irqrestore(&phba->hbalock, iflags);
return sum;
}
@@ -12830,7 +12852,7 @@ lpfc_sli4_sp_handle_mbox_event(struct lpfc_hba *phba, struct lpfc_mcqe *mcqe)
/* Move mbox data to caller's mailbox region, do endian swapping */
if (pmb->mbox_cmpl && mbox)
- lpfc_sli_pcimem_bcopy(mbox, mqe, sizeof(struct lpfc_mqe));
+ lpfc_sli4_pcimem_bcopy(mbox, mqe, sizeof(struct lpfc_mqe));
/*
* For mcqe errors, conditionally move a modified error code to
@@ -12913,7 +12935,7 @@ lpfc_sli4_sp_handle_mcqe(struct lpfc_hba *phba, struct lpfc_cqe *cqe)
bool workposted;
/* Copy the mailbox MCQE and convert endian order as needed */
- lpfc_sli_pcimem_bcopy(cqe, &mcqe, sizeof(struct lpfc_mcqe));
+ lpfc_sli4_pcimem_bcopy(cqe, &mcqe, sizeof(struct lpfc_mcqe));
/* Invoke the proper event handling routine */
if (!bf_get(lpfc_trailer_async, &mcqe))
@@ -12944,6 +12966,17 @@ lpfc_sli4_sp_handle_els_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
int txcmplq_cnt = 0;
int fcp_txcmplq_cnt = 0;
+ /* Check for response status */
+ if (unlikely(bf_get(lpfc_wcqe_c_status, wcqe))) {
+ /* Log the error status */
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "0357 ELS CQE error: status=x%x: "
+ "CQE: %08x %08x %08x %08x\n",
+ bf_get(lpfc_wcqe_c_status, wcqe),
+ wcqe->word0, wcqe->total_data_placed,
+ wcqe->parameter, wcqe->word3);
+ }
+
/* Get an irspiocbq for later ELS response processing use */
irspiocbq = lpfc_sli_get_iocbq(phba);
if (!irspiocbq) {
@@ -13173,7 +13206,7 @@ lpfc_sli4_sp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
bool workposted = false;
/* Copy the work queue CQE and convert endian order if needed */
- lpfc_sli_pcimem_bcopy(cqe, &cqevt, sizeof(struct lpfc_cqe));
+ lpfc_sli4_pcimem_bcopy(cqe, &cqevt, sizeof(struct lpfc_cqe));
/* Check and process for different type of WCQE and dispatch */
switch (bf_get(lpfc_cqe_code, &cqevt)) {
@@ -13364,14 +13397,12 @@ lpfc_sli4_fp_handle_fcp_wcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
phba->lpfc_rampdown_queue_depth(phba);
/* Log the error status */
- lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
- "0373 FCP complete error: status=x%x, "
- "hw_status=x%x, total_data_specified=%d, "
- "parameter=x%x, word3=x%x\n",
+ lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+ "0373 FCP CQE error: status=x%x: "
+ "CQE: %08x %08x %08x %08x\n",
bf_get(lpfc_wcqe_c_status, wcqe),
- bf_get(lpfc_wcqe_c_hw_status, wcqe),
- wcqe->total_data_placed, wcqe->parameter,
- wcqe->word3);
+ wcqe->word0, wcqe->total_data_placed,
+ wcqe->parameter, wcqe->word3);
}
/* Look up the FCP command IOCB and create pseudo response IOCB */
@@ -13581,7 +13612,7 @@ lpfc_sli4_fp_handle_cqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
bool workposted = false;
/* Copy the work queue CQE and convert endian order if needed */
- lpfc_sli_pcimem_bcopy(cqe, &wcqe, sizeof(struct lpfc_cqe));
+ lpfc_sli4_pcimem_bcopy(cqe, &wcqe, sizeof(struct lpfc_cqe));
/* Check and process for different type of WCQE and dispatch */
switch (bf_get(lpfc_wcqe_c_code, &wcqe)) {
@@ -19032,9 +19063,22 @@ lpfc_drain_txq(struct lpfc_hba *phba)
struct lpfc_sglq *sglq;
union lpfc_wqe128 wqe;
uint32_t txq_cnt = 0;
+ struct lpfc_queue *wq;
- pring = lpfc_phba_elsring(phba);
- if (unlikely(!pring))
+ if (phba->link_flag & LS_MDS_LOOPBACK) {
+ /* MDS WQE are posted only to first WQ*/
+ wq = phba->sli4_hba.fcp_wq[0];
+ if (unlikely(!wq))
+ return 0;
+ pring = wq->pring;
+ } else {
+ wq = phba->sli4_hba.els_wq;
+ if (unlikely(!wq))
+ return 0;
+ pring = lpfc_phba_elsring(phba);
+ }
+
+ if (unlikely(!pring) || list_empty(&pring->txq))
return 0;
spin_lock_irqsave(&pring->ring_lock, iflags);
@@ -19075,7 +19119,7 @@ lpfc_drain_txq(struct lpfc_hba *phba)
fail_msg = "to convert bpl to sgl";
else if (lpfc_sli4_iocb2wqe(phba, piocbq, &wqe))
fail_msg = "to convert iocb to wqe";
- else if (lpfc_sli4_wq_put(phba->sli4_hba.els_wq, &wqe))
+ else if (lpfc_sli4_wq_put(wq, &wqe))
fail_msg = " - Wq is full";
else
lpfc_sli_ringtxcmpl_put(phba, pring, piocbq);
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index e8b089a..18c23af 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -2,7 +2,7 @@
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
* Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
- * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. *
+ * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.broadcom.com *
@@ -20,7 +20,7 @@
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "12.0.0.1"
+#define LPFC_DRIVER_VERSION "12.0.0.4"
#define LPFC_DRIVER_NAME "lpfc"
/* Used for SLI 2/3 */
diff --git a/drivers/scsi/lpfc/lpfc_vport.c b/drivers/scsi/lpfc/lpfc_vport.c
index c9d33b1..81bc12d 100644
--- a/drivers/scsi/lpfc/lpfc_vport.c
+++ b/drivers/scsi/lpfc/lpfc_vport.c
@@ -840,7 +840,7 @@ lpfc_create_vport_work_array(struct lpfc_hba *phba)
struct lpfc_vport *port_iterator;
struct lpfc_vport **vports;
int index = 0;
- vports = kzalloc((phba->max_vports + 1) * sizeof(struct lpfc_vport *),
+ vports = kcalloc(phba->max_vports + 1, sizeof(struct lpfc_vport *),
GFP_KERNEL);
if (vports == NULL)
return NULL;
diff --git a/drivers/scsi/mac53c94.c b/drivers/scsi/mac53c94.c
index 8c4d3003..177701d 100644
--- a/drivers/scsi/mac53c94.c
+++ b/drivers/scsi/mac53c94.c
@@ -464,8 +464,9 @@ static int mac53c94_probe(struct macio_dev *mdev, const struct of_device_id *mat
* +1 to allow for aligning.
* XXX FIXME: Use DMA consistent routines
*/
- dma_cmd_space = kmalloc((host->sg_tablesize + 2) *
- sizeof(struct dbdma_cmd), GFP_KERNEL);
+ dma_cmd_space = kmalloc_array(host->sg_tablesize + 2,
+ sizeof(struct dbdma_cmd),
+ GFP_KERNEL);
if (dma_cmd_space == 0) {
printk(KERN_ERR "mac53c94: couldn't allocate dma "
"command space for %pOF\n", node);
diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
index 91f5e2c..8e8cf11 100644
--- a/drivers/scsi/megaraid.c
+++ b/drivers/scsi/megaraid.c
@@ -4166,6 +4166,9 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
int irq, i, j;
int error = -ENODEV;
+ if (hba_count >= MAX_CONTROLLERS)
+ goto out;
+
if (pci_enable_device(pdev))
goto out;
pci_set_master(pdev);
@@ -4289,7 +4292,8 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_host_put;
}
- adapter->scb_list = kmalloc(sizeof(scb_t) * MAX_COMMANDS, GFP_KERNEL);
+ adapter->scb_list = kmalloc_array(MAX_COMMANDS, sizeof(scb_t),
+ GFP_KERNEL);
if (!adapter->scb_list) {
dev_warn(&pdev->dev, "out of RAM\n");
goto out_free_cmd_buffer;
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c
index bb802b0..8428247 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -935,10 +935,12 @@ mraid_mm_register_adp(mraid_mmadp_t *lld_adp)
* Allocate single blocks of memory for all required kiocs,
* mailboxes and passthru structures.
*/
- adapter->kioc_list = kmalloc(sizeof(uioc_t) * lld_adp->max_kioc,
- GFP_KERNEL);
- adapter->mbox_list = kmalloc(sizeof(mbox64_t) * lld_adp->max_kioc,
- GFP_KERNEL);
+ adapter->kioc_list = kmalloc_array(lld_adp->max_kioc,
+ sizeof(uioc_t),
+ GFP_KERNEL);
+ adapter->mbox_list = kmalloc_array(lld_adp->max_kioc,
+ sizeof(mbox64_t),
+ GFP_KERNEL);
adapter->pthru_dma_pool = dma_pool_create("megaraid mm pthru pool",
&adapter->pdev->dev,
sizeof(mraid_passthru_t),
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 27fab82..75dc25f 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -35,8 +35,8 @@
/*
* MegaRAID SAS Driver meta data
*/
-#define MEGASAS_VERSION "07.704.04.00-rc1"
-#define MEGASAS_RELDATE "December 7, 2017"
+#define MEGASAS_VERSION "07.705.02.00-rc1"
+#define MEGASAS_RELDATE "April 4, 2018"
/*
* Device IDs
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index ce656c4..71d9757 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -92,7 +92,7 @@ MODULE_PARM_DESC(resetwaittime, "Wait time in seconds after I/O timeout "
int smp_affinity_enable = 1;
module_param(smp_affinity_enable, int, S_IRUGO);
-MODULE_PARM_DESC(smp_affinity_enable, "SMP affinity feature enable/disbale Default: enable(1)");
+MODULE_PARM_DESC(smp_affinity_enable, "SMP affinity feature enable/disable Default: enable(1)");
int rdpq_enable = 1;
module_param(rdpq_enable, int, S_IRUGO);
@@ -2224,9 +2224,9 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance,
sizeof(struct MR_LD_VF_AFFILIATION_111));
else {
new_affiliation_111 =
- pci_alloc_consistent(instance->pdev,
- sizeof(struct MR_LD_VF_AFFILIATION_111),
- &new_affiliation_111_h);
+ pci_zalloc_consistent(instance->pdev,
+ sizeof(struct MR_LD_VF_AFFILIATION_111),
+ &new_affiliation_111_h);
if (!new_affiliation_111) {
dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate "
"memory for new affiliation for scsi%d\n",
@@ -2234,8 +2234,6 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance,
megasas_return_cmd(instance, cmd);
return -ENOMEM;
}
- memset(new_affiliation_111, 0,
- sizeof(struct MR_LD_VF_AFFILIATION_111));
}
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
@@ -2333,10 +2331,10 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance,
sizeof(struct MR_LD_VF_AFFILIATION));
else {
new_affiliation =
- pci_alloc_consistent(instance->pdev,
- (MAX_LOGICAL_DRIVES + 1) *
- sizeof(struct MR_LD_VF_AFFILIATION),
- &new_affiliation_h);
+ pci_zalloc_consistent(instance->pdev,
+ (MAX_LOGICAL_DRIVES + 1) *
+ sizeof(struct MR_LD_VF_AFFILIATION),
+ &new_affiliation_h);
if (!new_affiliation) {
dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate "
"memory for new affiliation for scsi%d\n",
@@ -2344,8 +2342,6 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance,
megasas_return_cmd(instance, cmd);
return -ENOMEM;
}
- memset(new_affiliation, 0, (MAX_LOGICAL_DRIVES + 1) *
- sizeof(struct MR_LD_VF_AFFILIATION));
}
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
@@ -5423,9 +5419,9 @@ static int megasas_init_fw(struct megasas_instance *instance)
/* stream detection initialization */
if (instance->adapter_type == VENTURA_SERIES) {
fusion->stream_detect_by_ld =
- kzalloc(sizeof(struct LD_STREAM_DETECT *)
- * MAX_LOGICAL_DRIVES_EXT,
- GFP_KERNEL);
+ kcalloc(MAX_LOGICAL_DRIVES_EXT,
+ sizeof(struct LD_STREAM_DETECT *),
+ GFP_KERNEL);
if (!fusion->stream_detect_by_ld) {
dev_err(&instance->pdev->dev,
"unable to allocate stream detection for pool of LDs\n");
@@ -5636,16 +5632,15 @@ megasas_get_seq_num(struct megasas_instance *instance,
}
dcmd = &cmd->frame->dcmd;
- el_info = pci_alloc_consistent(instance->pdev,
- sizeof(struct megasas_evt_log_info),
- &el_info_h);
+ el_info = pci_zalloc_consistent(instance->pdev,
+ sizeof(struct megasas_evt_log_info),
+ &el_info_h);
if (!el_info) {
megasas_return_cmd(instance, cmd);
return -ENOMEM;
}
- memset(el_info, 0, sizeof(*el_info));
memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
dcmd->cmd = MFI_CMD_DCMD;
@@ -6144,7 +6139,7 @@ static inline int megasas_alloc_mfi_ctrl_mem(struct megasas_instance *instance)
*/
static int megasas_alloc_ctrl_mem(struct megasas_instance *instance)
{
- instance->reply_map = kzalloc(sizeof(unsigned int) * nr_cpu_ids,
+ instance->reply_map = kcalloc(nr_cpu_ids, sizeof(unsigned int),
GFP_KERNEL);
if (!instance->reply_map)
return -ENOMEM;
diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index f4d988d..94c23ad 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -487,7 +487,7 @@ megasas_alloc_cmdlist_fusion(struct megasas_instance *instance)
* commands.
*/
fusion->cmd_list =
- kzalloc(sizeof(struct megasas_cmd_fusion *) * max_mpt_cmd,
+ kcalloc(max_mpt_cmd, sizeof(struct megasas_cmd_fusion *),
GFP_KERNEL);
if (!fusion->cmd_list) {
dev_err(&instance->pdev->dev,
@@ -684,15 +684,14 @@ megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
array_size = sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) *
MAX_MSIX_QUEUES_FUSION;
- fusion->rdpq_virt = pci_alloc_consistent(instance->pdev, array_size,
- &fusion->rdpq_phys);
+ fusion->rdpq_virt = pci_zalloc_consistent(instance->pdev, array_size,
+ &fusion->rdpq_phys);
if (!fusion->rdpq_virt) {
dev_err(&instance->pdev->dev,
"Failed from %s %d\n", __func__, __LINE__);
return -ENOMEM;
}
- memset(fusion->rdpq_virt, 0, array_size);
msix_count = instance->msix_vectors > 0 ? instance->msix_vectors : 1;
fusion->reply_frames_desc_pool = dma_pool_create("mr_rdpq",
@@ -2981,6 +2980,9 @@ megasas_build_syspd_fusion(struct megasas_instance *instance,
pRAID_Context->timeout_value = cpu_to_le16(os_timeout_value);
pRAID_Context->virtual_disk_tgt_id = cpu_to_le16(device_id);
} else {
+ if (os_timeout_value)
+ os_timeout_value++;
+
/* system pd Fast Path */
io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
timeout_limit = (scmd->device->type == TYPE_DISK) ?
@@ -4827,8 +4829,9 @@ megasas_alloc_fusion_context(struct megasas_instance *instance)
(PLD_SPAN_INFO)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
fusion->log_to_span_pages);
if (!fusion->log_to_span) {
- fusion->log_to_span = vzalloc(MAX_LOGICAL_DRIVES_EXT *
- sizeof(LD_SPAN_INFO));
+ fusion->log_to_span =
+ vzalloc(array_size(MAX_LOGICAL_DRIVES_EXT,
+ sizeof(LD_SPAN_INFO)));
if (!fusion->log_to_span) {
dev_err(&instance->pdev->dev, "Failed from %s %d\n",
__func__, __LINE__);
@@ -4842,8 +4845,9 @@ megasas_alloc_fusion_context(struct megasas_instance *instance)
(struct LD_LOAD_BALANCE_INFO *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
fusion->load_balance_info_pages);
if (!fusion->load_balance_info) {
- fusion->load_balance_info = vzalloc(MAX_LOGICAL_DRIVES_EXT *
- sizeof(struct LD_LOAD_BALANCE_INFO));
+ fusion->load_balance_info =
+ vzalloc(array_size(MAX_LOGICAL_DRIVES_EXT,
+ sizeof(struct LD_LOAD_BALANCE_INFO)));
if (!fusion->load_balance_info)
dev_err(&instance->pdev->dev, "Failed to allocate load_balance_info, "
"continuing without Load Balance support\n");
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2.h b/drivers/scsi/mpt3sas/mpi/mpi2.h
index b015c30..1e45268 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2.h
@@ -9,7 +9,7 @@
* scatter/gather formats.
* Creation Date: June 21, 2006
*
- * mpi2.h Version: 02.00.48
+ * mpi2.h Version: 02.00.50
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@@ -114,6 +114,8 @@
* 09-02-16 02.00.46 Bumped MPI2_HEADER_VERSION_UNIT.
* 11-23-16 02.00.47 Bumped MPI2_HEADER_VERSION_UNIT.
* 02-03-17 02.00.48 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 06-13-17 02.00.49 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 09-29-17 02.00.50 Bumped MPI2_HEADER_VERSION_UNIT.
* --------------------------------------------------------------------------
*/
@@ -152,8 +154,9 @@
MPI26_VERSION_MINOR)
#define MPI2_VERSION_02_06 (0x0206)
-/*Unit and Dev versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT (0x30)
+
+/* Unit and Dev versioning for this MPI header set */
+#define MPI2_HEADER_VERSION_UNIT (0x32)
#define MPI2_HEADER_VERSION_DEV (0x00)
#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
index 0ad88de..5122920 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
@@ -7,7 +7,7 @@
* Title: MPI Configuration messages and pages
* Creation Date: November 10, 2006
*
- * mpi2_cnfg.h Version: 02.00.40
+ * mpi2_cnfg.h Version: 02.00.42
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@@ -219,6 +219,18 @@
* Added ChassisSlot field to SAS Enclosure Page 0.
* Added ChassisSlot Valid bit (bit 5) to the Flags field
* in SAS Enclosure Page 0.
+ * 06-13-17 02.00.41 Added MPI26_MFGPAGE_DEVID_SAS3816 and
+ * MPI26_MFGPAGE_DEVID_SAS3916 defines.
+ * Removed MPI26_MFGPAGE_DEVID_SAS4008 define.
+ * Added MPI26_PCIEIOUNIT1_LINKFLAGS_SRNS_EN define.
+ * Renamed PI26_PCIEIOUNIT1_LINKFLAGS_EN_SRIS to
+ * PI26_PCIEIOUNIT1_LINKFLAGS_SRIS_EN.
+ * Renamed MPI26_PCIEIOUNIT1_LINKFLAGS_DIS_SRIS to
+ * MPI26_PCIEIOUNIT1_LINKFLAGS_DIS_SEPARATE_REFCLK.
+ * 09-29-17 02.00.42 Added ControllerResetTO field to PCIe Device Page 2.
+ * Added NOIOB field to PCIe Device Page 2.
+ * Added MPI26_PCIEDEV2_CAP_DATA_BLK_ALIGN_AND_GRAN to
+ * the Capabilities field of PCIe Device Page 2.
* --------------------------------------------------------------------------
*/
@@ -556,7 +568,8 @@ typedef struct _MPI2_CONFIG_REPLY {
#define MPI26_MFGPAGE_DEVID_SAS3616 (0x00D1)
#define MPI26_MFGPAGE_DEVID_SAS3708 (0x00D2)
-#define MPI26_MFGPAGE_DEVID_SAS4008 (0x00A1)
+#define MPI26_MFGPAGE_DEVID_SAS3816 (0x00A1)
+#define MPI26_MFGPAGE_DEVID_SAS3916 (0x00A0)
/*Manufacturing Page 0 */
@@ -3864,20 +3877,25 @@ typedef struct _MPI26_CONFIG_PAGE_PCIEDEV_0 {
typedef struct _MPI26_CONFIG_PAGE_PCIEDEV_2 {
MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */
U16 DevHandle; /*0x08 */
- U16 Reserved1; /*0x0A */
- U32 MaximumDataTransferSize;/*0x0C */
+ U8 ControllerResetTO; /* 0x0A */
+ U8 Reserved1; /* 0x0B */
+ U32 MaximumDataTransferSize; /*0x0C */
U32 Capabilities; /*0x10 */
- U32 Reserved2; /*0x14 */
+ U16 NOIOB; /* 0x14 */
+ U16 Reserved2; /* 0x16 */
} MPI26_CONFIG_PAGE_PCIEDEV_2, *PTR_MPI26_CONFIG_PAGE_PCIEDEV_2,
Mpi26PCIeDevicePage2_t, *pMpi26PCIeDevicePage2_t;
-#define MPI26_PCIEDEVICE2_PAGEVERSION (0x00)
+#define MPI26_PCIEDEVICE2_PAGEVERSION (0x01)
/*defines for PCIe Device Page 2 Capabilities field */
+#define MPI26_PCIEDEV2_CAP_DATA_BLK_ALIGN_AND_GRAN (0x00000008)
#define MPI26_PCIEDEV2_CAP_SGL_FORMAT (0x00000004)
#define MPI26_PCIEDEV2_CAP_BIT_BUCKET_SUPPORT (0x00000002)
#define MPI26_PCIEDEV2_CAP_SGL_SUPPORT (0x00000001)
+/* Defines for the NOIOB field */
+#define MPI26_PCIEDEV2_NOIOB_UNSUPPORTED (0x0000)
/****************************************************************************
* PCIe Link Config Pages (MPI v2.6 and later)
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_init.h b/drivers/scsi/mpt3sas/mpi/mpi2_init.h
index 948a3ba..6213ce6 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_init.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_init.h
@@ -75,7 +75,7 @@
typedef struct _MPI2_SCSI_IO_CDB_EEDP32 {
U8 CDB[20]; /*0x00 */
- U32 PrimaryReferenceTag; /*0x14 */
+ __be32 PrimaryReferenceTag; /*0x14 */
U16 PrimaryApplicationTag; /*0x18 */
U16 PrimaryApplicationTagMask; /*0x1A */
U32 TransferLength; /*0x1C */
diff --git a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
index cc2aff7..1faec3a 100644
--- a/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
+++ b/drivers/scsi/mpt3sas/mpi/mpi2_ioc.h
@@ -7,7 +7,7 @@
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: October 11, 2006
*
- * mpi2_ioc.h Version: 02.00.32
+ * mpi2_ioc.h Version: 02.00.34
*
* NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25
* prefix are for use only on MPI v2.5 products, and must not be used
@@ -167,6 +167,10 @@
* 02-02-17 02.00.32 Added MPI2_FW_DOWNLOAD_ITYPE_CBB_BACKUP.
* Added MPI25_EVENT_DATA_ACTIVE_CABLE_EXCEPT and related
* defines for the ReasonCode field.
+ * 06-13-17 02.00.33 Added MPI2_FW_DOWNLOAD_ITYPE_CPLD.
+ * 09-29-17 02.00.34 Added MPI26_EVENT_PCIDEV_STAT_RC_PCIE_HOT_RESET_FAILED
+ * to the ReasonCode field in PCIe Device Status Change
+ * Event Data.
* --------------------------------------------------------------------------
*/
@@ -1182,6 +1186,7 @@ typedef struct _MPI26_EVENT_DATA_PCIE_DEVICE_STATUS_CHANGE {
#define MPI26_EVENT_PCIDEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E)
#define MPI26_EVENT_PCIDEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F)
#define MPI26_EVENT_PCIDEV_STAT_RC_DEV_INIT_FAILURE (0x10)
+#define MPI26_EVENT_PCIDEV_STAT_RC_PCIE_HOT_RESET_FAILED (0x11)
/*PCIe Enumeration Event data (MPI v2.6 and later) */
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 61f93a1..569392d 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -87,7 +87,7 @@ MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
static int smp_affinity_enable = 1;
module_param(smp_affinity_enable, int, S_IRUGO);
-MODULE_PARM_DESC(smp_affinity_enable, "SMP affinity feature enable/disbale Default: enable(1)");
+MODULE_PARM_DESC(smp_affinity_enable, "SMP affinity feature enable/disable Default: enable(1)");
static int max_msix_vectors = -1;
module_param(max_msix_vectors, int, 0);
@@ -297,12 +297,15 @@ static void *
_base_get_chain_buffer_dma_to_chain_buffer(struct MPT3SAS_ADAPTER *ioc,
dma_addr_t chain_buffer_dma)
{
- u16 index;
-
- for (index = 0; index < ioc->chain_depth; index++) {
- if (ioc->chain_lookup[index].chain_buffer_dma ==
- chain_buffer_dma)
- return ioc->chain_lookup[index].chain_buffer;
+ u16 index, j;
+ struct chain_tracker *ct;
+
+ for (index = 0; index < ioc->scsiio_depth; index++) {
+ for (j = 0; j < ioc->chains_needed_per_io; j++) {
+ ct = &ioc->chain_lookup[index].chains_per_smid[j];
+ if (ct && ct->chain_buffer_dma == chain_buffer_dma)
+ return ct->chain_buffer;
+ }
}
pr_info(MPT3SAS_FMT
"Provided chain_buffer_dma address is not in the lookup list\n",
@@ -394,13 +397,14 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc,
buff_ptr_phys = buffer_iomem_phys;
WARN_ON(buff_ptr_phys > U32_MAX);
- if (sgel->FlagsLength &
+ if (le32_to_cpu(sgel->FlagsLength) &
(MPI2_SGE_FLAGS_HOST_TO_IOC << MPI2_SGE_FLAGS_SHIFT))
is_write = 1;
for (i = 0; i < MPT_MIN_PHYS_SEGMENTS + ioc->facts.MaxChainDepth; i++) {
- sgl_flags = (sgel->FlagsLength >> MPI2_SGE_FLAGS_SHIFT);
+ sgl_flags =
+ (le32_to_cpu(sgel->FlagsLength) >> MPI2_SGE_FLAGS_SHIFT);
switch (sgl_flags & MPI2_SGE_FLAGS_ELEMENT_MASK) {
case MPI2_SGE_FLAGS_CHAIN_ELEMENT:
@@ -411,7 +415,7 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc,
*/
sgel_next =
_base_get_chain_buffer_dma_to_chain_buffer(ioc,
- sgel->Address);
+ le32_to_cpu(sgel->Address));
if (sgel_next == NULL)
return;
/*
@@ -426,7 +430,8 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc,
dst_addr_phys = _base_get_chain_phys(ioc,
smid, sge_chain_count);
WARN_ON(dst_addr_phys > U32_MAX);
- sgel->Address = (u32)dst_addr_phys;
+ sgel->Address =
+ cpu_to_le32(lower_32_bits(dst_addr_phys));
sgel = sgel_next;
sge_chain_count++;
break;
@@ -435,22 +440,28 @@ static void _clone_sg_entries(struct MPT3SAS_ADAPTER *ioc,
if (is_scsiio_req) {
_base_clone_to_sys_mem(buff_ptr,
sg_virt(sg_scmd),
- (sgel->FlagsLength & 0x00ffffff));
+ (le32_to_cpu(sgel->FlagsLength) &
+ 0x00ffffff));
/*
* FIXME: this relies on a a zero
* PCI mem_offset.
*/
- sgel->Address = (u32)buff_ptr_phys;
+ sgel->Address =
+ cpu_to_le32((u32)buff_ptr_phys);
} else {
_base_clone_to_sys_mem(buff_ptr,
ioc->config_vaddr,
- (sgel->FlagsLength & 0x00ffffff));
- sgel->Address = (u32)buff_ptr_phys;
+ (le32_to_cpu(sgel->FlagsLength) &
+ 0x00ffffff));
+ sgel->Address =
+ cpu_to_le32((u32)buff_ptr_phys);
}
}
- buff_ptr += (sgel->FlagsLength & 0x00ffffff);
- buff_ptr_phys += (sgel->FlagsLength & 0x00ffffff);
- if ((sgel->FlagsLength &
+ buff_ptr += (le32_to_cpu(sgel->FlagsLength) &
+ 0x00ffffff);
+ buff_ptr_phys += (le32_to_cpu(sgel->FlagsLength) &
+ 0x00ffffff);
+ if ((le32_to_cpu(sgel->FlagsLength) &
(MPI2_SGE_FLAGS_END_OF_BUFFER
<< MPI2_SGE_FLAGS_SHIFT)))
goto eob_clone_chain;
@@ -1019,6 +1030,9 @@ _base_display_event_data(struct MPT3SAS_ADAPTER *ioc,
case MPI2_EVENT_ACTIVE_CABLE_EXCEPTION:
desc = "Cable Event";
break;
+ case MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
+ desc = "SAS Device Discovery Error";
+ break;
case MPI2_EVENT_PCIE_DEVICE_STATUS_CHANGE:
desc = "PCIE Device Status Change";
break;
@@ -1433,7 +1447,7 @@ _base_interrupt(int irq, void *bus_id)
cpu_to_le32(reply);
if (ioc->is_mcpu_endpoint)
_base_clone_reply_to_sys_mem(ioc,
- cpu_to_le32(reply),
+ reply,
ioc->reply_free_host_index);
writel(ioc->reply_free_host_index,
&ioc->chip->ReplyFreeHostIndex);
@@ -1671,7 +1685,8 @@ _base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
* @ioc: per adapter object
* @scmd: SCSI commands of the IO request
*
- * Returns chain tracker(from ioc->free_chain_list)
+ * Returns chain tracker from chain_lookup table using key as
+ * smid and smid's chain_offset.
*/
static struct chain_tracker *
_base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc,
@@ -1679,20 +1694,15 @@ _base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc,
{
struct chain_tracker *chain_req;
struct scsiio_tracker *st = scsi_cmd_priv(scmd);
- unsigned long flags;
+ u16 smid = st->smid;
+ u8 chain_offset =
+ atomic_read(&ioc->chain_lookup[smid - 1].chain_offset);
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- if (list_empty(&ioc->free_chain_list)) {
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- dfailprintk(ioc, pr_warn(MPT3SAS_FMT
- "chain buffers not available\n", ioc->name));
+ if (chain_offset == ioc->chains_needed_per_io)
return NULL;
- }
- chain_req = list_entry(ioc->free_chain_list.next,
- struct chain_tracker, tracker_list);
- list_del_init(&chain_req->tracker_list);
- list_add_tail(&chain_req->tracker_list, &st->chain_list);
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+ chain_req = &ioc->chain_lookup[smid - 1].chains_per_smid[chain_offset];
+ atomic_inc(&ioc->chain_lookup[smid - 1].chain_offset);
return chain_req;
}
@@ -3044,7 +3054,7 @@ mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc)
for (i = 0; i < ioc->combined_reply_index_count; i++) {
ioc->replyPostRegisterIndex[i] = (resource_size_t *)
- ((u8 *)&ioc->chip->Doorbell +
+ ((u8 __force *)&ioc->chip->Doorbell +
MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET +
(i * MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET));
}
@@ -3273,13 +3283,7 @@ void mpt3sas_base_clear_st(struct MPT3SAS_ADAPTER *ioc,
return;
st->cb_idx = 0xFF;
st->direct_io = 0;
- if (!list_empty(&st->chain_list)) {
- unsigned long flags;
-
- spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
- list_splice_init(&st->chain_list, &ioc->free_chain_list);
- spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
- }
+ atomic_set(&ioc->chain_lookup[st->smid - 1].chain_offset, 0);
}
/**
@@ -3339,11 +3343,12 @@ _base_mpi_ep_writeq(__u64 b, volatile void __iomem *addr,
spinlock_t *writeq_lock)
{
unsigned long flags;
- __u64 data_out = cpu_to_le64(b);
+ __u64 data_out = b;
spin_lock_irqsave(writeq_lock, flags);
writel((u32)(data_out), addr);
writel((u32)(data_out >> 32), (addr + 4));
+ mmiowb();
spin_unlock_irqrestore(writeq_lock, flags);
}
@@ -3362,7 +3367,7 @@ _base_mpi_ep_writeq(__u64 b, volatile void __iomem *addr,
static inline void
_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock)
{
- writeq(cpu_to_le64(b), addr);
+ writeq(b, addr);
}
#else
static inline void
@@ -3389,7 +3394,7 @@ _base_put_smid_mpi_ep_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle)
__le32 *mfp = (__le32 *)mpt3sas_base_get_msg_frame(ioc, smid);
_clone_sg_entries(ioc, (void *) mfp, smid);
- mpi_req_iomem = (void *)ioc->chip +
+ mpi_req_iomem = (void __force *)ioc->chip +
MPI_FRAME_START_OFFSET + (smid * ioc->request_sz);
_base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp,
ioc->request_sz);
@@ -3473,7 +3478,8 @@ mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid,
request_hdr = (MPI2RequestHeader_t *)mfp;
/* TBD 256 is offset within sys register. */
- mpi_req_iomem = (void *)ioc->chip + MPI_FRAME_START_OFFSET
+ mpi_req_iomem = (void __force *)ioc->chip
+ + MPI_FRAME_START_OFFSET
+ (smid * ioc->request_sz);
_base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp,
ioc->request_sz);
@@ -3542,7 +3548,7 @@ mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid)
_clone_sg_entries(ioc, (void *) mfp, smid);
/* TBD 256 is offset within sys register */
- mpi_req_iomem = (void *)ioc->chip +
+ mpi_req_iomem = (void __force *)ioc->chip +
MPI_FRAME_START_OFFSET + (smid * ioc->request_sz);
_base_clone_mpi_to_sys_mem(mpi_req_iomem, (void *)mfp,
ioc->request_sz);
@@ -3823,6 +3829,105 @@ _base_display_OEMs_branding(struct MPT3SAS_ADAPTER *ioc)
}
/**
+ * _base_display_fwpkg_version - sends FWUpload request to pull FWPkg
+ * version from FW Image Header.
+ * @ioc: per adapter object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+ static int
+_base_display_fwpkg_version(struct MPT3SAS_ADAPTER *ioc)
+{
+ Mpi2FWImageHeader_t *FWImgHdr;
+ Mpi25FWUploadRequest_t *mpi_request;
+ Mpi2FWUploadReply_t mpi_reply;
+ int r = 0;
+ void *fwpkg_data = NULL;
+ dma_addr_t fwpkg_data_dma;
+ u16 smid, ioc_status;
+ size_t data_length;
+
+ dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
+ __func__));
+
+ if (ioc->base_cmds.status & MPT3_CMD_PENDING) {
+ pr_err(MPT3SAS_FMT "%s: internal command already in use\n",
+ ioc->name, __func__);
+ return -EAGAIN;
+ }
+
+ data_length = sizeof(Mpi2FWImageHeader_t);
+ fwpkg_data = pci_alloc_consistent(ioc->pdev, data_length,
+ &fwpkg_data_dma);
+ if (!fwpkg_data) {
+ pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -ENOMEM;
+ }
+
+ smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx);
+ if (!smid) {
+ pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ r = -EAGAIN;
+ goto out;
+ }
+
+ ioc->base_cmds.status = MPT3_CMD_PENDING;
+ mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
+ ioc->base_cmds.smid = smid;
+ memset(mpi_request, 0, sizeof(Mpi25FWUploadRequest_t));
+ mpi_request->Function = MPI2_FUNCTION_FW_UPLOAD;
+ mpi_request->ImageType = MPI2_FW_UPLOAD_ITYPE_FW_FLASH;
+ mpi_request->ImageSize = cpu_to_le32(data_length);
+ ioc->build_sg(ioc, &mpi_request->SGL, 0, 0, fwpkg_data_dma,
+ data_length);
+ init_completion(&ioc->base_cmds.done);
+ mpt3sas_base_put_smid_default(ioc, smid);
+ /* Wait for 15 seconds */
+ wait_for_completion_timeout(&ioc->base_cmds.done,
+ FW_IMG_HDR_READ_TIMEOUT*HZ);
+ pr_info(MPT3SAS_FMT "%s: complete\n",
+ ioc->name, __func__);
+ if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) {
+ pr_err(MPT3SAS_FMT "%s: timeout\n",
+ ioc->name, __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi25FWUploadRequest_t)/4);
+ r = -ETIME;
+ } else {
+ memset(&mpi_reply, 0, sizeof(Mpi2FWUploadReply_t));
+ if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID) {
+ memcpy(&mpi_reply, ioc->base_cmds.reply,
+ sizeof(Mpi2FWUploadReply_t));
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+ FWImgHdr = (Mpi2FWImageHeader_t *)fwpkg_data;
+ if (FWImgHdr->PackageVersion.Word) {
+ pr_info(MPT3SAS_FMT "FW Package Version"
+ "(%02d.%02d.%02d.%02d)\n",
+ ioc->name,
+ FWImgHdr->PackageVersion.Struct.Major,
+ FWImgHdr->PackageVersion.Struct.Minor,
+ FWImgHdr->PackageVersion.Struct.Unit,
+ FWImgHdr->PackageVersion.Struct.Dev);
+ }
+ } else {
+ _debug_dump_mf(&mpi_reply,
+ sizeof(Mpi2FWUploadReply_t)/4);
+ }
+ }
+ }
+ ioc->base_cmds.status = MPT3_CMD_NOT_USED;
+out:
+ if (fwpkg_data)
+ pci_free_consistent(ioc->pdev, data_length, fwpkg_data,
+ fwpkg_data_dma);
+ return r;
+}
+
+/**
* _base_display_ioc_capabilities - Disply IOC's capabilities.
* @ioc: per adapter object
*
@@ -4038,6 +4143,7 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
Mpi2ConfigReply_t mpi_reply;
u32 iounit_pg1_flags;
+ ioc->nvme_abort_timeout = 30;
mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
if (ioc->ir_firmware)
mpt3sas_config_get_manufacturing_pg10(ioc, &mpi_reply,
@@ -4056,6 +4162,18 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
mpt3sas_config_set_manufacturing_pg11(ioc, &mpi_reply,
&ioc->manu_pg11);
}
+ if (ioc->manu_pg11.AddlFlags2 & NVME_TASK_MNGT_CUSTOM_MASK)
+ ioc->tm_custom_handling = 1;
+ else {
+ ioc->tm_custom_handling = 0;
+ if (ioc->manu_pg11.NVMeAbortTO < NVME_TASK_ABORT_MIN_TIMEOUT)
+ ioc->nvme_abort_timeout = NVME_TASK_ABORT_MIN_TIMEOUT;
+ else if (ioc->manu_pg11.NVMeAbortTO >
+ NVME_TASK_ABORT_MAX_TIMEOUT)
+ ioc->nvme_abort_timeout = NVME_TASK_ABORT_MAX_TIMEOUT;
+ else
+ ioc->nvme_abort_timeout = ioc->manu_pg11.NVMeAbortTO;
+ }
mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
@@ -4085,6 +4203,27 @@ _base_static_config_pages(struct MPT3SAS_ADAPTER *ioc)
}
/**
+ * mpt3sas_free_enclosure_list - release memory
+ * @ioc: per adapter object
+ *
+ * Free memory allocated during encloure add.
+ *
+ * Return nothing.
+ */
+void
+mpt3sas_free_enclosure_list(struct MPT3SAS_ADAPTER *ioc)
+{
+ struct _enclosure_node *enclosure_dev, *enclosure_dev_next;
+
+ /* Free enclosure list */
+ list_for_each_entry_safe(enclosure_dev,
+ enclosure_dev_next, &ioc->enclosure_list, list) {
+ list_del(&enclosure_dev->list);
+ kfree(enclosure_dev);
+ }
+}
+
+/**
* _base_release_memory_pools - release memory
* @ioc: per adapter object
*
@@ -4096,6 +4235,8 @@ static void
_base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
{
int i = 0;
+ int j = 0;
+ struct chain_tracker *ct;
struct reply_post_struct *rps;
dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
@@ -4153,7 +4294,14 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
}
} while (ioc->rdpq_array_enable &&
(++i < ioc->reply_queue_count));
-
+ if (ioc->reply_post_free_array &&
+ ioc->rdpq_array_enable) {
+ dma_pool_free(ioc->reply_post_free_array_dma_pool,
+ ioc->reply_post_free_array,
+ ioc->reply_post_free_array_dma);
+ ioc->reply_post_free_array = NULL;
+ }
+ dma_pool_destroy(ioc->reply_post_free_array_dma_pool);
dma_pool_destroy(ioc->reply_post_free_dma_pool);
kfree(ioc->reply_post);
}
@@ -4179,19 +4327,49 @@ _base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc)
kfree(ioc->hpr_lookup);
kfree(ioc->internal_lookup);
if (ioc->chain_lookup) {
- for (i = 0; i < ioc->chain_depth; i++) {
- if (ioc->chain_lookup[i].chain_buffer)
- dma_pool_free(ioc->chain_dma_pool,
- ioc->chain_lookup[i].chain_buffer,
- ioc->chain_lookup[i].chain_buffer_dma);
+ for (i = 0; i < ioc->scsiio_depth; i++) {
+ for (j = ioc->chains_per_prp_buffer;
+ j < ioc->chains_needed_per_io; j++) {
+ ct = &ioc->chain_lookup[i].chains_per_smid[j];
+ if (ct && ct->chain_buffer)
+ dma_pool_free(ioc->chain_dma_pool,
+ ct->chain_buffer,
+ ct->chain_buffer_dma);
+ }
+ kfree(ioc->chain_lookup[i].chains_per_smid);
}
dma_pool_destroy(ioc->chain_dma_pool);
- free_pages((ulong)ioc->chain_lookup, ioc->chain_pages);
+ kfree(ioc->chain_lookup);
ioc->chain_lookup = NULL;
}
}
/**
+ * is_MSB_are_same - checks whether all reply queues in a set are
+ * having same upper 32bits in their base memory address.
+ * @reply_pool_start_address: Base address of a reply queue set
+ * @pool_sz: Size of single Reply Descriptor Post Queues pool size
+ *
+ * Returns 1 if reply queues in a set have a same upper 32bits
+ * in their base memory address,
+ * else 0
+ */
+
+static int
+is_MSB_are_same(long reply_pool_start_address, u32 pool_sz)
+{
+ long reply_pool_end_address;
+
+ reply_pool_end_address = reply_pool_start_address + pool_sz;
+
+ if (upper_32_bits(reply_pool_start_address) ==
+ upper_32_bits(reply_pool_end_address))
+ return 1;
+ else
+ return 0;
+}
+
+/**
* _base_allocate_memory_pools - allocate start of day memory pools
* @ioc: per adapter object
*
@@ -4203,12 +4381,13 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
struct mpt3sas_facts *facts;
u16 max_sge_elements;
u16 chains_needed_per_io;
- u32 sz, total_sz, reply_post_free_sz;
+ u32 sz, total_sz, reply_post_free_sz, reply_post_free_array_sz;
u32 retry_sz;
u16 max_request_credit, nvme_blocks_needed;
unsigned short sg_tablesize;
u16 sge_size;
- int i;
+ int i, j;
+ struct chain_tracker *ct;
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -4489,37 +4668,23 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
ioc->name, ioc->request, ioc->scsiio_depth));
ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH);
- sz = ioc->chain_depth * sizeof(struct chain_tracker);
- ioc->chain_pages = get_order(sz);
- ioc->chain_lookup = (struct chain_tracker *)__get_free_pages(
- GFP_KERNEL, ioc->chain_pages);
+ sz = ioc->scsiio_depth * sizeof(struct chain_lookup);
+ ioc->chain_lookup = kzalloc(sz, GFP_KERNEL);
if (!ioc->chain_lookup) {
- pr_err(MPT3SAS_FMT "chain_lookup: __get_free_pages failed\n",
- ioc->name);
+ pr_err(MPT3SAS_FMT "chain_lookup: __get_free_pages "
+ "failed\n", ioc->name);
goto out;
}
- ioc->chain_dma_pool = dma_pool_create("chain pool", &ioc->pdev->dev,
- ioc->chain_segment_sz, 16, 0);
- if (!ioc->chain_dma_pool) {
- pr_err(MPT3SAS_FMT "chain_dma_pool: dma_pool_create failed\n",
- ioc->name);
- goto out;
- }
- for (i = 0; i < ioc->chain_depth; i++) {
- ioc->chain_lookup[i].chain_buffer = dma_pool_alloc(
- ioc->chain_dma_pool , GFP_KERNEL,
- &ioc->chain_lookup[i].chain_buffer_dma);
- if (!ioc->chain_lookup[i].chain_buffer) {
- ioc->chain_depth = i;
- goto chain_done;
+
+ sz = ioc->chains_needed_per_io * sizeof(struct chain_tracker);
+ for (i = 0; i < ioc->scsiio_depth; i++) {
+ ioc->chain_lookup[i].chains_per_smid = kzalloc(sz, GFP_KERNEL);
+ if (!ioc->chain_lookup[i].chains_per_smid) {
+ pr_err(MPT3SAS_FMT "chain_lookup: "
+ " kzalloc failed\n", ioc->name);
+ goto out;
}
- total_sz += ioc->chain_segment_sz;
}
- chain_done:
- dinitprintk(ioc, pr_info(MPT3SAS_FMT
- "chain pool depth(%d), frame_size(%d), pool_size(%d kB)\n",
- ioc->name, ioc->chain_depth, ioc->chain_segment_sz,
- ((ioc->chain_depth * ioc->chain_segment_sz))/1024));
/* initialize hi-priority queue smid's */
ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth,
@@ -4561,6 +4726,7 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
* be required for NVMe PRP's, only each set of NVMe blocks will be
* contiguous, so a new set is allocated for each possible I/O.
*/
+ ioc->chains_per_prp_buffer = 0;
if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_NVME_DEVICES) {
nvme_blocks_needed =
(ioc->shost->sg_tablesize * NVME_PRP_SIZE) - 1;
@@ -4583,6 +4749,11 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
ioc->name);
goto out;
}
+
+ ioc->chains_per_prp_buffer = sz/ioc->chain_segment_sz;
+ ioc->chains_per_prp_buffer = min(ioc->chains_per_prp_buffer,
+ ioc->chains_needed_per_io);
+
for (i = 0; i < ioc->scsiio_depth; i++) {
ioc->pcie_sg_lookup[i].pcie_sgl = dma_pool_alloc(
ioc->pcie_sgl_dma_pool, GFP_KERNEL,
@@ -4593,13 +4764,55 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
ioc->name);
goto out;
}
+ for (j = 0; j < ioc->chains_per_prp_buffer; j++) {
+ ct = &ioc->chain_lookup[i].chains_per_smid[j];
+ ct->chain_buffer =
+ ioc->pcie_sg_lookup[i].pcie_sgl +
+ (j * ioc->chain_segment_sz);
+ ct->chain_buffer_dma =
+ ioc->pcie_sg_lookup[i].pcie_sgl_dma +
+ (j * ioc->chain_segment_sz);
+ }
}
dinitprintk(ioc, pr_info(MPT3SAS_FMT "PCIe sgl pool depth(%d), "
"element_size(%d), pool_size(%d kB)\n", ioc->name,
ioc->scsiio_depth, sz, (sz * ioc->scsiio_depth)/1024));
+ dinitprintk(ioc, pr_info(MPT3SAS_FMT "Number of chains can "
+ "fit in a PRP page(%d)\n", ioc->name,
+ ioc->chains_per_prp_buffer));
total_sz += sz * ioc->scsiio_depth;
}
+
+ ioc->chain_dma_pool = dma_pool_create("chain pool", &ioc->pdev->dev,
+ ioc->chain_segment_sz, 16, 0);
+ if (!ioc->chain_dma_pool) {
+ pr_err(MPT3SAS_FMT "chain_dma_pool: dma_pool_create failed\n",
+ ioc->name);
+ goto out;
+ }
+ for (i = 0; i < ioc->scsiio_depth; i++) {
+ for (j = ioc->chains_per_prp_buffer;
+ j < ioc->chains_needed_per_io; j++) {
+ ct = &ioc->chain_lookup[i].chains_per_smid[j];
+ ct->chain_buffer = dma_pool_alloc(
+ ioc->chain_dma_pool, GFP_KERNEL,
+ &ct->chain_buffer_dma);
+ if (!ct->chain_buffer) {
+ pr_err(MPT3SAS_FMT "chain_lookup: "
+ " pci_pool_alloc failed\n", ioc->name);
+ _base_release_memory_pools(ioc);
+ goto out;
+ }
+ }
+ total_sz += ioc->chain_segment_sz;
+ }
+
+ dinitprintk(ioc, pr_info(MPT3SAS_FMT
+ "chain pool depth(%d), frame_size(%d), pool_size(%d kB)\n",
+ ioc->name, ioc->chain_depth, ioc->chain_segment_sz,
+ ((ioc->chain_depth * ioc->chain_segment_sz))/1024));
+
/* sense buffers, 4 byte align */
sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE;
ioc->sense_dma_pool = dma_pool_create("sense pool", &ioc->pdev->dev, sz,
@@ -4616,6 +4829,37 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
ioc->name);
goto out;
}
+ /* sense buffer requires to be in same 4 gb region.
+ * Below function will check the same.
+ * In case of failure, new pci pool will be created with updated
+ * alignment. Older allocation and pool will be destroyed.
+ * Alignment will be used such a way that next allocation if
+ * success, will always meet same 4gb region requirement.
+ * Actual requirement is not alignment, but we need start and end of
+ * DMA address must have same upper 32 bit address.
+ */
+ if (!is_MSB_are_same((long)ioc->sense, sz)) {
+ //Release Sense pool & Reallocate
+ dma_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma);
+ dma_pool_destroy(ioc->sense_dma_pool);
+ ioc->sense = NULL;
+
+ ioc->sense_dma_pool =
+ dma_pool_create("sense pool", &ioc->pdev->dev, sz,
+ roundup_pow_of_two(sz), 0);
+ if (!ioc->sense_dma_pool) {
+ pr_err(MPT3SAS_FMT "sense pool: pci_pool_create failed\n",
+ ioc->name);
+ goto out;
+ }
+ ioc->sense = dma_pool_alloc(ioc->sense_dma_pool, GFP_KERNEL,
+ &ioc->sense_dma);
+ if (!ioc->sense) {
+ pr_err(MPT3SAS_FMT "sense pool: pci_pool_alloc failed\n",
+ ioc->name);
+ goto out;
+ }
+ }
dinitprintk(ioc, pr_info(MPT3SAS_FMT
"sense pool(0x%p): depth(%d), element_size(%d), pool_size"
"(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth,
@@ -4675,6 +4919,28 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
ioc->name, (unsigned long long)ioc->reply_free_dma));
total_sz += sz;
+ if (ioc->rdpq_array_enable) {
+ reply_post_free_array_sz = ioc->reply_queue_count *
+ sizeof(Mpi2IOCInitRDPQArrayEntry);
+ ioc->reply_post_free_array_dma_pool =
+ dma_pool_create("reply_post_free_array pool",
+ &ioc->pdev->dev, reply_post_free_array_sz, 16, 0);
+ if (!ioc->reply_post_free_array_dma_pool) {
+ dinitprintk(ioc,
+ pr_info(MPT3SAS_FMT "reply_post_free_array pool: "
+ "dma_pool_create failed\n", ioc->name));
+ goto out;
+ }
+ ioc->reply_post_free_array =
+ dma_pool_alloc(ioc->reply_post_free_array_dma_pool,
+ GFP_KERNEL, &ioc->reply_post_free_array_dma);
+ if (!ioc->reply_post_free_array) {
+ dinitprintk(ioc,
+ pr_info(MPT3SAS_FMT "reply_post_free_array pool: "
+ "dma_pool_alloc failed\n", ioc->name));
+ goto out;
+ }
+ }
ioc->config_page_sz = 512;
ioc->config_page = pci_alloc_consistent(ioc->pdev,
ioc->config_page_sz, &ioc->config_page_dma);
@@ -5002,7 +5268,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
/* send message 32-bits at a time */
for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
- writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
+ writel((u32)(request[i]), &ioc->chip->Doorbell);
if ((_base_wait_for_doorbell_ack(ioc, 5)))
failed = 1;
}
@@ -5023,7 +5289,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
}
/* read the first two 16-bits, it gives the total length of the reply */
- reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+ reply[0] = (u16)(readl(&ioc->chip->Doorbell)
& MPI2_DOORBELL_DATA_MASK);
writel(0, &ioc->chip->HostInterruptStatus);
if ((_base_wait_for_doorbell_int(ioc, 5))) {
@@ -5032,7 +5298,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
ioc->name, __LINE__);
return -EFAULT;
}
- reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+ reply[1] = (u16)(readl(&ioc->chip->Doorbell)
& MPI2_DOORBELL_DATA_MASK);
writel(0, &ioc->chip->HostInterruptStatus);
@@ -5046,7 +5312,7 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
if (i >= reply_bytes/2) /* overflow case */
readl(&ioc->chip->Doorbell);
else
- reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+ reply[i] = (u16)(readl(&ioc->chip->Doorbell)
& MPI2_DOORBELL_DATA_MASK);
writel(0, &ioc->chip->HostInterruptStatus);
}
@@ -5481,8 +5747,6 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc)
ktime_t current_time;
u16 ioc_status;
u32 reply_post_free_array_sz = 0;
- Mpi2IOCInitRDPQArrayEntry *reply_post_free_array = NULL;
- dma_addr_t reply_post_free_array_dma;
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -5516,23 +5780,14 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc)
if (ioc->rdpq_array_enable) {
reply_post_free_array_sz = ioc->reply_queue_count *
sizeof(Mpi2IOCInitRDPQArrayEntry);
- reply_post_free_array = pci_alloc_consistent(ioc->pdev,
- reply_post_free_array_sz, &reply_post_free_array_dma);
- if (!reply_post_free_array) {
- pr_err(MPT3SAS_FMT
- "reply_post_free_array: pci_alloc_consistent failed\n",
- ioc->name);
- r = -ENOMEM;
- goto out;
- }
- memset(reply_post_free_array, 0, reply_post_free_array_sz);
+ memset(ioc->reply_post_free_array, 0, reply_post_free_array_sz);
for (i = 0; i < ioc->reply_queue_count; i++)
- reply_post_free_array[i].RDPQBaseAddress =
+ ioc->reply_post_free_array[i].RDPQBaseAddress =
cpu_to_le64(
(u64)ioc->reply_post[i].reply_post_free_dma);
mpi_request.MsgFlags = MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE;
mpi_request.ReplyDescriptorPostQueueAddress =
- cpu_to_le64((u64)reply_post_free_array_dma);
+ cpu_to_le64((u64)ioc->reply_post_free_array_dma);
} else {
mpi_request.ReplyDescriptorPostQueueAddress =
cpu_to_le64((u64)ioc->reply_post[0].reply_post_free_dma);
@@ -5562,7 +5817,7 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc)
if (r != 0) {
pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n",
ioc->name, __func__, r);
- goto out;
+ return r;
}
ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
@@ -5572,11 +5827,6 @@ _base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc)
r = -EIO;
}
-out:
- if (reply_post_free_array)
- pci_free_consistent(ioc->pdev, reply_post_free_array_sz,
- reply_post_free_array,
- reply_post_free_array_dma);
return r;
}
@@ -6157,12 +6407,6 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
&ioc->internal_free_list);
}
- /* chain pool */
- INIT_LIST_HEAD(&ioc->free_chain_list);
- for (i = 0; i < ioc->chain_depth; i++)
- list_add_tail(&ioc->chain_lookup[i].tracker_list,
- &ioc->free_chain_list);
-
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
/* initialize Reply Free Queue */
@@ -6172,7 +6416,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
ioc->reply_free[i] = cpu_to_le32(reply_address);
if (ioc->is_mcpu_endpoint)
_base_clone_reply_to_sys_mem(ioc,
- (__le32)reply_address, i);
+ reply_address, i);
}
/* initialize reply queues */
@@ -6230,12 +6474,18 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
skip_init_reply_post_host_index:
_base_unmask_interrupts(ioc);
+
+ if (ioc->hba_mpi_version_belonged != MPI2_VERSION) {
+ r = _base_display_fwpkg_version(ioc);
+ if (r)
+ return r;
+ }
+
+ _base_static_config_pages(ioc);
r = _base_event_notification(ioc);
if (r)
return r;
- _base_static_config_pages(ioc);
-
if (ioc->is_driver_loading) {
if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier
@@ -6492,6 +6742,7 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
_base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
_base_unmask_events(ioc, MPI2_EVENT_TEMP_THRESHOLD);
_base_unmask_events(ioc, MPI2_EVENT_ACTIVE_CABLE_EXCEPTION);
+ _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR);
if (ioc->hba_mpi_version_belonged == MPI26_VERSION) {
if (ioc->is_gen35_ioc) {
_base_unmask_events(ioc,
@@ -6558,6 +6809,7 @@ mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc)
mpt3sas_base_stop_watchdog(ioc);
mpt3sas_base_free_resources(ioc);
_base_release_memory_pools(ioc);
+ mpt3sas_free_enclosure_list(ioc);
pci_set_drvdata(ioc->pdev, NULL);
kfree(ioc->cpu_msix_table);
if (ioc->is_warpdrive)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index ae36d8f..f02974c 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -74,8 +74,8 @@
#define MPT3SAS_DRIVER_NAME "mpt3sas"
#define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION "17.100.00.00"
-#define MPT3SAS_MAJOR_VERSION 17
+#define MPT3SAS_DRIVER_VERSION "25.100.00.00"
+#define MPT3SAS_MAJOR_VERSION 25
#define MPT3SAS_MINOR_VERSION 100
#define MPT3SAS_BUILD_VERSION 0
#define MPT3SAS_RELEASE_VERSION 00
@@ -138,6 +138,7 @@
#define MAX_CHAIN_ELEMT_SZ 16
#define DEFAULT_NUM_FWCHAIN_ELEMTS 8
+#define FW_IMG_HDR_READ_TIMEOUT 15
/*
* NVMe defines
*/
@@ -145,8 +146,12 @@
#define NVME_CMD_PRP1_OFFSET 24 /* PRP1 offset in NVMe cmd */
#define NVME_CMD_PRP2_OFFSET 32 /* PRP2 offset in NVMe cmd */
#define NVME_ERROR_RESPONSE_SIZE 16 /* Max NVME Error Response */
+#define NVME_TASK_ABORT_MIN_TIMEOUT 6
+#define NVME_TASK_ABORT_MAX_TIMEOUT 60
+#define NVME_TASK_MNGT_CUSTOM_MASK (0x0010)
#define NVME_PRP_PAGE_SIZE 4096 /* Page size */
+
/*
* reset phases
*/
@@ -362,7 +367,15 @@ struct Mpi2ManufacturingPage11_t {
u8 EEDPTagMode; /* 09h */
u8 Reserved3; /* 0Ah */
u8 Reserved4; /* 0Bh */
- __le32 Reserved5[23]; /* 0Ch-60h*/
+ __le32 Reserved5[8]; /* 0Ch-2Ch */
+ u16 AddlFlags2; /* 2Ch */
+ u8 AddlFlags3; /* 2Eh */
+ u8 Reserved6; /* 2Fh */
+ __le32 Reserved7[7]; /* 30h - 4Bh */
+ u8 NVMeAbortTO; /* 4Ch */
+ u8 Reserved8; /* 4Dh */
+ u16 Reserved9; /* 4Eh */
+ __le32 Reserved10[4]; /* 50h - 60h */
};
/**
@@ -572,6 +585,7 @@ struct _pcie_device {
u8 enclosure_level;
u8 connector_name[4];
u8 *serial_number;
+ u8 reset_timeout;
struct kref refcount;
};
/**
@@ -741,6 +755,17 @@ struct _sas_node {
struct list_head sas_port_list;
};
+
+/**
+ * struct _enclosure_node - enclosure information
+ * @list: list of enclosures
+ * @pg0: enclosure pg0;
+ */
+struct _enclosure_node {
+ struct list_head list;
+ Mpi2SasEnclosurePage0_t pg0;
+};
+
/**
* enum reset_type - reset state
* @FORCE_BIG_HAMMER: issue diagnostic reset
@@ -770,7 +795,11 @@ struct pcie_sg_list {
struct chain_tracker {
void *chain_buffer;
dma_addr_t chain_buffer_dma;
- struct list_head tracker_list;
+};
+
+struct chain_lookup {
+ struct chain_tracker *chains_per_smid;
+ atomic_t chain_offset;
};
/**
@@ -829,8 +858,8 @@ struct _sc_list {
*/
struct _event_ack_list {
struct list_head list;
- u16 Event;
- u32 EventContext;
+ U16 Event;
+ U32 EventContext;
};
/**
@@ -1009,6 +1038,7 @@ typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc);
* @iounit_pg8: static iounit page 8
* @sas_hba: sas host object
* @sas_expander_list: expander object list
+ * @enclosure_list: enclosure object list
* @sas_node_lock:
* @sas_device_list: sas device object list
* @sas_device_init_list: sas device object list (used only at init time)
@@ -1194,6 +1224,10 @@ struct MPT3SAS_ADAPTER {
void *event_log;
u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
+ u8 tm_custom_handling;
+ u8 nvme_abort_timeout;
+
+
/* static config pages */
struct mpt3sas_facts facts;
struct mpt3sas_port_facts *pfacts;
@@ -1214,6 +1248,7 @@ struct MPT3SAS_ADAPTER {
/* sas hba, expander, and device list */
struct _sas_node sas_hba;
struct list_head sas_expander_list;
+ struct list_head enclosure_list;
spinlock_t sas_node_lock;
struct list_head sas_device_list;
struct list_head sas_device_init_list;
@@ -1261,7 +1296,7 @@ struct MPT3SAS_ADAPTER {
u32 page_size;
/* chain */
- struct chain_tracker *chain_lookup;
+ struct chain_lookup *chain_lookup;
struct list_head free_chain_list;
struct dma_pool *chain_dma_pool;
ulong chain_pages;
@@ -1315,6 +1350,9 @@ struct MPT3SAS_ADAPTER {
u8 rdpq_array_enable;
u8 rdpq_array_enable_assigned;
struct dma_pool *reply_post_free_dma_pool;
+ struct dma_pool *reply_post_free_array_dma_pool;
+ Mpi2IOCInitRDPQArrayEntry *reply_post_free_array;
+ dma_addr_t reply_post_free_array_dma;
u8 reply_queue_count;
struct list_head reply_queue_list;
@@ -1384,6 +1422,7 @@ int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc);
int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc);
void mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc);
+void mpt3sas_free_enclosure_list(struct MPT3SAS_ADAPTER *ioc);
int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc,
enum reset_type type);
@@ -1451,10 +1490,11 @@ u8 mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
u32 reply);
void mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase);
-int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
- u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout);
+int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, u64 lun,
+ u8 type, u16 smid_task, u16 msix_task, u8 timeout, u8 tr_method);
int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
- u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout);
+ u64 lun, u8 type, u16 smid_task, u16 msix_task,
+ u8 timeout, u8 tr_method);
void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.c b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
index d3cb387..3269ef4 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.c
@@ -297,7 +297,7 @@ mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
nvme_error_reply =
(Mpi26NVMeEncapsulatedErrorReply_t *)mpi_reply;
sz = min_t(u32, NVME_ERROR_RESPONSE_SIZE,
- le32_to_cpu(nvme_error_reply->ErrorResponseCount));
+ le16_to_cpu(nvme_error_reply->ErrorResponseCount));
sense_data = mpt3sas_base_get_sense_buffer(ioc, smid);
memcpy(ioc->ctl_cmds.sense, sense_data, sz);
}
@@ -644,9 +644,10 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
MPI2RequestHeader_t *mpi_request = NULL, *request;
MPI2DefaultReply_t *mpi_reply;
Mpi26NVMeEncapsulatedRequest_t *nvme_encap_request = NULL;
+ struct _pcie_device *pcie_device = NULL;
u32 ioc_state;
u16 smid;
- unsigned long timeout;
+ u8 timeout;
u8 issue_reset;
u32 sz, sz_arg;
void *psge;
@@ -659,6 +660,7 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
long ret;
u16 wait_state_count;
u16 device_handle = MPT3SAS_INVALID_DEVICE_HANDLE;
+ u8 tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
issue_reset = 0;
@@ -803,12 +805,13 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
* Build the PRPs and set direction bits.
* Send the request.
*/
- nvme_encap_request->ErrorResponseBaseAddress = ioc->sense_dma &
- 0xFFFFFFFF00000000;
+ nvme_encap_request->ErrorResponseBaseAddress =
+ cpu_to_le64(ioc->sense_dma & 0xFFFFFFFF00000000UL);
nvme_encap_request->ErrorResponseBaseAddress |=
- (U64)mpt3sas_base_get_sense_buffer_dma(ioc, smid);
+ cpu_to_le64(le32_to_cpu(
+ mpt3sas_base_get_sense_buffer_dma(ioc, smid)));
nvme_encap_request->ErrorResponseAllocationLength =
- NVME_ERROR_RESPONSE_SIZE;
+ cpu_to_le16(NVME_ERROR_RESPONSE_SIZE);
memset(ioc->ctl_cmds.sense, 0, NVME_ERROR_RESPONSE_SIZE);
ioc->build_nvme_prp(ioc, smid, nvme_encap_request,
data_out_dma, data_out_sz, data_in_dma, data_in_sz);
@@ -1073,14 +1076,26 @@ _ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg,
ioc->name,
le16_to_cpu(mpi_request->FunctionDependent1));
mpt3sas_halt_firmware(ioc);
- mpt3sas_scsih_issue_locked_tm(ioc,
- le16_to_cpu(mpi_request->FunctionDependent1), 0,
- MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0, 30);
+ pcie_device = mpt3sas_get_pdev_by_handle(ioc,
+ le16_to_cpu(mpi_request->FunctionDependent1));
+ if (pcie_device && (!ioc->tm_custom_handling))
+ mpt3sas_scsih_issue_locked_tm(ioc,
+ le16_to_cpu(mpi_request->FunctionDependent1),
+ 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
+ 0, pcie_device->reset_timeout,
+ tr_method);
+ else
+ mpt3sas_scsih_issue_locked_tm(ioc,
+ le16_to_cpu(mpi_request->FunctionDependent1),
+ 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0,
+ 0, 30, MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET);
} else
mpt3sas_base_hard_reset_handler(ioc, FORCE_BIG_HAMMER);
}
out:
+ if (pcie_device)
+ pcie_device_put(pcie_device);
/* free memory associated with sg buffers */
if (data_in)
diff --git a/drivers/scsi/mpt3sas/mpt3sas_ctl.h b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
index a44046c..18b46fa 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_ctl.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_ctl.h
@@ -184,7 +184,7 @@ struct mpt3_ioctl_iocinfo {
/* number of event log entries */
-#define MPT3SAS_CTL_EVENT_LOG_SIZE (50)
+#define MPT3SAS_CTL_EVENT_LOG_SIZE (200)
/**
* struct mpt3_ioctl_eventquery - query event count and type
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 8cd3782..b8d131a 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -157,8 +157,8 @@ MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 ");
/* raid transport support */
-struct raid_template *mpt3sas_raid_template;
-struct raid_template *mpt2sas_raid_template;
+static struct raid_template *mpt3sas_raid_template;
+static struct raid_template *mpt2sas_raid_template;
/**
@@ -1088,7 +1088,7 @@ _scsih_pcie_device_remove(struct MPT3SAS_ADAPTER *ioc,
pcie_device->slot);
if (pcie_device->connector_name[0] != '\0')
pr_info(MPT3SAS_FMT
- "removing enclosure level(0x%04x), connector name( %s)\n",
+ "removing enclosure level(0x%04x), connector name( %s)\n",
ioc->name, pcie_device->enclosure_level,
pcie_device->connector_name);
@@ -1362,6 +1362,30 @@ mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
}
/**
+ * mpt3sas_scsih_enclosure_find_by_handle - exclosure device search
+ * @ioc: per adapter object
+ * @handle: enclosure handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->sas_device_lock
+ *
+ * This searches for enclosure device based on handle, then returns the
+ * enclosure object.
+ */
+static struct _enclosure_node *
+mpt3sas_scsih_enclosure_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle)
+{
+ struct _enclosure_node *enclosure_dev, *r;
+
+ r = NULL;
+ list_for_each_entry(enclosure_dev, &ioc->enclosure_list, list) {
+ if (le16_to_cpu(enclosure_dev->pg0.EnclosureHandle) != handle)
+ continue;
+ r = enclosure_dev;
+ goto out;
+ }
+out:
+ return r;
+}
+/**
* mpt3sas_scsih_expander_find_by_sas_address - expander device search
* @ioc: per adapter object
* @sas_address: sas address
@@ -2608,6 +2632,7 @@ mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
* @smid_task: smid assigned to the task
* @msix_task: MSIX table index supplied by the OS
* @timeout: timeout in seconds
+ * @tr_method: Target Reset Method
* Context: user
*
* A generic API for sending task management requests to firmware.
@@ -2618,8 +2643,8 @@ mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle)
* Return SUCCESS or FAILED.
*/
int
-mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
- u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout)
+mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, u64 lun,
+ u8 type, u16 smid_task, u16 msix_task, u8 timeout, u8 tr_method)
{
Mpi2SCSITaskManagementRequest_t *mpi_request;
Mpi2SCSITaskManagementReply_t *mpi_reply;
@@ -2665,8 +2690,8 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
}
dtmprintk(ioc, pr_info(MPT3SAS_FMT
- "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n",
- ioc->name, handle, type, smid_task));
+ "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d), timeout(%d), tr_method(0x%x)\n",
+ ioc->name, handle, type, smid_task, timeout, tr_method));
ioc->tm_cmds.status = MPT3_CMD_PENDING;
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
ioc->tm_cmds.smid = smid;
@@ -2675,6 +2700,7 @@ mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request->DevHandle = cpu_to_le16(handle);
mpi_request->TaskType = type;
+ mpi_request->MsgFlags = tr_method;
mpi_request->TaskMID = cpu_to_le16(smid_task);
int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
mpt3sas_scsih_set_tm_flag(ioc, handle);
@@ -2721,13 +2747,14 @@ out:
}
int mpt3sas_scsih_issue_locked_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle,
- u64 lun, u8 type, u16 smid_task, u16 msix_task, ulong timeout)
+ u64 lun, u8 type, u16 smid_task, u16 msix_task,
+ u8 timeout, u8 tr_method)
{
int ret;
mutex_lock(&ioc->tm_cmds.mutex);
ret = mpt3sas_scsih_issue_tm(ioc, handle, lun, type, smid_task,
- msix_task, timeout);
+ msix_task, timeout, tr_method);
mutex_unlock(&ioc->tm_cmds.mutex);
return ret;
@@ -2830,6 +2857,8 @@ scsih_abort(struct scsi_cmnd *scmd)
u16 handle;
int r;
+ u8 timeout = 30;
+ struct _pcie_device *pcie_device = NULL;
sdev_printk(KERN_INFO, scmd->device,
"attempting task abort! scmd(%p)\n", scmd);
_scsih_tm_display_info(ioc, scmd);
@@ -2864,15 +2893,20 @@ scsih_abort(struct scsi_cmnd *scmd)
mpt3sas_halt_firmware(ioc);
handle = sas_device_priv_data->sas_target->handle;
+ pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle);
+ if (pcie_device && (!ioc->tm_custom_handling))
+ timeout = ioc->nvme_abort_timeout;
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->lun,
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK,
- st->smid, st->msix_io, 30);
+ st->smid, st->msix_io, timeout, 0);
/* Command must be cleared after abort */
if (r == SUCCESS && st->cb_idx != 0xFF)
r = FAILED;
out:
sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n",
((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+ if (pcie_device)
+ pcie_device_put(pcie_device);
return r;
}
@@ -2888,7 +2922,10 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
struct MPT3SAS_DEVICE *sas_device_priv_data;
struct _sas_device *sas_device = NULL;
+ struct _pcie_device *pcie_device = NULL;
u16 handle;
+ u8 tr_method = 0;
+ u8 tr_timeout = 30;
int r;
struct scsi_target *starget = scmd->device->sdev_target;
@@ -2926,8 +2963,16 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
goto out;
}
+ pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle);
+
+ if (pcie_device && (!ioc->tm_custom_handling)) {
+ tr_timeout = pcie_device->reset_timeout;
+ tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
+ } else
+ tr_method = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, scmd->device->lun,
- MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 0, 30);
+ MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 0,
+ tr_timeout, tr_method);
/* Check for busy commands after reset */
if (r == SUCCESS && atomic_read(&scmd->device->device_busy))
r = FAILED;
@@ -2937,6 +2982,8 @@ scsih_dev_reset(struct scsi_cmnd *scmd)
if (sas_device)
sas_device_put(sas_device);
+ if (pcie_device)
+ pcie_device_put(pcie_device);
return r;
}
@@ -2953,7 +3000,10 @@ scsih_target_reset(struct scsi_cmnd *scmd)
struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
struct MPT3SAS_DEVICE *sas_device_priv_data;
struct _sas_device *sas_device = NULL;
+ struct _pcie_device *pcie_device = NULL;
u16 handle;
+ u8 tr_method = 0;
+ u8 tr_timeout = 30;
int r;
struct scsi_target *starget = scmd->device->sdev_target;
struct MPT3SAS_TARGET *target_priv_data = starget->hostdata;
@@ -2990,8 +3040,16 @@ scsih_target_reset(struct scsi_cmnd *scmd)
goto out;
}
+ pcie_device = mpt3sas_get_pdev_by_handle(ioc, handle);
+
+ if (pcie_device && (!ioc->tm_custom_handling)) {
+ tr_timeout = pcie_device->reset_timeout;
+ tr_method = MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
+ } else
+ tr_method = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
r = mpt3sas_scsih_issue_locked_tm(ioc, handle, 0,
- MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0, 30);
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 0,
+ tr_timeout, tr_method);
/* Check for busy commands after reset */
if (r == SUCCESS && atomic_read(&starget->target_busy))
r = FAILED;
@@ -3001,7 +3059,8 @@ scsih_target_reset(struct scsi_cmnd *scmd)
if (sas_device)
sas_device_put(sas_device);
-
+ if (pcie_device)
+ pcie_device_put(pcie_device);
return r;
}
@@ -3535,6 +3594,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
unsigned long flags;
struct _tr_list *delayed_tr;
u32 ioc_state;
+ u8 tr_method = 0;
if (ioc->pci_error_recovery) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
@@ -3577,6 +3637,11 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
sas_address = pcie_device->wwid;
}
spin_unlock_irqrestore(&ioc->pcie_device_lock, flags);
+ if (pcie_device && (!ioc->tm_custom_handling))
+ tr_method =
+ MPI26_SCSITASKMGMT_MSGFLAGS_PROTOCOL_LVL_RST_PCIE;
+ else
+ tr_method = MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET;
}
if (sas_target_priv_data) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
@@ -3640,6 +3705,7 @@ _scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
mpi_request->DevHandle = cpu_to_le16(handle);
mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
+ mpi_request->MsgFlags = tr_method;
set_bit(handle, ioc->device_remove_in_progress);
mpt3sas_base_put_smid_hi_priority(ioc, smid, 0);
mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL);
@@ -3680,11 +3746,7 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
u32 ioc_state;
struct _sc_list *delayed_sc;
- if (ioc->remove_host) {
- dewtprintk(ioc, pr_info(MPT3SAS_FMT
- "%s: host has been removed\n", __func__, ioc->name));
- return 1;
- } else if (ioc->pci_error_recovery) {
+ if (ioc->pci_error_recovery) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: host in pci error recovery\n", __func__,
ioc->name));
@@ -3725,7 +3787,7 @@ _scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index,
if (!delayed_sc)
return _scsih_check_for_pending_tm(ioc, smid);
INIT_LIST_HEAD(&delayed_sc->list);
- delayed_sc->handle = mpi_request_tm->DevHandle;
+ delayed_sc->handle = le16_to_cpu(mpi_request_tm->DevHandle);
list_add_tail(&delayed_sc->list, &ioc->delayed_sc_list);
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"DELAYED:sc:handle(0x%04x), (open)\n",
@@ -3806,8 +3868,7 @@ _scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle)
u16 smid;
struct _tr_list *delayed_tr;
- if (ioc->shost_recovery || ioc->remove_host ||
- ioc->pci_error_recovery) {
+ if (ioc->pci_error_recovery) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: host reset in progress!\n",
__func__, ioc->name));
@@ -3860,8 +3921,7 @@ _scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
Mpi2SCSITaskManagementReply_t *mpi_reply =
mpt3sas_base_get_reply_virt_addr(ioc, reply);
- if (ioc->shost_recovery || ioc->remove_host ||
- ioc->pci_error_recovery) {
+ if (ioc->shost_recovery || ioc->pci_error_recovery) {
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"%s: host reset in progress!\n",
__func__, ioc->name));
@@ -3903,8 +3963,8 @@ _scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid,
* Context - processed in interrupt context.
*/
static void
-_scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 event,
- u32 event_context)
+_scsih_issue_delayed_event_ack(struct MPT3SAS_ADAPTER *ioc, u16 smid, U16 event,
+ U32 event_context)
{
Mpi2EventAckRequest_t *ack_request;
int i = smid - ioc->internal_smid;
@@ -3979,13 +4039,13 @@ _scsih_issue_delayed_sas_io_unit_ctrl(struct MPT3SAS_ADAPTER *ioc,
dewtprintk(ioc, pr_info(MPT3SAS_FMT
"sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n",
- ioc->name, le16_to_cpu(handle), smid,
+ ioc->name, handle, smid,
ioc->tm_sas_control_cb_idx));
mpi_request = mpt3sas_base_get_msg_frame(ioc, smid);
memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE;
- mpi_request->DevHandle = handle;
+ mpi_request->DevHandle = cpu_to_le16(handle);
mpt3sas_base_put_smid_default(ioc, smid);
}
@@ -5618,10 +5678,10 @@ static int
_scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
{
struct _sas_node *sas_expander;
+ struct _enclosure_node *enclosure_dev;
Mpi2ConfigReply_t mpi_reply;
Mpi2ExpanderPage0_t expander_pg0;
Mpi2ExpanderPage1_t expander_pg1;
- Mpi2SasEnclosurePage0_t enclosure_pg0;
u32 ioc_status;
u16 parent_handle;
u64 sas_address, sas_address_parent = 0;
@@ -5743,11 +5803,12 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle)
}
if (sas_expander->enclosure_handle) {
- if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
- &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
- sas_expander->enclosure_handle)))
+ enclosure_dev =
+ mpt3sas_scsih_enclosure_find_by_handle(ioc,
+ sas_expander->enclosure_handle);
+ if (enclosure_dev)
sas_expander->enclosure_logical_id =
- le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
+ le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID);
}
_scsih_expander_node_add(ioc, sas_expander);
@@ -5891,52 +5952,6 @@ _scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address,
}
/**
- * _scsih_get_enclosure_logicalid_chassis_slot - get device's
- * EnclosureLogicalID and ChassisSlot information.
- * @ioc: per adapter object
- * @sas_device_pg0: SAS device page0
- * @sas_device: per sas device object
- *
- * Returns nothing.
- */
-static void
-_scsih_get_enclosure_logicalid_chassis_slot(struct MPT3SAS_ADAPTER *ioc,
- Mpi2SasDevicePage0_t *sas_device_pg0, struct _sas_device *sas_device)
-{
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasEnclosurePage0_t enclosure_pg0;
-
- if (!sas_device_pg0 || !sas_device)
- return;
-
- sas_device->enclosure_handle =
- le16_to_cpu(sas_device_pg0->EnclosureHandle);
- sas_device->is_chassis_slot_valid = 0;
-
- if (!le16_to_cpu(sas_device_pg0->EnclosureHandle))
- return;
-
- if (mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
- &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
- le16_to_cpu(sas_device_pg0->EnclosureHandle))) {
- pr_err(MPT3SAS_FMT
- "Enclosure Pg0 read failed for handle(0x%04x)\n",
- ioc->name, le16_to_cpu(sas_device_pg0->EnclosureHandle));
- return;
- }
-
- sas_device->enclosure_logical_id =
- le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
-
- if (le16_to_cpu(enclosure_pg0.Flags) &
- MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) {
- sas_device->is_chassis_slot_valid = 1;
- sas_device->chassis_slot = enclosure_pg0.ChassisSlot;
- }
-}
-
-
-/**
* _scsih_check_device - checking device responsiveness
* @ioc: per adapter object
* @parent_sas_address: sas address of parent expander or sas host
@@ -5953,6 +5968,7 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t sas_device_pg0;
struct _sas_device *sas_device;
+ struct _enclosure_node *enclosure_dev = NULL;
u32 ioc_status;
unsigned long flags;
u64 sas_address;
@@ -6007,8 +6023,21 @@ _scsih_check_device(struct MPT3SAS_ADAPTER *ioc,
sas_device->connector_name[0] = '\0';
}
- _scsih_get_enclosure_logicalid_chassis_slot(ioc,
- &sas_device_pg0, sas_device);
+ sas_device->enclosure_handle =
+ le16_to_cpu(sas_device_pg0.EnclosureHandle);
+ sas_device->is_chassis_slot_valid = 0;
+ enclosure_dev = mpt3sas_scsih_enclosure_find_by_handle(ioc,
+ sas_device->enclosure_handle);
+ if (enclosure_dev) {
+ sas_device->enclosure_logical_id =
+ le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID);
+ if (le16_to_cpu(enclosure_dev->pg0.Flags) &
+ MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) {
+ sas_device->is_chassis_slot_valid = 1;
+ sas_device->chassis_slot =
+ enclosure_dev->pg0.ChassisSlot;
+ }
+ }
}
/* check if device is present */
@@ -6055,12 +6084,11 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
{
Mpi2ConfigReply_t mpi_reply;
Mpi2SasDevicePage0_t sas_device_pg0;
- Mpi2SasEnclosurePage0_t enclosure_pg0;
struct _sas_device *sas_device;
+ struct _enclosure_node *enclosure_dev = NULL;
u32 ioc_status;
u64 sas_address;
u32 device_info;
- int encl_pg0_rc = -1;
if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
@@ -6106,12 +6134,12 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
}
if (sas_device_pg0.EnclosureHandle) {
- encl_pg0_rc = mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
- &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
- sas_device_pg0.EnclosureHandle);
- if (encl_pg0_rc)
- pr_info(MPT3SAS_FMT
- "Enclosure Pg0 read failed for handle(0x%04x)\n",
+ enclosure_dev =
+ mpt3sas_scsih_enclosure_find_by_handle(ioc,
+ le16_to_cpu(sas_device_pg0.EnclosureHandle));
+ if (enclosure_dev == NULL)
+ pr_info(MPT3SAS_FMT "Enclosure handle(0x%04x)"
+ "doesn't match with enclosure device!\n",
ioc->name, sas_device_pg0.EnclosureHandle);
}
@@ -6152,18 +6180,16 @@ _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num,
sas_device->enclosure_level = 0;
sas_device->connector_name[0] = '\0';
}
-
- /* get enclosure_logical_id & chassis_slot */
+ /* get enclosure_logical_id & chassis_slot*/
sas_device->is_chassis_slot_valid = 0;
- if (encl_pg0_rc == 0) {
+ if (enclosure_dev) {
sas_device->enclosure_logical_id =
- le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
-
- if (le16_to_cpu(enclosure_pg0.Flags) &
+ le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID);
+ if (le16_to_cpu(enclosure_dev->pg0.Flags) &
MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) {
sas_device->is_chassis_slot_valid = 1;
sas_device->chassis_slot =
- enclosure_pg0.ChassisSlot;
+ enclosure_dev->pg0.ChassisSlot;
}
}
@@ -6845,8 +6871,8 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
Mpi26PCIeDevicePage0_t pcie_device_pg0;
Mpi26PCIeDevicePage2_t pcie_device_pg2;
Mpi2ConfigReply_t mpi_reply;
- Mpi2SasEnclosurePage0_t enclosure_pg0;
struct _pcie_device *pcie_device;
+ struct _enclosure_node *enclosure_dev;
u32 pcie_device_type;
u32 ioc_status;
u64 wwid;
@@ -6917,7 +6943,7 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
if (pcie_device->enclosure_handle != 0)
pcie_device->slot = le16_to_cpu(pcie_device_pg0.Slot);
- if (le16_to_cpu(pcie_device_pg0.Flags) &
+ if (le32_to_cpu(pcie_device_pg0.Flags) &
MPI26_PCIEDEV0_FLAGS_ENCL_LEVEL_VALID) {
pcie_device->enclosure_level = pcie_device_pg0.EnclosureLevel;
memcpy(&pcie_device->connector_name[0],
@@ -6928,13 +6954,14 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
}
/* get enclosure_logical_id */
- if (pcie_device->enclosure_handle &&
- !(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
- &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
- pcie_device->enclosure_handle)))
- pcie_device->enclosure_logical_id =
- le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
-
+ if (pcie_device->enclosure_handle) {
+ enclosure_dev =
+ mpt3sas_scsih_enclosure_find_by_handle(ioc,
+ pcie_device->enclosure_handle);
+ if (enclosure_dev)
+ pcie_device->enclosure_logical_id =
+ le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID);
+ }
/* TODO -- Add device name once FW supports it */
if (mpt3sas_config_get_pcie_device_pg2(ioc, &mpi_reply,
&pcie_device_pg2, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle)) {
@@ -6953,6 +6980,11 @@ _scsih_pcie_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle)
}
pcie_device->nvme_mdts =
le32_to_cpu(pcie_device_pg2.MaximumDataTransferSize);
+ if (pcie_device_pg2.ControllerResetTO)
+ pcie_device->reset_timeout =
+ pcie_device_pg2.ControllerResetTO;
+ else
+ pcie_device->reset_timeout = 30;
if (ioc->wait_for_discovery_to_complete)
_scsih_pcie_device_init_add(ioc, pcie_device);
@@ -7205,6 +7237,9 @@ _scsih_pcie_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc,
case MPI26_EVENT_PCIDEV_STAT_RC_ASYNC_NOTIFICATION:
reason_str = "internal async notification";
break;
+ case MPI26_EVENT_PCIDEV_STAT_RC_PCIE_HOT_RESET_FAILED:
+ reason_str = "pcie hot reset failed";
+ break;
default:
reason_str = "unknown reason";
break;
@@ -7320,10 +7355,60 @@ static void
_scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc,
struct fw_event_work *fw_event)
{
+ Mpi2ConfigReply_t mpi_reply;
+ struct _enclosure_node *enclosure_dev = NULL;
+ Mpi2EventDataSasEnclDevStatusChange_t *event_data =
+ (Mpi2EventDataSasEnclDevStatusChange_t *)fw_event->event_data;
+ int rc;
+ u16 enclosure_handle = le16_to_cpu(event_data->EnclosureHandle);
+
if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
_scsih_sas_enclosure_dev_status_change_event_debug(ioc,
(Mpi2EventDataSasEnclDevStatusChange_t *)
fw_event->event_data);
+ if (ioc->shost_recovery)
+ return;
+
+ if (enclosure_handle)
+ enclosure_dev =
+ mpt3sas_scsih_enclosure_find_by_handle(ioc,
+ enclosure_handle);
+ switch (event_data->ReasonCode) {
+ case MPI2_EVENT_SAS_ENCL_RC_ADDED:
+ if (!enclosure_dev) {
+ enclosure_dev =
+ kzalloc(sizeof(struct _enclosure_node),
+ GFP_KERNEL);
+ if (!enclosure_dev) {
+ pr_info(MPT3SAS_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__);
+ return;
+ }
+ rc = mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
+ &enclosure_dev->pg0,
+ MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
+ enclosure_handle);
+
+ if (rc || (le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK)) {
+ kfree(enclosure_dev);
+ return;
+ }
+
+ list_add_tail(&enclosure_dev->list,
+ &ioc->enclosure_list);
+ }
+ break;
+ case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
+ if (enclosure_dev) {
+ list_del(&enclosure_dev->list);
+ kfree(enclosure_dev);
+ }
+ break;
+ default:
+ break;
+ }
}
/**
@@ -7409,7 +7494,7 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
r = mpt3sas_scsih_issue_tm(ioc, handle, lun,
MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, st->smid,
- st->msix_io, 30);
+ st->msix_io, 30, 0);
if (r == FAILED) {
sdev_printk(KERN_WARNING, sdev,
"mpt3sas_scsih_issue_tm: FAILED when sending "
@@ -7450,7 +7535,7 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc,
r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->lun,
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, st->smid,
- st->msix_io, 30);
+ st->msix_io, 30, 0);
if (r == FAILED || st->cb_idx != 0xFF) {
sdev_printk(KERN_WARNING, sdev,
"mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : "
@@ -7527,6 +7612,44 @@ _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc,
}
/**
+ * _scsih_sas_device_discovery_error_event - display SAS device discovery error
+ * events
+ * @ioc: per adapter object
+ * @fw_event: The fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_device_discovery_error_event(struct MPT3SAS_ADAPTER *ioc,
+ struct fw_event_work *fw_event)
+{
+ Mpi25EventDataSasDeviceDiscoveryError_t *event_data =
+ (Mpi25EventDataSasDeviceDiscoveryError_t *)fw_event->event_data;
+
+ switch (event_data->ReasonCode) {
+ case MPI25_EVENT_SAS_DISC_ERR_SMP_FAILED:
+ pr_warn(MPT3SAS_FMT "SMP command sent to the expander"
+ "(handle:0x%04x, sas_address:0x%016llx,"
+ "physical_port:0x%02x) has failed",
+ ioc->name, le16_to_cpu(event_data->DevHandle),
+ (unsigned long long)le64_to_cpu(event_data->SASAddress),
+ event_data->PhysicalPort);
+ break;
+ case MPI25_EVENT_SAS_DISC_ERR_SMP_TIMEOUT:
+ pr_warn(MPT3SAS_FMT "SMP command sent to the expander"
+ "(handle:0x%04x, sas_address:0x%016llx,"
+ "physical_port:0x%02x) has timed out",
+ ioc->name, le16_to_cpu(event_data->DevHandle),
+ (unsigned long long)le64_to_cpu(event_data->SASAddress),
+ event_data->PhysicalPort);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
* _scsih_pcie_enumeration_event - handle enumeration events
* @ioc: per adapter object
* @fw_event: The fw_event_work object
@@ -8360,12 +8483,23 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
struct MPT3SAS_TARGET *sas_target_priv_data = NULL;
struct scsi_target *starget;
struct _sas_device *sas_device = NULL;
+ struct _enclosure_node *enclosure_dev = NULL;
unsigned long flags;
+ if (sas_device_pg0->EnclosureHandle) {
+ enclosure_dev =
+ mpt3sas_scsih_enclosure_find_by_handle(ioc,
+ le16_to_cpu(sas_device_pg0->EnclosureHandle));
+ if (enclosure_dev == NULL)
+ pr_info(MPT3SAS_FMT "Enclosure handle(0x%04x)"
+ "doesn't match with enclosure device!\n",
+ ioc->name, sas_device_pg0->EnclosureHandle);
+ }
spin_lock_irqsave(&ioc->sas_device_lock, flags);
list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
- if ((sas_device->sas_address == sas_device_pg0->SASAddress) &&
- (sas_device->slot == sas_device_pg0->Slot)) {
+ if ((sas_device->sas_address == le64_to_cpu(
+ sas_device_pg0->SASAddress)) && (sas_device->slot ==
+ le16_to_cpu(sas_device_pg0->Slot))) {
sas_device->responding = 1;
starget = sas_device->starget;
if (starget && starget->hostdata) {
@@ -8377,7 +8511,7 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
if (starget) {
starget_printk(KERN_INFO, starget,
"handle(0x%04x), sas_addr(0x%016llx)\n",
- sas_device_pg0->DevHandle,
+ le16_to_cpu(sas_device_pg0->DevHandle),
(unsigned long long)
sas_device->sas_address);
@@ -8389,7 +8523,7 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
sas_device->enclosure_logical_id,
sas_device->slot);
}
- if (sas_device_pg0->Flags &
+ if (le16_to_cpu(sas_device_pg0->Flags) &
MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) {
sas_device->enclosure_level =
sas_device_pg0->EnclosureLevel;
@@ -8400,17 +8534,30 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
sas_device->connector_name[0] = '\0';
}
- _scsih_get_enclosure_logicalid_chassis_slot(ioc,
- sas_device_pg0, sas_device);
+ sas_device->enclosure_handle =
+ le16_to_cpu(sas_device_pg0->EnclosureHandle);
+ sas_device->is_chassis_slot_valid = 0;
+ if (enclosure_dev) {
+ sas_device->enclosure_logical_id = le64_to_cpu(
+ enclosure_dev->pg0.EnclosureLogicalID);
+ if (le16_to_cpu(enclosure_dev->pg0.Flags) &
+ MPI2_SAS_ENCLS0_FLAGS_CHASSIS_SLOT_VALID) {
+ sas_device->is_chassis_slot_valid = 1;
+ sas_device->chassis_slot =
+ enclosure_dev->pg0.ChassisSlot;
+ }
+ }
- if (sas_device->handle == sas_device_pg0->DevHandle)
+ if (sas_device->handle == le16_to_cpu(
+ sas_device_pg0->DevHandle))
goto out;
pr_info("\thandle changed from(0x%04x)!!!\n",
sas_device->handle);
- sas_device->handle = sas_device_pg0->DevHandle;
+ sas_device->handle = le16_to_cpu(
+ sas_device_pg0->DevHandle);
if (sas_target_priv_data)
sas_target_priv_data->handle =
- sas_device_pg0->DevHandle;
+ le16_to_cpu(sas_device_pg0->DevHandle);
goto out;
}
}
@@ -8419,6 +8566,52 @@ Mpi2SasDevicePage0_t *sas_device_pg0)
}
/**
+ * _scsih_create_enclosure_list_after_reset - Free Existing list,
+ * And create enclosure list by scanning all Enclosure Page(0)s
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_scsih_create_enclosure_list_after_reset(struct MPT3SAS_ADAPTER *ioc)
+{
+ struct _enclosure_node *enclosure_dev;
+ Mpi2ConfigReply_t mpi_reply;
+ u16 enclosure_handle;
+ int rc;
+
+ /* Free existing enclosure list */
+ mpt3sas_free_enclosure_list(ioc);
+
+ /* Re constructing enclosure list after reset*/
+ enclosure_handle = 0xFFFF;
+ do {
+ enclosure_dev =
+ kzalloc(sizeof(struct _enclosure_node), GFP_KERNEL);
+ if (!enclosure_dev) {
+ pr_err(MPT3SAS_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__);
+ return;
+ }
+ rc = mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
+ &enclosure_dev->pg0,
+ MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE,
+ enclosure_handle);
+
+ if (rc || (le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK)) {
+ kfree(enclosure_dev);
+ return;
+ }
+ list_add_tail(&enclosure_dev->list,
+ &ioc->enclosure_list);
+ enclosure_handle =
+ le16_to_cpu(enclosure_dev->pg0.EnclosureHandle);
+ } while (1);
+}
+
+/**
* _scsih_search_responding_sas_devices -
* @ioc: per adapter object
*
@@ -8449,15 +8642,10 @@ _scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc)
MPI2_IOCSTATUS_MASK;
if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
break;
- handle = sas_device_pg0.DevHandle =
- le16_to_cpu(sas_device_pg0.DevHandle);
+ handle = le16_to_cpu(sas_device_pg0.DevHandle);
device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
if (!(_scsih_is_end_device(device_info)))
continue;
- sas_device_pg0.SASAddress =
- le64_to_cpu(sas_device_pg0.SASAddress);
- sas_device_pg0.Slot = le16_to_cpu(sas_device_pg0.Slot);
- sas_device_pg0.Flags = le16_to_cpu(sas_device_pg0.Flags);
_scsih_mark_responding_sas_device(ioc, &sas_device_pg0);
}
@@ -8487,8 +8675,9 @@ _scsih_mark_responding_pcie_device(struct MPT3SAS_ADAPTER *ioc,
spin_lock_irqsave(&ioc->pcie_device_lock, flags);
list_for_each_entry(pcie_device, &ioc->pcie_device_list, list) {
- if ((pcie_device->wwid == pcie_device_pg0->WWID) &&
- (pcie_device->slot == pcie_device_pg0->Slot)) {
+ if ((pcie_device->wwid == le64_to_cpu(pcie_device_pg0->WWID))
+ && (pcie_device->slot == le16_to_cpu(
+ pcie_device_pg0->Slot))) {
pcie_device->responding = 1;
starget = pcie_device->starget;
if (starget && starget->hostdata) {
@@ -8523,14 +8712,16 @@ _scsih_mark_responding_pcie_device(struct MPT3SAS_ADAPTER *ioc,
pcie_device->connector_name[0] = '\0';
}
- if (pcie_device->handle == pcie_device_pg0->DevHandle)
+ if (pcie_device->handle == le16_to_cpu(
+ pcie_device_pg0->DevHandle))
goto out;
pr_info("\thandle changed from(0x%04x)!!!\n",
pcie_device->handle);
- pcie_device->handle = pcie_device_pg0->DevHandle;
+ pcie_device->handle = le16_to_cpu(
+ pcie_device_pg0->DevHandle);
if (sas_target_priv_data)
sas_target_priv_data->handle =
- pcie_device_pg0->DevHandle;
+ le16_to_cpu(pcie_device_pg0->DevHandle);
goto out;
}
}
@@ -8579,10 +8770,6 @@ _scsih_search_responding_pcie_devices(struct MPT3SAS_ADAPTER *ioc)
device_info = le32_to_cpu(pcie_device_pg0.DeviceInfo);
if (!(_scsih_is_nvme_device(device_info)))
continue;
- pcie_device_pg0.WWID = le64_to_cpu(pcie_device_pg0.WWID),
- pcie_device_pg0.Slot = le16_to_cpu(pcie_device_pg0.Slot);
- pcie_device_pg0.Flags = le32_to_cpu(pcie_device_pg0.Flags);
- pcie_device_pg0.DevHandle = handle;
_scsih_mark_responding_pcie_device(ioc, &pcie_device_pg0);
}
out:
@@ -8736,22 +8923,16 @@ _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc,
{
struct _sas_node *sas_expander = NULL;
unsigned long flags;
- int i, encl_pg0_rc = -1;
- Mpi2ConfigReply_t mpi_reply;
- Mpi2SasEnclosurePage0_t enclosure_pg0;
+ int i;
+ struct _enclosure_node *enclosure_dev = NULL;
u16 handle = le16_to_cpu(expander_pg0->DevHandle);
+ u16 enclosure_handle = le16_to_cpu(expander_pg0->EnclosureHandle);
u64 sas_address = le64_to_cpu(expander_pg0->SASAddress);
- if (le16_to_cpu(expander_pg0->EnclosureHandle)) {
- encl_pg0_rc = mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply,
- &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
- le16_to_cpu(expander_pg0->EnclosureHandle));
- if (encl_pg0_rc)
- pr_info(MPT3SAS_FMT
- "Enclosure Pg0 read failed for handle(0x%04x)\n",
- ioc->name,
- le16_to_cpu(expander_pg0->EnclosureHandle));
- }
+ if (enclosure_handle)
+ enclosure_dev =
+ mpt3sas_scsih_enclosure_find_by_handle(ioc,
+ enclosure_handle);
spin_lock_irqsave(&ioc->sas_node_lock, flags);
list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
@@ -8759,12 +8940,12 @@ _scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc,
continue;
sas_expander->responding = 1;
- if (!encl_pg0_rc)
+ if (enclosure_dev) {
sas_expander->enclosure_logical_id =
- le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
-
- sas_expander->enclosure_handle =
- le16_to_cpu(expander_pg0->EnclosureHandle);
+ le64_to_cpu(enclosure_dev->pg0.EnclosureLogicalID);
+ sas_expander->enclosure_handle =
+ le16_to_cpu(expander_pg0->EnclosureHandle);
+ }
if (sas_expander->handle == handle)
goto out;
@@ -9286,6 +9467,7 @@ mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase)
if ((!ioc->is_driver_loading) && !(disable_discovery > 0 &&
!ioc->sas_hba.num_phys)) {
_scsih_prep_device_scan(ioc);
+ _scsih_create_enclosure_list_after_reset(ioc);
_scsih_search_responding_sas_devices(ioc);
_scsih_search_responding_pcie_devices(ioc);
_scsih_search_responding_raid_devices(ioc);
@@ -9356,6 +9538,9 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
case MPI2_EVENT_SAS_DISCOVERY:
_scsih_sas_discovery_event(ioc, fw_event);
break;
+ case MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
+ _scsih_sas_device_discovery_error_event(ioc, fw_event);
+ break;
case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
_scsih_sas_broadcast_primitive_event(ioc, fw_event);
break;
@@ -9433,8 +9618,8 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
u16 sz;
Mpi26EventDataActiveCableExcept_t *ActiveCableEventData;
- /* events turned off due to host reset or driver unloading */
- if (ioc->remove_host || ioc->pci_error_recovery)
+ /* events turned off due to host reset */
+ if (ioc->pci_error_recovery)
return 1;
mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply);
@@ -9540,6 +9725,7 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index,
case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
case MPI2_EVENT_IR_OPERATION_STATUS:
case MPI2_EVENT_SAS_DISCOVERY:
+ case MPI2_EVENT_SAS_DEVICE_DISCOVERY_ERROR:
case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
case MPI2_EVENT_IR_PHYSICAL_DISK:
case MPI2_EVENT_PCIE_ENUMERATION:
@@ -10513,6 +10699,7 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
INIT_LIST_HEAD(&ioc->sas_device_list);
INIT_LIST_HEAD(&ioc->sas_device_init_list);
INIT_LIST_HEAD(&ioc->sas_expander_list);
+ INIT_LIST_HEAD(&ioc->enclosure_list);
INIT_LIST_HEAD(&ioc->pcie_device_list);
INIT_LIST_HEAD(&ioc->pcie_device_init_list);
INIT_LIST_HEAD(&ioc->fw_event_list);
@@ -11100,10 +11287,10 @@ _mpt3sas_exit(void)
pr_info("mpt3sas version %s unloading\n",
MPT3SAS_DRIVER_VERSION);
- pci_unregister_driver(&mpt3sas_driver);
-
mpt3sas_ctl_exit(hbas_to_enumerate);
+ pci_unregister_driver(&mpt3sas_driver);
+
scsih_exit();
}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c b/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c
index 6bfcee4..45aa949 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_warpdrive.c
@@ -177,7 +177,8 @@ mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc,
if (mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
&pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
vol_pg0->PhysDisk[count].PhysDiskNum) ||
- pd_pg0.DevHandle == MPT3SAS_INVALID_DEVICE_HANDLE) {
+ le16_to_cpu(pd_pg0.DevHandle) ==
+ MPT3SAS_INVALID_DEVICE_HANDLE) {
pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is "
"disabled for the drive with handle(0x%04x) member"
"handle retrieval failed for member number=%d\n",
diff --git a/drivers/scsi/mvumi.c b/drivers/scsi/mvumi.c
index afd2716..b3cd9a6 100644
--- a/drivers/scsi/mvumi.c
+++ b/drivers/scsi/mvumi.c
@@ -2693,22 +2693,4 @@ static struct pci_driver mvumi_pci_driver = {
#endif
};
-/**
- * mvumi_init - Driver load entry point
- */
-static int __init mvumi_init(void)
-{
- return pci_register_driver(&mvumi_pci_driver);
-}
-
-/**
- * mvumi_exit - Driver unload entry point
- */
-static void __exit mvumi_exit(void)
-{
-
- pci_unregister_driver(&mvumi_pci_driver);
-}
-
-module_init(mvumi_init);
-module_exit(mvumi_exit);
+module_pci_driver(mvumi_pci_driver);
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 5a33e1a..67b1457 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -1840,14 +1840,14 @@ int osd_req_decode_sense_full(struct osd_request *or,
case osd_sense_response_integrity_check:
{
struct osd_sense_response_integrity_check_descriptor
- *osricd = cur_descriptor;
- const unsigned len =
- sizeof(osricd->integrity_check_value);
- char key_dump[len*4 + 2]; /* 2nibbles+space+ASCII */
-
- hex_dump_to_buffer(osricd->integrity_check_value, len,
- 32, 1, key_dump, sizeof(key_dump), true);
- OSD_SENSE_PRINT2("response_integrity [%s]\n", key_dump);
+ *d = cur_descriptor;
+ /* 2nibbles+space+ASCII */
+ char dump[sizeof(d->integrity_check_value) * 4 + 2];
+
+ hex_dump_to_buffer(d->integrity_check_value,
+ sizeof(d->integrity_check_value),
+ 32, 1, dump, sizeof(dump), true);
+ OSD_SENSE_PRINT2("response_integrity [%s]\n", dump);
}
case osd_sense_attribute_identification:
{
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 2bbe797..7a1a1ed 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -381,7 +381,7 @@ static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
int i;
- pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
+ pages = kcalloc(use_sg, sizeof(struct page *), GFP_KERNEL);
if (!pages)
goto free_req;
@@ -1488,7 +1488,7 @@ static int osst_read_back_buffer_and_rewrite(struct osst_tape * STp, struct osst
int dbg = debugging;
#endif
- if ((buffer = vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
+ if ((buffer = vmalloc(array_size((nframes + 1), OS_DATA_SIZE))) == NULL)
return (-EIO);
printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
@@ -5856,7 +5856,9 @@ static int osst_probe(struct device *dev)
/* if this is the first attach, build the infrastructure */
write_lock(&os_scsi_tapes_lock);
if (os_scsi_tapes == NULL) {
- os_scsi_tapes = kmalloc(osst_max_dev * sizeof(struct osst_tape *), GFP_ATOMIC);
+ os_scsi_tapes = kmalloc_array(osst_max_dev,
+ sizeof(struct osst_tape *),
+ GFP_ATOMIC);
if (os_scsi_tapes == NULL) {
write_unlock(&os_scsi_tapes_lock);
printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 596f3ff..d193961 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -705,7 +705,7 @@ static ssize_t pm8001_store_update_fw(struct device *cdev,
return -EINPROGRESS;
pm8001_ha->fw_status = FLASH_IN_PROGRESS;
- cmd_ptr = kzalloc(count*2, GFP_KERNEL);
+ cmd_ptr = kcalloc(count, 2, GFP_KERNEL);
if (!cmd_ptr) {
pm8001_ha->fw_status = FAIL_OUT_MEMORY;
return -ENOMEM;
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index db88a8e7..4dd6cad 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3607,7 +3607,7 @@ int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
break;
default:
PM8001_MSG_DBG(pm8001_ha,
- pm8001_printk("DEVREG_FAILURE_DEVICE_TYPE_NOT_UNSORPORTED\n"));
+ pm8001_printk("DEVREG_FAILURE_DEVICE_TYPE_NOT_SUPPORTED\n"));
break;
}
complete(pm8001_dev->dcompletion);
diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c
index 9553039..4e86994 100644
--- a/drivers/scsi/pmcraid.c
+++ b/drivers/scsi/pmcraid.c
@@ -4873,8 +4873,9 @@ static int pmcraid_allocate_config_buffers(struct pmcraid_instance *pinstance)
int i;
pinstance->res_entries =
- kzalloc(sizeof(struct pmcraid_resource_entry) *
- PMCRAID_MAX_RESOURCES, GFP_KERNEL);
+ kcalloc(PMCRAID_MAX_RESOURCES,
+ sizeof(struct pmcraid_resource_entry),
+ GFP_KERNEL);
if (NULL == pinstance->res_entries) {
pmcraid_err("failed to allocate memory for resource table\n");
diff --git a/drivers/scsi/qedf/drv_fcoe_fw_funcs.c b/drivers/scsi/qedf/drv_fcoe_fw_funcs.c
index a980ef7..5bd10b5 100644
--- a/drivers/scsi/qedf/drv_fcoe_fw_funcs.c
+++ b/drivers/scsi/qedf/drv_fcoe_fw_funcs.c
@@ -1,5 +1,5 @@
/* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/drv_fcoe_fw_funcs.h b/drivers/scsi/qedf/drv_fcoe_fw_funcs.h
index b5c236e..42fde55 100644
--- a/drivers/scsi/qedf/drv_fcoe_fw_funcs.h
+++ b/drivers/scsi/qedf/drv_fcoe_fw_funcs.h
@@ -1,5 +1,5 @@
/* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/drv_scsi_fw_funcs.c b/drivers/scsi/qedf/drv_scsi_fw_funcs.c
index 5d5095e..29a5525 100644
--- a/drivers/scsi/qedf/drv_scsi_fw_funcs.c
+++ b/drivers/scsi/qedf/drv_scsi_fw_funcs.c
@@ -1,5 +1,5 @@
/* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/drv_scsi_fw_funcs.h b/drivers/scsi/qedf/drv_scsi_fw_funcs.h
index 8fbe6e4..bf10220 100644
--- a/drivers/scsi/qedf/drv_scsi_fw_funcs.h
+++ b/drivers/scsi/qedf/drv_scsi_fw_funcs.h
@@ -1,5 +1,5 @@
/* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h
index cabb6af..2c78d8f 100644
--- a/drivers/scsi/qedf/qedf.h
+++ b/drivers/scsi/qedf/qedf.h
@@ -1,6 +1,6 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
@@ -180,6 +180,7 @@ struct qedf_rport {
spinlock_t rport_lock;
#define QEDF_RPORT_SESSION_READY 1
#define QEDF_RPORT_UPLOADING_CONNECTION 2
+#define QEDF_RPORT_IN_RESET 3
unsigned long flags;
unsigned long retry_delay_timestamp;
struct fc_rport *rport;
@@ -300,6 +301,7 @@ struct qedf_ctx {
#define QEDF_FALLBACK_VLAN 1002
#define QEDF_DEFAULT_PRIO 3
int vlan_id;
+ u8 prio;
struct qed_dev *cdev;
struct qed_dev_fcoe_info dev_info;
struct qed_int_info int_info;
@@ -365,6 +367,7 @@ struct qedf_ctx {
#define QEDF_IO_WORK_MIN 64
mempool_t *io_mempool;
struct workqueue_struct *dpc_wq;
+ struct delayed_work grcdump_work;
u32 slow_sge_ios;
u32 fast_sge_ios;
@@ -504,6 +507,7 @@ extern int qedf_send_flogi(struct qedf_ctx *qedf);
extern void qedf_get_protocol_tlv_data(void *dev, void *data);
extern void qedf_fp_io_handler(struct work_struct *work);
extern void qedf_get_generic_tlv_data(void *dev, struct qed_generic_tlvs *data);
+extern void qedf_wq_grcdump(struct work_struct *work);
#define FCOE_WORD_TO_BYTE 4
#define QEDF_MAX_TASK_NUM 0xFFFF
diff --git a/drivers/scsi/qedf/qedf_attr.c b/drivers/scsi/qedf/qedf_attr.c
index fa67276..0487b72 100644
--- a/drivers/scsi/qedf/qedf_attr.c
+++ b/drivers/scsi/qedf/qedf_attr.c
@@ -1,6 +1,6 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/qedf_dbg.c b/drivers/scsi/qedf/qedf_dbg.c
index bd1cef25..f2397ee 100644
--- a/drivers/scsi/qedf/qedf_dbg.c
+++ b/drivers/scsi/qedf/qedf_dbg.c
@@ -1,6 +1,6 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
@@ -147,7 +147,7 @@ qedf_get_grc_dump(struct qed_dev *cdev, const struct qed_common_ops *common,
if (!*buf)
return -EINVAL;
- return common->dbg_grc(cdev, *buf, grcsize);
+ return common->dbg_all_data(cdev, *buf);
}
void
diff --git a/drivers/scsi/qedf/qedf_dbg.h b/drivers/scsi/qedf/qedf_dbg.h
index 77c27e8..dd01096 100644
--- a/drivers/scsi/qedf/qedf_dbg.h
+++ b/drivers/scsi/qedf/qedf_dbg.h
@@ -1,6 +1,6 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c
index 5789ce1..c29c162 100644
--- a/drivers/scsi/qedf/qedf_debugfs.c
+++ b/drivers/scsi/qedf/qedf_debugfs.c
@@ -1,6 +1,6 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 QLogic Corporation
+ * Copyright (c) 2016-2018 QLogic Corporation
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c
index aa22b11..04f0c4d 100644
--- a/drivers/scsi/qedf/qedf_els.c
+++ b/drivers/scsi/qedf/qedf_els.c
@@ -1,6 +1,6 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
@@ -14,8 +14,8 @@ static int qedf_initiate_els(struct qedf_rport *fcport, unsigned int op,
void (*cb_func)(struct qedf_els_cb_arg *cb_arg),
struct qedf_els_cb_arg *cb_arg, uint32_t timer_msec)
{
- struct qedf_ctx *qedf = fcport->qedf;
- struct fc_lport *lport = qedf->lport;
+ struct qedf_ctx *qedf;
+ struct fc_lport *lport;
struct qedf_ioreq *els_req;
struct qedf_mp_req *mp_req;
struct fc_frame_header *fc_hdr;
@@ -29,6 +29,15 @@ static int qedf_initiate_els(struct qedf_rport *fcport, unsigned int op,
unsigned long flags;
u16 sqe_idx;
+ if (!fcport) {
+ QEDF_ERR(NULL, "fcport is NULL");
+ rc = -EINVAL;
+ goto els_err;
+ }
+
+ qedf = fcport->qedf;
+ lport = qedf->lport;
+
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_ELS, "Sending ELS\n");
rc = fc_remote_port_chkready(fcport->rport);
@@ -201,6 +210,14 @@ static void qedf_rrq_compl(struct qedf_els_cb_arg *cb_arg)
kref_put(&orig_io_req->refcount, qedf_release_cmd);
out_free:
+ /*
+ * Release a reference to the rrq request if we timed out as the
+ * rrq completion handler is called directly from the timeout handler
+ * and not from els_compl where the reference would have normally been
+ * released.
+ */
+ if (rrq_req->event == QEDF_IOREQ_EV_ELS_TMO)
+ kref_put(&rrq_req->refcount, qedf_release_cmd);
kfree(cb_arg);
}
@@ -322,6 +339,17 @@ void qedf_restart_rport(struct qedf_rport *fcport)
if (!fcport)
return;
+ if (test_bit(QEDF_RPORT_IN_RESET, &fcport->flags) ||
+ !test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags) ||
+ test_bit(QEDF_RPORT_UPLOADING_CONNECTION, &fcport->flags)) {
+ QEDF_ERR(&(fcport->qedf->dbg_ctx), "fcport %p already in reset or not offloaded.\n",
+ fcport);
+ return;
+ }
+
+ /* Set that we are now in reset */
+ set_bit(QEDF_RPORT_IN_RESET, &fcport->flags);
+
rdata = fcport->rdata;
if (rdata) {
lport = fcport->qedf->lport;
@@ -334,6 +362,7 @@ void qedf_restart_rport(struct qedf_rport *fcport)
if (rdata)
fc_rport_login(rdata);
}
+ clear_bit(QEDF_RPORT_IN_RESET, &fcport->flags);
}
static void qedf_l2_els_compl(struct qedf_els_cb_arg *cb_arg)
diff --git a/drivers/scsi/qedf/qedf_fip.c b/drivers/scsi/qedf/qedf_fip.c
index 16d1a21..3fd3af7 100644
--- a/drivers/scsi/qedf/qedf_fip.c
+++ b/drivers/scsi/qedf/qedf_fip.c
@@ -1,6 +1,6 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
@@ -137,7 +137,7 @@ void qedf_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2, "FIP frame send: "
"dest=%pM op=%x sub=%x vlan=%04x.", eth_hdr->h_dest, op, sub,
- ntohs(vlan_tci));
+ vlan_tci);
if (qedf_dump_frames)
print_hex_dump(KERN_WARNING, "fip ", DUMP_PREFIX_OFFSET, 16, 1,
skb->data, skb->len, false);
@@ -184,6 +184,7 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff *skb)
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
"Dropping CVL since FCF has not been selected "
"yet.");
+ kfree_skb(skb);
return;
}
diff --git a/drivers/scsi/qedf/qedf_hsi.h b/drivers/scsi/qedf/qedf_hsi.h
index 503c1ae..f6f634e4 100644
--- a/drivers/scsi/qedf/qedf_hsi.h
+++ b/drivers/scsi/qedf/qedf_hsi.h
@@ -1,6 +1,6 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c
index 3fe579d..6bbc38b 100644
--- a/drivers/scsi/qedf/qedf_io.c
+++ b/drivers/scsi/qedf/qedf_io.c
@@ -1,6 +1,6 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
@@ -23,12 +23,31 @@ static void qedf_cmd_timeout(struct work_struct *work)
struct qedf_ioreq *io_req =
container_of(work, struct qedf_ioreq, timeout_work.work);
- struct qedf_ctx *qedf = io_req->fcport->qedf;
- struct qedf_rport *fcport = io_req->fcport;
+ struct qedf_ctx *qedf;
+ struct qedf_rport *fcport;
u8 op = 0;
+ if (io_req == NULL) {
+ QEDF_INFO(NULL, QEDF_LOG_IO, "io_req is NULL.\n");
+ return;
+ }
+
+ fcport = io_req->fcport;
+ if (io_req->fcport == NULL) {
+ QEDF_INFO(NULL, QEDF_LOG_IO, "fcport is NULL.\n");
+ return;
+ }
+
+ qedf = fcport->qedf;
+
switch (io_req->cmd_type) {
case QEDF_ABTS:
+ if (qedf == NULL) {
+ QEDF_INFO(NULL, QEDF_LOG_IO, "qedf is NULL for xid=0x%x.\n",
+ io_req->xid);
+ return;
+ }
+
QEDF_ERR((&qedf->dbg_ctx), "ABTS timeout, xid=0x%x.\n",
io_req->xid);
/* Cleanup timed out ABTS */
@@ -931,6 +950,15 @@ qedf_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd)
return 0;
}
+ if (!qedf->pdev->msix_enabled) {
+ QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_IO,
+ "Completing sc_cmd=%p DID_NO_CONNECT as MSI-X is not enabled.\n",
+ sc_cmd);
+ sc_cmd->result = DID_NO_CONNECT << 16;
+ sc_cmd->scsi_done(sc_cmd);
+ return 0;
+ }
+
rval = fc_remote_port_chkready(rport);
if (rval) {
sc_cmd->result = rval;
@@ -1420,6 +1448,12 @@ void qedf_flush_active_ios(struct qedf_rport *fcport, int lun)
if (!fcport)
return;
+ /* Check that fcport is still offloaded */
+ if (!test_bit(QEDF_RPORT_SESSION_READY, &fcport->flags)) {
+ QEDF_ERR(NULL, "fcport is no longer offloaded.\n");
+ return;
+ }
+
qedf = fcport->qedf;
cmd_mgr = qedf->cmd_mgr;
@@ -1436,8 +1470,8 @@ void qedf_flush_active_ios(struct qedf_rport *fcport, int lun)
rc = kref_get_unless_zero(&io_req->refcount);
if (!rc) {
QEDF_ERR(&(qedf->dbg_ctx),
- "Could not get kref for io_req=0x%p.\n",
- io_req);
+ "Could not get kref for ELS io_req=0x%p xid=0x%x.\n",
+ io_req, io_req->xid);
continue;
}
qedf_flush_els_req(qedf, io_req);
@@ -1448,6 +1482,31 @@ void qedf_flush_active_ios(struct qedf_rport *fcport, int lun)
goto free_cmd;
}
+ if (io_req->cmd_type == QEDF_ABTS) {
+ rc = kref_get_unless_zero(&io_req->refcount);
+ if (!rc) {
+ QEDF_ERR(&(qedf->dbg_ctx),
+ "Could not get kref for abort io_req=0x%p xid=0x%x.\n",
+ io_req, io_req->xid);
+ continue;
+ }
+ QEDF_INFO(&qedf->dbg_ctx, QEDF_LOG_IO,
+ "Flushing abort xid=0x%x.\n", io_req->xid);
+
+ clear_bit(QEDF_CMD_IN_ABORT, &io_req->flags);
+
+ if (io_req->sc_cmd) {
+ if (io_req->return_scsi_cmd_on_abts)
+ qedf_scsi_done(qedf, io_req, DID_ERROR);
+ }
+
+ /* Notify eh_abort handler that ABTS is complete */
+ complete(&io_req->abts_done);
+ kref_put(&io_req->refcount, qedf_release_cmd);
+
+ goto free_cmd;
+ }
+
if (!io_req->sc_cmd)
continue;
if (lun > 0) {
@@ -1463,7 +1522,7 @@ void qedf_flush_active_ios(struct qedf_rport *fcport, int lun)
rc = kref_get_unless_zero(&io_req->refcount);
if (!rc) {
QEDF_ERR(&(qedf->dbg_ctx), "Could not get kref for "
- "io_req=0x%p\n", io_req);
+ "io_req=0x%p xid=0x%x\n", io_req, io_req->xid);
continue;
}
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_IO,
@@ -1525,6 +1584,21 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool return_scsi_cmd_on_abts)
goto abts_err;
}
+ if (test_bit(QEDF_RPORT_UPLOADING_CONNECTION, &fcport->flags)) {
+ QEDF_ERR(&qedf->dbg_ctx, "fcport is uploading.\n");
+ rc = 1;
+ goto out;
+ }
+
+ if (!test_bit(QEDF_CMD_OUTSTANDING, &io_req->flags) ||
+ test_bit(QEDF_CMD_IN_CLEANUP, &io_req->flags) ||
+ test_bit(QEDF_CMD_IN_ABORT, &io_req->flags)) {
+ QEDF_ERR(&(qedf->dbg_ctx), "io_req xid=0x%x already in "
+ "cleanup or abort processing or already "
+ "completed.\n", io_req->xid);
+ rc = 1;
+ goto out;
+ }
kref_get(&io_req->refcount);
@@ -1564,6 +1638,7 @@ abts_err:
* task at the firmware.
*/
qedf_initiate_cleanup(io_req, return_scsi_cmd_on_abts);
+out:
return rc;
}
diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index d3f73d8..90394ce 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -1,6 +1,6 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
@@ -44,20 +44,20 @@ module_param_named(debug, qedf_debug, uint, S_IRUGO);
MODULE_PARM_DESC(debug, " Debug mask. Pass '1' to enable default debugging"
" mask");
-static uint qedf_fipvlan_retries = 30;
+static uint qedf_fipvlan_retries = 60;
module_param_named(fipvlan_retries, qedf_fipvlan_retries, int, S_IRUGO);
MODULE_PARM_DESC(fipvlan_retries, " Number of FIP VLAN requests to attempt "
- "before giving up (default 30)");
+ "before giving up (default 60)");
static uint qedf_fallback_vlan = QEDF_FALLBACK_VLAN;
module_param_named(fallback_vlan, qedf_fallback_vlan, int, S_IRUGO);
MODULE_PARM_DESC(fallback_vlan, " VLAN ID to try if fip vlan request fails "
"(default 1002).");
-static uint qedf_default_prio = QEDF_DEFAULT_PRIO;
+static int qedf_default_prio = -1;
module_param_named(default_prio, qedf_default_prio, int, S_IRUGO);
-MODULE_PARM_DESC(default_prio, " Default 802.1q priority for FIP and FCoE"
- " traffic (default 3).");
+MODULE_PARM_DESC(default_prio, " Override 802.1q priority for FIP and FCoE"
+ " traffic (value between 0 and 7, default 3).");
uint qedf_dump_frames;
module_param_named(dump_frames, qedf_dump_frames, int, S_IRUGO | S_IWUSR);
@@ -89,6 +89,11 @@ module_param_named(retry_delay, qedf_retry_delay, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(retry_delay, " Enable/disable handling of FCP_RSP IU retry "
"delay handling (default off).");
+static bool qedf_dcbx_no_wait;
+module_param_named(dcbx_no_wait, qedf_dcbx_no_wait, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(dcbx_no_wait, " Do not wait for DCBX convergence to start "
+ "sending FIP VLAN requests on link up (Default: off).");
+
static uint qedf_dp_module;
module_param_named(dp_module, qedf_dp_module, uint, S_IRUGO);
MODULE_PARM_DESC(dp_module, " bit flags control for verbose printk passed "
@@ -109,9 +114,9 @@ static struct kmem_cache *qedf_io_work_cache;
void qedf_set_vlan_id(struct qedf_ctx *qedf, int vlan_id)
{
qedf->vlan_id = vlan_id;
- qedf->vlan_id |= qedf_default_prio << VLAN_PRIO_SHIFT;
+ qedf->vlan_id |= qedf->prio << VLAN_PRIO_SHIFT;
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC, "Setting vlan_id=%04x "
- "prio=%d.\n", vlan_id, qedf_default_prio);
+ "prio=%d.\n", vlan_id, qedf->prio);
}
/* Returns true if we have a valid vlan, false otherwise */
@@ -480,6 +485,11 @@ static void qedf_link_update(void *dev, struct qed_link_output *link)
struct qedf_ctx *qedf = (struct qedf_ctx *)dev;
if (link->link_up) {
+ if (atomic_read(&qedf->link_state) == QEDF_LINK_UP) {
+ QEDF_INFO((&qedf->dbg_ctx), QEDF_LOG_DISC,
+ "Ignoring link up event as link is already up.\n");
+ return;
+ }
QEDF_ERR(&(qedf->dbg_ctx), "LINK UP (%d GB/s).\n",
link->speed / 1000);
@@ -489,7 +499,8 @@ static void qedf_link_update(void *dev, struct qed_link_output *link)
atomic_set(&qedf->link_state, QEDF_LINK_UP);
qedf_update_link_speed(qedf, link);
- if (atomic_read(&qedf->dcbx) == QEDF_DCBX_DONE) {
+ if (atomic_read(&qedf->dcbx) == QEDF_DCBX_DONE ||
+ qedf_dcbx_no_wait) {
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
"DCBx done.\n");
if (atomic_read(&qedf->link_down_tmo_valid) > 0)
@@ -515,7 +526,7 @@ static void qedf_link_update(void *dev, struct qed_link_output *link)
"Starting link down tmo.\n");
atomic_set(&qedf->link_down_tmo_valid, 1);
}
- qedf->vlan_id = 0;
+ qedf->vlan_id = 0;
qedf_update_link_speed(qedf, link);
queue_delayed_work(qedf->link_update_wq, &qedf->link_update,
qedf_link_down_tmo * HZ);
@@ -526,6 +537,7 @@ static void qedf_link_update(void *dev, struct qed_link_output *link)
static void qedf_dcbx_handler(void *dev, struct qed_dcbx_get *get, u32 mib_type)
{
struct qedf_ctx *qedf = (struct qedf_ctx *)dev;
+ u8 tmp_prio;
QEDF_ERR(&(qedf->dbg_ctx), "DCBx event valid=%d enabled=%d fcoe "
"prio=%d.\n", get->operational.valid, get->operational.enabled,
@@ -541,7 +553,26 @@ static void qedf_dcbx_handler(void *dev, struct qed_dcbx_get *get, u32 mib_type)
atomic_set(&qedf->dcbx, QEDF_DCBX_DONE);
- if (atomic_read(&qedf->link_state) == QEDF_LINK_UP) {
+ /*
+ * Set the 8021q priority in the following manner:
+ *
+ * 1. If a modparam is set use that
+ * 2. If the value is not between 0..7 use the default
+ * 3. Use the priority we get from the DCBX app tag
+ */
+ tmp_prio = get->operational.app_prio.fcoe;
+ if (qedf_default_prio > -1)
+ qedf->prio = qedf_default_prio;
+ else if (tmp_prio < 0 || tmp_prio > 7) {
+ QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
+ "FIP/FCoE prio %d out of range, setting to %d.\n",
+ tmp_prio, QEDF_DEFAULT_PRIO);
+ qedf->prio = QEDF_DEFAULT_PRIO;
+ } else
+ qedf->prio = tmp_prio;
+
+ if (atomic_read(&qedf->link_state) == QEDF_LINK_UP &&
+ !qedf_dcbx_no_wait) {
if (atomic_read(&qedf->link_down_tmo_valid) > 0)
queue_delayed_work(qedf->link_update_wq,
&qedf->link_recovery, 0);
@@ -614,16 +645,6 @@ static int qedf_eh_abort(struct scsi_cmnd *sc_cmd)
goto out;
}
- if (!test_bit(QEDF_CMD_OUTSTANDING, &io_req->flags) ||
- test_bit(QEDF_CMD_IN_CLEANUP, &io_req->flags) ||
- test_bit(QEDF_CMD_IN_ABORT, &io_req->flags)) {
- QEDF_ERR(&(qedf->dbg_ctx), "io_req xid=0x%x already in "
- "cleanup or abort processing or already "
- "completed.\n", io_req->xid);
- rc = SUCCESS;
- goto out;
- }
-
QEDF_ERR(&(qedf->dbg_ctx), "Aborting io_req sc_cmd=%p xid=0x%x "
"fp_idx=%d.\n", sc_cmd, io_req->xid, io_req->fp_idx);
@@ -705,7 +726,6 @@ static void qedf_ctx_soft_reset(struct fc_lport *lport)
/* For host reset, essentially do a soft link up/down */
atomic_set(&qedf->link_state, QEDF_LINK_DOWN);
- atomic_set(&qedf->dcbx, QEDF_DCBX_PENDING);
queue_delayed_work(qedf->link_update_wq, &qedf->link_update,
0);
qedf_wait_for_upload(qedf);
@@ -720,6 +740,22 @@ static int qedf_eh_host_reset(struct scsi_cmnd *sc_cmd)
{
struct fc_lport *lport;
struct qedf_ctx *qedf;
+ struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+ struct fc_rport_libfc_priv *rp = rport->dd_data;
+ struct qedf_rport *fcport = (struct qedf_rport *)&rp[1];
+ int rval;
+
+ rval = fc_remote_port_chkready(rport);
+
+ if (rval) {
+ QEDF_ERR(NULL, "device_reset rport not ready\n");
+ return FAILED;
+ }
+
+ if (fcport == NULL) {
+ QEDF_ERR(NULL, "device_reset: rport is NULL\n");
+ return FAILED;
+ }
lport = shost_priv(sc_cmd->device->host);
qedf = lport_priv(lport);
@@ -1109,7 +1145,7 @@ static int qedf_offload_connection(struct qedf_ctx *qedf,
conn_info.vlan_tag = qedf->vlan_id <<
FCOE_CONN_OFFLOAD_RAMROD_DATA_VLAN_ID_SHIFT;
conn_info.vlan_tag |=
- qedf_default_prio << FCOE_CONN_OFFLOAD_RAMROD_DATA_PRIORITY_SHIFT;
+ qedf->prio << FCOE_CONN_OFFLOAD_RAMROD_DATA_PRIORITY_SHIFT;
conn_info.flags |= (FCOE_CONN_OFFLOAD_RAMROD_DATA_B_VLAN_FLAG_MASK <<
FCOE_CONN_OFFLOAD_RAMROD_DATA_B_VLAN_FLAG_SHIFT);
@@ -1649,6 +1685,15 @@ static int qedf_vport_destroy(struct fc_vport *vport)
struct Scsi_Host *shost = vport_to_shost(vport);
struct fc_lport *n_port = shost_priv(shost);
struct fc_lport *vn_port = vport->dd_data;
+ struct qedf_ctx *qedf = lport_priv(vn_port);
+
+ if (!qedf) {
+ QEDF_ERR(NULL, "qedf is NULL.\n");
+ goto out;
+ }
+
+ /* Set unloading bit on vport qedf_ctx to prevent more I/O */
+ set_bit(QEDF_UNLOADING, &qedf->flags);
mutex_lock(&n_port->lp_mutex);
list_del(&vn_port->list);
@@ -1675,6 +1720,7 @@ static int qedf_vport_destroy(struct fc_vport *vport)
if (vn_port->host)
scsi_host_put(vn_port->host);
+out:
return 0;
}
@@ -2109,7 +2155,8 @@ static int qedf_setup_int(struct qedf_ctx *qedf)
QEDF_SIMD_HANDLER_NUM, qedf_simd_int_handler);
qedf->int_info.used_cnt = 1;
- return 0;
+ QEDF_ERR(&qedf->dbg_ctx, "Only MSI-X supported. Failing probe.\n");
+ return -EINVAL;
}
/* Main function for libfc frame reception */
@@ -2195,6 +2242,7 @@ static void qedf_recv_frame(struct qedf_ctx *qedf,
if (ntoh24(&dest_mac[3]) != ntoh24(fh->fh_d_id)) {
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
"FC frame d_id mismatch with MAC %pM.\n", dest_mac);
+ kfree_skb(skb);
return;
}
@@ -2983,8 +3031,17 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
qedf->link_update_wq = create_workqueue(host_buf);
INIT_DELAYED_WORK(&qedf->link_update, qedf_handle_link_update);
INIT_DELAYED_WORK(&qedf->link_recovery, qedf_link_recovery);
-
+ INIT_DELAYED_WORK(&qedf->grcdump_work, qedf_wq_grcdump);
qedf->fipvlan_retries = qedf_fipvlan_retries;
+ /* Set a default prio in case DCBX doesn't converge */
+ if (qedf_default_prio > -1) {
+ /*
+ * This is the case where we pass a modparam in so we want to
+ * honor it even if dcbx doesn't converge.
+ */
+ qedf->prio = qedf_default_prio;
+ } else
+ qedf->prio = QEDF_DEFAULT_PRIO;
/*
* Common probe. Takes care of basic hardware init and pci_*
@@ -3214,7 +3271,8 @@ static int __qedf_probe(struct pci_dev *pdev, int mode)
* unload process.
*/
if (mode != QEDF_MODE_RECOVERY) {
- qedf->grcdump_size = qed_ops->common->dbg_grc_size(qedf->cdev);
+ qedf->grcdump_size =
+ qed_ops->common->dbg_all_data_size(qedf->cdev);
if (qedf->grcdump_size) {
rc = qedf_alloc_grc_dump_buf(&qedf->grcdump,
qedf->grcdump_size);
@@ -3398,6 +3456,15 @@ static void qedf_remove(struct pci_dev *pdev)
__qedf_remove(pdev, QEDF_MODE_NORMAL);
}
+void qedf_wq_grcdump(struct work_struct *work)
+{
+ struct qedf_ctx *qedf =
+ container_of(work, struct qedf_ctx, grcdump_work.work);
+
+ QEDF_ERR(&(qedf->dbg_ctx), "Collecting GRC dump.\n");
+ qedf_capture_grc_dump(qedf);
+}
+
/*
* Protocol TLV handler
*/
@@ -3508,6 +3575,17 @@ static int __init qedf_init(void)
if (qedf_debug == QEDF_LOG_DEFAULT)
qedf_debug = QEDF_DEFAULT_LOG_MASK;
+ /*
+ * Check that default prio for FIP/FCoE traffic is between 0..7 if a
+ * value has been set
+ */
+ if (qedf_default_prio > -1)
+ if (qedf_default_prio > 7) {
+ qedf_default_prio = QEDF_DEFAULT_PRIO;
+ QEDF_ERR(NULL, "FCoE/FIP priority out of range, resetting to %d.\n",
+ QEDF_DEFAULT_PRIO);
+ }
+
/* Print driver banner */
QEDF_INFO(NULL, QEDF_LOG_INFO, "%s v%s.\n", QEDF_DESCR,
QEDF_VERSION);
diff --git a/drivers/scsi/qedf/qedf_version.h b/drivers/scsi/qedf/qedf_version.h
index c247805..9455faa 100644
--- a/drivers/scsi/qedf/qedf_version.h
+++ b/drivers/scsi/qedf/qedf_version.h
@@ -1,15 +1,15 @@
/*
* QLogic FCoE Offload Driver
- * Copyright (c) 2016-2017 Cavium Inc.
+ * Copyright (c) 2016-2018 Cavium Inc.
*
* This software is available under the terms of the GNU General Public License
* (GPL) Version 2, available from the file COPYING in the main directory of
* this source tree.
*/
-#define QEDF_VERSION "8.33.0.20"
+#define QEDF_VERSION "8.33.16.20"
#define QEDF_DRIVER_MAJOR_VER 8
#define QEDF_DRIVER_MINOR_VER 33
-#define QEDF_DRIVER_REV_VER 0
+#define QEDF_DRIVER_REV_VER 16
#define QEDF_DRIVER_ENG_VER 20
diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c
index 32ee7f6..cf274a7 100644
--- a/drivers/scsi/qedi/qedi_main.c
+++ b/drivers/scsi/qedi/qedi_main.c
@@ -524,7 +524,7 @@ static int qedi_init_id_tbl(struct qedi_portid_tbl *id_tbl, u16 size,
id_tbl->max = size;
id_tbl->next = next;
spin_lock_init(&id_tbl->lock);
- id_tbl->table = kzalloc(DIV_ROUND_UP(size, 32) * 4, GFP_KERNEL);
+ id_tbl->table = kcalloc(DIV_ROUND_UP(size, 32), 4, GFP_KERNEL);
if (!id_tbl->table)
return -ENOMEM;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index eb2ec1f..9442e18 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2279,8 +2279,6 @@ enum discovery_state {
DSC_LOGIN_PEND,
DSC_LOGIN_FAILED,
DSC_GPDB,
- DSC_GFPN_ID,
- DSC_GPSC,
DSC_UPD_FCPORT,
DSC_LOGIN_COMPLETE,
DSC_ADISC,
@@ -2346,6 +2344,7 @@ typedef struct fc_port {
unsigned int login_succ:1;
unsigned int query:1;
unsigned int id_changed:1;
+ unsigned int rscn_rcvd:1;
struct work_struct nvme_del_work;
struct completion nvme_del_done;
@@ -3226,6 +3225,7 @@ enum qla_work_type {
QLA_EVT_GNNID,
QLA_EVT_GFPNID,
QLA_EVT_SP_RETRY,
+ QLA_EVT_IIDMA,
};
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index 3c4c84e..f68eb60 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -116,7 +116,8 @@ extern int qla2x00_post_async_prlo_work(struct scsi_qla_host *, fc_port_t *,
uint16_t *);
extern int qla2x00_post_async_prlo_done_work(struct scsi_qla_host *,
fc_port_t *, uint16_t *);
-
+int qla_post_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport);
+void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport);
/*
* Global Data in qla_os.c source file.
*/
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index 9e914f9..4bc2b66 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3175,7 +3175,6 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t *fcport)
done_free_sp:
sp->free(sp);
- fcport->flags &= ~FCF_ASYNC_SENT;
done:
fcport->flags &= ~FCF_ASYNC_ACTIVE;
return rval;
@@ -3239,7 +3238,7 @@ void qla24xx_handle_gpsc_event(scsi_qla_host_t *vha, struct event_arg *ea)
return;
}
- qla24xx_post_upd_fcport_work(vha, ea->fcport);
+ qla_post_iidma_work(vha, fcport);
}
static void qla24xx_async_gpsc_sp_done(void *s, int res)
@@ -3257,8 +3256,6 @@ static void qla24xx_async_gpsc_sp_done(void *s, int res)
"Async done-%s res %x, WWPN %8phC \n",
sp->name, res, fcport->port_name);
- fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
-
if (res == (DID_ERROR << 16)) {
/* entry status error */
goto done;
@@ -3327,7 +3324,6 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t *fcport)
if (!sp)
goto done;
- fcport->flags |= FCF_ASYNC_SENT;
sp->type = SRB_CT_PTHRU_CMD;
sp->name = "gpsc";
sp->gen1 = fcport->rscn_gen;
@@ -3862,6 +3858,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
bool found;
struct fab_scan_rp *rp;
unsigned long flags;
+ u8 recheck = 0;
ql_dbg(ql_dbg_disc, vha, 0xffff,
"%s enter\n", __func__);
@@ -3914,8 +3911,8 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
list_for_each_entry(fcport, &vha->vp_fcports, list) {
if (memcmp(rp->port_name, fcport->port_name, WWN_SIZE))
continue;
+ fcport->rscn_rcvd = 0;
fcport->scan_state = QLA_FCPORT_FOUND;
- fcport->d_id.b24 = rp->id.b24;
found = true;
/*
* If device was not a fabric device before.
@@ -3923,7 +3920,10 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
qla2x00_clear_loop_id(fcport);
fcport->flags |= FCF_FABRIC_DEVICE;
+ } else if (fcport->d_id.b24 != rp->id.b24) {
+ qlt_schedule_sess_for_deletion(fcport);
}
+ fcport->d_id.b24 = rp->id.b24;
break;
}
@@ -3940,10 +3940,13 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
* Logout all previous fabric dev marked lost, except FCP2 devices.
*/
list_for_each_entry(fcport, &vha->vp_fcports, list) {
- if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
+ if ((fcport->flags & FCF_FABRIC_DEVICE) == 0) {
+ fcport->rscn_rcvd = 0;
continue;
+ }
if (fcport->scan_state != QLA_FCPORT_FOUND) {
+ fcport->rscn_rcvd = 0;
if ((qla_dual_mode_enabled(vha) ||
qla_ini_mode_enabled(vha)) &&
atomic_read(&fcport->state) == FCS_ONLINE) {
@@ -3961,15 +3964,31 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
continue;
}
}
- } else
- qla24xx_fcport_handle_login(vha, fcport);
+ } else {
+ if (fcport->rscn_rcvd ||
+ fcport->disc_state != DSC_LOGIN_COMPLETE) {
+ fcport->rscn_rcvd = 0;
+ qla24xx_fcport_handle_login(vha, fcport);
+ }
+ }
}
+ recheck = 1;
out:
qla24xx_sp_unmap(vha, sp);
spin_lock_irqsave(&vha->work_lock, flags);
vha->scan.scan_flags &= ~SF_SCANNING;
spin_unlock_irqrestore(&vha->work_lock, flags);
+
+ if (recheck) {
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+ if (fcport->rscn_rcvd) {
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ break;
+ }
+ }
+ }
}
static void qla2x00_find_free_fcp_nvme_slot(struct scsi_qla_host *vha,
@@ -4532,7 +4551,6 @@ int qla24xx_async_gnnid(scsi_qla_host_t *vha, fc_port_t *fcport)
done_free_sp:
sp->free(sp);
- fcport->flags &= ~FCF_ASYNC_SENT;
done:
return rval;
}
@@ -4594,7 +4612,6 @@ static void qla2x00_async_gfpnid_sp_done(void *s, int res)
struct event_arg ea;
u64 wwn;
- fcport->flags &= ~FCF_ASYNC_SENT;
wwn = wwn_to_u64(fpn);
if (wwn)
memcpy(fcport->fabric_port_name, fpn, WWN_SIZE);
@@ -4623,12 +4640,10 @@ int qla24xx_async_gfpnid(scsi_qla_host_t *vha, fc_port_t *fcport)
if (!vha->flags.online || (fcport->flags & FCF_ASYNC_SENT))
return rval;
- fcport->disc_state = DSC_GFPN_ID;
sp = qla2x00_get_sp(vha, fcport, GFP_ATOMIC);
if (!sp)
goto done;
- fcport->flags |= FCF_ASYNC_SENT;
sp->type = SRB_CT_PTHRU_CMD;
sp->name = "gfpnid";
sp->gen1 = fcport->rscn_gen;
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 8f55dd4..7b67524 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1021,30 +1021,11 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
vha->fcport_count++;
ea->fcport->login_succ = 1;
- if (!IS_IIDMA_CAPABLE(vha->hw) ||
- !vha->hw->flags.gpsc_supported) {
- ql_dbg(ql_dbg_disc, vha, 0x20d6,
- "%s %d %8phC post upd_fcport fcp_cnt %d\n",
- __func__, __LINE__, ea->fcport->port_name,
- vha->fcport_count);
-
- qla24xx_post_upd_fcport_work(vha, ea->fcport);
- } else {
- if (ea->fcport->id_changed) {
- ea->fcport->id_changed = 0;
- ql_dbg(ql_dbg_disc, vha, 0x20d7,
- "%s %d %8phC post gfpnid fcp_cnt %d\n",
- __func__, __LINE__, ea->fcport->port_name,
- vha->fcport_count);
- qla24xx_post_gfpnid_work(vha, ea->fcport);
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x20d7,
- "%s %d %8phC post gpsc fcp_cnt %d\n",
- __func__, __LINE__, ea->fcport->port_name,
- vha->fcport_count);
- qla24xx_post_gpsc_work(vha, ea->fcport);
- }
- }
+ ql_dbg(ql_dbg_disc, vha, 0x20d6,
+ "%s %d %8phC post upd_fcport fcp_cnt %d\n",
+ __func__, __LINE__, ea->fcport->port_name,
+ vha->fcport_count);
+ qla24xx_post_upd_fcport_work(vha, ea->fcport);
} else if (ea->fcport->login_succ) {
/*
* We have an existing session. A late RSCN delivery
@@ -1167,9 +1148,6 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
fcport->login_gen, fcport->login_retry,
fcport->loop_id, fcport->scan_state);
- if (fcport->login_retry == 0)
- return 0;
-
if (fcport->scan_state != QLA_FCPORT_FOUND)
return 0;
@@ -1194,7 +1172,8 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
return 0;
}
- fcport->login_retry--;
+ if (fcport->login_retry > 0)
+ fcport->login_retry--;
switch (fcport->disc_state) {
case DSC_DELETED:
@@ -1350,20 +1329,7 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
fc_port_t *f, *tf;
uint32_t id = 0, mask, rid;
unsigned long flags;
-
- switch (ea->event) {
- case FCME_RSCN:
- case FCME_GIDPN_DONE:
- case FCME_GPSC_DONE:
- case FCME_GPNID_DONE:
- case FCME_GNNID_DONE:
- if (test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags) ||
- test_bit(LOOP_RESYNC_ACTIVE, &vha->dpc_flags))
- return;
- break;
- default:
- break;
- }
+ fc_port_t *fcport;
switch (ea->event) {
case FCME_RELOGIN:
@@ -1377,6 +1343,11 @@ void qla2x00_fcport_event_handler(scsi_qla_host_t *vha, struct event_arg *ea)
return;
switch (ea->id.b.rsvd_1) {
case RSCN_PORT_ADDR:
+ fcport = qla2x00_find_fcport_by_nportid
+ (vha, &ea->id, 1);
+ if (fcport)
+ fcport->rscn_rcvd = 1;
+
spin_lock_irqsave(&vha->work_lock, flags);
if (vha->scan.scan_flags == 0) {
ql_dbg(ql_dbg_disc, vha, 0xffff,
@@ -3118,8 +3089,9 @@ qla2x00_alloc_outstanding_cmds(struct qla_hw_data *ha, struct req_que *req)
req->num_outstanding_cmds = ha->cur_fw_iocb_count;
}
- req->outstanding_cmds = kzalloc(sizeof(srb_t *) *
- req->num_outstanding_cmds, GFP_KERNEL);
+ req->outstanding_cmds = kcalloc(req->num_outstanding_cmds,
+ sizeof(srb_t *),
+ GFP_KERNEL);
if (!req->outstanding_cmds) {
/*
@@ -3127,8 +3099,9 @@ qla2x00_alloc_outstanding_cmds(struct qla_hw_data *ha, struct req_que *req)
* initialization.
*/
req->num_outstanding_cmds = MIN_OUTSTANDING_COMMANDS;
- req->outstanding_cmds = kzalloc(sizeof(srb_t *) *
- req->num_outstanding_cmds, GFP_KERNEL);
+ req->outstanding_cmds = kcalloc(req->num_outstanding_cmds,
+ sizeof(srb_t *),
+ GFP_KERNEL);
if (!req->outstanding_cmds) {
ql_log(ql_log_fatal, NULL, 0x0126,
@@ -4532,7 +4505,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
fcport->fw_login_state = DSC_LS_PORT_UNAVAIL;
fcport->deleted = QLA_SESS_DELETED;
fcport->login_retry = vha->hw->login_retry_count;
- fcport->login_retry = 5;
fcport->logout_on_delete = 1;
if (!fcport->ct_desc.ct_sns) {
@@ -5037,7 +5009,8 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
return;
if (fcport->fp_speed == PORT_SPEED_UNKNOWN ||
- fcport->fp_speed > ha->link_data_rate)
+ fcport->fp_speed > ha->link_data_rate ||
+ !ha->flags.gpsc_supported)
return;
rval = qla2x00_set_idma_speed(vha, fcport->loop_id, fcport->fp_speed,
@@ -5054,6 +5027,24 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
}
}
+void qla_do_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+ qla2x00_iidma_fcport(vha, fcport);
+ qla24xx_update_fcport_fcp_prio(vha, fcport);
+}
+
+int qla_post_iidma_work(struct scsi_qla_host *vha, fc_port_t *fcport)
+{
+ struct qla_work_evt *e;
+
+ e = qla2x00_alloc_work(vha, QLA_EVT_IIDMA);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ e->u.fcport.fcport = fcport;
+ return qla2x00_post_work(vha, e);
+}
+
/* qla2x00_reg_remote_port is reserved for Initiator Mode only.*/
static void
qla2x00_reg_remote_port(scsi_qla_host_t *vha, fc_port_t *fcport)
@@ -5122,13 +5113,14 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
if (IS_QLAFX00(vha->hw)) {
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
- goto reg_port;
+ } else {
+ fcport->login_retry = 0;
+ fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+ fcport->disc_state = DSC_LOGIN_COMPLETE;
+ fcport->deleted = 0;
+ fcport->logout_on_delete = 1;
+ qla2x00_set_fcport_state(fcport, FCS_ONLINE);
}
- fcport->login_retry = 0;
- fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
- fcport->disc_state = DSC_LOGIN_COMPLETE;
- fcport->deleted = 0;
- fcport->logout_on_delete = 1;
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
qla2x00_iidma_fcport(vha, fcport);
@@ -5140,7 +5132,6 @@ qla2x00_update_fcport(scsi_qla_host_t *vha, fc_port_t *fcport)
qla24xx_update_fcport_fcp_prio(vha, fcport);
-reg_port:
switch (vha->host->active_mode) {
case MODE_INITIATOR:
qla2x00_reg_remote_port(vha, fcport);
@@ -5159,6 +5150,23 @@ reg_port:
default:
break;
}
+
+ if (IS_IIDMA_CAPABLE(vha->hw) && vha->hw->flags.gpsc_supported) {
+ if (fcport->id_changed) {
+ fcport->id_changed = 0;
+ ql_dbg(ql_dbg_disc, vha, 0x20d7,
+ "%s %d %8phC post gfpnid fcp_cnt %d\n",
+ __func__, __LINE__, fcport->port_name,
+ vha->fcport_count);
+ qla24xx_post_gfpnid_work(vha, fcport);
+ } else {
+ ql_dbg(ql_dbg_disc, vha, 0x20d7,
+ "%s %d %8phC post gpsc fcp_cnt %d\n",
+ __func__, __LINE__, fcport->port_name,
+ vha->fcport_count);
+ qla24xx_post_gpsc_work(vha, fcport);
+ }
+ }
}
/*
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index a3dc83f..9fa5a25 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -2494,8 +2494,12 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
ox_id = le16_to_cpu(sts24->ox_id);
par_sense_len = sizeof(sts24->data);
/* Valid values of the retry delay timer are 0x1-0xffef */
- if (sts24->retry_delay > 0 && sts24->retry_delay < 0xfff1)
- retry_delay = sts24->retry_delay;
+ if (sts24->retry_delay > 0 && sts24->retry_delay < 0xfff1) {
+ retry_delay = sts24->retry_delay & 0x3fff;
+ ql_dbg(ql_dbg_io, sp->vha, 0x3033,
+ "%s: scope=%#x retry_delay=%#x\n", __func__,
+ sts24->retry_delay >> 14, retry_delay);
+ }
} else {
if (scsi_status & SS_SENSE_LEN_VALID)
sense_len = le16_to_cpu(sts->req_sense_length);
@@ -3434,8 +3438,9 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
"Adjusted Max no of queues pairs: %d.\n", ha->max_qpairs);
}
}
- ha->msix_entries = kzalloc(sizeof(struct qla_msix_entry) *
- ha->msix_count, GFP_KERNEL);
+ ha->msix_entries = kcalloc(ha->msix_count,
+ sizeof(struct qla_msix_entry),
+ GFP_KERNEL);
if (!ha->msix_entries) {
ql_log(ql_log_fatal, vha, 0x00c8,
"Failed to allocate memory for ha->msix_entries.\n");
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index d8a36c1..7e875f5 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -292,6 +292,14 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
if (time_after(jiffies, wait_time))
break;
+ /*
+ * Check if it's UNLOADING, cause we cannot poll in
+ * this case, or else a NULL pointer dereference
+ * is triggered.
+ */
+ if (unlikely(test_bit(UNLOADING, &base_vha->dpc_flags)))
+ return QLA_FUNCTION_TIMEOUT;
+
/* Check for pending interrupts. */
qla2x00_poll(ha->rsp_q_map[0]);
diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index 872d66d..de2bc78 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -1230,7 +1230,7 @@ qla82xx_pinit_from_rom(scsi_qla_host_t *vha)
ql_log(ql_log_info, vha, 0x0072,
"%d CRB init values found in ROM.\n", n);
- buf = kmalloc(n * sizeof(struct crb_addr_pair), GFP_KERNEL);
+ buf = kmalloc_array(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
if (buf == NULL) {
ql_log(ql_log_fatal, vha, 0x010c,
"Unable to allocate memory.\n");
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 15eaa6d..e881fce 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -410,7 +410,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
struct rsp_que *rsp)
{
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
- ha->req_q_map = kzalloc(sizeof(struct req_que *) * ha->max_req_queues,
+ ha->req_q_map = kcalloc(ha->max_req_queues, sizeof(struct req_que *),
GFP_KERNEL);
if (!ha->req_q_map) {
ql_log(ql_log_fatal, vha, 0x003b,
@@ -418,7 +418,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
goto fail_req_map;
}
- ha->rsp_q_map = kzalloc(sizeof(struct rsp_que *) * ha->max_rsp_queues,
+ ha->rsp_q_map = kcalloc(ha->max_rsp_queues, sizeof(struct rsp_que *),
GFP_KERNEL);
if (!ha->rsp_q_map) {
ql_log(ql_log_fatal, vha, 0x003c,
@@ -4045,8 +4045,9 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
(*rsp)->ring);
/* Allocate memory for NVRAM data for vports */
if (ha->nvram_npiv_size) {
- ha->npiv_info = kzalloc(sizeof(struct qla_npiv_entry) *
- ha->nvram_npiv_size, GFP_KERNEL);
+ ha->npiv_info = kcalloc(ha->nvram_npiv_size,
+ sizeof(struct qla_npiv_entry),
+ GFP_KERNEL);
if (!ha->npiv_info) {
ql_log_pci(ql_log_fatal, ha->pdev, 0x002d,
"Failed to allocate memory for npiv_info.\n");
@@ -4080,8 +4081,9 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
INIT_LIST_HEAD(&ha->vp_list);
/* Allocate memory for our loop_id bitmap */
- ha->loop_id_map = kzalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE) * sizeof(long),
- GFP_KERNEL);
+ ha->loop_id_map = kcalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE),
+ sizeof(long),
+ GFP_KERNEL);
if (!ha->loop_id_map)
goto fail_loop_id_map;
else {
@@ -5063,6 +5065,10 @@ qla2x00_do_work(struct scsi_qla_host *vha)
break;
case QLA_EVT_SP_RETRY:
qla_sp_retry(vha, e);
+ break;
+ case QLA_EVT_IIDMA:
+ qla_do_iidma_work(vha, e->u.fcport.fcport);
+ break;
}
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index 025dc2d..0fea2e2 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -601,24 +601,18 @@ void qla2x00_async_nack_sp_done(void *s, int res)
vha->fcport_count++;
- if (!IS_IIDMA_CAPABLE(vha->hw) ||
- !vha->hw->flags.gpsc_supported) {
- ql_dbg(ql_dbg_disc, vha, 0x20f3,
- "%s %d %8phC post upd_fcport fcp_cnt %d\n",
- __func__, __LINE__,
- sp->fcport->port_name,
- vha->fcport_count);
- sp->fcport->disc_state = DSC_UPD_FCPORT;
- qla24xx_post_upd_fcport_work(vha, sp->fcport);
- } else {
- ql_dbg(ql_dbg_disc, vha, 0x20f5,
- "%s %d %8phC post gpsc fcp_cnt %d\n",
- __func__, __LINE__,
- sp->fcport->port_name,
- vha->fcport_count);
-
- qla24xx_post_gpsc_work(vha, sp->fcport);
- }
+ ql_dbg(ql_dbg_disc, vha, 0x20f3,
+ "%s %d %8phC post upd_fcport fcp_cnt %d\n",
+ __func__, __LINE__,
+ sp->fcport->port_name,
+ vha->fcport_count);
+ sp->fcport->disc_state = DSC_UPD_FCPORT;
+ qla24xx_post_upd_fcport_work(vha, sp->fcport);
+ } else {
+ sp->fcport->login_retry = 0;
+ sp->fcport->disc_state = DSC_LOGIN_COMPLETE;
+ sp->fcport->deleted = 0;
+ sp->fcport->logout_on_delete = 1;
}
break;
@@ -1930,13 +1924,84 @@ static void abort_cmds_for_lun(struct scsi_qla_host *vha,
spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
}
+static struct qla_qpair_hint *qlt_find_qphint(struct scsi_qla_host *vha,
+ uint64_t unpacked_lun)
+{
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ struct qla_qpair_hint *h = NULL;
+
+ if (vha->flags.qpairs_available) {
+ h = btree_lookup64(&tgt->lun_qpair_map, unpacked_lun);
+ if (!h)
+ h = &tgt->qphints[0];
+ } else {
+ h = &tgt->qphints[0];
+ }
+
+ return h;
+}
+
+static void qlt_do_tmr_work(struct work_struct *work)
+{
+ struct qla_tgt_mgmt_cmd *mcmd =
+ container_of(work, struct qla_tgt_mgmt_cmd, work);
+ struct qla_hw_data *ha = mcmd->vha->hw;
+ int rc = EIO;
+ uint32_t tag;
+ unsigned long flags;
+
+ switch (mcmd->tmr_func) {
+ case QLA_TGT_ABTS:
+ tag = mcmd->orig_iocb.abts.exchange_addr_to_abort;
+ break;
+ default:
+ tag = 0;
+ break;
+ }
+
+ rc = ha->tgt.tgt_ops->handle_tmr(mcmd, mcmd->unpacked_lun,
+ mcmd->tmr_func, tag);
+
+ if (rc != 0) {
+ spin_lock_irqsave(mcmd->qpair->qp_lock_ptr, flags);
+ switch (mcmd->tmr_func) {
+ case QLA_TGT_ABTS:
+ qlt_24xx_send_abts_resp(mcmd->qpair,
+ &mcmd->orig_iocb.abts,
+ FCP_TMF_REJECTED, false);
+ break;
+ case QLA_TGT_LUN_RESET:
+ case QLA_TGT_CLEAR_TS:
+ case QLA_TGT_ABORT_TS:
+ case QLA_TGT_CLEAR_ACA:
+ case QLA_TGT_TARGET_RESET:
+ qlt_send_busy(mcmd->qpair, &mcmd->orig_iocb.atio,
+ qla_sam_status);
+ break;
+
+ case QLA_TGT_ABORT_ALL:
+ case QLA_TGT_NEXUS_LOSS_SESS:
+ case QLA_TGT_NEXUS_LOSS:
+ qlt_send_notify_ack(mcmd->qpair,
+ &mcmd->orig_iocb.imm_ntfy, 0, 0, 0, 0, 0, 0);
+ break;
+ }
+ spin_unlock_irqrestore(mcmd->qpair->qp_lock_ptr, flags);
+
+ ql_dbg(ql_dbg_tgt_mgt, mcmd->vha, 0xf052,
+ "qla_target(%d): tgt_ops->handle_tmr() failed: %d\n",
+ mcmd->vha->vp_idx, rc);
+ mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
+ }
+}
+
/* ha->hardware_lock supposed to be held on entry */
static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
struct abts_recv_from_24xx *abts, struct fc_port *sess)
{
struct qla_hw_data *ha = vha->hw;
struct qla_tgt_mgmt_cmd *mcmd;
- int rc;
+ struct qla_qpair_hint *h = &vha->vha_tgt.qla_tgt->qphints[0];
if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) {
/* send TASK_ABORT response immediately */
@@ -1961,23 +2026,29 @@ static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
memcpy(&mcmd->orig_iocb.abts, abts, sizeof(mcmd->orig_iocb.abts));
mcmd->reset_count = ha->base_qpair->chip_reset;
mcmd->tmr_func = QLA_TGT_ABTS;
- mcmd->qpair = ha->base_qpair;
+ mcmd->qpair = h->qpair;
mcmd->vha = vha;
/*
* LUN is looked up by target-core internally based on the passed
* abts->exchange_addr_to_abort tag.
*/
- rc = ha->tgt.tgt_ops->handle_tmr(mcmd, 0, mcmd->tmr_func,
- abts->exchange_addr_to_abort);
- if (rc != 0) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf052,
- "qla_target(%d): tgt_ops->handle_tmr()"
- " failed: %d", vha->vp_idx, rc);
- mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
- return -EFAULT;
+ mcmd->se_cmd.cpuid = h->cpuid;
+
+ if (ha->tgt.tgt_ops->find_cmd_by_tag) {
+ struct qla_tgt_cmd *abort_cmd;
+
+ abort_cmd = ha->tgt.tgt_ops->find_cmd_by_tag(sess,
+ abts->exchange_addr_to_abort);
+ if (abort_cmd && abort_cmd->qpair) {
+ mcmd->qpair = abort_cmd->qpair;
+ mcmd->se_cmd.cpuid = abort_cmd->se_cmd.cpuid;
+ }
}
+ INIT_WORK(&mcmd->work, qlt_do_tmr_work);
+ queue_work_on(mcmd->se_cmd.cpuid, qla_tgt_wq, &mcmd->work);
+
return 0;
}
@@ -3556,13 +3627,6 @@ static int __qlt_send_term_exchange(struct qla_qpair *qpair,
temp = be16_to_cpu(atio->u.isp24.fcp_hdr.ox_id);
ctio24->u.status1.ox_id = cpu_to_le16(temp);
- /* Most likely, it isn't needed */
- ctio24->u.status1.residual = get_unaligned((uint32_t *)
- &atio->u.isp24.fcp_cmnd.add_cdb[
- atio->u.isp24.fcp_cmnd.add_cdb_len]);
- if (ctio24->u.status1.residual != 0)
- ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER;
-
/* Memory Barrier */
wmb();
if (qpair->reqq_start_iocbs)
@@ -4057,9 +4121,7 @@ static void __qlt_do_work(struct qla_tgt_cmd *cmd)
fcp_task_attr = qlt_get_fcp_task_attr(vha,
atio->u.isp24.fcp_cmnd.task_attr);
- data_length = be32_to_cpu(get_unaligned((uint32_t *)
- &atio->u.isp24.fcp_cmnd.add_cdb[
- atio->u.isp24.fcp_cmnd.add_cdb_len]));
+ data_length = get_datalen_for_atio(atio);
ret = ha->tgt.tgt_ops->handle_cmd(vha, cmd, cdb, data_length,
fcp_task_attr, data_dir, bidi);
@@ -4335,7 +4397,7 @@ static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun,
struct qla_hw_data *ha = vha->hw;
struct qla_tgt_mgmt_cmd *mcmd;
struct atio_from_isp *a = (struct atio_from_isp *)iocb;
- int res;
+ struct qla_qpair_hint *h = &vha->vha_tgt.qla_tgt->qphints[0];
mcmd = mempool_alloc(qla_tgt_mgmt_cmd_mempool, GFP_ATOMIC);
if (!mcmd) {
@@ -4355,24 +4417,36 @@ static int qlt_issue_task_mgmt(struct fc_port *sess, u64 lun,
mcmd->tmr_func = fn;
mcmd->flags = flags;
mcmd->reset_count = ha->base_qpair->chip_reset;
- mcmd->qpair = ha->base_qpair;
+ mcmd->qpair = h->qpair;
mcmd->vha = vha;
+ mcmd->se_cmd.cpuid = h->cpuid;
+ mcmd->unpacked_lun = lun;
switch (fn) {
case QLA_TGT_LUN_RESET:
- abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id);
- break;
- }
+ case QLA_TGT_CLEAR_TS:
+ case QLA_TGT_ABORT_TS:
+ abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id);
+ /* drop through */
+ case QLA_TGT_CLEAR_ACA:
+ h = qlt_find_qphint(vha, mcmd->unpacked_lun);
+ mcmd->qpair = h->qpair;
+ mcmd->se_cmd.cpuid = h->cpuid;
+ break;
- res = ha->tgt.tgt_ops->handle_tmr(mcmd, lun, mcmd->tmr_func, 0);
- if (res != 0) {
- ql_dbg(ql_dbg_tgt_tmr, vha, 0x1000b,
- "qla_target(%d): tgt.tgt_ops->handle_tmr() failed: %d\n",
- sess->vha->vp_idx, res);
- mempool_free(mcmd, qla_tgt_mgmt_cmd_mempool);
- return -EFAULT;
+ case QLA_TGT_TARGET_RESET:
+ case QLA_TGT_NEXUS_LOSS_SESS:
+ case QLA_TGT_NEXUS_LOSS:
+ case QLA_TGT_ABORT_ALL:
+ default:
+ /* no-op */
+ break;
}
+ INIT_WORK(&mcmd->work, qlt_do_tmr_work);
+ queue_work_on(mcmd->se_cmd.cpuid, qla_tgt_wq,
+ &mcmd->work);
+
return 0;
}
@@ -4841,7 +4915,6 @@ static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
switch (sess->disc_state) {
case DSC_LOGIN_PEND:
case DSC_GPDB:
- case DSC_GPSC:
case DSC_UPD_FCPORT:
case DSC_LOGIN_COMPLETE:
case DSC_ADISC:
@@ -5113,8 +5186,6 @@ static void qlt_handle_imm_notify(struct scsi_qla_host *vha,
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf038,
"qla_target(%d): Immediate notify task %x\n",
vha->vp_idx, iocb->u.isp2x.task_flags);
- if (qlt_handle_task_mgmt(vha, iocb) == 0)
- send_notify_ack = 0;
break;
case IMM_NTFY_ELS:
@@ -5147,10 +5218,15 @@ static int __qlt_send_busy(struct qla_qpair *qpair,
struct fc_port *sess = NULL;
unsigned long flags;
u16 temp;
+ port_id_t id;
+
+ id.b.al_pa = atio->u.isp24.fcp_hdr.s_id[2];
+ id.b.area = atio->u.isp24.fcp_hdr.s_id[1];
+ id.b.domain = atio->u.isp24.fcp_hdr.s_id[0];
+ id.b.rsvd_1 = 0;
spin_lock_irqsave(&ha->tgt.sess_lock, flags);
- sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
- atio->u.isp24.fcp_hdr.s_id);
+ sess = qla2x00_find_fcport_by_nportid(vha, &id, 1);
spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
if (!sess) {
qlt_send_term_exchange(qpair, NULL, atio, 1, 0);
@@ -5189,6 +5265,12 @@ static int __qlt_send_busy(struct qla_qpair *qpair,
*/
ctio24->u.status1.ox_id = swab16(atio->u.isp24.fcp_hdr.ox_id);
ctio24->u.status1.scsi_status = cpu_to_le16(status);
+
+ ctio24->u.status1.residual = get_datalen_for_atio(atio);
+
+ if (ctio24->u.status1.residual != 0)
+ ctio24->u.status1.scsi_status |= SS_RESIDUAL_UNDER;
+
/* Memory Barrier */
wmb();
if (qpair->reqq_start_iocbs)
@@ -6166,8 +6248,9 @@ int qlt_add_target(struct qla_hw_data *ha, struct scsi_qla_host *base_vha)
return -ENOMEM;
}
- tgt->qphints = kzalloc((ha->max_qpairs + 1) *
- sizeof(struct qla_qpair_hint), GFP_KERNEL);
+ tgt->qphints = kcalloc(ha->max_qpairs + 1,
+ sizeof(struct qla_qpair_hint),
+ GFP_KERNEL);
if (!tgt->qphints) {
kfree(tgt);
ql_log(ql_log_warn, base_vha, 0x0197,
@@ -7007,8 +7090,9 @@ qlt_mem_alloc(struct qla_hw_data *ha)
if (!QLA_TGT_MODE_ENABLED())
return 0;
- ha->tgt.tgt_vp_map = kzalloc(sizeof(struct qla_tgt_vp_map) *
- MAX_MULTI_ID_FABRIC, GFP_KERNEL);
+ ha->tgt.tgt_vp_map = kcalloc(MAX_MULTI_ID_FABRIC,
+ sizeof(struct qla_tgt_vp_map),
+ GFP_KERNEL);
if (!ha->tgt.tgt_vp_map)
return -ENOMEM;
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 728ce74..fecf96f 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -682,7 +682,7 @@ struct qla_tgt_cmd;
* target module (tcm_qla2xxx).
*/
struct qla_tgt_func_tmpl {
-
+ struct qla_tgt_cmd *(*find_cmd_by_tag)(struct fc_port *, uint64_t);
int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
unsigned char *, uint32_t, int, int, int);
void (*handle_data)(struct qla_tgt_cmd *);
@@ -966,6 +966,8 @@ struct qla_tgt_mgmt_cmd {
unsigned int flags;
uint32_t reset_count;
#define QLA24XX_MGMT_SEND_NACK 1
+ struct work_struct work;
+ uint64_t unpacked_lun;
union {
struct atio_from_isp atio;
struct imm_ntfy_from_isp imm_ntfy;
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index 0c55d70..1ad7582 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "10.00.00.06-k"
+#define QLA2XXX_VERSION "10.00.00.07-k"
#define QLA_DRIVER_MAJOR_VER 10
#define QLA_DRIVER_MINOR_VER 0
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index aadfeaa..7732e93 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -48,7 +48,6 @@
#include "tcm_qla2xxx.h"
static struct workqueue_struct *tcm_qla2xxx_free_wq;
-static struct workqueue_struct *tcm_qla2xxx_cmd_wq;
/*
* Parse WWN.
@@ -630,6 +629,32 @@ static int tcm_qla2xxx_handle_tmr(struct qla_tgt_mgmt_cmd *mcmd, u64 lun,
transl_tmr_func, GFP_ATOMIC, tag, flags);
}
+static struct qla_tgt_cmd *tcm_qla2xxx_find_cmd_by_tag(struct fc_port *sess,
+ uint64_t tag)
+{
+ struct qla_tgt_cmd *cmd = NULL;
+ struct se_cmd *secmd;
+ unsigned long flags;
+
+ if (!sess->se_sess)
+ return NULL;
+
+ spin_lock_irqsave(&sess->se_sess->sess_cmd_lock, flags);
+ list_for_each_entry(secmd, &sess->se_sess->sess_cmd_list, se_cmd_list) {
+ /* skip task management functions, including tmr->task_cmd */
+ if (secmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
+ continue;
+
+ if (secmd->tag == tag) {
+ cmd = container_of(secmd, struct qla_tgt_cmd, se_cmd);
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&sess->se_sess->sess_cmd_lock, flags);
+
+ return cmd;
+}
+
static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
{
struct qla_tgt_cmd *cmd = container_of(se_cmd,
@@ -1608,6 +1633,7 @@ static void tcm_qla2xxx_update_sess(struct fc_port *sess, port_id_t s_id,
* Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.
*/
static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {
+ .find_cmd_by_tag = tcm_qla2xxx_find_cmd_by_tag,
.handle_cmd = tcm_qla2xxx_handle_cmd,
.handle_data = tcm_qla2xxx_handle_data,
.handle_tmr = tcm_qla2xxx_handle_tmr,
@@ -1635,7 +1661,9 @@ static int tcm_qla2xxx_init_lport(struct tcm_qla2xxx_lport *lport)
return rc;
}
- lport->lport_loopid_map = vzalloc(sizeof(struct tcm_qla2xxx_fc_loopid) * 65536);
+ lport->lport_loopid_map =
+ vzalloc(array_size(65536,
+ sizeof(struct tcm_qla2xxx_fc_loopid)));
if (!lport->lport_loopid_map) {
pr_err("Unable to allocate lport->lport_loopid_map of %zu bytes\n",
sizeof(struct tcm_qla2xxx_fc_loopid) * 65536);
@@ -1976,16 +2004,8 @@ static int tcm_qla2xxx_register_configfs(void)
goto out_fabric_npiv;
}
- tcm_qla2xxx_cmd_wq = alloc_workqueue("tcm_qla2xxx_cmd", 0, 0);
- if (!tcm_qla2xxx_cmd_wq) {
- ret = -ENOMEM;
- goto out_free_wq;
- }
-
return 0;
-out_free_wq:
- destroy_workqueue(tcm_qla2xxx_free_wq);
out_fabric_npiv:
target_unregister_template(&tcm_qla2xxx_npiv_ops);
out_fabric:
@@ -1995,7 +2015,6 @@ out_fabric:
static void tcm_qla2xxx_deregister_configfs(void)
{
- destroy_workqueue(tcm_qla2xxx_cmd_wq);
destroy_workqueue(tcm_qla2xxx_free_wq);
target_unregister_template(&tcm_qla2xxx_ops);
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index 43f7358..d2b333d 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -1077,7 +1077,7 @@ qla4_82xx_pinit_from_rom(struct scsi_qla_host *ha, int verbose)
ql4_printk(KERN_INFO, ha,
"%s: %d CRB init values found in ROM.\n", DRIVER_NAME, n);
- buf = kmalloc(n * sizeof(struct crb_addr_pair), GFP_KERNEL);
+ buf = kmalloc_array(n, sizeof(struct crb_addr_pair), GFP_KERNEL);
if (buf == NULL) {
ql4_printk(KERN_WARNING, ha,
"%s: [ERROR] Unable to malloc memory.\n", DRIVER_NAME);
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index cec9a14..8578e56 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -1385,6 +1385,9 @@ fail_unmap_queues:
qpti->req_cpu, qpti->req_dvma);
#undef QSIZE
+fail_free_irq:
+ free_irq(qpti->irq, qpti);
+
fail_unmap_regs:
of_iounmap(&op->resource[0], qpti->qregs,
resource_size(&op->resource[0]));
@@ -1392,9 +1395,6 @@ fail_unmap_regs:
of_iounmap(&op->resource[0], qpti->sreg,
sizeof(unsigned char));
-fail_free_irq:
- free_irq(qpti->irq, qpti);
-
fail_unlink:
scsi_host_put(host);
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 656c98e..24d7496 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -3450,7 +3450,7 @@ static int resp_comp_write(struct scsi_cmnd *scp,
return check_condition_result;
}
dnum = 2 * num;
- arr = kzalloc(dnum * lb_size, GFP_ATOMIC);
+ arr = kcalloc(lb_size, dnum, GFP_ATOMIC);
if (NULL == arr) {
mk_sense_buffer(scp, ILLEGAL_REQUEST, INSUFF_RES_ASC,
INSUFF_RES_ASCQ);
@@ -5439,7 +5439,8 @@ static int __init scsi_debug_init(void)
}
map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1;
- map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long));
+ map_storep = vmalloc(array_size(sizeof(long),
+ BITS_TO_LONGS(map_size)));
pr_info("%lu provisioning blocks\n", map_size);
diff --git a/drivers/scsi/scsi_debugfs.c b/drivers/scsi/scsi_debugfs.c
index b784002..c5a8756 100644
--- a/drivers/scsi/scsi_debugfs.c
+++ b/drivers/scsi/scsi_debugfs.c
@@ -4,7 +4,7 @@
#include <scsi/scsi_dbg.h>
#include "scsi_debugfs.h"
-#define SCSI_CMD_FLAG_NAME(name) [ilog2(SCMD_##name)] = #name
+#define SCSI_CMD_FLAG_NAME(name)[const_ilog2(SCMD_##name)] = #name
static const char *const scsi_cmd_flags[] = {
SCSI_CMD_FLAG_NAME(TAGGED),
SCSI_CMD_FLAG_NAME(UNCHECKED_ISA_DMA),
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index dd107dc..c4cbfd0 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -161,15 +161,16 @@ static struct {
{"DGC", "RAID", NULL, BLIST_SPARSELUN}, /* EMC CLARiiON, storage on LUN 0 */
{"DGC", "DISK", NULL, BLIST_SPARSELUN}, /* EMC CLARiiON, no storage on LUN 0 */
{"EMC", "Invista", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
- {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN | BLIST_REPORTLUN2},
+ {"EMC", "SYMMETRIX", NULL, BLIST_SPARSELUN | BLIST_LARGELUN |
+ BLIST_REPORTLUN2 | BLIST_RETRY_ITF},
{"EMULEX", "MD21/S2 ESDI", NULL, BLIST_SINGLELUN},
{"easyRAID", "16P", NULL, BLIST_NOREPORTLUN},
{"easyRAID", "X6P", NULL, BLIST_NOREPORTLUN},
{"easyRAID", "F8", NULL, BLIST_NOREPORTLUN},
{"FSC", "CentricStor", "*", BLIST_SPARSELUN | BLIST_LARGELUN},
+ {"FUJITSU", "ETERNUS_DXM", "*", BLIST_RETRY_ASC_C1},
{"Generic", "USB SD Reader", "1.00", BLIST_FORCELUN | BLIST_INQUIRY_36},
- {"Generic", "USB Storage-SMC", "0180", BLIST_FORCELUN | BLIST_INQUIRY_36},
- {"Generic", "USB Storage-SMC", "0207", BLIST_FORCELUN | BLIST_INQUIRY_36},
+ {"Generic", "USB Storage-SMC", NULL, BLIST_FORCELUN | BLIST_INQUIRY_36}, /* FW: 0180 and 0207 */
{"HITACHI", "DF400", "*", BLIST_REPORTLUN2},
{"HITACHI", "DF500", "*", BLIST_REPORTLUN2},
{"HITACHI", "DISK-SUBSYSTEM", "*", BLIST_REPORTLUN2},
@@ -361,8 +362,22 @@ int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model,
scsi_strcpy_devinfo("model", devinfo->model, sizeof(devinfo->model),
model, compatible);
- if (strflags)
- flags = (__force blist_flags_t)simple_strtoul(strflags, NULL, 0);
+ if (strflags) {
+ unsigned long long val;
+ int ret = kstrtoull(strflags, 0, &val);
+
+ if (ret != 0) {
+ kfree(devinfo);
+ return ret;
+ }
+ flags = (__force blist_flags_t)val;
+ }
+ if (flags & __BLIST_UNUSED_MASK) {
+ pr_err("scsi_devinfo (%s:%s): unsupported flags 0x%llx",
+ vendor, model, flags & __BLIST_UNUSED_MASK);
+ kfree(devinfo);
+ return -EINVAL;
+ }
devinfo->flags = flags;
devinfo->compatible = compatible;
@@ -615,7 +630,7 @@ static int devinfo_seq_show(struct seq_file *m, void *v)
devinfo_table->name)
seq_printf(m, "[%s]:\n", devinfo_table->name);
- seq_printf(m, "'%.8s' '%.16s' 0x%x\n",
+ seq_printf(m, "'%.8s' '%.16s' 0x%llx\n",
devinfo->vendor, devinfo->model, devinfo->flags);
return 0;
}
@@ -734,9 +749,9 @@ MODULE_PARM_DESC(dev_flags,
" list entries for vendor and model with an integer value of flags"
" to the scsi device info list");
-module_param_named(default_dev_flags, scsi_default_dev_flags, int, S_IRUGO|S_IWUSR);
+module_param_named(default_dev_flags, scsi_default_dev_flags, ullong, 0644);
MODULE_PARM_DESC(default_dev_flags,
- "scsi default device flag integer value");
+ "scsi default device flag uint64_t value");
/**
* scsi_exit_devinfo - remove /proc/scsi/device_info & the scsi_dev_info_list
diff --git a/drivers/scsi/scsi_dh.c b/drivers/scsi/scsi_dh.c
index 188f305..5a58cbf 100644
--- a/drivers/scsi/scsi_dh.c
+++ b/drivers/scsi/scsi_dh.c
@@ -58,7 +58,10 @@ static const struct scsi_dh_blist scsi_dh_blist[] = {
{"IBM", "3526", "rdac", },
{"IBM", "3542", "rdac", },
{"IBM", "3552", "rdac", },
- {"SGI", "TP9", "rdac", },
+ {"SGI", "TP9300", "rdac", },
+ {"SGI", "TP9400", "rdac", },
+ {"SGI", "TP9500", "rdac", },
+ {"SGI", "TP9700", "rdac", },
{"SGI", "IS", "rdac", },
{"STK", "OPENstorage", "rdac", },
{"STK", "FLEXLINE 380", "rdac", },
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 9c02ba2..8932ae8 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -38,6 +38,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/scsi_dh.h>
+#include <scsi/scsi_devinfo.h>
#include <scsi/sg.h>
#include "scsi_priv.h"
@@ -525,6 +526,12 @@ int scsi_check_sense(struct scsi_cmnd *scmd)
if (sshdr.asc == 0x10) /* DIF */
return SUCCESS;
+ if (sshdr.asc == 0x44 && sdev->sdev_bflags & BLIST_RETRY_ITF)
+ return ADD_TO_MLQUEUE;
+ if (sshdr.asc == 0xc1 && sshdr.ascq == 0x01 &&
+ sdev->sdev_bflags & BLIST_RETRY_ASC_C1)
+ return ADD_TO_MLQUEUE;
+
return NEEDS_RETRY;
case NOT_READY:
case UNIT_ATTENTION:
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index fb38aef..41e9ac9 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -985,6 +985,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
case 0x08: /* Long write in progress */
case 0x09: /* self test in progress */
case 0x14: /* space allocation in progress */
+ case 0x1a: /* start stop unit in progress */
+ case 0x1b: /* sanitize in progress */
+ case 0x1d: /* configuration in progress */
+ case 0x24: /* depopulation in progress */
action = ACTION_DELAYED_RETRY;
break;
default:
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 1e36c9a..7943b76 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -968,7 +968,7 @@ sdev_show_wwid(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(wwid, S_IRUGO, sdev_show_wwid, NULL);
#define BLIST_FLAG_NAME(name) \
- [ilog2((__force unsigned int)BLIST_##name)] = #name
+ [const_ilog2((__force __u64)BLIST_##name)] = #name
static const char *const sdev_bflags_name[] = {
#include "scsi_devinfo_tbl.c"
};
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 1da3d71..1394810 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -3592,7 +3592,7 @@ fc_bsg_job_timeout(struct request *req)
/* the blk_end_sync_io() doesn't check the error */
if (inflight)
- blk_mq_complete_request(req);
+ __blk_complete_request(req);
return BLK_EH_DONE;
}
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index e2953b4..0cd16e8 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -213,10 +213,6 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
to_sas_host_attrs(shost)->q = q;
}
- /*
- * by default assume old behaviour and bounce for any highmem page
- */
- blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
blk_queue_flag_set(QUEUE_FLAG_BIDI, q);
return 0;
}
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 0d663b5..392c7d0 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -74,12 +74,12 @@ struct scsi_disk {
struct gendisk *disk;
struct opal_dev *opal_dev;
#ifdef CONFIG_BLK_DEV_ZONED
- unsigned int nr_zones;
- unsigned int zone_blocks;
- unsigned int zone_shift;
- unsigned int zones_optimal_open;
- unsigned int zones_optimal_nonseq;
- unsigned int zones_max_open;
+ u32 nr_zones;
+ u32 zone_blocks;
+ u32 zone_shift;
+ u32 zones_optimal_open;
+ u32 zones_optimal_nonseq;
+ u32 zones_max_open;
#endif
atomic_t openers;
sector_t capacity; /* size in logical blocks */
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index 210407c..a14fef1 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -299,16 +299,6 @@ void sd_zbc_complete(struct scsi_cmnd *cmd, unsigned int good_bytes,
case REQ_OP_WRITE:
case REQ_OP_WRITE_ZEROES:
case REQ_OP_WRITE_SAME:
-
- if (result &&
- sshdr->sense_key == ILLEGAL_REQUEST &&
- sshdr->asc == 0x21)
- /*
- * INVALID ADDRESS FOR WRITE error: It is unlikely that
- * retrying write requests failed with any kind of
- * alignement error will result in success. So don't.
- */
- cmd->allowed = 0;
break;
case REQ_OP_ZONE_REPORT:
@@ -452,7 +442,7 @@ static s64 sd_zbc_check_zone_size(struct scsi_disk *sdkp)
} else if (this_zone_blocks != zone_blocks &&
(block + this_zone_blocks < sdkp->capacity
|| this_zone_blocks > zone_blocks)) {
- this_zone_blocks = 0;
+ zone_blocks = 0;
goto out;
}
block += this_zone_blocks;
@@ -504,7 +494,7 @@ out_free:
static inline unsigned long *
sd_zbc_alloc_zone_bitmap(u32 nr_zones, int numa_node)
{
- return kzalloc_node(BITS_TO_LONGS(nr_zones) * sizeof(unsigned long),
+ return kcalloc_node(BITS_TO_LONGS(nr_zones), sizeof(unsigned long),
GFP_KERNEL, numa_node);
}
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index 62f04c0..0fc3922 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -747,7 +747,7 @@ static int ses_intf_add(struct device *cdev,
buf = NULL;
}
page2_not_supported:
- scomp = kzalloc(sizeof(struct ses_component) * components, GFP_KERNEL);
+ scomp = kcalloc(components, sizeof(struct ses_component), GFP_KERNEL);
if (!scomp)
goto err_free;
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 6fc58e2..53ae52d 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1045,7 +1045,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
else {
sg_req_info_t *rinfo;
- rinfo = kzalloc(SZ_SG_REQ_INFO * SG_MAX_QUEUE,
+ rinfo = kcalloc(SG_MAX_QUEUE, SZ_SG_REQ_INFO,
GFP_KERNEL);
if (!rinfo)
return -ENOMEM;
@@ -1191,7 +1191,7 @@ sg_fasync(int fd, struct file *filp, int mode)
return fasync_helper(fd, filp, mode, &sfp->async_qp);
}
-static int
+static vm_fault_t
sg_vma_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c
index 592b6db..b78d20b 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -1820,8 +1820,9 @@ static int pqi_update_scsi_devices(struct pqi_ctrl_info *ctrl_info)
num_new_devices = num_physicals + num_logicals;
- new_device_list = kmalloc(sizeof(*new_device_list) *
- num_new_devices, GFP_KERNEL);
+ new_device_list = kmalloc_array(num_new_devices,
+ sizeof(*new_device_list),
+ GFP_KERNEL);
if (!new_device_list) {
dev_warn(&ctrl_info->pci_dev->dev, "%s\n", out_of_memory_msg);
rc = -ENOMEM;
@@ -4251,8 +4252,9 @@ static int pqi_alloc_io_resources(struct pqi_ctrl_info *ctrl_info)
struct device *dev;
struct pqi_io_request *io_request;
- ctrl_info->io_request_pool = kzalloc(ctrl_info->max_io_slots *
- sizeof(ctrl_info->io_request_pool[0]), GFP_KERNEL);
+ ctrl_info->io_request_pool =
+ kcalloc(ctrl_info->max_io_slots,
+ sizeof(ctrl_info->io_request_pool[0]), GFP_KERNEL);
if (!ctrl_info->io_request_pool) {
dev_err(&ctrl_info->pci_dev->dev,
diff --git a/drivers/scsi/snic/snic_scsi.c b/drivers/scsi/snic/snic_scsi.c
index d8a376b..d9b2e46 100644
--- a/drivers/scsi/snic/snic_scsi.c
+++ b/drivers/scsi/snic/snic_scsi.c
@@ -47,10 +47,10 @@ static const char * const snic_req_state_str[] = {
[SNIC_IOREQ_NOT_INITED] = "SNIC_IOREQ_NOT_INITED",
[SNIC_IOREQ_PENDING] = "SNIC_IOREQ_PENDING",
[SNIC_IOREQ_ABTS_PENDING] = "SNIC_IOREQ_ABTS_PENDING",
- [SNIC_IOREQ_ABTS_COMPLETE] = "SNIC_IOREQ_ABTS_COMPELTE",
+ [SNIC_IOREQ_ABTS_COMPLETE] = "SNIC_IOREQ_ABTS_COMPLETE",
[SNIC_IOREQ_LR_PENDING] = "SNIC_IOREQ_LR_PENDING",
- [SNIC_IOREQ_LR_COMPLETE] = "SNIC_IOREQ_LR_COMPELTE",
- [SNIC_IOREQ_COMPLETE] = "SNIC_IOREQ_CMD_COMPELTE",
+ [SNIC_IOREQ_LR_COMPLETE] = "SNIC_IOREQ_LR_COMPLETE",
+ [SNIC_IOREQ_COMPLETE] = "SNIC_IOREQ_CMD_COMPLETE",
};
/* snic cmd status strings */
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index a427ce9..50c66cc 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -3878,7 +3878,7 @@ static struct st_buffer *new_tape_buffer(int need_dma, int max_sg)
{
struct st_buffer *tb;
- tb = kzalloc(sizeof(struct st_buffer), GFP_ATOMIC);
+ tb = kzalloc(sizeof(struct st_buffer), GFP_KERNEL);
if (!tb) {
printk(KERN_NOTICE "st: Can't allocate new tape buffer.\n");
return NULL;
@@ -3888,8 +3888,8 @@ static struct st_buffer *new_tape_buffer(int need_dma, int max_sg)
tb->dma = need_dma;
tb->buffer_size = 0;
- tb->reserved_pages = kzalloc(max_sg * sizeof(struct page *),
- GFP_ATOMIC);
+ tb->reserved_pages = kcalloc(max_sg, sizeof(struct page *),
+ GFP_KERNEL);
if (!tb->reserved_pages) {
kfree(tb);
return NULL;
@@ -4290,7 +4290,7 @@ static int st_probe(struct device *dev)
goto out_buffer_free;
}
- tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC);
+ tpnt = kzalloc(sizeof(struct scsi_tape), GFP_KERNEL);
if (tpnt == NULL) {
sdev_printk(KERN_ERR, SDp,
"st: Can't allocate device descriptor.\n");
@@ -4915,7 +4915,8 @@ static int sgl_map_user_pages(struct st_buffer *STbp,
if (count == 0)
return 0;
- if ((pages = kmalloc(max_pages * sizeof(*pages), GFP_KERNEL)) == NULL)
+ pages = kmalloc_array(max_pages, sizeof(*pages), GFP_KERNEL);
+ if (pages == NULL)
return -ENOMEM;
/* Try to fault in all of the necessary pages */
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index a2ec0bc..33a4a4d 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -395,6 +395,12 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)");
module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO);
MODULE_PARM_DESC(storvsc_vcpus_per_sub_channel, "Ratio of VCPUs to subchannels");
+
+static int ring_avail_percent_lowater = 10;
+module_param(ring_avail_percent_lowater, int, S_IRUGO);
+MODULE_PARM_DESC(ring_avail_percent_lowater,
+ "Select a channel if available ring size > this in percent");
+
/*
* Timeout in seconds for all devices managed by this driver.
*/
@@ -1241,7 +1247,7 @@ static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device,
{
u16 slot = 0;
u16 hash_qnum;
- struct cpumask alloced_mask;
+ const struct cpumask *node_mask;
int num_channels, tgt_cpu;
if (stor_device->num_sc == 0)
@@ -1257,10 +1263,13 @@ static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device,
* III. Mapping is persistent.
*/
- cpumask_and(&alloced_mask, &stor_device->alloced_cpus,
- cpumask_of_node(cpu_to_node(q_num)));
+ node_mask = cpumask_of_node(cpu_to_node(q_num));
- num_channels = cpumask_weight(&alloced_mask);
+ num_channels = 0;
+ for_each_cpu(tgt_cpu, &stor_device->alloced_cpus) {
+ if (cpumask_test_cpu(tgt_cpu, node_mask))
+ num_channels++;
+ }
if (num_channels == 0)
return stor_device->device->channel;
@@ -1268,7 +1277,9 @@ static struct vmbus_channel *get_og_chn(struct storvsc_device *stor_device,
while (hash_qnum >= num_channels)
hash_qnum -= num_channels;
- for_each_cpu(tgt_cpu, &alloced_mask) {
+ for_each_cpu(tgt_cpu, &stor_device->alloced_cpus) {
+ if (!cpumask_test_cpu(tgt_cpu, node_mask))
+ continue;
if (slot == hash_qnum)
break;
slot++;
@@ -1285,9 +1296,9 @@ static int storvsc_do_io(struct hv_device *device,
{
struct storvsc_device *stor_device;
struct vstor_packet *vstor_packet;
- struct vmbus_channel *outgoing_channel;
+ struct vmbus_channel *outgoing_channel, *channel;
int ret = 0;
- struct cpumask alloced_mask;
+ const struct cpumask *node_mask;
int tgt_cpu;
vstor_packet = &request->vstor_packet;
@@ -1301,22 +1312,52 @@ static int storvsc_do_io(struct hv_device *device,
/*
* Select an an appropriate channel to send the request out.
*/
-
if (stor_device->stor_chns[q_num] != NULL) {
outgoing_channel = stor_device->stor_chns[q_num];
- if (outgoing_channel->target_cpu == smp_processor_id()) {
+ if (outgoing_channel->target_cpu == q_num) {
/*
* Ideally, we want to pick a different channel if
* available on the same NUMA node.
*/
- cpumask_and(&alloced_mask, &stor_device->alloced_cpus,
- cpumask_of_node(cpu_to_node(q_num)));
- for_each_cpu_wrap(tgt_cpu, &alloced_mask,
- outgoing_channel->target_cpu + 1) {
- if (tgt_cpu != outgoing_channel->target_cpu) {
- outgoing_channel =
- stor_device->stor_chns[tgt_cpu];
- break;
+ node_mask = cpumask_of_node(cpu_to_node(q_num));
+ for_each_cpu_wrap(tgt_cpu,
+ &stor_device->alloced_cpus, q_num + 1) {
+ if (!cpumask_test_cpu(tgt_cpu, node_mask))
+ continue;
+ if (tgt_cpu == q_num)
+ continue;
+ channel = stor_device->stor_chns[tgt_cpu];
+ if (hv_get_avail_to_write_percent(
+ &channel->outbound)
+ > ring_avail_percent_lowater) {
+ outgoing_channel = channel;
+ goto found_channel;
+ }
+ }
+
+ /*
+ * All the other channels on the same NUMA node are
+ * busy. Try to use the channel on the current CPU
+ */
+ if (hv_get_avail_to_write_percent(
+ &outgoing_channel->outbound)
+ > ring_avail_percent_lowater)
+ goto found_channel;
+
+ /*
+ * If we reach here, all the channels on the current
+ * NUMA node are busy. Try to find a channel in
+ * other NUMA nodes
+ */
+ for_each_cpu(tgt_cpu, &stor_device->alloced_cpus) {
+ if (cpumask_test_cpu(tgt_cpu, node_mask))
+ continue;
+ channel = stor_device->stor_chns[tgt_cpu];
+ if (hv_get_avail_to_write_percent(
+ &channel->outbound)
+ > ring_avail_percent_lowater) {
+ outgoing_channel = channel;
+ goto found_channel;
}
}
}
@@ -1324,7 +1365,7 @@ static int storvsc_do_io(struct hv_device *device,
outgoing_channel = get_og_chn(stor_device, q_num);
}
-
+found_channel:
vstor_packet->flags |= REQUEST_COMPLETION_FLAG;
vstor_packet->vm_srb.length = (sizeof(struct vmscsi_request) -
@@ -1382,9 +1423,6 @@ static int storvsc_device_alloc(struct scsi_device *sdevice)
static int storvsc_device_configure(struct scsi_device *sdevice)
{
-
- blk_queue_bounce_limit(sdevice->request_queue, BLK_BOUNCE_ANY);
-
blk_queue_rq_timeout(sdevice->request_queue, (storvsc_timeout * HZ));
/* Ensure there are no gaps in presented sgls */
@@ -1732,8 +1770,9 @@ static int storvsc_probe(struct hv_device *device,
(num_cpus - 1) / storvsc_vcpus_per_sub_channel;
}
- scsi_driver.can_queue = (max_outstanding_req_per_channel *
- (max_sub_channels + 1));
+ scsi_driver.can_queue = max_outstanding_req_per_channel *
+ (max_sub_channels + 1) *
+ (100 - ring_avail_percent_lowater) / 100;
host = scsi_host_alloc(&scsi_driver,
sizeof(struct hv_host_device));
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 2b38db2..221820a 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -1098,7 +1098,7 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC;
}
- if (host->hw_ver.major >= 0x2) {
+ if (host->hw_ver.major == 0x2) {
hba->quirks |= UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION;
if (!ufs_qcom_cap_qunipro(host))
diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c
index e82bde0..895a9b5 100644
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -86,8 +86,8 @@ static int ufshcd_parse_clock_info(struct ufs_hba *hba)
goto out;
}
- clkfreq = devm_kzalloc(dev, sz * sizeof(*clkfreq),
- GFP_KERNEL);
+ clkfreq = devm_kcalloc(dev, sz, sizeof(*clkfreq),
+ GFP_KERNEL);
if (!clkfreq) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index d0a1674..397081d 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -233,8 +233,6 @@ static void ufshcd_suspend_clkscaling(struct ufs_hba *hba);
static void __ufshcd_suspend_clkscaling(struct ufs_hba *hba);
static int ufshcd_scale_clks(struct ufs_hba *hba, bool scale_up);
static irqreturn_t ufshcd_intr(int irq, void *__hba);
-static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
- struct ufs_pa_layer_attr *desired_pwr_mode);
static int ufshcd_change_power_mode(struct ufs_hba *hba,
struct ufs_pa_layer_attr *pwr_mode);
static inline bool ufshcd_valid_tag(struct ufs_hba *hba, int tag)
@@ -266,6 +264,18 @@ static inline void ufshcd_disable_irq(struct ufs_hba *hba)
}
}
+static void ufshcd_scsi_unblock_requests(struct ufs_hba *hba)
+{
+ if (atomic_dec_and_test(&hba->scsi_block_reqs_cnt))
+ scsi_unblock_requests(hba->host);
+}
+
+static void ufshcd_scsi_block_requests(struct ufs_hba *hba)
+{
+ if (atomic_inc_return(&hba->scsi_block_reqs_cnt) == 1)
+ scsi_block_requests(hba->host);
+}
+
/* replace non-printable or non-ASCII characters with spaces */
static inline void ufshcd_remove_non_printable(char *val)
{
@@ -675,7 +685,24 @@ static inline void ufshcd_put_tm_slot(struct ufs_hba *hba, int slot)
*/
static inline void ufshcd_utrl_clear(struct ufs_hba *hba, u32 pos)
{
- ufshcd_writel(hba, ~(1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
+ if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR)
+ ufshcd_writel(hba, (1 << pos), REG_UTP_TRANSFER_REQ_LIST_CLEAR);
+ else
+ ufshcd_writel(hba, ~(1 << pos),
+ REG_UTP_TRANSFER_REQ_LIST_CLEAR);
+}
+
+/**
+ * ufshcd_utmrl_clear - Clear a bit in UTRMLCLR register
+ * @hba: per adapter instance
+ * @pos: position of the bit to be cleared
+ */
+static inline void ufshcd_utmrl_clear(struct ufs_hba *hba, u32 pos)
+{
+ if (hba->quirks & UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR)
+ ufshcd_writel(hba, (1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR);
+ else
+ ufshcd_writel(hba, ~(1 << pos), REG_UTP_TASK_REQ_LIST_CLEAR);
}
/**
@@ -1091,12 +1118,12 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)
* make sure that there are no outstanding requests when
* clock scaling is in progress
*/
- scsi_block_requests(hba->host);
+ ufshcd_scsi_block_requests(hba);
down_write(&hba->clk_scaling_lock);
if (ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) {
ret = -EBUSY;
up_write(&hba->clk_scaling_lock);
- scsi_unblock_requests(hba->host);
+ ufshcd_scsi_unblock_requests(hba);
}
return ret;
@@ -1105,7 +1132,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)
static void ufshcd_clock_scaling_unprepare(struct ufs_hba *hba)
{
up_write(&hba->clk_scaling_lock);
- scsi_unblock_requests(hba->host);
+ ufshcd_scsi_unblock_requests(hba);
}
/**
@@ -1200,16 +1227,13 @@ static int ufshcd_devfreq_target(struct device *dev,
struct ufs_hba *hba = dev_get_drvdata(dev);
ktime_t start;
bool scale_up, sched_clk_scaling_suspend_work = false;
+ struct list_head *clk_list = &hba->clk_list_head;
+ struct ufs_clk_info *clki;
unsigned long irq_flags;
if (!ufshcd_is_clkscaling_supported(hba))
return -EINVAL;
- if ((*freq > 0) && (*freq < UINT_MAX)) {
- dev_err(hba->dev, "%s: invalid freq = %lu\n", __func__, *freq);
- return -EINVAL;
- }
-
spin_lock_irqsave(hba->host->host_lock, irq_flags);
if (ufshcd_eh_in_progress(hba)) {
spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
@@ -1219,7 +1243,13 @@ static int ufshcd_devfreq_target(struct device *dev,
if (!hba->clk_scaling.active_reqs)
sched_clk_scaling_suspend_work = true;
- scale_up = (*freq == UINT_MAX) ? true : false;
+ if (list_empty(clk_list)) {
+ spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
+ goto out;
+ }
+
+ clki = list_first_entry(&hba->clk_list_head, struct ufs_clk_info, list);
+ scale_up = (*freq == clki->max_freq) ? true : false;
if (!ufshcd_is_devfreq_scaling_required(hba, scale_up)) {
spin_unlock_irqrestore(hba->host->host_lock, irq_flags);
ret = 0;
@@ -1287,6 +1317,55 @@ static struct devfreq_dev_profile ufs_devfreq_profile = {
.get_dev_status = ufshcd_devfreq_get_dev_status,
};
+static int ufshcd_devfreq_init(struct ufs_hba *hba)
+{
+ struct list_head *clk_list = &hba->clk_list_head;
+ struct ufs_clk_info *clki;
+ struct devfreq *devfreq;
+ int ret;
+
+ /* Skip devfreq if we don't have any clocks in the list */
+ if (list_empty(clk_list))
+ return 0;
+
+ clki = list_first_entry(clk_list, struct ufs_clk_info, list);
+ dev_pm_opp_add(hba->dev, clki->min_freq, 0);
+ dev_pm_opp_add(hba->dev, clki->max_freq, 0);
+
+ devfreq = devfreq_add_device(hba->dev,
+ &ufs_devfreq_profile,
+ DEVFREQ_GOV_SIMPLE_ONDEMAND,
+ NULL);
+ if (IS_ERR(devfreq)) {
+ ret = PTR_ERR(devfreq);
+ dev_err(hba->dev, "Unable to register with devfreq %d\n", ret);
+
+ dev_pm_opp_remove(hba->dev, clki->min_freq);
+ dev_pm_opp_remove(hba->dev, clki->max_freq);
+ return ret;
+ }
+
+ hba->devfreq = devfreq;
+
+ return 0;
+}
+
+static void ufshcd_devfreq_remove(struct ufs_hba *hba)
+{
+ struct list_head *clk_list = &hba->clk_list_head;
+ struct ufs_clk_info *clki;
+
+ if (!hba->devfreq)
+ return;
+
+ devfreq_remove_device(hba->devfreq);
+ hba->devfreq = NULL;
+
+ clki = list_first_entry(clk_list, struct ufs_clk_info, list);
+ dev_pm_opp_remove(hba->dev, clki->min_freq);
+ dev_pm_opp_remove(hba->dev, clki->max_freq);
+}
+
static void __ufshcd_suspend_clkscaling(struct ufs_hba *hba)
{
unsigned long flags;
@@ -1425,7 +1504,7 @@ static void ufshcd_ungate_work(struct work_struct *work)
hba->clk_gating.is_suspended = false;
}
unblock_reqs:
- scsi_unblock_requests(hba->host);
+ ufshcd_scsi_unblock_requests(hba);
}
/**
@@ -1481,11 +1560,12 @@ start:
* work and to enable clocks.
*/
case CLKS_OFF:
- scsi_block_requests(hba->host);
+ ufshcd_scsi_block_requests(hba);
hba->clk_gating.state = REQ_CLKS_ON;
trace_ufshcd_clk_gating(dev_name(hba->dev),
hba->clk_gating.state);
- schedule_work(&hba->clk_gating.ungate_work);
+ queue_work(hba->clk_gating.clk_gating_workq,
+ &hba->clk_gating.ungate_work);
/*
* fall through to check if we should wait for this
* work to be done or not.
@@ -1671,6 +1751,8 @@ out:
static void ufshcd_init_clk_gating(struct ufs_hba *hba)
{
+ char wq_name[sizeof("ufs_clk_gating_00")];
+
if (!ufshcd_is_clkgating_allowed(hba))
return;
@@ -1678,6 +1760,11 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba)
INIT_DELAYED_WORK(&hba->clk_gating.gate_work, ufshcd_gate_work);
INIT_WORK(&hba->clk_gating.ungate_work, ufshcd_ungate_work);
+ snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_clk_gating_%d",
+ hba->host->host_no);
+ hba->clk_gating.clk_gating_workq = alloc_ordered_workqueue(wq_name,
+ WQ_MEM_RECLAIM);
+
hba->clk_gating.is_enabled = true;
hba->clk_gating.delay_attr.show = ufshcd_clkgate_delay_show;
@@ -1705,6 +1792,7 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba)
device_remove_file(hba->dev, &hba->clk_gating.enable_attr);
cancel_work_sync(&hba->clk_gating.ungate_work);
cancel_delayed_work_sync(&hba->clk_gating.gate_work);
+ destroy_workqueue(hba->clk_gating.clk_gating_workq);
}
/* Must be called with host lock acquired */
@@ -3269,8 +3357,8 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba)
}
/* Allocate memory for local reference block */
- hba->lrb = devm_kzalloc(hba->dev,
- hba->nutrs * sizeof(struct ufshcd_lrb),
+ hba->lrb = devm_kcalloc(hba->dev,
+ hba->nutrs, sizeof(struct ufshcd_lrb),
GFP_KERNEL);
if (!hba->lrb) {
dev_err(hba->dev, "LRB Memory allocation failed\n");
@@ -3383,6 +3471,52 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba)
"dme-link-startup: error code %d\n", ret);
return ret;
}
+/**
+ * ufshcd_dme_reset - UIC command for DME_RESET
+ * @hba: per adapter instance
+ *
+ * DME_RESET command is issued in order to reset UniPro stack.
+ * This function now deal with cold reset.
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int ufshcd_dme_reset(struct ufs_hba *hba)
+{
+ struct uic_command uic_cmd = {0};
+ int ret;
+
+ uic_cmd.command = UIC_CMD_DME_RESET;
+
+ ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+ if (ret)
+ dev_err(hba->dev,
+ "dme-reset: error code %d\n", ret);
+
+ return ret;
+}
+
+/**
+ * ufshcd_dme_enable - UIC command for DME_ENABLE
+ * @hba: per adapter instance
+ *
+ * DME_ENABLE command is issued in order to enable UniPro stack.
+ *
+ * Returns 0 on success, non-zero value on failure
+ */
+static int ufshcd_dme_enable(struct ufs_hba *hba)
+{
+ struct uic_command uic_cmd = {0};
+ int ret;
+
+ uic_cmd.command = UIC_CMD_DME_ENABLE;
+
+ ret = ufshcd_send_uic_cmd(hba, &uic_cmd);
+ if (ret)
+ dev_err(hba->dev,
+ "dme-reset: error code %d\n", ret);
+
+ return ret;
+}
static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba)
{
@@ -3906,7 +4040,7 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba,
* @hba: per-adapter instance
* @desired_pwr_mode: desired power configuration
*/
-static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
+int ufshcd_config_pwr_mode(struct ufs_hba *hba,
struct ufs_pa_layer_attr *desired_pwr_mode)
{
struct ufs_pa_layer_attr final_params = { 0 };
@@ -3924,6 +4058,7 @@ static int ufshcd_config_pwr_mode(struct ufs_hba *hba,
return ret;
}
+EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode);
/**
* ufshcd_complete_dev_init() - checks device readiness
@@ -4041,7 +4176,7 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep)
}
/**
- * ufshcd_hba_enable - initialize the controller
+ * ufshcd_hba_execute_hce - initialize the controller
* @hba: per adapter instance
*
* The controller resets itself and controller firmware initialization
@@ -4050,7 +4185,7 @@ static inline void ufshcd_hba_stop(struct ufs_hba *hba, bool can_sleep)
*
* Returns 0 on success, non-zero value on failure
*/
-static int ufshcd_hba_enable(struct ufs_hba *hba)
+static int ufshcd_hba_execute_hce(struct ufs_hba *hba)
{
int retry;
@@ -4105,6 +4240,31 @@ static int ufshcd_hba_enable(struct ufs_hba *hba)
return 0;
}
+static int ufshcd_hba_enable(struct ufs_hba *hba)
+{
+ int ret;
+
+ if (hba->quirks & UFSHCI_QUIRK_BROKEN_HCE) {
+ ufshcd_set_link_off(hba);
+ ufshcd_vops_hce_enable_notify(hba, PRE_CHANGE);
+
+ /* enable UIC related interrupts */
+ ufshcd_enable_intr(hba, UFSHCD_UIC_MASK);
+ ret = ufshcd_dme_reset(hba);
+ if (!ret) {
+ ret = ufshcd_dme_enable(hba);
+ if (!ret)
+ ufshcd_vops_hce_enable_notify(hba, POST_CHANGE);
+ if (ret)
+ dev_err(hba->dev,
+ "Host controller enable failed with non-hce\n");
+ }
+ } else {
+ ret = ufshcd_hba_execute_hce(hba);
+ }
+
+ return ret;
+}
static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer)
{
int tx_lanes, i, err = 0;
@@ -4678,7 +4838,8 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
* false interrupt if device completes another request after resetting
* aggregation and before reading the DB.
*/
- if (ufshcd_is_intr_aggr_allowed(hba))
+ if (ufshcd_is_intr_aggr_allowed(hba) &&
+ !(hba->quirks & UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR))
ufshcd_reset_intr_aggr(hba);
tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
@@ -4969,6 +5130,7 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
hba = container_of(work, struct ufs_hba, eeh_work);
pm_runtime_get_sync(hba->dev);
+ scsi_block_requests(hba->host);
err = ufshcd_get_ee_status(hba, &status);
if (err) {
dev_err(hba->dev, "%s: failed to get exception status %d\n",
@@ -4982,6 +5144,7 @@ static void ufshcd_exception_event_handler(struct work_struct *work)
ufshcd_bkops_exception_event_handler(hba);
out:
+ scsi_unblock_requests(hba->host);
pm_runtime_put_sync(hba->dev);
return;
}
@@ -5192,7 +5355,7 @@ skip_err_handling:
out:
spin_unlock_irqrestore(hba->host->host_lock, flags);
- scsi_unblock_requests(hba->host);
+ ufshcd_scsi_unblock_requests(hba);
ufshcd_release(hba);
pm_runtime_put_sync(hba->dev);
}
@@ -5294,7 +5457,7 @@ static void ufshcd_check_errors(struct ufs_hba *hba)
/* handle fatal errors only when link is functional */
if (hba->ufshcd_state == UFSHCD_STATE_OPERATIONAL) {
/* block commands from scsi mid-layer */
- scsi_block_requests(hba->host);
+ ufshcd_scsi_block_requests(hba);
hba->ufshcd_state = UFSHCD_STATE_EH_SCHEDULED;
@@ -5371,19 +5534,30 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
u32 intr_status, enabled_intr_status;
irqreturn_t retval = IRQ_NONE;
struct ufs_hba *hba = __hba;
+ int retries = hba->nutrs;
spin_lock(hba->host->host_lock);
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
- enabled_intr_status =
- intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
- if (intr_status)
- ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
+ /*
+ * There could be max of hba->nutrs reqs in flight and in worst case
+ * if the reqs get finished 1 by 1 after the interrupt status is
+ * read, make sure we handle them by checking the interrupt status
+ * again in a loop until we process all of the reqs before returning.
+ */
+ do {
+ enabled_intr_status =
+ intr_status & ufshcd_readl(hba, REG_INTERRUPT_ENABLE);
+ if (intr_status)
+ ufshcd_writel(hba, intr_status, REG_INTERRUPT_STATUS);
+ if (enabled_intr_status) {
+ ufshcd_sl_intr(hba, enabled_intr_status);
+ retval = IRQ_HANDLED;
+ }
+
+ intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
+ } while (intr_status && --retries);
- if (enabled_intr_status) {
- ufshcd_sl_intr(hba, enabled_intr_status);
- retval = IRQ_HANDLED;
- }
spin_unlock(hba->host->host_lock);
return retval;
}
@@ -5398,7 +5572,7 @@ static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag)
goto out;
spin_lock_irqsave(hba->host->host_lock, flags);
- ufshcd_writel(hba, ~(1 << tag), REG_UTP_TASK_REQ_LIST_CLEAR);
+ ufshcd_utmrl_clear(hba, tag);
spin_unlock_irqrestore(hba->host->host_lock, flags);
/* poll for max. 1 sec to clear door bell register by h/w */
@@ -5958,14 +6132,18 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
{
int ret;
int buff_len = hba->desc_size.pwr_desc;
- u8 desc_buf[hba->desc_size.pwr_desc];
+ u8 *desc_buf;
+
+ desc_buf = kmalloc(buff_len, GFP_KERNEL);
+ if (!desc_buf)
+ return;
ret = ufshcd_read_power_desc(hba, desc_buf, buff_len);
if (ret) {
dev_err(hba->dev,
"%s: Failed reading power descriptor.len = %d ret = %d",
__func__, buff_len, ret);
- return;
+ goto out;
}
hba->init_prefetch_data.icc_level =
@@ -5983,6 +6161,8 @@ static void ufshcd_init_icc_levels(struct ufs_hba *hba)
"%s: Failed configuring bActiveICCLevel = %d ret = %d",
__func__, hba->init_prefetch_data.icc_level , ret);
+out:
+ kfree(desc_buf);
}
/**
@@ -6052,9 +6232,17 @@ static int ufs_get_device_desc(struct ufs_hba *hba,
struct ufs_dev_desc *dev_desc)
{
int err;
+ size_t buff_len;
u8 model_index;
- u8 str_desc_buf[QUERY_DESC_MAX_SIZE + 1] = {0};
- u8 desc_buf[hba->desc_size.dev_desc];
+ u8 *desc_buf;
+
+ buff_len = max_t(size_t, hba->desc_size.dev_desc,
+ QUERY_DESC_MAX_SIZE + 1);
+ desc_buf = kmalloc(buff_len, GFP_KERNEL);
+ if (!desc_buf) {
+ err = -ENOMEM;
+ goto out;
+ }
err = ufshcd_read_device_desc(hba, desc_buf, hba->desc_size.dev_desc);
if (err) {
@@ -6072,7 +6260,10 @@ static int ufs_get_device_desc(struct ufs_hba *hba,
model_index = desc_buf[DEVICE_DESC_PARAM_PRDCT_NAME];
- err = ufshcd_read_string_desc(hba, model_index, str_desc_buf,
+ /* Zero-pad entire buffer for string termination. */
+ memset(desc_buf, 0, buff_len);
+
+ err = ufshcd_read_string_desc(hba, model_index, desc_buf,
QUERY_DESC_MAX_SIZE, true/*ASCII*/);
if (err) {
dev_err(hba->dev, "%s: Failed reading Product Name. err = %d\n",
@@ -6080,15 +6271,16 @@ static int ufs_get_device_desc(struct ufs_hba *hba,
goto out;
}
- str_desc_buf[QUERY_DESC_MAX_SIZE] = '\0';
- strlcpy(dev_desc->model, (str_desc_buf + QUERY_DESC_HDR_SIZE),
- min_t(u8, str_desc_buf[QUERY_DESC_LENGTH_OFFSET],
+ desc_buf[QUERY_DESC_MAX_SIZE] = '\0';
+ strlcpy(dev_desc->model, (desc_buf + QUERY_DESC_HDR_SIZE),
+ min_t(u8, desc_buf[QUERY_DESC_LENGTH_OFFSET],
MAX_MODEL_LEN));
/* Null terminate the model string */
dev_desc->model[MAX_MODEL_LEN] = '\0';
out:
+ kfree(desc_buf);
return err;
}
@@ -6439,16 +6631,9 @@ static int ufshcd_probe_hba(struct ufs_hba *hba)
sizeof(struct ufs_pa_layer_attr));
hba->clk_scaling.saved_pwr_info.is_valid = true;
if (!hba->devfreq) {
- hba->devfreq = devm_devfreq_add_device(hba->dev,
- &ufs_devfreq_profile,
- "simple_ondemand",
- NULL);
- if (IS_ERR(hba->devfreq)) {
- ret = PTR_ERR(hba->devfreq);
- dev_err(hba->dev, "Unable to register with devfreq %d\n",
- ret);
+ ret = ufshcd_devfreq_init(hba);
+ if (ret)
goto out;
- }
}
hba->clk_scaling.is_allowed = true;
}
@@ -6799,9 +6984,16 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
if (list_empty(head))
goto out;
- ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE);
- if (ret)
- return ret;
+ /*
+ * vendor specific setup_clocks ops may depend on clocks managed by
+ * this standard driver hence call the vendor specific setup_clocks
+ * before disabling the clocks managed here.
+ */
+ if (!on) {
+ ret = ufshcd_vops_setup_clocks(hba, on, PRE_CHANGE);
+ if (ret)
+ return ret;
+ }
list_for_each_entry(clki, head, list) {
if (!IS_ERR_OR_NULL(clki->clk)) {
@@ -6825,9 +7017,16 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on,
}
}
- ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE);
- if (ret)
- return ret;
+ /*
+ * vendor specific setup_clocks ops may depend on clocks managed by
+ * this standard driver hence call the vendor specific setup_clocks
+ * after enabling the clocks managed here.
+ */
+ if (on) {
+ ret = ufshcd_vops_setup_clocks(hba, on, POST_CHANGE);
+ if (ret)
+ return ret;
+ }
out:
if (ret) {
@@ -6992,6 +7191,7 @@ static void ufshcd_hba_exit(struct ufs_hba *hba)
if (hba->devfreq)
ufshcd_suspend_clkscaling(hba);
destroy_workqueue(hba->clk_scaling.workq);
+ ufshcd_devfreq_remove(hba);
}
ufshcd_setup_clocks(hba, false);
ufshcd_setup_hba_vreg(hba, false);
@@ -7904,7 +8104,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
/* Hold auto suspend until async scan completes */
pm_runtime_get_sync(dev);
-
+ atomic_set(&hba->scsi_block_reqs_cnt, 0);
/*
* We are assuming that device wasn't put in sleep/power-down
* state exclusively during the boot stage before kernel.
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 8110dcd..f51758f 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -362,6 +362,7 @@ struct ufs_clk_gating {
struct device_attribute enable_attr;
bool is_enabled;
int active_reqs;
+ struct workqueue_struct *clk_gating_workq;
};
struct ufs_saved_pwr_info {
@@ -499,6 +500,7 @@ struct ufs_stats {
* @urgent_bkops_lvl: keeps track of urgent bkops level for device
* @is_urgent_bkops_lvl_checked: keeps track if the urgent bkops level for
* device is known or not.
+ * @scsi_block_reqs_cnt: reference counting for scsi block requests
*/
struct ufs_hba {
void __iomem *mmio_base;
@@ -595,6 +597,22 @@ struct ufs_hba {
*/
#define UFSHCD_QUIRK_PRDT_BYTE_GRAN 0x80
+ /*
+ * Clear handling for transfer/task request list is just opposite.
+ */
+ #define UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR 0x100
+
+ /*
+ * This quirk needs to be enabled if host controller doesn't allow
+ * that the interrupt aggregation timer and counter are reset by s/w.
+ */
+ #define UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR 0x200
+
+ /*
+ * This quirks needs to be enabled if host controller cannot be
+ * enabled via HCE register.
+ */
+ #define UFSHCI_QUIRK_BROKEN_HCE 0x400
unsigned int quirks; /* Deviations from standard UFSHCI spec. */
/* Device deviations from standard UFS device spec. */
@@ -683,6 +701,7 @@ struct ufs_hba {
struct rw_semaphore clk_scaling_lock;
struct ufs_desc_size desc_size;
+ atomic_t scsi_block_reqs_cnt;
};
/* Returns true if clocks can be gated. Otherwise false */
@@ -789,6 +808,8 @@ extern int ufshcd_dme_set_attr(struct ufs_hba *hba, u32 attr_sel,
u8 attr_set, u32 mib_val, u8 peer);
extern int ufshcd_dme_get_attr(struct ufs_hba *hba, u32 attr_sel,
u32 *mib_val, u8 peer);
+extern int ufshcd_config_pwr_mode(struct ufs_hba *hba,
+ struct ufs_pa_layer_attr *desired_pwr_mode);
/* UIC command interfaces for DME primitives */
#define DME_LOCAL 0
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 45d0463..6dc8891 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -794,9 +794,10 @@ static int virtscsi_init(struct virtio_device *vdev,
struct irq_affinity desc = { .pre_vectors = 2 };
num_vqs = vscsi->num_queues + VIRTIO_SCSI_VQ_BASE;
- vqs = kmalloc(num_vqs * sizeof(struct virtqueue *), GFP_KERNEL);
- callbacks = kmalloc(num_vqs * sizeof(vq_callback_t *), GFP_KERNEL);
- names = kmalloc(num_vqs * sizeof(char *), GFP_KERNEL);
+ vqs = kmalloc_array(num_vqs, sizeof(struct virtqueue *), GFP_KERNEL);
+ callbacks = kmalloc_array(num_vqs, sizeof(vq_callback_t *),
+ GFP_KERNEL);
+ names = kmalloc_array(num_vqs, sizeof(char *), GFP_KERNEL);
if (!callbacks || !vqs || !names) {
err = -ENOMEM;
diff --git a/drivers/scsi/wd719x.c b/drivers/scsi/wd719x.c
index 2ba2b7b..974bfb3 100644
--- a/drivers/scsi/wd719x.c
+++ b/drivers/scsi/wd719x.c
@@ -978,18 +978,7 @@ static struct pci_driver wd719x_pci_driver = {
.remove = wd719x_pci_remove,
};
-static int __init wd719x_init(void)
-{
- return pci_register_driver(&wd719x_pci_driver);
-}
-
-static void __exit wd719x_exit(void)
-{
- pci_unregister_driver(&wd719x_pci_driver);
-}
-
-module_init(wd719x_init);
-module_exit(wd719x_exit);
+module_pci_driver(wd719x_pci_driver);
MODULE_DESCRIPTION("Western Digital WD7193/7197/7296 SCSI driver");
MODULE_AUTHOR("Ondrej Zary, Aaron Dewell, Juergen Gaertner");
diff --git a/drivers/scsi/xen-scsifront.c b/drivers/scsi/xen-scsifront.c
index 36f59a1..61389bd 100644
--- a/drivers/scsi/xen-scsifront.c
+++ b/drivers/scsi/xen-scsifront.c
@@ -654,10 +654,17 @@ static int scsifront_dev_reset_handler(struct scsi_cmnd *sc)
static int scsifront_sdev_configure(struct scsi_device *sdev)
{
struct vscsifrnt_info *info = shost_priv(sdev->host);
+ int err;
- if (info && current == info->curr)
- xenbus_printf(XBT_NIL, info->dev->nodename,
+ if (info && current == info->curr) {
+ err = xenbus_printf(XBT_NIL, info->dev->nodename,
info->dev_state_path, "%d", XenbusStateConnected);
+ if (err) {
+ xenbus_dev_error(info->dev, err,
+ "%s: writing dev_state_path", __func__);
+ return err;
+ }
+ }
return 0;
}
@@ -665,10 +672,15 @@ static int scsifront_sdev_configure(struct scsi_device *sdev)
static void scsifront_sdev_destroy(struct scsi_device *sdev)
{
struct vscsifrnt_info *info = shost_priv(sdev->host);
+ int err;
- if (info && current == info->curr)
- xenbus_printf(XBT_NIL, info->dev->nodename,
+ if (info && current == info->curr) {
+ err = xenbus_printf(XBT_NIL, info->dev->nodename,
info->dev_state_path, "%d", XenbusStateClosed);
+ if (err)
+ xenbus_dev_error(info->dev, err,
+ "%s: writing dev_state_path", __func__);
+ }
}
static struct scsi_host_template scsifront_sht = {
@@ -1003,9 +1015,12 @@ static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op)
if (scsi_add_device(info->host, chn, tgt, lun)) {
dev_err(&dev->dev, "scsi_add_device\n");
- xenbus_printf(XBT_NIL, dev->nodename,
+ err = xenbus_printf(XBT_NIL, dev->nodename,
info->dev_state_path,
"%d", XenbusStateClosed);
+ if (err)
+ xenbus_dev_error(dev, err,
+ "%s: writing dev_state_path", __func__);
}
break;
case VSCSIFRONT_OP_DEL_LUN:
@@ -1019,10 +1034,14 @@ static void scsifront_do_lun_hotplug(struct vscsifrnt_info *info, int op)
}
break;
case VSCSIFRONT_OP_READD_LUN:
- if (device_state == XenbusStateConnected)
- xenbus_printf(XBT_NIL, dev->nodename,
+ if (device_state == XenbusStateConnected) {
+ err = xenbus_printf(XBT_NIL, dev->nodename,
info->dev_state_path,
"%d", XenbusStateConnected);
+ if (err)
+ xenbus_dev_error(dev, err,
+ "%s: writing dev_state_path", __func__);
+ }
break;
default:
break;
diff --git a/drivers/scsi/zorro_esp.c b/drivers/scsi/zorro_esp.c
new file mode 100644
index 0000000..bb70882
--- /dev/null
+++ b/drivers/scsi/zorro_esp.c
@@ -0,0 +1,1172 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ESP front-end for Amiga ZORRO SCSI systems.
+ *
+ * Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * Copyright (C) 2011,2018 Michael Schmitz (schmitz@debian.org) for
+ * migration to ESP SCSI core
+ *
+ * Copyright (C) 2013 Tuomas Vainikka (tuomas.vainikka@aalto.fi) for
+ * Blizzard 1230 DMA and probe function fixes
+ *
+ * Copyright (C) 2017 Finn Thain for PIO code from Mac ESP driver adapted here
+ */
+/*
+ * ZORRO bus code from:
+ */
+/*
+ * Detection routine for the NCR53c710 based Amiga SCSI Controllers for Linux.
+ * Amiga MacroSystemUS WarpEngine SCSI controller.
+ * Amiga Technologies/DKB A4091 SCSI controller.
+ *
+ * Written 1997 by Alan Hourihane <alanh@fairlite.demon.co.uk>
+ * plus modifications of the 53c7xx.c driver to support the Amiga.
+ *
+ * Rewritten to use 53c700.c by Kars de Jong <jongk@linux-m68k.org>
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
+#include <linux/delay.h>
+#include <linux/zorro.h>
+#include <linux/slab.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_spi.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_tcq.h>
+
+#include "esp_scsi.h"
+
+MODULE_AUTHOR("Michael Schmitz <schmitz@debian.org>");
+MODULE_DESCRIPTION("Amiga Zorro NCR5C9x (ESP) driver");
+MODULE_LICENSE("GPL");
+
+/* per-board register layout definitions */
+
+/* Blizzard 1230 DMA interface */
+
+struct blz1230_dma_registers {
+ unsigned char dma_addr; /* DMA address [0x0000] */
+ unsigned char dmapad2[0x7fff];
+ unsigned char dma_latch; /* DMA latch [0x8000] */
+};
+
+/* Blizzard 1230II DMA interface */
+
+struct blz1230II_dma_registers {
+ unsigned char dma_addr; /* DMA address [0x0000] */
+ unsigned char dmapad2[0xf];
+ unsigned char dma_latch; /* DMA latch [0x0010] */
+};
+
+/* Blizzard 2060 DMA interface */
+
+struct blz2060_dma_registers {
+ unsigned char dma_led_ctrl; /* DMA led control [0x000] */
+ unsigned char dmapad1[0x0f];
+ unsigned char dma_addr0; /* DMA address (MSB) [0x010] */
+ unsigned char dmapad2[0x03];
+ unsigned char dma_addr1; /* DMA address [0x014] */
+ unsigned char dmapad3[0x03];
+ unsigned char dma_addr2; /* DMA address [0x018] */
+ unsigned char dmapad4[0x03];
+ unsigned char dma_addr3; /* DMA address (LSB) [0x01c] */
+};
+
+/* DMA control bits */
+#define DMA_WRITE 0x80000000
+
+/* Cyberstorm DMA interface */
+
+struct cyber_dma_registers {
+ unsigned char dma_addr0; /* DMA address (MSB) [0x000] */
+ unsigned char dmapad1[1];
+ unsigned char dma_addr1; /* DMA address [0x002] */
+ unsigned char dmapad2[1];
+ unsigned char dma_addr2; /* DMA address [0x004] */
+ unsigned char dmapad3[1];
+ unsigned char dma_addr3; /* DMA address (LSB) [0x006] */
+ unsigned char dmapad4[0x3fb];
+ unsigned char cond_reg; /* DMA cond (ro) [0x402] */
+#define ctrl_reg cond_reg /* DMA control (wo) [0x402] */
+};
+
+/* DMA control bits */
+#define CYBER_DMA_WRITE 0x40 /* DMA direction. 1 = write */
+#define CYBER_DMA_Z3 0x20 /* 16 (Z2) or 32 (CHIP/Z3) bit DMA transfer */
+
+/* DMA status bits */
+#define CYBER_DMA_HNDL_INTR 0x80 /* DMA IRQ pending? */
+
+/* The CyberStorm II DMA interface */
+struct cyberII_dma_registers {
+ unsigned char cond_reg; /* DMA cond (ro) [0x000] */
+#define ctrl_reg cond_reg /* DMA control (wo) [0x000] */
+ unsigned char dmapad4[0x3f];
+ unsigned char dma_addr0; /* DMA address (MSB) [0x040] */
+ unsigned char dmapad1[3];
+ unsigned char dma_addr1; /* DMA address [0x044] */
+ unsigned char dmapad2[3];
+ unsigned char dma_addr2; /* DMA address [0x048] */
+ unsigned char dmapad3[3];
+ unsigned char dma_addr3; /* DMA address (LSB) [0x04c] */
+};
+
+/* Fastlane DMA interface */
+
+struct fastlane_dma_registers {
+ unsigned char cond_reg; /* DMA status (ro) [0x0000] */
+#define ctrl_reg cond_reg /* DMA control (wo) [0x0000] */
+ char dmapad1[0x3f];
+ unsigned char clear_strobe; /* DMA clear (wo) [0x0040] */
+};
+
+/*
+ * The controller registers can be found in the Z2 config area at these
+ * offsets:
+ */
+#define FASTLANE_ESP_ADDR 0x1000001
+
+/* DMA status bits */
+#define FASTLANE_DMA_MINT 0x80
+#define FASTLANE_DMA_IACT 0x40
+#define FASTLANE_DMA_CREQ 0x20
+
+/* DMA control bits */
+#define FASTLANE_DMA_FCODE 0xa0
+#define FASTLANE_DMA_MASK 0xf3
+#define FASTLANE_DMA_WRITE 0x08 /* 1 = write */
+#define FASTLANE_DMA_ENABLE 0x04 /* Enable DMA */
+#define FASTLANE_DMA_EDI 0x02 /* Enable DMA IRQ ? */
+#define FASTLANE_DMA_ESI 0x01 /* Enable SCSI IRQ */
+
+/*
+ * private data used for driver
+ */
+struct zorro_esp_priv {
+ struct esp *esp; /* our ESP instance - for Scsi_host* */
+ void __iomem *board_base; /* virtual address (Zorro III board) */
+ int error; /* PIO error flag */
+ int zorro3; /* board is Zorro III */
+ unsigned char ctrl_data; /* shadow copy of ctrl_reg */
+};
+
+/*
+ * On all implementations except for the Oktagon, padding between ESP
+ * registers is three bytes.
+ * On Oktagon, it is one byte - use a different accessor there.
+ *
+ * Oktagon needs PDMA - currently unsupported!
+ */
+
+static void zorro_esp_write8(struct esp *esp, u8 val, unsigned long reg)
+{
+ writeb(val, esp->regs + (reg * 4UL));
+}
+
+static u8 zorro_esp_read8(struct esp *esp, unsigned long reg)
+{
+ return readb(esp->regs + (reg * 4UL));
+}
+
+static dma_addr_t zorro_esp_map_single(struct esp *esp, void *buf,
+ size_t sz, int dir)
+{
+ return dma_map_single(esp->dev, buf, sz, dir);
+}
+
+static int zorro_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+ int num_sg, int dir)
+{
+ return dma_map_sg(esp->dev, sg, num_sg, dir);
+}
+
+static void zorro_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+ size_t sz, int dir)
+{
+ dma_unmap_single(esp->dev, addr, sz, dir);
+}
+
+static void zorro_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+ int num_sg, int dir)
+{
+ dma_unmap_sg(esp->dev, sg, num_sg, dir);
+}
+
+static int zorro_esp_irq_pending(struct esp *esp)
+{
+ /* check ESP status register; DMA has no status reg. */
+ if (zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR)
+ return 1;
+
+ return 0;
+}
+
+static int cyber_esp_irq_pending(struct esp *esp)
+{
+ struct cyber_dma_registers __iomem *dregs = esp->dma_regs;
+ unsigned char dma_status = readb(&dregs->cond_reg);
+
+ /* It's important to check the DMA IRQ bit in the correct way! */
+ return ((zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR) &&
+ (dma_status & CYBER_DMA_HNDL_INTR));
+}
+
+static int fastlane_esp_irq_pending(struct esp *esp)
+{
+ struct fastlane_dma_registers __iomem *dregs = esp->dma_regs;
+ unsigned char dma_status;
+
+ dma_status = readb(&dregs->cond_reg);
+
+ if (dma_status & FASTLANE_DMA_IACT)
+ return 0; /* not our IRQ */
+
+ /* Return non-zero if ESP requested IRQ */
+ return (
+ (dma_status & FASTLANE_DMA_CREQ) &&
+ (!(dma_status & FASTLANE_DMA_MINT)) &&
+ (zorro_esp_read8(esp, ESP_STATUS) & ESP_STAT_INTR));
+}
+
+static u32 zorro_esp_dma_length_limit(struct esp *esp, u32 dma_addr,
+ u32 dma_len)
+{
+ return dma_len > 0xFFFFFF ? 0xFFFFFF : dma_len;
+}
+
+static void zorro_esp_reset_dma(struct esp *esp)
+{
+ /* nothing to do here */
+}
+
+static void zorro_esp_dma_drain(struct esp *esp)
+{
+ /* nothing to do here */
+}
+
+static void zorro_esp_dma_invalidate(struct esp *esp)
+{
+ /* nothing to do here */
+}
+
+static void fastlane_esp_dma_invalidate(struct esp *esp)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev);
+ struct fastlane_dma_registers __iomem *dregs = esp->dma_regs;
+ unsigned char *ctrl_data = &zep->ctrl_data;
+
+ *ctrl_data = (*ctrl_data & FASTLANE_DMA_MASK);
+ writeb(0, &dregs->clear_strobe);
+ z_writel(0, zep->board_base);
+}
+
+/*
+ * Programmed IO routines follow.
+ */
+
+static inline unsigned int zorro_esp_wait_for_fifo(struct esp *esp)
+{
+ int i = 500000;
+
+ do {
+ unsigned int fbytes = zorro_esp_read8(esp, ESP_FFLAGS)
+ & ESP_FF_FBYTES;
+
+ if (fbytes)
+ return fbytes;
+
+ udelay(2);
+ } while (--i);
+
+ pr_err("FIFO is empty (sreg %02x)\n",
+ zorro_esp_read8(esp, ESP_STATUS));
+ return 0;
+}
+
+static inline int zorro_esp_wait_for_intr(struct esp *esp)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev);
+ int i = 500000;
+
+ do {
+ esp->sreg = zorro_esp_read8(esp, ESP_STATUS);
+ if (esp->sreg & ESP_STAT_INTR)
+ return 0;
+
+ udelay(2);
+ } while (--i);
+
+ pr_err("IRQ timeout (sreg %02x)\n", esp->sreg);
+ zep->error = 1;
+ return 1;
+}
+
+/*
+ * PIO macros as used in mac_esp.c.
+ * Note that addr and fifo arguments are local-scope variables declared
+ * in zorro_esp_send_pio_cmd(), the macros are only used in that function,
+ * and addr and fifo are referenced in each use of the macros so there
+ * is no need to pass them as macro parameters.
+ */
+#define ZORRO_ESP_PIO_LOOP(operands, reg1) \
+ asm volatile ( \
+ "1: moveb " operands "\n" \
+ " subqw #1,%1 \n" \
+ " jbne 1b \n" \
+ : "+a" (addr), "+r" (reg1) \
+ : "a" (fifo));
+
+#define ZORRO_ESP_PIO_FILL(operands, reg1) \
+ asm volatile ( \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " moveb " operands "\n" \
+ " subqw #8,%1 \n" \
+ " subqw #8,%1 \n" \
+ : "+a" (addr), "+r" (reg1) \
+ : "a" (fifo));
+
+#define ZORRO_ESP_FIFO_SIZE 16
+
+static void zorro_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
+ u32 dma_count, int write, u8 cmd)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev);
+ u8 __iomem *fifo = esp->regs + ESP_FDATA * 16;
+ u8 phase = esp->sreg & ESP_STAT_PMASK;
+
+ cmd &= ~ESP_CMD_DMA;
+
+ if (write) {
+ u8 *dst = (u8 *)addr;
+ u8 mask = ~(phase == ESP_MIP ? ESP_INTR_FDONE : ESP_INTR_BSERV);
+
+ scsi_esp_cmd(esp, cmd);
+
+ while (1) {
+ if (!zorro_esp_wait_for_fifo(esp))
+ break;
+
+ *dst++ = zorro_esp_read8(esp, ESP_FDATA);
+ --esp_count;
+
+ if (!esp_count)
+ break;
+
+ if (zorro_esp_wait_for_intr(esp))
+ break;
+
+ if ((esp->sreg & ESP_STAT_PMASK) != phase)
+ break;
+
+ esp->ireg = zorro_esp_read8(esp, ESP_INTRPT);
+ if (esp->ireg & mask) {
+ zep->error = 1;
+ break;
+ }
+
+ if (phase == ESP_MIP)
+ scsi_esp_cmd(esp, ESP_CMD_MOK);
+
+ scsi_esp_cmd(esp, ESP_CMD_TI);
+ }
+ } else { /* unused, as long as we only handle MIP here */
+ scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+
+ if (esp_count >= ZORRO_ESP_FIFO_SIZE)
+ ZORRO_ESP_PIO_FILL("%0@+,%2@", esp_count)
+ else
+ ZORRO_ESP_PIO_LOOP("%0@+,%2@", esp_count)
+
+ scsi_esp_cmd(esp, cmd);
+
+ while (esp_count) {
+ unsigned int n;
+
+ if (zorro_esp_wait_for_intr(esp))
+ break;
+
+ if ((esp->sreg & ESP_STAT_PMASK) != phase)
+ break;
+
+ esp->ireg = zorro_esp_read8(esp, ESP_INTRPT);
+ if (esp->ireg & ~ESP_INTR_BSERV) {
+ zep->error = 1;
+ break;
+ }
+
+ n = ZORRO_ESP_FIFO_SIZE -
+ (zorro_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES);
+ if (n > esp_count)
+ n = esp_count;
+
+ if (n == ZORRO_ESP_FIFO_SIZE)
+ ZORRO_ESP_PIO_FILL("%0@+,%2@", esp_count)
+ else {
+ esp_count -= n;
+ ZORRO_ESP_PIO_LOOP("%0@+,%2@", n)
+ }
+
+ scsi_esp_cmd(esp, ESP_CMD_TI);
+ }
+ }
+}
+
+/* Blizzard 1230/60 SCSI-IV DMA */
+
+static void zorro_esp_send_blz1230_dma_cmd(struct esp *esp, u32 addr,
+ u32 esp_count, u32 dma_count, int write, u8 cmd)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev);
+ struct blz1230_dma_registers __iomem *dregs = esp->dma_regs;
+ u8 phase = esp->sreg & ESP_STAT_PMASK;
+
+ zep->error = 0;
+ /*
+ * Use PIO if transferring message bytes to esp->command_block_dma.
+ * PIO requires a virtual address, so substitute esp->command_block
+ * for addr.
+ */
+ if (phase == ESP_MIP && addr == esp->command_block_dma) {
+ zorro_esp_send_pio_cmd(esp, (u32) esp->command_block,
+ esp_count, dma_count, write, cmd);
+ return;
+ }
+
+ if (write)
+ /* DMA receive */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_FROM_DEVICE);
+ else
+ /* DMA send */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_TO_DEVICE);
+
+ addr >>= 1;
+ if (write)
+ addr &= ~(DMA_WRITE);
+ else
+ addr |= DMA_WRITE;
+
+ writeb((addr >> 24) & 0xff, &dregs->dma_latch);
+ writeb((addr >> 24) & 0xff, &dregs->dma_addr);
+ writeb((addr >> 16) & 0xff, &dregs->dma_addr);
+ writeb((addr >> 8) & 0xff, &dregs->dma_addr);
+ writeb(addr & 0xff, &dregs->dma_addr);
+
+ scsi_esp_cmd(esp, ESP_CMD_DMA);
+ zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+ zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+ zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
+
+ scsi_esp_cmd(esp, cmd);
+}
+
+/* Blizzard 1230-II DMA */
+
+static void zorro_esp_send_blz1230II_dma_cmd(struct esp *esp, u32 addr,
+ u32 esp_count, u32 dma_count, int write, u8 cmd)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev);
+ struct blz1230II_dma_registers __iomem *dregs = esp->dma_regs;
+ u8 phase = esp->sreg & ESP_STAT_PMASK;
+
+ zep->error = 0;
+ /* Use PIO if transferring message bytes to esp->command_block_dma */
+ if (phase == ESP_MIP && addr == esp->command_block_dma) {
+ zorro_esp_send_pio_cmd(esp, (u32) esp->command_block,
+ esp_count, dma_count, write, cmd);
+ return;
+ }
+
+ if (write)
+ /* DMA receive */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_FROM_DEVICE);
+ else
+ /* DMA send */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_TO_DEVICE);
+
+ addr >>= 1;
+ if (write)
+ addr &= ~(DMA_WRITE);
+ else
+ addr |= DMA_WRITE;
+
+ writeb((addr >> 24) & 0xff, &dregs->dma_latch);
+ writeb((addr >> 16) & 0xff, &dregs->dma_addr);
+ writeb((addr >> 8) & 0xff, &dregs->dma_addr);
+ writeb(addr & 0xff, &dregs->dma_addr);
+
+ scsi_esp_cmd(esp, ESP_CMD_DMA);
+ zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+ zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+ zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
+
+ scsi_esp_cmd(esp, cmd);
+}
+
+/* Blizzard 2060 DMA */
+
+static void zorro_esp_send_blz2060_dma_cmd(struct esp *esp, u32 addr,
+ u32 esp_count, u32 dma_count, int write, u8 cmd)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev);
+ struct blz2060_dma_registers __iomem *dregs = esp->dma_regs;
+ u8 phase = esp->sreg & ESP_STAT_PMASK;
+
+ zep->error = 0;
+ /* Use PIO if transferring message bytes to esp->command_block_dma */
+ if (phase == ESP_MIP && addr == esp->command_block_dma) {
+ zorro_esp_send_pio_cmd(esp, (u32) esp->command_block,
+ esp_count, dma_count, write, cmd);
+ return;
+ }
+
+ if (write)
+ /* DMA receive */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_FROM_DEVICE);
+ else
+ /* DMA send */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_TO_DEVICE);
+
+ addr >>= 1;
+ if (write)
+ addr &= ~(DMA_WRITE);
+ else
+ addr |= DMA_WRITE;
+
+ writeb(addr & 0xff, &dregs->dma_addr3);
+ writeb((addr >> 8) & 0xff, &dregs->dma_addr2);
+ writeb((addr >> 16) & 0xff, &dregs->dma_addr1);
+ writeb((addr >> 24) & 0xff, &dregs->dma_addr0);
+
+ scsi_esp_cmd(esp, ESP_CMD_DMA);
+ zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+ zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+ zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
+
+ scsi_esp_cmd(esp, cmd);
+}
+
+/* Cyberstorm I DMA */
+
+static void zorro_esp_send_cyber_dma_cmd(struct esp *esp, u32 addr,
+ u32 esp_count, u32 dma_count, int write, u8 cmd)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev);
+ struct cyber_dma_registers __iomem *dregs = esp->dma_regs;
+ u8 phase = esp->sreg & ESP_STAT_PMASK;
+ unsigned char *ctrl_data = &zep->ctrl_data;
+
+ zep->error = 0;
+ /* Use PIO if transferring message bytes to esp->command_block_dma */
+ if (phase == ESP_MIP && addr == esp->command_block_dma) {
+ zorro_esp_send_pio_cmd(esp, (u32) esp->command_block,
+ esp_count, dma_count, write, cmd);
+ return;
+ }
+
+ zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+ zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+ zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
+
+ if (write) {
+ /* DMA receive */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_FROM_DEVICE);
+ addr &= ~(1);
+ } else {
+ /* DMA send */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_TO_DEVICE);
+ addr |= 1;
+ }
+
+ writeb((addr >> 24) & 0xff, &dregs->dma_addr0);
+ writeb((addr >> 16) & 0xff, &dregs->dma_addr1);
+ writeb((addr >> 8) & 0xff, &dregs->dma_addr2);
+ writeb(addr & 0xff, &dregs->dma_addr3);
+
+ if (write)
+ *ctrl_data &= ~(CYBER_DMA_WRITE);
+ else
+ *ctrl_data |= CYBER_DMA_WRITE;
+
+ *ctrl_data &= ~(CYBER_DMA_Z3); /* Z2, do 16 bit DMA */
+
+ writeb(*ctrl_data, &dregs->ctrl_reg);
+
+ scsi_esp_cmd(esp, cmd);
+}
+
+/* Cyberstorm II DMA */
+
+static void zorro_esp_send_cyberII_dma_cmd(struct esp *esp, u32 addr,
+ u32 esp_count, u32 dma_count, int write, u8 cmd)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev);
+ struct cyberII_dma_registers __iomem *dregs = esp->dma_regs;
+ u8 phase = esp->sreg & ESP_STAT_PMASK;
+
+ zep->error = 0;
+ /* Use PIO if transferring message bytes to esp->command_block_dma */
+ if (phase == ESP_MIP && addr == esp->command_block_dma) {
+ zorro_esp_send_pio_cmd(esp, (u32) esp->command_block,
+ esp_count, dma_count, write, cmd);
+ return;
+ }
+
+ zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+ zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+ zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
+
+ if (write) {
+ /* DMA receive */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_FROM_DEVICE);
+ addr &= ~(1);
+ } else {
+ /* DMA send */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_TO_DEVICE);
+ addr |= 1;
+ }
+
+ writeb((addr >> 24) & 0xff, &dregs->dma_addr0);
+ writeb((addr >> 16) & 0xff, &dregs->dma_addr1);
+ writeb((addr >> 8) & 0xff, &dregs->dma_addr2);
+ writeb(addr & 0xff, &dregs->dma_addr3);
+
+ scsi_esp_cmd(esp, cmd);
+}
+
+/* Fastlane DMA */
+
+static void zorro_esp_send_fastlane_dma_cmd(struct esp *esp, u32 addr,
+ u32 esp_count, u32 dma_count, int write, u8 cmd)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev);
+ struct fastlane_dma_registers __iomem *dregs = esp->dma_regs;
+ u8 phase = esp->sreg & ESP_STAT_PMASK;
+ unsigned char *ctrl_data = &zep->ctrl_data;
+
+ zep->error = 0;
+ /* Use PIO if transferring message bytes to esp->command_block_dma */
+ if (phase == ESP_MIP && addr == esp->command_block_dma) {
+ zorro_esp_send_pio_cmd(esp, (u32) esp->command_block,
+ esp_count, dma_count, write, cmd);
+ return;
+ }
+
+ zorro_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+ zorro_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+ zorro_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
+
+ if (write) {
+ /* DMA receive */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_FROM_DEVICE);
+ addr &= ~(1);
+ } else {
+ /* DMA send */
+ dma_sync_single_for_device(esp->dev, addr, esp_count,
+ DMA_TO_DEVICE);
+ addr |= 1;
+ }
+
+ writeb(0, &dregs->clear_strobe);
+ z_writel(addr, ((addr & 0x00ffffff) + zep->board_base));
+
+ if (write) {
+ *ctrl_data = (*ctrl_data & FASTLANE_DMA_MASK) |
+ FASTLANE_DMA_ENABLE;
+ } else {
+ *ctrl_data = ((*ctrl_data & FASTLANE_DMA_MASK) |
+ FASTLANE_DMA_ENABLE |
+ FASTLANE_DMA_WRITE);
+ }
+
+ writeb(*ctrl_data, &dregs->ctrl_reg);
+
+ scsi_esp_cmd(esp, cmd);
+}
+
+static int zorro_esp_dma_error(struct esp *esp)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(esp->dev);
+
+ /* check for error in case we've been doing PIO */
+ if (zep->error == 1)
+ return 1;
+
+ /* do nothing - there seems to be no way to check for DMA errors */
+ return 0;
+}
+
+/* per-board ESP driver ops */
+
+static const struct esp_driver_ops blz1230_esp_ops = {
+ .esp_write8 = zorro_esp_write8,
+ .esp_read8 = zorro_esp_read8,
+ .map_single = zorro_esp_map_single,
+ .map_sg = zorro_esp_map_sg,
+ .unmap_single = zorro_esp_unmap_single,
+ .unmap_sg = zorro_esp_unmap_sg,
+ .irq_pending = zorro_esp_irq_pending,
+ .dma_length_limit = zorro_esp_dma_length_limit,
+ .reset_dma = zorro_esp_reset_dma,
+ .dma_drain = zorro_esp_dma_drain,
+ .dma_invalidate = zorro_esp_dma_invalidate,
+ .send_dma_cmd = zorro_esp_send_blz1230_dma_cmd,
+ .dma_error = zorro_esp_dma_error,
+};
+
+static const struct esp_driver_ops blz1230II_esp_ops = {
+ .esp_write8 = zorro_esp_write8,
+ .esp_read8 = zorro_esp_read8,
+ .map_single = zorro_esp_map_single,
+ .map_sg = zorro_esp_map_sg,
+ .unmap_single = zorro_esp_unmap_single,
+ .unmap_sg = zorro_esp_unmap_sg,
+ .irq_pending = zorro_esp_irq_pending,
+ .dma_length_limit = zorro_esp_dma_length_limit,
+ .reset_dma = zorro_esp_reset_dma,
+ .dma_drain = zorro_esp_dma_drain,
+ .dma_invalidate = zorro_esp_dma_invalidate,
+ .send_dma_cmd = zorro_esp_send_blz1230II_dma_cmd,
+ .dma_error = zorro_esp_dma_error,
+};
+
+static const struct esp_driver_ops blz2060_esp_ops = {
+ .esp_write8 = zorro_esp_write8,
+ .esp_read8 = zorro_esp_read8,
+ .map_single = zorro_esp_map_single,
+ .map_sg = zorro_esp_map_sg,
+ .unmap_single = zorro_esp_unmap_single,
+ .unmap_sg = zorro_esp_unmap_sg,
+ .irq_pending = zorro_esp_irq_pending,
+ .dma_length_limit = zorro_esp_dma_length_limit,
+ .reset_dma = zorro_esp_reset_dma,
+ .dma_drain = zorro_esp_dma_drain,
+ .dma_invalidate = zorro_esp_dma_invalidate,
+ .send_dma_cmd = zorro_esp_send_blz2060_dma_cmd,
+ .dma_error = zorro_esp_dma_error,
+};
+
+static const struct esp_driver_ops cyber_esp_ops = {
+ .esp_write8 = zorro_esp_write8,
+ .esp_read8 = zorro_esp_read8,
+ .map_single = zorro_esp_map_single,
+ .map_sg = zorro_esp_map_sg,
+ .unmap_single = zorro_esp_unmap_single,
+ .unmap_sg = zorro_esp_unmap_sg,
+ .irq_pending = cyber_esp_irq_pending,
+ .dma_length_limit = zorro_esp_dma_length_limit,
+ .reset_dma = zorro_esp_reset_dma,
+ .dma_drain = zorro_esp_dma_drain,
+ .dma_invalidate = zorro_esp_dma_invalidate,
+ .send_dma_cmd = zorro_esp_send_cyber_dma_cmd,
+ .dma_error = zorro_esp_dma_error,
+};
+
+static const struct esp_driver_ops cyberII_esp_ops = {
+ .esp_write8 = zorro_esp_write8,
+ .esp_read8 = zorro_esp_read8,
+ .map_single = zorro_esp_map_single,
+ .map_sg = zorro_esp_map_sg,
+ .unmap_single = zorro_esp_unmap_single,
+ .unmap_sg = zorro_esp_unmap_sg,
+ .irq_pending = zorro_esp_irq_pending,
+ .dma_length_limit = zorro_esp_dma_length_limit,
+ .reset_dma = zorro_esp_reset_dma,
+ .dma_drain = zorro_esp_dma_drain,
+ .dma_invalidate = zorro_esp_dma_invalidate,
+ .send_dma_cmd = zorro_esp_send_cyberII_dma_cmd,
+ .dma_error = zorro_esp_dma_error,
+};
+
+static const struct esp_driver_ops fastlane_esp_ops = {
+ .esp_write8 = zorro_esp_write8,
+ .esp_read8 = zorro_esp_read8,
+ .map_single = zorro_esp_map_single,
+ .map_sg = zorro_esp_map_sg,
+ .unmap_single = zorro_esp_unmap_single,
+ .unmap_sg = zorro_esp_unmap_sg,
+ .irq_pending = fastlane_esp_irq_pending,
+ .dma_length_limit = zorro_esp_dma_length_limit,
+ .reset_dma = zorro_esp_reset_dma,
+ .dma_drain = zorro_esp_dma_drain,
+ .dma_invalidate = fastlane_esp_dma_invalidate,
+ .send_dma_cmd = zorro_esp_send_fastlane_dma_cmd,
+ .dma_error = zorro_esp_dma_error,
+};
+
+/* Zorro driver config data */
+
+struct zorro_driver_data {
+ const char *name;
+ unsigned long offset;
+ unsigned long dma_offset;
+ int absolute; /* offset is absolute address */
+ int scsi_option;
+ const struct esp_driver_ops *esp_ops;
+};
+
+/* board types */
+
+enum {
+ ZORRO_BLZ1230,
+ ZORRO_BLZ1230II,
+ ZORRO_BLZ2060,
+ ZORRO_CYBER,
+ ZORRO_CYBERII,
+ ZORRO_FASTLANE,
+};
+
+/* per-board config data */
+
+static const struct zorro_driver_data zorro_esp_boards[] = {
+ [ZORRO_BLZ1230] = {
+ .name = "Blizzard 1230",
+ .offset = 0x8000,
+ .dma_offset = 0x10000,
+ .scsi_option = 1,
+ .esp_ops = &blz1230_esp_ops,
+ },
+ [ZORRO_BLZ1230II] = {
+ .name = "Blizzard 1230II",
+ .offset = 0x10000,
+ .dma_offset = 0x10021,
+ .scsi_option = 1,
+ .esp_ops = &blz1230II_esp_ops,
+ },
+ [ZORRO_BLZ2060] = {
+ .name = "Blizzard 2060",
+ .offset = 0x1ff00,
+ .dma_offset = 0x1ffe0,
+ .esp_ops = &blz2060_esp_ops,
+ },
+ [ZORRO_CYBER] = {
+ .name = "CyberStormI",
+ .offset = 0xf400,
+ .dma_offset = 0xf800,
+ .esp_ops = &cyber_esp_ops,
+ },
+ [ZORRO_CYBERII] = {
+ .name = "CyberStormII",
+ .offset = 0x1ff03,
+ .dma_offset = 0x1ff43,
+ .scsi_option = 1,
+ .esp_ops = &cyberII_esp_ops,
+ },
+ [ZORRO_FASTLANE] = {
+ .name = "Fastlane",
+ .offset = 0x1000001,
+ .dma_offset = 0x1000041,
+ .esp_ops = &fastlane_esp_ops,
+ },
+};
+
+static const struct zorro_device_id zorro_esp_zorro_tbl[] = {
+ { /* Blizzard 1230 IV */
+ .id = ZORRO_ID(PHASE5, 0x11, 0),
+ .driver_data = ZORRO_BLZ1230,
+ },
+ { /* Blizzard 1230 II (Zorro II) or Fastlane (Zorro III) */
+ .id = ZORRO_ID(PHASE5, 0x0B, 0),
+ .driver_data = ZORRO_BLZ1230II,
+ },
+ { /* Blizzard 2060 */
+ .id = ZORRO_ID(PHASE5, 0x18, 0),
+ .driver_data = ZORRO_BLZ2060,
+ },
+ { /* Cyberstorm */
+ .id = ZORRO_ID(PHASE5, 0x0C, 0),
+ .driver_data = ZORRO_CYBER,
+ },
+ { /* Cyberstorm II */
+ .id = ZORRO_ID(PHASE5, 0x19, 0),
+ .driver_data = ZORRO_CYBERII,
+ },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(zorro, zorro_esp_zorro_tbl);
+
+static int zorro_esp_probe(struct zorro_dev *z,
+ const struct zorro_device_id *ent)
+{
+ struct scsi_host_template *tpnt = &scsi_esp_template;
+ struct Scsi_Host *host;
+ struct esp *esp;
+ const struct zorro_driver_data *zdd;
+ struct zorro_esp_priv *zep;
+ unsigned long board, ioaddr, dmaaddr;
+ int err;
+
+ board = zorro_resource_start(z);
+ zdd = &zorro_esp_boards[ent->driver_data];
+
+ pr_info("%s found at address 0x%lx.\n", zdd->name, board);
+
+ zep = kzalloc(sizeof(*zep), GFP_KERNEL);
+ if (!zep) {
+ pr_err("Can't allocate device private data!\n");
+ return -ENOMEM;
+ }
+
+ /* let's figure out whether we have a Zorro II or Zorro III board */
+ if ((z->rom.er_Type & ERT_TYPEMASK) == ERT_ZORROIII) {
+ if (board > 0xffffff)
+ zep->zorro3 = 1;
+ } else {
+ /*
+ * Even though most of these boards identify as Zorro II,
+ * they are in fact CPU expansion slot boards and have full
+ * access to all of memory. Fix up DMA bitmask here.
+ */
+ z->dev.coherent_dma_mask = DMA_BIT_MASK(32);
+ }
+
+ /*
+ * If Zorro III and ID matches Fastlane, our device table entry
+ * contains data for the Blizzard 1230 II board which does share the
+ * same ID. Fix up device table entry here.
+ * TODO: Some Cyberstom060 boards also share this ID but would need
+ * to use the Cyberstorm I driver data ... we catch this by checking
+ * for presence of ESP chip later, but don't try to fix up yet.
+ */
+ if (zep->zorro3 && ent->driver_data == ZORRO_BLZ1230II) {
+ pr_info("%s at address 0x%lx is Fastlane Z3, fixing data!\n",
+ zdd->name, board);
+ zdd = &zorro_esp_boards[ZORRO_FASTLANE];
+ }
+
+ if (zdd->absolute) {
+ ioaddr = zdd->offset;
+ dmaaddr = zdd->dma_offset;
+ } else {
+ ioaddr = board + zdd->offset;
+ dmaaddr = board + zdd->dma_offset;
+ }
+
+ if (!zorro_request_device(z, zdd->name)) {
+ pr_err("cannot reserve region 0x%lx, abort\n",
+ board);
+ err = -EBUSY;
+ goto fail_free_zep;
+ }
+
+ host = scsi_host_alloc(tpnt, sizeof(struct esp));
+
+ if (!host) {
+ pr_err("No host detected; board configuration problem?\n");
+ err = -ENOMEM;
+ goto fail_release_device;
+ }
+
+ host->base = ioaddr;
+ host->this_id = 7;
+
+ esp = shost_priv(host);
+ esp->host = host;
+ esp->dev = &z->dev;
+
+ esp->scsi_id = host->this_id;
+ esp->scsi_id_mask = (1 << esp->scsi_id);
+
+ esp->cfreq = 40000000;
+
+ zep->esp = esp;
+
+ dev_set_drvdata(esp->dev, zep);
+
+ /* additional setup required for Fastlane */
+ if (zep->zorro3 && ent->driver_data == ZORRO_BLZ1230II) {
+ /* map full address space up to ESP base for DMA */
+ zep->board_base = ioremap_nocache(board,
+ FASTLANE_ESP_ADDR-1);
+ if (!zep->board_base) {
+ pr_err("Cannot allocate board address space\n");
+ err = -ENOMEM;
+ goto fail_free_host;
+ }
+ /* initialize DMA control shadow register */
+ zep->ctrl_data = (FASTLANE_DMA_FCODE |
+ FASTLANE_DMA_EDI | FASTLANE_DMA_ESI);
+ }
+
+ esp->ops = zdd->esp_ops;
+
+ if (ioaddr > 0xffffff)
+ esp->regs = ioremap_nocache(ioaddr, 0x20);
+ else
+ /* ZorroII address space remapped nocache by early startup */
+ esp->regs = ZTWO_VADDR(ioaddr);
+
+ if (!esp->regs) {
+ err = -ENOMEM;
+ goto fail_unmap_fastlane;
+ }
+
+ /* Check whether a Blizzard 12x0 or CyberstormII really has SCSI */
+ if (zdd->scsi_option) {
+ zorro_esp_write8(esp, (ESP_CONFIG1_PENABLE | 7), ESP_CFG1);
+ if (zorro_esp_read8(esp, ESP_CFG1) != (ESP_CONFIG1_PENABLE|7)) {
+ err = -ENODEV;
+ goto fail_unmap_regs;
+ }
+ }
+
+ if (zep->zorro3) {
+ /*
+ * Only Fastlane Z3 for now - add switch for correct struct
+ * dma_registers size if adding any more
+ */
+ esp->dma_regs = ioremap_nocache(dmaaddr,
+ sizeof(struct fastlane_dma_registers));
+ } else
+ /* ZorroII address space remapped nocache by early startup */
+ esp->dma_regs = ZTWO_VADDR(dmaaddr);
+
+ if (!esp->dma_regs) {
+ err = -ENOMEM;
+ goto fail_unmap_regs;
+ }
+
+ esp->command_block = dma_alloc_coherent(esp->dev, 16,
+ &esp->command_block_dma,
+ GFP_KERNEL);
+
+ if (!esp->command_block) {
+ err = -ENOMEM;
+ goto fail_unmap_dma_regs;
+ }
+
+ host->irq = IRQ_AMIGA_PORTS;
+ err = request_irq(host->irq, scsi_esp_intr, IRQF_SHARED,
+ "Amiga Zorro ESP", esp);
+ if (err < 0) {
+ err = -ENODEV;
+ goto fail_free_command_block;
+ }
+
+ /* register the chip */
+ err = scsi_esp_register(esp, &z->dev);
+
+ if (err) {
+ err = -ENOMEM;
+ goto fail_free_irq;
+ }
+
+ return 0;
+
+fail_free_irq:
+ free_irq(host->irq, esp);
+
+fail_free_command_block:
+ dma_free_coherent(esp->dev, 16,
+ esp->command_block,
+ esp->command_block_dma);
+
+fail_unmap_dma_regs:
+ if (zep->zorro3)
+ iounmap(esp->dma_regs);
+
+fail_unmap_regs:
+ if (ioaddr > 0xffffff)
+ iounmap(esp->regs);
+
+fail_unmap_fastlane:
+ if (zep->zorro3)
+ iounmap(zep->board_base);
+
+fail_free_host:
+ scsi_host_put(host);
+
+fail_release_device:
+ zorro_release_device(z);
+
+fail_free_zep:
+ kfree(zep);
+
+ return err;
+}
+
+static void zorro_esp_remove(struct zorro_dev *z)
+{
+ struct zorro_esp_priv *zep = dev_get_drvdata(&z->dev);
+ struct esp *esp = zep->esp;
+ struct Scsi_Host *host = esp->host;
+
+ scsi_esp_unregister(esp);
+
+ free_irq(host->irq, esp);
+ dma_free_coherent(esp->dev, 16,
+ esp->command_block,
+ esp->command_block_dma);
+
+ if (zep->zorro3) {
+ iounmap(zep->board_base);
+ iounmap(esp->dma_regs);
+ }
+
+ if (host->base > 0xffffff)
+ iounmap(esp->regs);
+
+ scsi_host_put(host);
+
+ zorro_release_device(z);
+
+ kfree(zep);
+}
+
+static struct zorro_driver zorro_esp_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = zorro_esp_zorro_tbl,
+ .probe = zorro_esp_probe,
+ .remove = zorro_esp_remove,
+};
+
+static int __init zorro_esp_scsi_init(void)
+{
+ return zorro_register_driver(&zorro_esp_driver);
+}
+
+static void __exit zorro_esp_scsi_exit(void)
+{
+ zorro_unregister_driver(&zorro_esp_driver);
+}
+
+module_init(zorro_esp_scsi_init);
+module_exit(zorro_esp_scsi_exit);
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
index 7442bc1..eeb028b 100644
--- a/drivers/sh/clk/cpg.c
+++ b/drivers/sh/clk/cpg.c
@@ -249,7 +249,7 @@ static int __init sh_clk_div_register_ops(struct clk *clks, int nr,
int k;
freq_table_size *= (nr_divs + 1);
- freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
+ freq_table = kcalloc(nr, freq_table_size, GFP_KERNEL);
if (!freq_table) {
pr_err("%s: unable to alloc memory\n", __func__);
return -ENOMEM;
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
index 8e72bcb..46f0f32 100644
--- a/drivers/sh/intc/core.c
+++ b/drivers/sh/intc/core.c
@@ -203,7 +203,7 @@ int __init register_intc_controller(struct intc_desc *desc)
if (desc->num_resources) {
d->nr_windows = desc->num_resources;
- d->window = kzalloc(d->nr_windows * sizeof(*d->window),
+ d->window = kcalloc(d->nr_windows, sizeof(*d->window),
GFP_NOWAIT);
if (!d->window)
goto err1;
@@ -230,12 +230,12 @@ int __init register_intc_controller(struct intc_desc *desc)
d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0;
d->nr_reg += hw->subgroups ? hw->nr_subgroups : 0;
- d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT);
+ d->reg = kcalloc(d->nr_reg, sizeof(*d->reg), GFP_NOWAIT);
if (!d->reg)
goto err2;
#ifdef CONFIG_SMP
- d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT);
+ d->smp = kcalloc(d->nr_reg, sizeof(*d->smp), GFP_NOWAIT);
if (!d->smp)
goto err3;
#endif
@@ -253,7 +253,7 @@ int __init register_intc_controller(struct intc_desc *desc)
}
if (hw->prio_regs) {
- d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio),
+ d->prio = kcalloc(hw->nr_vectors, sizeof(*d->prio),
GFP_NOWAIT);
if (!d->prio)
goto err4;
@@ -269,7 +269,7 @@ int __init register_intc_controller(struct intc_desc *desc)
}
if (hw->sense_regs) {
- d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense),
+ d->sense = kcalloc(hw->nr_vectors, sizeof(*d->sense),
GFP_NOWAIT);
if (!d->sense)
goto err5;
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c
index 7525039..2e45988 100644
--- a/drivers/sh/maple/maple.c
+++ b/drivers/sh/maple/maple.c
@@ -161,7 +161,7 @@ int maple_add_packet(struct maple_device *mdev, u32 function, u32 command,
void *sendbuf = NULL;
if (length) {
- sendbuf = kzalloc(length * 4, GFP_KERNEL);
+ sendbuf = kcalloc(length, 4, GFP_KERNEL);
if (!sendbuf) {
ret = -ENOMEM;
goto out;
diff --git a/drivers/slimbus/qcom-ctrl.c b/drivers/slimbus/qcom-ctrl.c
index bb36a8f..db1f513 100644
--- a/drivers/slimbus/qcom-ctrl.c
+++ b/drivers/slimbus/qcom-ctrl.c
@@ -540,7 +540,7 @@ static int qcom_slim_probe(struct platform_device *pdev)
ctrl->tx.sl_sz = SLIM_MSGQ_BUF_LEN;
ctrl->rx.n = QCOM_RX_MSGS;
ctrl->rx.sl_sz = SLIM_MSGQ_BUF_LEN;
- ctrl->wr_comp = kzalloc(sizeof(struct completion *) * QCOM_TX_MSGS,
+ ctrl->wr_comp = kcalloc(QCOM_TX_MSGS, sizeof(struct completion *),
GFP_KERNEL);
if (!ctrl->wr_comp)
return -ENOMEM;
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 4052357..113e884 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_ARCH_MXC) += imx/
obj-$(CONFIG_SOC_XWAY) += lantiq/
obj-y += mediatek/
obj-$(CONFIG_ARCH_MESON) += amlogic/
-obj-$(CONFIG_ARCH_QCOM) += qcom/
+obj-y += qcom/
obj-y += renesas/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
obj-$(CONFIG_SOC_SAMSUNG) += samsung/
diff --git a/drivers/soc/bcm/raspberrypi-power.c b/drivers/soc/bcm/raspberrypi-power.c
index f7ed118..a78dfe0 100644
--- a/drivers/soc/bcm/raspberrypi-power.c
+++ b/drivers/soc/bcm/raspberrypi-power.c
@@ -165,8 +165,10 @@ static int rpi_power_probe(struct platform_device *pdev)
return -ENOMEM;
rpi_domains->xlate.domains =
- devm_kzalloc(dev, sizeof(*rpi_domains->xlate.domains) *
- RPI_POWER_DOMAIN_COUNT, GFP_KERNEL);
+ devm_kcalloc(dev,
+ RPI_POWER_DOMAIN_COUNT,
+ sizeof(*rpi_domains->xlate.domains),
+ GFP_KERNEL);
if (!rpi_domains->xlate.domains)
return -ENOMEM;
diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c
index ba3cfa8..ecb2274 100644
--- a/drivers/soc/fsl/qbman/qman.c
+++ b/drivers/soc/fsl/qbman/qman.c
@@ -1021,7 +1021,8 @@ int qman_alloc_fq_table(u32 _num_fqids)
{
num_fqids = _num_fqids;
- fq_table = vzalloc(num_fqids * 2 * sizeof(struct qman_fq *));
+ fq_table = vzalloc(array3_size(sizeof(struct qman_fq *),
+ num_fqids, 2));
if (!fq_table)
return -ENOMEM;
@@ -1181,7 +1182,7 @@ static int qman_create_portal(struct qman_portal *portal,
qm_dqrr_set_ithresh(p, QMAN_PIRQ_DQRR_ITHRESH);
qm_mr_set_ithresh(p, QMAN_PIRQ_MR_ITHRESH);
qm_out(p, QM_REG_ITPR, QMAN_PIRQ_IPERIOD);
- portal->cgrs = kmalloc(2 * sizeof(*cgrs), GFP_KERNEL);
+ portal->cgrs = kmalloc_array(2, sizeof(*cgrs), GFP_KERNEL);
if (!portal->cgrs)
goto fail_cgrs;
/* initial snapshot is no-depletion */
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
index c4d35f3..32f0748 100644
--- a/drivers/soc/imx/gpc.c
+++ b/drivers/soc/imx/gpc.c
@@ -443,17 +443,25 @@ static int imx_gpc_probe(struct platform_device *pdev)
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;
+
+ ret = platform_device_add_data(pd_pdev,
+ &imx_gpc_domains[domain_index],
+ sizeof(imx_gpc_domains[domain_index]));
+ if (ret) {
+ platform_device_put(pd_pdev);
+ of_node_put(np);
+ return ret;
+ }
+ domain = pd_pdev->dev.platform_data;
+ domain->regmap = regmap;
+ domain->ipg_rate_mhz = ipg_rate_mhz;
+
pd_pdev->dev.parent = &pdev->dev;
pd_pdev->dev.of_node = np;
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index afc7ecc..f4e3bd4 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -155,7 +155,7 @@ 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[] = {
+static const struct imx7_pgc_domain imx7_pgc_domains[] = {
[IMX7_POWER_DOMAIN_MIPI_PHY] = {
.genpd = {
.name = "mipi-phy",
@@ -321,11 +321,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
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) {
@@ -334,7 +329,20 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
return -ENOMEM;
}
- pd_pdev->dev.platform_data = domain;
+ ret = platform_device_add_data(pd_pdev,
+ &imx7_pgc_domains[domain_index],
+ sizeof(imx7_pgc_domains[domain_index]));
+ if (ret) {
+ platform_device_put(pd_pdev);
+ of_node_put(np);
+ return ret;
+ }
+
+ domain = pd_pdev->dev.platform_data;
+ 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->dev.parent = dev;
pd_pdev->dev.of_node = np;
diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c
index 8c310de..958861c 100644
--- a/drivers/soc/mediatek/mtk-infracfg.c
+++ b/drivers/soc/mediatek/mtk-infracfg.c
@@ -17,6 +17,9 @@
#include <linux/soc/mediatek/infracfg.h>
#include <asm/processor.h>
+#define MTK_POLL_DELAY_US 10
+#define MTK_POLL_TIMEOUT (jiffies_to_usecs(HZ))
+
#define INFRA_TOPAXI_PROTECTEN 0x0220
#define INFRA_TOPAXI_PROTECTSTA1 0x0228
#define INFRA_TOPAXI_PROTECTEN_SET 0x0260
@@ -37,7 +40,6 @@
int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
bool reg_update)
{
- unsigned long expired;
u32 val;
int ret;
@@ -47,22 +49,11 @@ int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
else
regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask);
- expired = jiffies + HZ;
-
- while (1) {
- ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
- if (ret)
- return ret;
-
- if ((val & mask) == mask)
- break;
+ ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1,
+ val, (val & mask) == mask,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
- cpu_relax();
- if (time_after(jiffies, expired))
- return -EIO;
- }
-
- return 0;
+ return ret;
}
/**
@@ -80,30 +71,17 @@ int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
bool reg_update)
{
- unsigned long expired;
int ret;
+ u32 val;
if (reg_update)
regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0);
else
regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_CLR, mask);
- expired = jiffies + HZ;
-
- while (1) {
- u32 val;
-
- ret = regmap_read(infracfg, INFRA_TOPAXI_PROTECTSTA1, &val);
- if (ret)
- return ret;
-
- if (!(val & mask))
- break;
-
- cpu_relax();
- if (time_after(jiffies, expired))
- return -EIO;
- }
+ ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1,
+ val, !(val & mask),
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
- return 0;
+ return ret;
}
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index e9e054a..2afae64 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -1458,19 +1458,12 @@ static int pwrap_probe(struct platform_device *pdev)
int ret, irq;
struct pmic_wrapper *wrp;
struct device_node *np = pdev->dev.of_node;
- const struct of_device_id *of_id =
- of_match_device(of_pwrap_match_tbl, &pdev->dev);
const struct of_device_id *of_slave_id = NULL;
struct resource *res;
- if (!of_id) {
- dev_err(&pdev->dev, "Error: No device match found\n");
- return -ENODEV;
- }
+ if (np->child)
+ of_slave_id = of_match_node(of_slave_match_tbl, np->child);
- if (pdev->dev.of_node->child)
- of_slave_id = of_match_node(of_slave_match_tbl,
- pdev->dev.of_node->child);
if (!of_slave_id) {
dev_dbg(&pdev->dev, "slave pmic should be defined in dts\n");
return -EINVAL;
@@ -1482,7 +1475,7 @@ static int pwrap_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, wrp);
- wrp->master = of_id->data;
+ wrp->master = of_device_get_match_data(&pdev->dev);
wrp->slave = of_slave_id->data;
wrp->dev = &pdev->dev;
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index d762a46..5b24bb4 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -13,6 +13,7 @@
#include <linux/clk.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/mfd/syscon.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -27,6 +28,13 @@
#include <dt-bindings/power/mt7623a-power.h>
#include <dt-bindings/power/mt8173-power.h>
+#define MTK_POLL_DELAY_US 10
+#define MTK_POLL_TIMEOUT (jiffies_to_usecs(HZ))
+
+#define MTK_SCPD_ACTIVE_WAKEUP BIT(0)
+#define MTK_SCPD_FWAIT_SRAM BIT(1)
+#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x))
+
#define SPM_VDE_PWR_CON 0x0210
#define SPM_MFG_PWR_CON 0x0214
#define SPM_VEN_PWR_CON 0x0230
@@ -116,7 +124,7 @@ struct scp_domain_data {
u32 sram_pdn_ack_bits;
u32 bus_prot_mask;
enum clk_id clk_id[MAX_CLKS];
- bool active_wakeup;
+ u8 caps;
};
struct scp;
@@ -184,12 +192,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
{
struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
struct scp *scp = scpd->scp;
- unsigned long timeout;
- bool expired;
void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
- u32 sram_pdn_ack = scpd->data->sram_pdn_ack_bits;
+ u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
u32 val;
- int ret;
+ int ret, tmp;
int i;
if (scpd->supply) {
@@ -215,23 +221,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
writel(val, ctl_addr);
/* wait until PWR_ACK = 1 */
- timeout = jiffies + HZ;
- expired = false;
- while (1) {
- ret = scpsys_domain_is_on(scpd);
- if (ret > 0)
- break;
-
- if (expired) {
- ret = -ETIMEDOUT;
- goto err_pwr_ack;
- }
-
- cpu_relax();
-
- if (time_after(jiffies, timeout))
- expired = true;
- }
+ ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp > 0,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ goto err_pwr_ack;
val &= ~PWR_CLK_DIS_BIT;
writel(val, ctl_addr);
@@ -245,20 +238,20 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
val &= ~scpd->data->sram_pdn_bits;
writel(val, ctl_addr);
- /* wait until SRAM_PDN_ACK all 0 */
- timeout = jiffies + HZ;
- expired = false;
- while (sram_pdn_ack && (readl(ctl_addr) & sram_pdn_ack)) {
+ /* Either wait until SRAM_PDN_ACK all 0 or have a force wait */
+ if (MTK_SCPD_CAPS(scpd, MTK_SCPD_FWAIT_SRAM)) {
+ /*
+ * Currently, MTK_SCPD_FWAIT_SRAM is necessary only for
+ * MT7622_POWER_DOMAIN_WB and thus just a trivial setup is
+ * applied here.
+ */
+ usleep_range(12000, 12100);
- if (expired) {
- ret = -ETIMEDOUT;
+ } else {
+ ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == 0,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret < 0)
goto err_pwr_ack;
- }
-
- cpu_relax();
-
- if (time_after(jiffies, timeout))
- expired = true;
}
if (scpd->data->bus_prot_mask) {
@@ -289,12 +282,10 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
{
struct scp_domain *scpd = container_of(genpd, struct scp_domain, genpd);
struct scp *scp = scpd->scp;
- unsigned long timeout;
- bool expired;
void __iomem *ctl_addr = scp->base + scpd->data->ctl_offs;
u32 pdn_ack = scpd->data->sram_pdn_ack_bits;
u32 val;
- int ret;
+ int ret, tmp;
int i;
if (scpd->data->bus_prot_mask) {
@@ -310,19 +301,10 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
writel(val, ctl_addr);
/* wait until SRAM_PDN_ACK all 1 */
- timeout = jiffies + HZ;
- expired = false;
- while (pdn_ack && (readl(ctl_addr) & pdn_ack) != pdn_ack) {
- if (expired) {
- ret = -ETIMEDOUT;
- goto out;
- }
-
- cpu_relax();
-
- if (time_after(jiffies, timeout))
- expired = true;
- }
+ ret = readl_poll_timeout(ctl_addr, tmp, (tmp & pdn_ack) == pdn_ack,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ goto out;
val |= PWR_ISO_BIT;
writel(val, ctl_addr);
@@ -340,23 +322,10 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
writel(val, ctl_addr);
/* wait until PWR_ACK = 0 */
- timeout = jiffies + HZ;
- expired = false;
- while (1) {
- ret = scpsys_domain_is_on(scpd);
- if (ret == 0)
- break;
-
- if (expired) {
- ret = -ETIMEDOUT;
- goto out;
- }
-
- cpu_relax();
-
- if (time_after(jiffies, timeout))
- expired = true;
- }
+ ret = readx_poll_timeout(scpsys_domain_is_on, scpd, tmp, tmp == 0,
+ MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
+ if (ret < 0)
+ goto out;
for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
clk_disable_unprepare(scpd->clk[i]);
@@ -407,15 +376,15 @@ static struct scp *init_scp(struct platform_device *pdev,
if (IS_ERR(scp->base))
return ERR_CAST(scp->base);
- scp->domains = devm_kzalloc(&pdev->dev,
- sizeof(*scp->domains) * num, GFP_KERNEL);
+ scp->domains = devm_kcalloc(&pdev->dev,
+ num, sizeof(*scp->domains), GFP_KERNEL);
if (!scp->domains)
return ERR_PTR(-ENOMEM);
pd_data = &scp->pd_data;
- pd_data->domains = devm_kzalloc(&pdev->dev,
- sizeof(*pd_data->domains) * num, GFP_KERNEL);
+ pd_data->domains = devm_kcalloc(&pdev->dev,
+ num, sizeof(*pd_data->domains), GFP_KERNEL);
if (!pd_data->domains)
return ERR_PTR(-ENOMEM);
@@ -469,7 +438,7 @@ static struct scp *init_scp(struct platform_device *pdev,
genpd->name = data->name;
genpd->power_off = scpsys_power_off;
genpd->power_on = scpsys_power_on;
- if (scpd->data->active_wakeup)
+ if (MTK_SCPD_CAPS(scpd, MTK_SCPD_ACTIVE_WAKEUP))
genpd->flags |= GENPD_FLAG_ACTIVE_WAKEUP;
}
@@ -522,7 +491,7 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = {
.bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
MT2701_TOP_AXI_PROT_EN_CONN_S,
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2701_POWER_DOMAIN_DISP] = {
.name = "disp",
@@ -531,7 +500,7 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = {
.sram_pdn_bits = GENMASK(11, 8),
.clk_id = {CLK_MM},
.bus_prot_mask = MT2701_TOP_AXI_PROT_EN_MM_M0,
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2701_POWER_DOMAIN_MFG] = {
.name = "mfg",
@@ -540,7 +509,7 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_MFG},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2701_POWER_DOMAIN_VDEC] = {
.name = "vdec",
@@ -549,7 +518,7 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_MM},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2701_POWER_DOMAIN_ISP] = {
.name = "isp",
@@ -558,7 +527,7 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.clk_id = {CLK_MM},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2701_POWER_DOMAIN_BDP] = {
.name = "bdp",
@@ -566,7 +535,7 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = {
.ctl_offs = SPM_BDP_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2701_POWER_DOMAIN_ETH] = {
.name = "eth",
@@ -575,7 +544,7 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_ETHIF},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2701_POWER_DOMAIN_HIF] = {
.name = "hif",
@@ -584,14 +553,14 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_ETHIF},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2701_POWER_DOMAIN_IFR_MSC] = {
.name = "ifr_msc",
.sta_mask = PWR_STATUS_IFR_MSC,
.ctl_offs = SPM_IFR_MSC_PWR_CON,
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
};
@@ -606,7 +575,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_MM},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2712_POWER_DOMAIN_VDEC] = {
.name = "vdec",
@@ -615,7 +584,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.clk_id = {CLK_MM, CLK_VDEC},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2712_POWER_DOMAIN_VENC] = {
.name = "venc",
@@ -624,7 +593,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_MM, CLK_VENC, CLK_JPGDEC},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2712_POWER_DOMAIN_ISP] = {
.name = "isp",
@@ -633,7 +602,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.clk_id = {CLK_MM},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2712_POWER_DOMAIN_AUDIO] = {
.name = "audio",
@@ -642,7 +611,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_AUDIO},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2712_POWER_DOMAIN_USB] = {
.name = "usb",
@@ -651,7 +620,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_bits = GENMASK(10, 8),
.sram_pdn_ack_bits = GENMASK(14, 12),
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2712_POWER_DOMAIN_USB2] = {
.name = "usb2",
@@ -660,7 +629,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_bits = GENMASK(10, 8),
.sram_pdn_ack_bits = GENMASK(14, 12),
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2712_POWER_DOMAIN_MFG] = {
.name = "mfg",
@@ -670,7 +639,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_ack_bits = GENMASK(16, 16),
.clk_id = {CLK_MFG},
.bus_prot_mask = BIT(14) | BIT(21) | BIT(23),
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2712_POWER_DOMAIN_MFG_SC1] = {
.name = "mfg_sc1",
@@ -679,7 +648,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(16, 16),
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2712_POWER_DOMAIN_MFG_SC2] = {
.name = "mfg_sc2",
@@ -688,7 +657,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(16, 16),
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT2712_POWER_DOMAIN_MFG_SC3] = {
.name = "mfg_sc3",
@@ -697,7 +666,7 @@ static const struct scp_domain_data scp_domain_data_mt2712[] = {
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(16, 16),
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
};
@@ -797,7 +766,7 @@ static const struct scp_domain_data scp_domain_data_mt7622[] = {
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_NONE},
.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS,
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT7622_POWER_DOMAIN_HIF0] = {
.name = "hif0",
@@ -807,7 +776,7 @@ static const struct scp_domain_data scp_domain_data_mt7622[] = {
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_HIFSEL},
.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0,
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT7622_POWER_DOMAIN_HIF1] = {
.name = "hif1",
@@ -817,7 +786,7 @@ static const struct scp_domain_data scp_domain_data_mt7622[] = {
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_HIFSEL},
.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1,
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT7622_POWER_DOMAIN_WB] = {
.name = "wb",
@@ -827,7 +796,7 @@ static const struct scp_domain_data scp_domain_data_mt7622[] = {
.sram_pdn_ack_bits = 0,
.clk_id = {CLK_NONE},
.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB,
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP | MTK_SCPD_FWAIT_SRAM,
},
};
@@ -843,7 +812,7 @@ static const struct scp_domain_data scp_domain_data_mt7623a[] = {
.bus_prot_mask = MT2701_TOP_AXI_PROT_EN_CONN_M |
MT2701_TOP_AXI_PROT_EN_CONN_S,
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT7623A_POWER_DOMAIN_ETH] = {
.name = "eth",
@@ -852,7 +821,7 @@ static const struct scp_domain_data scp_domain_data_mt7623a[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_ETHIF},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT7623A_POWER_DOMAIN_HIF] = {
.name = "hif",
@@ -861,14 +830,14 @@ static const struct scp_domain_data scp_domain_data_mt7623a[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_ETHIF},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT7623A_POWER_DOMAIN_IFR_MSC] = {
.name = "ifr_msc",
.sta_mask = PWR_STATUS_IFR_MSC,
.ctl_offs = SPM_IFR_MSC_PWR_CON,
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
};
@@ -934,7 +903,7 @@ static const struct scp_domain_data scp_domain_data_mt8173[] = {
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_NONE},
- .active_wakeup = true,
+ .caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT8173_POWER_DOMAIN_MFG_ASYNC] = {
.name = "mfg_async",
@@ -1067,15 +1036,13 @@ static const struct of_device_id of_scpsys_match_tbl[] = {
static int scpsys_probe(struct platform_device *pdev)
{
- const struct of_device_id *match;
const struct scp_subdomain *sd;
const struct scp_soc_data *soc;
struct scp *scp;
struct genpd_onecell_data *pd_data;
int i, ret;
- match = of_match_device(of_scpsys_match_tbl, &pdev->dev);
- soc = (const struct scp_soc_data *)match->data;
+ soc = of_device_get_match_data(&pdev->dev);
scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs,
soc->bus_prot_reg_update);
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index d053f26..9dc02f3 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -3,6 +3,24 @@
#
menu "Qualcomm SoC drivers"
+config QCOM_COMMAND_DB
+ bool "Qualcomm Command DB"
+ depends on (ARCH_QCOM && OF) || COMPILE_TEST
+ help
+ Command DB queries shared memory by key string for shared system
+ resources. Platform drivers that require to set state of a shared
+ resource on a RPM-hardened platform must use this database to get
+ SoC specific identifier and information for the shared resources.
+
+config QCOM_GENI_SE
+ tristate "QCOM GENI Serial Engine Driver"
+ depends on ARCH_QCOM || COMPILE_TEST
+ help
+ This driver is used to manage Generic Interface (GENI) firmware based
+ Qualcomm Technologies, Inc. Universal Peripheral (QUP) Wrapper. This
+ driver is also used to manage the common aspects of multiple Serial
+ Engines present in the QUP.
+
config QCOM_GLINK_SSR
tristate "Qualcomm Glink SSR driver"
depends on RPMSG
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 39de5de..19dcf95 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o
+obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
obj-$(CONFIG_QCOM_GLINK_SSR) += glink_ssr.o
obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
new file mode 100644
index 0000000..a6f6462
--- /dev/null
+++ b/drivers/soc/qcom/cmd-db.c
@@ -0,0 +1,317 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include <soc/qcom/cmd-db.h>
+
+#define NUM_PRIORITY 2
+#define MAX_SLV_ID 8
+#define SLAVE_ID_MASK 0x7
+#define SLAVE_ID_SHIFT 16
+
+/**
+ * struct entry_header: header for each entry in cmddb
+ *
+ * @id: resource's identifier
+ * @priority: unused
+ * @addr: the address of the resource
+ * @len: length of the data
+ * @offset: offset from :@data_offset, start of the data
+ */
+struct entry_header {
+ u8 id[8];
+ __le32 priority[NUM_PRIORITY];
+ __le32 addr;
+ __le16 len;
+ __le16 offset;
+};
+
+/**
+ * struct rsc_hdr: resource header information
+ *
+ * @slv_id: id for the resource
+ * @header_offset: entry's header at offset from the end of the cmd_db_header
+ * @data_offset: entry's data at offset from the end of the cmd_db_header
+ * @cnt: number of entries for HW type
+ * @version: MSB is major, LSB is minor
+ * @reserved: reserved for future use.
+ */
+struct rsc_hdr {
+ __le16 slv_id;
+ __le16 header_offset;
+ __le16 data_offset;
+ __le16 cnt;
+ __le16 version;
+ __le16 reserved[3];
+};
+
+/**
+ * struct cmd_db_header: The DB header information
+ *
+ * @version: The cmd db version
+ * @magic: constant expected in the database
+ * @header: array of resources
+ * @checksum: checksum for the header. Unused.
+ * @reserved: reserved memory
+ * @data: driver specific data
+ */
+struct cmd_db_header {
+ __le32 version;
+ u8 magic[4];
+ struct rsc_hdr header[MAX_SLV_ID];
+ __le32 checksum;
+ __le32 reserved;
+ u8 data[];
+};
+
+/**
+ * DOC: Description of the Command DB database.
+ *
+ * At the start of the command DB memory is the cmd_db_header structure.
+ * The cmd_db_header holds the version, checksum, magic key as well as an
+ * array for header for each slave (depicted by the rsc_header). Each h/w
+ * based accelerator is a 'slave' (shared resource) and has slave id indicating
+ * the type of accelerator. The rsc_header is the header for such individual
+ * slaves of a given type. The entries for each of these slaves begin at the
+ * rsc_hdr.header_offset. In addition each slave could have auxiliary data
+ * that may be needed by the driver. The data for the slave starts at the
+ * entry_header.offset to the location pointed to by the rsc_hdr.data_offset.
+ *
+ * Drivers have a stringified key to a slave/resource. They can query the slave
+ * information and get the slave id and the auxiliary data and the length of the
+ * data. Using this information, they can format the request to be sent to the
+ * h/w accelerator and request a resource state.
+ */
+
+static const u8 CMD_DB_MAGIC[] = { 0xdb, 0x30, 0x03, 0x0c };
+
+static bool cmd_db_magic_matches(const struct cmd_db_header *header)
+{
+ const u8 *magic = header->magic;
+
+ return memcmp(magic, CMD_DB_MAGIC, ARRAY_SIZE(CMD_DB_MAGIC)) == 0;
+}
+
+static struct cmd_db_header *cmd_db_header;
+
+
+static inline void *rsc_to_entry_header(struct rsc_hdr *hdr)
+{
+ u16 offset = le16_to_cpu(hdr->header_offset);
+
+ return cmd_db_header->data + offset;
+}
+
+static inline void *
+rsc_offset(struct rsc_hdr *hdr, struct entry_header *ent)
+{
+ u16 offset = le16_to_cpu(hdr->data_offset);
+ u16 loffset = le16_to_cpu(ent->offset);
+
+ return cmd_db_header->data + offset + loffset;
+}
+
+/**
+ * cmd_db_ready - Indicates if command DB is available
+ *
+ * Return: 0 on success, errno otherwise
+ */
+int cmd_db_ready(void)
+{
+ if (cmd_db_header == NULL)
+ return -EPROBE_DEFER;
+ else if (!cmd_db_magic_matches(cmd_db_header))
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL(cmd_db_ready);
+
+static int cmd_db_get_header(const char *id, struct entry_header *eh,
+ struct rsc_hdr *rh)
+{
+ struct rsc_hdr *rsc_hdr;
+ struct entry_header *ent;
+ int ret, i, j;
+ u8 query[8];
+
+ ret = cmd_db_ready();
+ if (ret)
+ return ret;
+
+ if (!eh || !rh)
+ return -EINVAL;
+
+ /* Pad out query string to same length as in DB */
+ strncpy(query, id, sizeof(query));
+
+ for (i = 0; i < MAX_SLV_ID; i++) {
+ rsc_hdr = &cmd_db_header->header[i];
+ if (!rsc_hdr->slv_id)
+ break;
+
+ ent = rsc_to_entry_header(rsc_hdr);
+ for (j = 0; j < le16_to_cpu(rsc_hdr->cnt); j++, ent++) {
+ if (memcmp(ent->id, query, sizeof(ent->id)) == 0)
+ break;
+ }
+
+ if (j < le16_to_cpu(rsc_hdr->cnt)) {
+ memcpy(eh, ent, sizeof(*ent));
+ memcpy(rh, rsc_hdr, sizeof(*rh));
+ return 0;
+ }
+ }
+
+ return -ENODEV;
+}
+
+/**
+ * cmd_db_read_addr() - Query command db for resource id address.
+ *
+ * @id: resource id to query for address
+ *
+ * Return: resource address on success, 0 on error
+ *
+ * This is used to retrieve resource address based on resource
+ * id.
+ */
+u32 cmd_db_read_addr(const char *id)
+{
+ int ret;
+ struct entry_header ent;
+ struct rsc_hdr rsc_hdr;
+
+ ret = cmd_db_get_header(id, &ent, &rsc_hdr);
+
+ return ret < 0 ? 0 : le32_to_cpu(ent.addr);
+}
+EXPORT_SYMBOL(cmd_db_read_addr);
+
+/**
+ * cmd_db_read_aux_data() - Query command db for aux data.
+ *
+ * @id: Resource to retrieve AUX Data on.
+ * @data: Data buffer to copy returned aux data to. Returns size on NULL
+ * @len: Caller provides size of data buffer passed in.
+ *
+ * Return: size of data on success, errno otherwise
+ */
+int cmd_db_read_aux_data(const char *id, u8 *data, size_t len)
+{
+ int ret;
+ struct entry_header ent;
+ struct rsc_hdr rsc_hdr;
+ u16 ent_len;
+
+ if (!data)
+ return -EINVAL;
+
+ ret = cmd_db_get_header(id, &ent, &rsc_hdr);
+ if (ret)
+ return ret;
+
+ ent_len = le16_to_cpu(ent.len);
+ if (len < ent_len)
+ return -EINVAL;
+
+ len = min_t(u16, ent_len, len);
+ memcpy(data, rsc_offset(&rsc_hdr, &ent), len);
+
+ return len;
+}
+EXPORT_SYMBOL(cmd_db_read_aux_data);
+
+/**
+ * cmd_db_read_aux_data_len - Get the length of the auxiliary data stored in DB.
+ *
+ * @id: Resource to retrieve AUX Data.
+ *
+ * Return: size on success, 0 on error
+ */
+size_t cmd_db_read_aux_data_len(const char *id)
+{
+ int ret;
+ struct entry_header ent;
+ struct rsc_hdr rsc_hdr;
+
+ ret = cmd_db_get_header(id, &ent, &rsc_hdr);
+
+ return ret < 0 ? 0 : le16_to_cpu(ent.len);
+}
+EXPORT_SYMBOL(cmd_db_read_aux_data_len);
+
+/**
+ * cmd_db_read_slave_id - Get the slave ID for a given resource address
+ *
+ * @id: Resource id to query the DB for version
+ *
+ * Return: cmd_db_hw_type enum on success, CMD_DB_HW_INVALID on error
+ */
+enum cmd_db_hw_type cmd_db_read_slave_id(const char *id)
+{
+ int ret;
+ struct entry_header ent;
+ struct rsc_hdr rsc_hdr;
+ u32 addr;
+
+ ret = cmd_db_get_header(id, &ent, &rsc_hdr);
+ if (ret < 0)
+ return CMD_DB_HW_INVALID;
+
+ addr = le32_to_cpu(ent.addr);
+ return (addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK;
+}
+EXPORT_SYMBOL(cmd_db_read_slave_id);
+
+static int cmd_db_dev_probe(struct platform_device *pdev)
+{
+ struct reserved_mem *rmem;
+ int ret = 0;
+
+ rmem = of_reserved_mem_lookup(pdev->dev.of_node);
+ if (!rmem) {
+ dev_err(&pdev->dev, "failed to acquire memory region\n");
+ return -EINVAL;
+ }
+
+ cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
+ if (IS_ERR_OR_NULL(cmd_db_header)) {
+ ret = PTR_ERR(cmd_db_header);
+ cmd_db_header = NULL;
+ return ret;
+ }
+
+ if (!cmd_db_magic_matches(cmd_db_header)) {
+ dev_err(&pdev->dev, "Invalid Command DB Magic\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct of_device_id cmd_db_match_table[] = {
+ { .compatible = "qcom,cmd-db" },
+ { },
+};
+
+static struct platform_driver cmd_db_dev_driver = {
+ .probe = cmd_db_dev_probe,
+ .driver = {
+ .name = "cmd-db",
+ .of_match_table = cmd_db_match_table,
+ },
+};
+
+static int __init cmd_db_device_init(void)
+{
+ return platform_driver_register(&cmd_db_dev_driver);
+}
+arch_initcall(cmd_db_device_init);
diff --git a/drivers/soc/qcom/mdt_loader.c b/drivers/soc/qcom/mdt_loader.c
index 17b314d..dc09d7a 100644
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -50,7 +50,7 @@ ssize_t qcom_mdt_get_size(const struct firmware *fw)
const struct elf32_phdr *phdrs;
const struct elf32_phdr *phdr;
const struct elf32_hdr *ehdr;
- phys_addr_t min_addr = (phys_addr_t)ULLONG_MAX;
+ phys_addr_t min_addr = PHYS_ADDR_MAX;
phys_addr_t max_addr = 0;
int i;
@@ -97,7 +97,7 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw,
const struct elf32_hdr *ehdr;
const struct firmware *seg_fw;
phys_addr_t mem_reloc;
- phys_addr_t min_addr = (phys_addr_t)ULLONG_MAX;
+ phys_addr_t min_addr = PHYS_ADDR_MAX;
phys_addr_t max_addr = 0;
size_t fw_name_len;
ssize_t offset;
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
new file mode 100644
index 0000000..feed3db2
--- /dev/null
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -0,0 +1,748 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/platform_device.h>
+#include <linux/qcom-geni-se.h>
+
+/**
+ * DOC: Overview
+ *
+ * Generic Interface (GENI) Serial Engine (SE) Wrapper driver is introduced
+ * to manage GENI firmware based Qualcomm Universal Peripheral (QUP) Wrapper
+ * controller. QUP Wrapper is designed to support various serial bus protocols
+ * like UART, SPI, I2C, I3C, etc.
+ */
+
+/**
+ * DOC: Hardware description
+ *
+ * GENI based QUP is a highly-flexible and programmable module for supporting
+ * a wide range of serial interfaces like UART, SPI, I2C, I3C, etc. A single
+ * QUP module can provide upto 8 serial interfaces, using its internal
+ * serial engines. The actual configuration is determined by the target
+ * platform configuration. The protocol supported by each interface is
+ * determined by the firmware loaded to the serial engine. Each SE consists
+ * of a DMA Engine and GENI sub modules which enable serial engines to
+ * support FIFO and DMA modes of operation.
+ *
+ *
+ * +-----------------------------------------+
+ * |QUP Wrapper |
+ * | +----------------------------+ |
+ * --QUP & SE Clocks--> | Serial Engine N | +-IO------>
+ * | | ... | | Interface
+ * <---Clock Perf.----+ +----+-----------------------+ | |
+ * State Interface | | Serial Engine 1 | | |
+ * | | | | |
+ * | | | | |
+ * <--------AHB-------> | | | |
+ * | | +----+ |
+ * | | | |
+ * | | | |
+ * <------SE IRQ------+ +----------------------------+ |
+ * | |
+ * +-----------------------------------------+
+ *
+ * Figure 1: GENI based QUP Wrapper
+ *
+ * The GENI submodules include primary and secondary sequencers which are
+ * used to drive TX & RX operations. On serial interfaces that operate using
+ * master-slave model, primary sequencer drives both TX & RX operations. On
+ * serial interfaces that operate using peer-to-peer model, primary sequencer
+ * drives TX operation and secondary sequencer drives RX operation.
+ */
+
+/**
+ * DOC: Software description
+ *
+ * GENI SE Wrapper driver is structured into 2 parts:
+ *
+ * geni_wrapper represents QUP Wrapper controller. This part of the driver
+ * manages QUP Wrapper information such as hardware version, clock
+ * performance table that is common to all the internal serial engines.
+ *
+ * geni_se represents serial engine. This part of the driver manages serial
+ * engine information such as clocks, containing QUP Wrapper, etc. This part
+ * of driver also supports operations (eg. initialize the concerned serial
+ * engine, select between FIFO and DMA mode of operation etc.) that are
+ * common to all the serial engines and are independent of serial interfaces.
+ */
+
+#define MAX_CLK_PERF_LEVEL 32
+#define NUM_AHB_CLKS 2
+
+/**
+ * @struct geni_wrapper - Data structure to represent the QUP Wrapper Core
+ * @dev: Device pointer of the QUP wrapper core
+ * @base: Base address of this instance of QUP wrapper core
+ * @ahb_clks: Handle to the primary & secondary AHB clocks
+ */
+struct geni_wrapper {
+ struct device *dev;
+ void __iomem *base;
+ struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
+};
+
+#define QUP_HW_VER_REG 0x4
+
+/* Common SE registers */
+#define GENI_INIT_CFG_REVISION 0x0
+#define GENI_S_INIT_CFG_REVISION 0x4
+#define GENI_OUTPUT_CTRL 0x24
+#define GENI_CGC_CTRL 0x28
+#define GENI_CLK_CTRL_RO 0x60
+#define GENI_IF_DISABLE_RO 0x64
+#define GENI_FW_S_REVISION_RO 0x6c
+#define SE_GENI_BYTE_GRAN 0x254
+#define SE_GENI_TX_PACKING_CFG0 0x260
+#define SE_GENI_TX_PACKING_CFG1 0x264
+#define SE_GENI_RX_PACKING_CFG0 0x284
+#define SE_GENI_RX_PACKING_CFG1 0x288
+#define SE_GENI_M_GP_LENGTH 0x910
+#define SE_GENI_S_GP_LENGTH 0x914
+#define SE_DMA_TX_PTR_L 0xc30
+#define SE_DMA_TX_PTR_H 0xc34
+#define SE_DMA_TX_ATTR 0xc38
+#define SE_DMA_TX_LEN 0xc3c
+#define SE_DMA_TX_IRQ_EN 0xc48
+#define SE_DMA_TX_IRQ_EN_SET 0xc4c
+#define SE_DMA_TX_IRQ_EN_CLR 0xc50
+#define SE_DMA_TX_LEN_IN 0xc54
+#define SE_DMA_TX_MAX_BURST 0xc5c
+#define SE_DMA_RX_PTR_L 0xd30
+#define SE_DMA_RX_PTR_H 0xd34
+#define SE_DMA_RX_ATTR 0xd38
+#define SE_DMA_RX_LEN 0xd3c
+#define SE_DMA_RX_IRQ_EN 0xd48
+#define SE_DMA_RX_IRQ_EN_SET 0xd4c
+#define SE_DMA_RX_IRQ_EN_CLR 0xd50
+#define SE_DMA_RX_LEN_IN 0xd54
+#define SE_DMA_RX_MAX_BURST 0xd5c
+#define SE_DMA_RX_FLUSH 0xd60
+#define SE_GSI_EVENT_EN 0xe18
+#define SE_IRQ_EN 0xe1c
+#define SE_DMA_GENERAL_CFG 0xe30
+
+/* GENI_OUTPUT_CTRL fields */
+#define DEFAULT_IO_OUTPUT_CTRL_MSK GENMASK(6, 0)
+
+/* GENI_CGC_CTRL fields */
+#define CFG_AHB_CLK_CGC_ON BIT(0)
+#define CFG_AHB_WR_ACLK_CGC_ON BIT(1)
+#define DATA_AHB_CLK_CGC_ON BIT(2)
+#define SCLK_CGC_ON BIT(3)
+#define TX_CLK_CGC_ON BIT(4)
+#define RX_CLK_CGC_ON BIT(5)
+#define EXT_CLK_CGC_ON BIT(6)
+#define PROG_RAM_HCLK_OFF BIT(8)
+#define PROG_RAM_SCLK_OFF BIT(9)
+#define DEFAULT_CGC_EN GENMASK(6, 0)
+
+/* SE_GSI_EVENT_EN fields */
+#define DMA_RX_EVENT_EN BIT(0)
+#define DMA_TX_EVENT_EN BIT(1)
+#define GENI_M_EVENT_EN BIT(2)
+#define GENI_S_EVENT_EN BIT(3)
+
+/* SE_IRQ_EN fields */
+#define DMA_RX_IRQ_EN BIT(0)
+#define DMA_TX_IRQ_EN BIT(1)
+#define GENI_M_IRQ_EN BIT(2)
+#define GENI_S_IRQ_EN BIT(3)
+
+/* SE_DMA_GENERAL_CFG */
+#define DMA_RX_CLK_CGC_ON BIT(0)
+#define DMA_TX_CLK_CGC_ON BIT(1)
+#define DMA_AHB_SLV_CFG_ON BIT(2)
+#define AHB_SEC_SLV_CLK_CGC_ON BIT(3)
+#define DUMMY_RX_NON_BUFFERABLE BIT(4)
+#define RX_DMA_ZERO_PADDING_EN BIT(5)
+#define RX_DMA_IRQ_DELAY_MSK GENMASK(8, 6)
+#define RX_DMA_IRQ_DELAY_SHFT 6
+
+/**
+ * geni_se_get_qup_hw_version() - Read the QUP wrapper Hardware version
+ * @se: Pointer to the corresponding serial engine.
+ *
+ * Return: Hardware Version of the wrapper.
+ */
+u32 geni_se_get_qup_hw_version(struct geni_se *se)
+{
+ struct geni_wrapper *wrapper = se->wrapper;
+
+ return readl_relaxed(wrapper->base + QUP_HW_VER_REG);
+}
+EXPORT_SYMBOL(geni_se_get_qup_hw_version);
+
+static void geni_se_io_set_mode(void __iomem *base)
+{
+ u32 val;
+
+ val = readl_relaxed(base + SE_IRQ_EN);
+ val |= GENI_M_IRQ_EN | GENI_S_IRQ_EN;
+ val |= DMA_TX_IRQ_EN | DMA_RX_IRQ_EN;
+ writel_relaxed(val, base + SE_IRQ_EN);
+
+ val = readl_relaxed(base + SE_GENI_DMA_MODE_EN);
+ val &= ~GENI_DMA_MODE_EN;
+ writel_relaxed(val, base + SE_GENI_DMA_MODE_EN);
+
+ writel_relaxed(0, base + SE_GSI_EVENT_EN);
+}
+
+static void geni_se_io_init(void __iomem *base)
+{
+ u32 val;
+
+ val = readl_relaxed(base + GENI_CGC_CTRL);
+ val |= DEFAULT_CGC_EN;
+ writel_relaxed(val, base + GENI_CGC_CTRL);
+
+ val = readl_relaxed(base + SE_DMA_GENERAL_CFG);
+ val |= AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CFG_ON;
+ val |= DMA_TX_CLK_CGC_ON | DMA_RX_CLK_CGC_ON;
+ writel_relaxed(val, base + SE_DMA_GENERAL_CFG);
+
+ writel_relaxed(DEFAULT_IO_OUTPUT_CTRL_MSK, base + GENI_OUTPUT_CTRL);
+ writel_relaxed(FORCE_DEFAULT, base + GENI_FORCE_DEFAULT_REG);
+}
+
+/**
+ * geni_se_init() - Initialize the GENI serial engine
+ * @se: Pointer to the concerned serial engine.
+ * @rx_wm: Receive watermark, in units of FIFO words.
+ * @rx_rfr_wm: Ready-for-receive watermark, in units of FIFO words.
+ *
+ * This function is used to initialize the GENI serial engine, configure
+ * receive watermark and ready-for-receive watermarks.
+ */
+void geni_se_init(struct geni_se *se, u32 rx_wm, u32 rx_rfr)
+{
+ u32 val;
+
+ geni_se_io_init(se->base);
+ geni_se_io_set_mode(se->base);
+
+ writel_relaxed(rx_wm, se->base + SE_GENI_RX_WATERMARK_REG);
+ writel_relaxed(rx_rfr, se->base + SE_GENI_RX_RFR_WATERMARK_REG);
+
+ val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
+ val |= M_COMMON_GENI_M_IRQ_EN;
+ writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
+
+ val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
+ val |= S_COMMON_GENI_S_IRQ_EN;
+ writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
+}
+EXPORT_SYMBOL(geni_se_init);
+
+static void geni_se_select_fifo_mode(struct geni_se *se)
+{
+ u32 proto = geni_se_read_proto(se);
+ u32 val;
+
+ writel_relaxed(0, se->base + SE_GSI_EVENT_EN);
+ writel_relaxed(0xffffffff, se->base + SE_GENI_M_IRQ_CLEAR);
+ writel_relaxed(0xffffffff, se->base + SE_GENI_S_IRQ_CLEAR);
+ writel_relaxed(0xffffffff, se->base + SE_DMA_TX_IRQ_CLR);
+ writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR);
+ writel_relaxed(0xffffffff, se->base + SE_IRQ_EN);
+
+ val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
+ if (proto != GENI_SE_UART) {
+ val |= M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN;
+ val |= M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN;
+ }
+ writel_relaxed(val, se->base + SE_GENI_M_IRQ_EN);
+
+ val = readl_relaxed(se->base + SE_GENI_S_IRQ_EN);
+ if (proto != GENI_SE_UART)
+ val |= S_CMD_DONE_EN;
+ writel_relaxed(val, se->base + SE_GENI_S_IRQ_EN);
+
+ val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
+ val &= ~GENI_DMA_MODE_EN;
+ writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
+}
+
+static void geni_se_select_dma_mode(struct geni_se *se)
+{
+ u32 val;
+
+ writel_relaxed(0, se->base + SE_GSI_EVENT_EN);
+ writel_relaxed(0xffffffff, se->base + SE_GENI_M_IRQ_CLEAR);
+ writel_relaxed(0xffffffff, se->base + SE_GENI_S_IRQ_CLEAR);
+ writel_relaxed(0xffffffff, se->base + SE_DMA_TX_IRQ_CLR);
+ writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR);
+ writel_relaxed(0xffffffff, se->base + SE_IRQ_EN);
+
+ val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
+ val |= GENI_DMA_MODE_EN;
+ writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
+}
+
+/**
+ * geni_se_select_mode() - Select the serial engine transfer mode
+ * @se: Pointer to the concerned serial engine.
+ * @mode: Transfer mode to be selected.
+ */
+void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode)
+{
+ WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA);
+
+ switch (mode) {
+ case GENI_SE_FIFO:
+ geni_se_select_fifo_mode(se);
+ break;
+ case GENI_SE_DMA:
+ geni_se_select_dma_mode(se);
+ break;
+ case GENI_SE_INVALID:
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL(geni_se_select_mode);
+
+/**
+ * DOC: Overview
+ *
+ * GENI FIFO packing is highly configurable. TX/RX packing/unpacking consist
+ * of up to 4 operations, each operation represented by 4 configuration vectors
+ * of 10 bits programmed in GENI_TX_PACKING_CFG0 and GENI_TX_PACKING_CFG1 for
+ * TX FIFO and in GENI_RX_PACKING_CFG0 and GENI_RX_PACKING_CFG1 for RX FIFO.
+ * Refer to below examples for detailed bit-field description.
+ *
+ * Example 1: word_size = 7, packing_mode = 4 x 8, msb_to_lsb = 1
+ *
+ * +-----------+-------+-------+-------+-------+
+ * | | vec_0 | vec_1 | vec_2 | vec_3 |
+ * +-----------+-------+-------+-------+-------+
+ * | start | 0x6 | 0xe | 0x16 | 0x1e |
+ * | direction | 1 | 1 | 1 | 1 |
+ * | length | 6 | 6 | 6 | 6 |
+ * | stop | 0 | 0 | 0 | 1 |
+ * +-----------+-------+-------+-------+-------+
+ *
+ * Example 2: word_size = 15, packing_mode = 2 x 16, msb_to_lsb = 0
+ *
+ * +-----------+-------+-------+-------+-------+
+ * | | vec_0 | vec_1 | vec_2 | vec_3 |
+ * +-----------+-------+-------+-------+-------+
+ * | start | 0x0 | 0x8 | 0x10 | 0x18 |
+ * | direction | 0 | 0 | 0 | 0 |
+ * | length | 7 | 6 | 7 | 6 |
+ * | stop | 0 | 0 | 0 | 1 |
+ * +-----------+-------+-------+-------+-------+
+ *
+ * Example 3: word_size = 23, packing_mode = 1 x 32, msb_to_lsb = 1
+ *
+ * +-----------+-------+-------+-------+-------+
+ * | | vec_0 | vec_1 | vec_2 | vec_3 |
+ * +-----------+-------+-------+-------+-------+
+ * | start | 0x16 | 0xe | 0x6 | 0x0 |
+ * | direction | 1 | 1 | 1 | 1 |
+ * | length | 7 | 7 | 6 | 0 |
+ * | stop | 0 | 0 | 1 | 0 |
+ * +-----------+-------+-------+-------+-------+
+ *
+ */
+
+#define NUM_PACKING_VECTORS 4
+#define PACKING_START_SHIFT 5
+#define PACKING_DIR_SHIFT 4
+#define PACKING_LEN_SHIFT 1
+#define PACKING_STOP_BIT BIT(0)
+#define PACKING_VECTOR_SHIFT 10
+/**
+ * geni_se_config_packing() - Packing configuration of the serial engine
+ * @se: Pointer to the concerned serial engine
+ * @bpw: Bits of data per transfer word.
+ * @pack_words: Number of words per fifo element.
+ * @msb_to_lsb: Transfer from MSB to LSB or vice-versa.
+ * @tx_cfg: Flag to configure the TX Packing.
+ * @rx_cfg: Flag to configure the RX Packing.
+ *
+ * This function is used to configure the packing rules for the current
+ * transfer.
+ */
+void geni_se_config_packing(struct geni_se *se, int bpw, int pack_words,
+ bool msb_to_lsb, bool tx_cfg, bool rx_cfg)
+{
+ u32 cfg0, cfg1, cfg[NUM_PACKING_VECTORS] = {0};
+ int len;
+ int temp_bpw = bpw;
+ int idx_start = msb_to_lsb ? bpw - 1 : 0;
+ int idx = idx_start;
+ int idx_delta = msb_to_lsb ? -BITS_PER_BYTE : BITS_PER_BYTE;
+ int ceil_bpw = ALIGN(bpw, BITS_PER_BYTE);
+ int iter = (ceil_bpw * pack_words) / BITS_PER_BYTE;
+ int i;
+
+ if (iter <= 0 || iter > NUM_PACKING_VECTORS)
+ return;
+
+ for (i = 0; i < iter; i++) {
+ len = min_t(int, temp_bpw, BITS_PER_BYTE) - 1;
+ cfg[i] = idx << PACKING_START_SHIFT;
+ cfg[i] |= msb_to_lsb << PACKING_DIR_SHIFT;
+ cfg[i] |= len << PACKING_LEN_SHIFT;
+
+ if (temp_bpw <= BITS_PER_BYTE) {
+ idx = ((i + 1) * BITS_PER_BYTE) + idx_start;
+ temp_bpw = bpw;
+ } else {
+ idx = idx + idx_delta;
+ temp_bpw = temp_bpw - BITS_PER_BYTE;
+ }
+ }
+ cfg[iter - 1] |= PACKING_STOP_BIT;
+ cfg0 = cfg[0] | (cfg[1] << PACKING_VECTOR_SHIFT);
+ cfg1 = cfg[2] | (cfg[3] << PACKING_VECTOR_SHIFT);
+
+ if (tx_cfg) {
+ writel_relaxed(cfg0, se->base + SE_GENI_TX_PACKING_CFG0);
+ writel_relaxed(cfg1, se->base + SE_GENI_TX_PACKING_CFG1);
+ }
+ if (rx_cfg) {
+ writel_relaxed(cfg0, se->base + SE_GENI_RX_PACKING_CFG0);
+ writel_relaxed(cfg1, se->base + SE_GENI_RX_PACKING_CFG1);
+ }
+
+ /*
+ * Number of protocol words in each FIFO entry
+ * 0 - 4x8, four words in each entry, max word size of 8 bits
+ * 1 - 2x16, two words in each entry, max word size of 16 bits
+ * 2 - 1x32, one word in each entry, max word size of 32 bits
+ * 3 - undefined
+ */
+ if (pack_words || bpw == 32)
+ writel_relaxed(bpw / 16, se->base + SE_GENI_BYTE_GRAN);
+}
+EXPORT_SYMBOL(geni_se_config_packing);
+
+static void geni_se_clks_off(struct geni_se *se)
+{
+ struct geni_wrapper *wrapper = se->wrapper;
+
+ clk_disable_unprepare(se->clk);
+ clk_bulk_disable_unprepare(ARRAY_SIZE(wrapper->ahb_clks),
+ wrapper->ahb_clks);
+}
+
+/**
+ * geni_se_resources_off() - Turn off resources associated with the serial
+ * engine
+ * @se: Pointer to the concerned serial engine.
+ *
+ * Return: 0 on success, standard Linux error codes on failure/error.
+ */
+int geni_se_resources_off(struct geni_se *se)
+{
+ int ret;
+
+ ret = pinctrl_pm_select_sleep_state(se->dev);
+ if (ret)
+ return ret;
+
+ geni_se_clks_off(se);
+ return 0;
+}
+EXPORT_SYMBOL(geni_se_resources_off);
+
+static int geni_se_clks_on(struct geni_se *se)
+{
+ int ret;
+ struct geni_wrapper *wrapper = se->wrapper;
+
+ ret = clk_bulk_prepare_enable(ARRAY_SIZE(wrapper->ahb_clks),
+ wrapper->ahb_clks);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(se->clk);
+ if (ret)
+ clk_bulk_disable_unprepare(ARRAY_SIZE(wrapper->ahb_clks),
+ wrapper->ahb_clks);
+ return ret;
+}
+
+/**
+ * geni_se_resources_on() - Turn on resources associated with the serial
+ * engine
+ * @se: Pointer to the concerned serial engine.
+ *
+ * Return: 0 on success, standard Linux error codes on failure/error.
+ */
+int geni_se_resources_on(struct geni_se *se)
+{
+ int ret;
+
+ ret = geni_se_clks_on(se);
+ if (ret)
+ return ret;
+
+ ret = pinctrl_pm_select_default_state(se->dev);
+ if (ret)
+ geni_se_clks_off(se);
+
+ return ret;
+}
+EXPORT_SYMBOL(geni_se_resources_on);
+
+/**
+ * geni_se_clk_tbl_get() - Get the clock table to program DFS
+ * @se: Pointer to the concerned serial engine.
+ * @tbl: Table in which the output is returned.
+ *
+ * This function is called by the protocol drivers to determine the different
+ * clock frequencies supported by serial engine core clock. The protocol
+ * drivers use the output to determine the clock frequency index to be
+ * programmed into DFS.
+ *
+ * Return: number of valid performance levels in the table on success,
+ * standard Linux error codes on failure.
+ */
+int geni_se_clk_tbl_get(struct geni_se *se, unsigned long **tbl)
+{
+ unsigned long freq = 0;
+ int i;
+
+ if (se->clk_perf_tbl) {
+ *tbl = se->clk_perf_tbl;
+ return se->num_clk_levels;
+ }
+
+ se->clk_perf_tbl = devm_kcalloc(se->dev, MAX_CLK_PERF_LEVEL,
+ sizeof(*se->clk_perf_tbl),
+ GFP_KERNEL);
+ if (!se->clk_perf_tbl)
+ return -ENOMEM;
+
+ for (i = 0; i < MAX_CLK_PERF_LEVEL; i++) {
+ freq = clk_round_rate(se->clk, freq + 1);
+ if (!freq || freq == se->clk_perf_tbl[i - 1])
+ break;
+ se->clk_perf_tbl[i] = freq;
+ }
+ se->num_clk_levels = i;
+ *tbl = se->clk_perf_tbl;
+ return se->num_clk_levels;
+}
+EXPORT_SYMBOL(geni_se_clk_tbl_get);
+
+/**
+ * geni_se_clk_freq_match() - Get the matching or closest SE clock frequency
+ * @se: Pointer to the concerned serial engine.
+ * @req_freq: Requested clock frequency.
+ * @index: Index of the resultant frequency in the table.
+ * @res_freq: Resultant frequency which matches or is closer to the
+ * requested frequency.
+ * @exact: Flag to indicate exact multiple requirement of the requested
+ * frequency.
+ *
+ * This function is called by the protocol drivers to determine the matching
+ * or exact multiple of the requested frequency, as provided by the serial
+ * engine clock in order to meet the performance requirements. If there is
+ * no matching or exact multiple of the requested frequency found, then it
+ * selects the closest floor frequency, if exact flag is not set.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+int geni_se_clk_freq_match(struct geni_se *se, unsigned long req_freq,
+ unsigned int *index, unsigned long *res_freq,
+ bool exact)
+{
+ unsigned long *tbl;
+ int num_clk_levels;
+ int i;
+
+ num_clk_levels = geni_se_clk_tbl_get(se, &tbl);
+ if (num_clk_levels < 0)
+ return num_clk_levels;
+
+ if (num_clk_levels == 0)
+ return -EINVAL;
+
+ *res_freq = 0;
+ for (i = 0; i < num_clk_levels; i++) {
+ if (!(tbl[i] % req_freq)) {
+ *index = i;
+ *res_freq = tbl[i];
+ return 0;
+ }
+
+ if (!(*res_freq) || ((tbl[i] > *res_freq) &&
+ (tbl[i] < req_freq))) {
+ *index = i;
+ *res_freq = tbl[i];
+ }
+ }
+
+ if (exact)
+ return -EINVAL;
+
+ return 0;
+}
+EXPORT_SYMBOL(geni_se_clk_freq_match);
+
+#define GENI_SE_DMA_DONE_EN BIT(0)
+#define GENI_SE_DMA_EOT_EN BIT(1)
+#define GENI_SE_DMA_AHB_ERR_EN BIT(2)
+#define GENI_SE_DMA_EOT_BUF BIT(0)
+/**
+ * geni_se_tx_dma_prep() - Prepare the serial engine for TX DMA transfer
+ * @se: Pointer to the concerned serial engine.
+ * @buf: Pointer to the TX buffer.
+ * @len: Length of the TX buffer.
+ * @iova: Pointer to store the mapped DMA address.
+ *
+ * This function is used to prepare the buffers for DMA TX.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
+ dma_addr_t *iova)
+{
+ struct geni_wrapper *wrapper = se->wrapper;
+ u32 val;
+
+ *iova = dma_map_single(wrapper->dev, buf, len, DMA_TO_DEVICE);
+ if (dma_mapping_error(wrapper->dev, *iova))
+ return -EIO;
+
+ val = GENI_SE_DMA_DONE_EN;
+ val |= GENI_SE_DMA_EOT_EN;
+ val |= GENI_SE_DMA_AHB_ERR_EN;
+ writel_relaxed(val, se->base + SE_DMA_TX_IRQ_EN_SET);
+ writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_TX_PTR_L);
+ writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_TX_PTR_H);
+ writel_relaxed(GENI_SE_DMA_EOT_BUF, se->base + SE_DMA_TX_ATTR);
+ writel_relaxed(len, se->base + SE_DMA_TX_LEN);
+ return 0;
+}
+EXPORT_SYMBOL(geni_se_tx_dma_prep);
+
+/**
+ * geni_se_rx_dma_prep() - Prepare the serial engine for RX DMA transfer
+ * @se: Pointer to the concerned serial engine.
+ * @buf: Pointer to the RX buffer.
+ * @len: Length of the RX buffer.
+ * @iova: Pointer to store the mapped DMA address.
+ *
+ * This function is used to prepare the buffers for DMA RX.
+ *
+ * Return: 0 on success, standard Linux error codes on failure.
+ */
+int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
+ dma_addr_t *iova)
+{
+ struct geni_wrapper *wrapper = se->wrapper;
+ u32 val;
+
+ *iova = dma_map_single(wrapper->dev, buf, len, DMA_FROM_DEVICE);
+ if (dma_mapping_error(wrapper->dev, *iova))
+ return -EIO;
+
+ val = GENI_SE_DMA_DONE_EN;
+ val |= GENI_SE_DMA_EOT_EN;
+ val |= GENI_SE_DMA_AHB_ERR_EN;
+ writel_relaxed(val, se->base + SE_DMA_RX_IRQ_EN_SET);
+ writel_relaxed(lower_32_bits(*iova), se->base + SE_DMA_RX_PTR_L);
+ writel_relaxed(upper_32_bits(*iova), se->base + SE_DMA_RX_PTR_H);
+ /* RX does not have EOT buffer type bit. So just reset RX_ATTR */
+ writel_relaxed(0, se->base + SE_DMA_RX_ATTR);
+ writel_relaxed(len, se->base + SE_DMA_RX_LEN);
+ return 0;
+}
+EXPORT_SYMBOL(geni_se_rx_dma_prep);
+
+/**
+ * geni_se_tx_dma_unprep() - Unprepare the serial engine after TX DMA transfer
+ * @se: Pointer to the concerned serial engine.
+ * @iova: DMA address of the TX buffer.
+ * @len: Length of the TX buffer.
+ *
+ * This function is used to unprepare the DMA buffers after DMA TX.
+ */
+void geni_se_tx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
+{
+ struct geni_wrapper *wrapper = se->wrapper;
+
+ if (iova && !dma_mapping_error(wrapper->dev, iova))
+ dma_unmap_single(wrapper->dev, iova, len, DMA_TO_DEVICE);
+}
+EXPORT_SYMBOL(geni_se_tx_dma_unprep);
+
+/**
+ * geni_se_rx_dma_unprep() - Unprepare the serial engine after RX DMA transfer
+ * @se: Pointer to the concerned serial engine.
+ * @iova: DMA address of the RX buffer.
+ * @len: Length of the RX buffer.
+ *
+ * This function is used to unprepare the DMA buffers after DMA RX.
+ */
+void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
+{
+ struct geni_wrapper *wrapper = se->wrapper;
+
+ if (iova && !dma_mapping_error(wrapper->dev, iova))
+ dma_unmap_single(wrapper->dev, iova, len, DMA_FROM_DEVICE);
+}
+EXPORT_SYMBOL(geni_se_rx_dma_unprep);
+
+static int geni_se_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct geni_wrapper *wrapper;
+ int ret;
+
+ wrapper = devm_kzalloc(dev, sizeof(*wrapper), GFP_KERNEL);
+ if (!wrapper)
+ return -ENOMEM;
+
+ wrapper->dev = dev;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ wrapper->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(wrapper->base))
+ return PTR_ERR(wrapper->base);
+
+ wrapper->ahb_clks[0].id = "m-ahb";
+ wrapper->ahb_clks[1].id = "s-ahb";
+ ret = devm_clk_bulk_get(dev, NUM_AHB_CLKS, wrapper->ahb_clks);
+ if (ret) {
+ dev_err(dev, "Err getting AHB clks %d\n", ret);
+ return ret;
+ }
+
+ dev_set_drvdata(dev, wrapper);
+ dev_dbg(dev, "GENI SE Driver probed\n");
+ return devm_of_platform_populate(dev);
+}
+
+static const struct of_device_id geni_se_dt_match[] = {
+ { .compatible = "qcom,geni-se-qup", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, geni_se_dt_match);
+
+static struct platform_driver geni_se_driver = {
+ .driver = {
+ .name = "geni_se_qup",
+ .of_match_table = geni_se_dt_match,
+ },
+ .probe = geni_se_probe,
+};
+module_platform_driver(geni_se_driver);
+
+MODULE_DESCRIPTION("GENI Serial Engine Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
index 3219822..938ca41c 100644
--- a/drivers/soc/qcom/qmi_interface.c
+++ b/drivers/soc/qcom/qmi_interface.c
@@ -639,10 +639,11 @@ int qmi_handle_init(struct qmi_handle *qmi, size_t recv_buf_size,
if (ops)
qmi->ops = *ops;
+ /* Make room for the header */
+ recv_buf_size += sizeof(struct qmi_header);
+ /* Must also be sufficient to hold a control packet */
if (recv_buf_size < sizeof(struct qrtr_ctrl_pkt))
recv_buf_size = sizeof(struct qrtr_ctrl_pkt);
- else
- recv_buf_size += sizeof(struct qmi_header);
qmi->recv_buf_size = recv_buf_size;
qmi->recv_buf = kzalloc(recv_buf_size, GFP_KERNEL);
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index c234675..93517ed 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -226,6 +226,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
{ .compatible = "qcom,rpm-msm8916" },
{ .compatible = "qcom,rpm-msm8974" },
{ .compatible = "qcom,rpm-msm8996" },
+ { .compatible = "qcom,rpm-msm8998" },
{}
};
MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match);
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index 0b94d62..70b2ee8 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -280,7 +280,7 @@ struct qcom_smem {
struct smem_region regions[0];
};
-static struct smem_private_entry *
+static void *
phdr_to_last_uncached_entry(struct smem_partition_header *phdr)
{
void *p = phdr;
@@ -288,15 +288,18 @@ phdr_to_last_uncached_entry(struct smem_partition_header *phdr)
return p + le32_to_cpu(phdr->offset_free_uncached);
}
-static void *phdr_to_first_cached_entry(struct smem_partition_header *phdr,
+static struct smem_private_entry *
+phdr_to_first_cached_entry(struct smem_partition_header *phdr,
size_t cacheline)
{
void *p = phdr;
+ struct smem_private_entry *e;
- return p + le32_to_cpu(phdr->size) - ALIGN(sizeof(*phdr), cacheline);
+ return p + le32_to_cpu(phdr->size) - ALIGN(sizeof(*e), cacheline);
}
-static void *phdr_to_last_cached_entry(struct smem_partition_header *phdr)
+static void *
+phdr_to_last_cached_entry(struct smem_partition_header *phdr)
{
void *p = phdr;
@@ -361,14 +364,14 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
end = phdr_to_last_uncached_entry(phdr);
cached = phdr_to_last_cached_entry(phdr);
- while (hdr < end) {
- if (hdr->canary != SMEM_PRIVATE_CANARY) {
- dev_err(smem->dev,
- "Found invalid canary in hosts %d:%d partition\n",
- phdr->host0, phdr->host1);
- return -EINVAL;
- }
+ if (smem->global_partition) {
+ dev_err(smem->dev, "Already found the global partition\n");
+ return -EINVAL;
+ }
+ while (hdr < end) {
+ if (hdr->canary != SMEM_PRIVATE_CANARY)
+ goto bad_canary;
if (le16_to_cpu(hdr->item) == item)
return -EEXIST;
@@ -377,7 +380,7 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
/* Check that we don't grow into the cached region */
alloc_size = sizeof(*hdr) + ALIGN(size, 8);
- if ((void *)hdr + alloc_size >= cached) {
+ if ((void *)hdr + alloc_size > cached) {
dev_err(smem->dev, "Out of memory\n");
return -ENOSPC;
}
@@ -397,6 +400,11 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
le32_add_cpu(&phdr->offset_free_uncached, alloc_size);
return 0;
+bad_canary:
+ dev_err(smem->dev, "Found invalid canary in hosts %hu:%hu partition\n",
+ le16_to_cpu(phdr->host0), le16_to_cpu(phdr->host1));
+
+ return -EINVAL;
}
static int qcom_smem_alloc_global(struct qcom_smem *smem,
@@ -560,8 +568,8 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
return ERR_PTR(-ENOENT);
invalid_canary:
- dev_err(smem->dev, "Found invalid canary in hosts %d:%d partition\n",
- phdr->host0, phdr->host1);
+ dev_err(smem->dev, "Found invalid canary in hosts %hu:%hu partition\n",
+ le16_to_cpu(phdr->host0), le16_to_cpu(phdr->host1));
return ERR_PTR(-EINVAL);
}
@@ -647,6 +655,33 @@ int qcom_smem_get_free_space(unsigned host)
}
EXPORT_SYMBOL(qcom_smem_get_free_space);
+/**
+ * qcom_smem_virt_to_phys() - return the physical address associated
+ * with an smem item pointer (previously returned by qcom_smem_get()
+ * @p: the virtual address to convert
+ *
+ * Returns 0 if the pointer provided is not within any smem region.
+ */
+phys_addr_t qcom_smem_virt_to_phys(void *p)
+{
+ unsigned i;
+
+ for (i = 0; i < __smem->num_regions; i++) {
+ struct smem_region *region = &__smem->regions[i];
+
+ if (p < region->virt_base)
+ continue;
+ if (p < region->virt_base + region->size) {
+ u64 offset = p - region->virt_base;
+
+ return (phys_addr_t)region->aux_base + offset;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(qcom_smem_virt_to_phys);
+
static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
{
struct smem_header *header;
@@ -695,9 +730,10 @@ static u32 qcom_smem_get_item_count(struct qcom_smem *smem)
static int qcom_smem_set_global_partition(struct qcom_smem *smem)
{
struct smem_partition_header *header;
- struct smem_ptable_entry *entry = NULL;
+ struct smem_ptable_entry *entry;
struct smem_ptable *ptable;
u32 host0, host1, size;
+ bool found = false;
int i;
ptable = qcom_smem_get_ptable(smem);
@@ -709,11 +745,13 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
host0 = le16_to_cpu(entry->host0);
host1 = le16_to_cpu(entry->host1);
- if (host0 == SMEM_GLOBAL_HOST && host0 == host1)
+ if (host0 == SMEM_GLOBAL_HOST && host0 == host1) {
+ found = true;
break;
+ }
}
- if (!entry) {
+ if (!found) {
dev_err(smem->dev, "Missing entry for global partition\n");
return -EINVAL;
}
@@ -723,11 +761,6 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
return -EINVAL;
}
- if (smem->global_partition) {
- dev_err(smem->dev, "Already found the global partition\n");
- return -EINVAL;
- }
-
header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
host0 = le16_to_cpu(header->host0);
host1 = le16_to_cpu(header->host1);
diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig
index 3bbe611..1d824cb 100644
--- a/drivers/soc/renesas/Kconfig
+++ b/drivers/soc/renesas/Kconfig
@@ -4,9 +4,11 @@ config SOC_RENESAS
select SOC_BUS
select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || \
ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77965 || \
- ARCH_R8A77970 || ARCH_R8A77980 || ARCH_R8A77995
+ ARCH_R8A77970 || ARCH_R8A77980 || ARCH_R8A77990 || \
+ ARCH_R8A77995
select SYSC_R8A7743 if ARCH_R8A7743
select SYSC_R8A7745 if ARCH_R8A7745
+ select SYSC_R8A77470 if ARCH_R8A77470
select SYSC_R8A7779 if ARCH_R8A7779
select SYSC_R8A7790 if ARCH_R8A7790
select SYSC_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793
@@ -17,6 +19,7 @@ config SOC_RENESAS
select SYSC_R8A77965 if ARCH_R8A77965
select SYSC_R8A77970 if ARCH_R8A77970
select SYSC_R8A77980 if ARCH_R8A77980
+ select SYSC_R8A77990 if ARCH_R8A77990
select SYSC_R8A77995 if ARCH_R8A77995
if SOC_RENESAS
@@ -30,6 +33,10 @@ config SYSC_R8A7745
bool "RZ/G1E System Controller support" if COMPILE_TEST
select SYSC_RCAR
+config SYSC_R8A77470
+ bool "RZ/G1C System Controller support" if COMPILE_TEST
+ select SYSC_RCAR
+
config SYSC_R8A7779
bool "R-Car H1 System Controller support" if COMPILE_TEST
select SYSC_RCAR
@@ -70,6 +77,10 @@ config SYSC_R8A77980
bool "R-Car V3H System Controller support" if COMPILE_TEST
select SYSC_RCAR
+config SYSC_R8A77990
+ bool "R-Car E3 System Controller support" if COMPILE_TEST
+ select SYSC_RCAR
+
config SYSC_R8A77995
bool "R-Car D3 System Controller support" if COMPILE_TEST
select SYSC_RCAR
diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile
index ccb5ec5..7dc0f20 100644
--- a/drivers/soc/renesas/Makefile
+++ b/drivers/soc/renesas/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_SOC_RENESAS) += renesas-soc.o
# SoC
obj-$(CONFIG_SYSC_R8A7743) += r8a7743-sysc.o
obj-$(CONFIG_SYSC_R8A7745) += r8a7745-sysc.o
+obj-$(CONFIG_SYSC_R8A77470) += r8a77470-sysc.o
obj-$(CONFIG_SYSC_R8A7779) += r8a7779-sysc.o
obj-$(CONFIG_SYSC_R8A7790) += r8a7790-sysc.o
obj-$(CONFIG_SYSC_R8A7791) += r8a7791-sysc.o
@@ -15,6 +16,7 @@ obj-$(CONFIG_SYSC_R8A7796) += r8a7796-sysc.o
obj-$(CONFIG_SYSC_R8A77965) += r8a77965-sysc.o
obj-$(CONFIG_SYSC_R8A77970) += r8a77970-sysc.o
obj-$(CONFIG_SYSC_R8A77980) += r8a77980-sysc.o
+obj-$(CONFIG_SYSC_R8A77990) += r8a77990-sysc.o
obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o
# Family
diff --git a/drivers/soc/renesas/r8a77470-sysc.c b/drivers/soc/renesas/r8a77470-sysc.c
new file mode 100644
index 0000000..cfa015e
--- /dev/null
+++ b/drivers/soc/renesas/r8a77470-sysc.c
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas RZ/G1C System Controller
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+
+#include <dt-bindings/power/r8a77470-sysc.h>
+
+#include "rcar-sysc.h"
+
+static const struct rcar_sysc_area r8a77470_areas[] __initconst = {
+ { "always-on", 0, 0, R8A77470_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+ { "ca7-scu", 0x100, 0, R8A77470_PD_CA7_SCU, R8A77470_PD_ALWAYS_ON,
+ PD_SCU },
+ { "ca7-cpu0", 0x1c0, 0, R8A77470_PD_CA7_CPU0, R8A77470_PD_CA7_SCU,
+ PD_CPU_NOCR },
+ { "ca7-cpu1", 0x1c0, 1, R8A77470_PD_CA7_CPU1, R8A77470_PD_CA7_SCU,
+ PD_CPU_NOCR },
+ { "sgx", 0xc0, 0, R8A77470_PD_SGX, R8A77470_PD_ALWAYS_ON },
+};
+
+const struct rcar_sysc_info r8a77470_sysc_info __initconst = {
+ .areas = r8a77470_areas,
+ .num_areas = ARRAY_SIZE(r8a77470_areas),
+};
diff --git a/drivers/soc/renesas/r8a77990-sysc.c b/drivers/soc/renesas/r8a77990-sysc.c
new file mode 100644
index 0000000..15579eb
--- /dev/null
+++ b/drivers/soc/renesas/r8a77990-sysc.c
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Renesas R-Car E3 System Controller
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+
+#include <linux/bug.h>
+#include <linux/kernel.h>
+#include <linux/sys_soc.h>
+
+#include <dt-bindings/power/r8a77990-sysc.h>
+
+#include "rcar-sysc.h"
+
+static struct rcar_sysc_area r8a77990_areas[] __initdata = {
+ { "always-on", 0, 0, R8A77990_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
+ { "ca53-scu", 0x140, 0, R8A77990_PD_CA53_SCU, R8A77990_PD_ALWAYS_ON,
+ PD_SCU },
+ { "ca53-cpu0", 0x200, 0, R8A77990_PD_CA53_CPU0, R8A77990_PD_CA53_SCU,
+ PD_CPU_NOCR },
+ { "ca53-cpu1", 0x200, 1, R8A77990_PD_CA53_CPU1, R8A77990_PD_CA53_SCU,
+ PD_CPU_NOCR },
+ { "cr7", 0x240, 0, R8A77990_PD_CR7, R8A77990_PD_ALWAYS_ON },
+ { "a3vc", 0x380, 0, R8A77990_PD_A3VC, R8A77990_PD_ALWAYS_ON },
+ { "a2vc1", 0x3c0, 1, R8A77990_PD_A2VC1, R8A77990_PD_A3VC },
+ { "3dg-a", 0x100, 0, R8A77990_PD_3DG_A, R8A77990_PD_ALWAYS_ON },
+ { "3dg-b", 0x100, 1, R8A77990_PD_3DG_B, R8A77990_PD_3DG_A },
+};
+
+static void __init rcar_sysc_fix_parent(struct rcar_sysc_area *areas,
+ unsigned int num_areas, u8 id,
+ int new_parent)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_areas; i++)
+ if (areas[i].isr_bit == id) {
+ areas[i].parent = new_parent;
+ return;
+ }
+}
+
+/* Fixups for R-Car E3 ES1.0 revision */
+static const struct soc_device_attribute r8a77990[] __initconst = {
+ { .soc_id = "r8a77990", .revision = "ES1.0" },
+ { /* sentinel */ }
+};
+
+static int __init r8a77990_sysc_init(void)
+{
+ if (soc_device_match(r8a77990)) {
+ rcar_sysc_fix_parent(r8a77990_areas,
+ ARRAY_SIZE(r8a77990_areas),
+ R8A77990_PD_3DG_A, R8A77990_PD_3DG_B);
+ rcar_sysc_fix_parent(r8a77990_areas,
+ ARRAY_SIZE(r8a77990_areas),
+ R8A77990_PD_3DG_B, R8A77990_PD_ALWAYS_ON);
+ }
+
+ return 0;
+}
+
+const struct rcar_sysc_info r8a77990_sysc_info __initconst = {
+ .init = r8a77990_sysc_init,
+ .areas = r8a77990_areas,
+ .num_areas = ARRAY_SIZE(r8a77990_areas),
+};
diff --git a/drivers/soc/renesas/r8a77995-sysc.c b/drivers/soc/renesas/r8a77995-sysc.c
index f718429..1b2ef41 100644
--- a/drivers/soc/renesas/r8a77995-sysc.c
+++ b/drivers/soc/renesas/r8a77995-sysc.c
@@ -10,13 +10,12 @@
#include <linux/bug.h>
#include <linux/kernel.h>
-#include <linux/sys_soc.h>
#include <dt-bindings/power/r8a77995-sysc.h>
#include "rcar-sysc.h"
-static struct rcar_sysc_area r8a77995_areas[] __initdata = {
+static const struct rcar_sysc_area r8a77995_areas[] __initconst = {
{ "always-on", 0, 0, R8A77995_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca53-scu", 0x140, 0, R8A77995_PD_CA53_SCU, R8A77995_PD_ALWAYS_ON,
PD_SCU },
diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c
index 8e9cb79..d9c1034 100644
--- a/drivers/soc/renesas/rcar-rst.c
+++ b/drivers/soc/renesas/rcar-rst.c
@@ -44,6 +44,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
/* RZ/G is handled like R-Car Gen2 */
{ .compatible = "renesas,r8a7743-rst", .data = &rcar_rst_gen2 },
{ .compatible = "renesas,r8a7745-rst", .data = &rcar_rst_gen2 },
+ { .compatible = "renesas,r8a77470-rst", .data = &rcar_rst_gen2 },
/* R-Car Gen1 */
{ .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 },
{ .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 },
@@ -59,6 +60,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
{ .compatible = "renesas,r8a77965-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a77970-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a77980-rst", .data = &rcar_rst_gen3 },
+ { .compatible = "renesas,r8a77990-rst", .data = &rcar_rst_gen3 },
{ .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen3 },
{ /* sentinel */ }
};
diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
index faf20e7..95120ac 100644
--- a/drivers/soc/renesas/rcar-sysc.c
+++ b/drivers/soc/renesas/rcar-sysc.c
@@ -261,6 +261,9 @@ static const struct of_device_id rcar_sysc_matches[] __initconst = {
#ifdef CONFIG_SYSC_R8A7745
{ .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info },
#endif
+#ifdef CONFIG_SYSC_R8A77470
+ { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info },
+#endif
#ifdef CONFIG_SYSC_R8A7779
{ .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info },
#endif
@@ -293,6 +296,9 @@ static const struct of_device_id rcar_sysc_matches[] __initconst = {
#ifdef CONFIG_SYSC_R8A77980
{ .compatible = "renesas,r8a77980-sysc", .data = &r8a77980_sysc_info },
#endif
+#ifdef CONFIG_SYSC_R8A77990
+ { .compatible = "renesas,r8a77990-sysc", .data = &r8a77990_sysc_info },
+#endif
#ifdef CONFIG_SYSC_R8A77995
{ .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info },
#endif
diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h
index dcdc9ec..a22e7cf 100644
--- a/drivers/soc/renesas/rcar-sysc.h
+++ b/drivers/soc/renesas/rcar-sysc.h
@@ -51,6 +51,7 @@ struct rcar_sysc_info {
extern const struct rcar_sysc_info r8a7743_sysc_info;
extern const struct rcar_sysc_info r8a7745_sysc_info;
+extern const struct rcar_sysc_info r8a77470_sysc_info;
extern const struct rcar_sysc_info r8a7779_sysc_info;
extern const struct rcar_sysc_info r8a7790_sysc_info;
extern const struct rcar_sysc_info r8a7791_sysc_info;
@@ -61,6 +62,7 @@ extern const struct rcar_sysc_info r8a7796_sysc_info;
extern const struct rcar_sysc_info r8a77965_sysc_info;
extern const struct rcar_sysc_info r8a77970_sysc_info;
extern const struct rcar_sysc_info r8a77980_sysc_info;
+extern const struct rcar_sysc_info r8a77990_sysc_info;
extern const struct rcar_sysc_info r8a77995_sysc_info;
diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c
index ea71c41..d44d0e6 100644
--- a/drivers/soc/renesas/renesas-soc.c
+++ b/drivers/soc/renesas/renesas-soc.c
@@ -100,6 +100,11 @@ static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = {
.id = 0x4c,
};
+static const struct renesas_soc soc_rz_g1c __initconst __maybe_unused = {
+ .family = &fam_rzg,
+ .id = 0x53,
+};
+
static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = {
.family = &fam_rcar_gen1,
};
@@ -159,6 +164,11 @@ static const struct renesas_soc soc_rcar_v3h __initconst __maybe_unused = {
.id = 0x56,
};
+static const struct renesas_soc soc_rcar_e3 __initconst __maybe_unused = {
+ .family = &fam_rcar_gen3,
+ .id = 0x57,
+};
+
static const struct renesas_soc soc_rcar_d3 __initconst __maybe_unused = {
.family = &fam_rcar_gen3,
.id = 0x58,
@@ -192,6 +202,9 @@ static const struct of_device_id renesas_socs[] __initconst = {
#ifdef CONFIG_ARCH_R8A7745
{ .compatible = "renesas,r8a7745", .data = &soc_rz_g1e },
#endif
+#ifdef CONFIG_ARCH_R8A77470
+ { .compatible = "renesas,r8a77470", .data = &soc_rz_g1c },
+#endif
#ifdef CONFIG_ARCH_R8A7778
{ .compatible = "renesas,r8a7778", .data = &soc_rcar_m1a },
#endif
@@ -228,6 +241,9 @@ static const struct of_device_id renesas_socs[] __initconst = {
#ifdef CONFIG_ARCH_R8A77980
{ .compatible = "renesas,r8a77980", .data = &soc_rcar_v3h },
#endif
+#ifdef CONFIG_ARCH_R8A77990
+ { .compatible = "renesas,r8a77990", .data = &soc_rcar_e3 },
+#endif
#ifdef CONFIG_ARCH_R8A77995
{ .compatible = "renesas,r8a77995", .data = &soc_rcar_d3 },
#endif
diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c
index f874baa..6dff868 100644
--- a/drivers/soc/rockchip/pm_domains.c
+++ b/drivers/soc/rockchip/pm_domains.c
@@ -19,6 +19,10 @@
#include <linux/clk.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
+#include <dt-bindings/power/px30-power.h>
+#include <dt-bindings/power/rk3036-power.h>
+#include <dt-bindings/power/rk3128-power.h>
+#include <dt-bindings/power/rk3228-power.h>
#include <dt-bindings/power/rk3288-power.h>
#include <dt-bindings/power/rk3328-power.h>
#include <dt-bindings/power/rk3366-power.h>
@@ -104,6 +108,18 @@ struct rockchip_pmu {
.active_wakeup = wakeup, \
}
+#define DOMAIN_RK3036(req, ack, idle, wakeup) \
+{ \
+ .req_mask = (req >= 0) ? BIT(req) : 0, \
+ .req_w_mask = (req >= 0) ? BIT(req + 16) : 0, \
+ .ack_mask = (ack >= 0) ? BIT(ack) : 0, \
+ .idle_mask = (idle >= 0) ? BIT(idle) : 0, \
+ .active_wakeup = wakeup, \
+}
+
+#define DOMAIN_PX30(pwr, status, req, wakeup) \
+ DOMAIN_M(pwr, status, req, (req) + 16, req, wakeup)
+
#define DOMAIN_RK3288(pwr, status, req, wakeup) \
DOMAIN(pwr, status, req, req, (req) + 16, wakeup)
@@ -256,7 +272,7 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
return;
else if (pd->info->pwr_w_mask)
regmap_write(pmu->regmap, pmu->info->pwr_offset,
- on ? pd->info->pwr_mask :
+ on ? pd->info->pwr_w_mask :
(pd->info->pwr_mask | pd->info->pwr_w_mask));
else
regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
@@ -700,6 +716,49 @@ err_out:
return error;
}
+static const struct rockchip_domain_info px30_pm_domains[] = {
+ [PX30_PD_USB] = DOMAIN_PX30(5, 5, 10, false),
+ [PX30_PD_SDCARD] = DOMAIN_PX30(8, 8, 9, false),
+ [PX30_PD_GMAC] = DOMAIN_PX30(10, 10, 6, false),
+ [PX30_PD_MMC_NAND] = DOMAIN_PX30(11, 11, 5, false),
+ [PX30_PD_VPU] = DOMAIN_PX30(12, 12, 14, false),
+ [PX30_PD_VO] = DOMAIN_PX30(13, 13, 7, false),
+ [PX30_PD_VI] = DOMAIN_PX30(14, 14, 8, false),
+ [PX30_PD_GPU] = DOMAIN_PX30(15, 15, 2, false),
+};
+
+static const struct rockchip_domain_info rk3036_pm_domains[] = {
+ [RK3036_PD_MSCH] = DOMAIN_RK3036(14, 23, 30, true),
+ [RK3036_PD_CORE] = DOMAIN_RK3036(13, 17, 24, false),
+ [RK3036_PD_PERI] = DOMAIN_RK3036(12, 18, 25, false),
+ [RK3036_PD_VIO] = DOMAIN_RK3036(11, 19, 26, false),
+ [RK3036_PD_VPU] = DOMAIN_RK3036(10, 20, 27, false),
+ [RK3036_PD_GPU] = DOMAIN_RK3036(9, 21, 28, false),
+ [RK3036_PD_SYS] = DOMAIN_RK3036(8, 22, 29, false),
+};
+
+static const struct rockchip_domain_info rk3128_pm_domains[] = {
+ [RK3128_PD_CORE] = DOMAIN_RK3288(0, 0, 4, false),
+ [RK3128_PD_MSCH] = DOMAIN_RK3288(-1, -1, 6, true),
+ [RK3128_PD_VIO] = DOMAIN_RK3288(3, 3, 2, false),
+ [RK3128_PD_VIDEO] = DOMAIN_RK3288(2, 2, 1, false),
+ [RK3128_PD_GPU] = DOMAIN_RK3288(1, 1, 3, false),
+};
+
+static const struct rockchip_domain_info rk3228_pm_domains[] = {
+ [RK3228_PD_CORE] = DOMAIN_RK3036(0, 0, 16, true),
+ [RK3228_PD_MSCH] = DOMAIN_RK3036(1, 1, 17, true),
+ [RK3228_PD_BUS] = DOMAIN_RK3036(2, 2, 18, true),
+ [RK3228_PD_SYS] = DOMAIN_RK3036(3, 3, 19, true),
+ [RK3228_PD_VIO] = DOMAIN_RK3036(4, 4, 20, false),
+ [RK3228_PD_VOP] = DOMAIN_RK3036(5, 5, 21, false),
+ [RK3228_PD_VPU] = DOMAIN_RK3036(6, 6, 22, false),
+ [RK3228_PD_RKVDEC] = DOMAIN_RK3036(7, 7, 23, false),
+ [RK3228_PD_GPU] = DOMAIN_RK3036(8, 8, 24, false),
+ [RK3228_PD_PERI] = DOMAIN_RK3036(9, 9, 25, true),
+ [RK3228_PD_GMAC] = DOMAIN_RK3036(10, 10, 26, false),
+};
+
static const struct rockchip_domain_info rk3288_pm_domains[] = {
[RK3288_PD_VIO] = DOMAIN_RK3288(7, 7, 4, false),
[RK3288_PD_HEVC] = DOMAIN_RK3288(14, 10, 9, false),
@@ -767,6 +826,46 @@ static const struct rockchip_domain_info rk3399_pm_domains[] = {
[RK3399_PD_SDIOAUDIO] = DOMAIN_RK3399(31, 31, 29, true),
};
+static const struct rockchip_pmu_info px30_pmu = {
+ .pwr_offset = 0x18,
+ .status_offset = 0x20,
+ .req_offset = 0x64,
+ .idle_offset = 0x6c,
+ .ack_offset = 0x6c,
+
+ .num_domains = ARRAY_SIZE(px30_pm_domains),
+ .domain_info = px30_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3036_pmu = {
+ .req_offset = 0x148,
+ .idle_offset = 0x14c,
+ .ack_offset = 0x14c,
+
+ .num_domains = ARRAY_SIZE(rk3036_pm_domains),
+ .domain_info = rk3036_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3128_pmu = {
+ .pwr_offset = 0x04,
+ .status_offset = 0x08,
+ .req_offset = 0x0c,
+ .idle_offset = 0x10,
+ .ack_offset = 0x10,
+
+ .num_domains = ARRAY_SIZE(rk3128_pm_domains),
+ .domain_info = rk3128_pm_domains,
+};
+
+static const struct rockchip_pmu_info rk3228_pmu = {
+ .req_offset = 0x40c,
+ .idle_offset = 0x488,
+ .ack_offset = 0x488,
+
+ .num_domains = ARRAY_SIZE(rk3228_pm_domains),
+ .domain_info = rk3228_pm_domains,
+};
+
static const struct rockchip_pmu_info rk3288_pmu = {
.pwr_offset = 0x08,
.status_offset = 0x0c,
@@ -842,6 +941,22 @@ static const struct rockchip_pmu_info rk3399_pmu = {
static const struct of_device_id rockchip_pm_domain_dt_match[] = {
{
+ .compatible = "rockchip,px30-power-controller",
+ .data = (void *)&px30_pmu,
+ },
+ {
+ .compatible = "rockchip,rk3036-power-controller",
+ .data = (void *)&rk3036_pmu,
+ },
+ {
+ .compatible = "rockchip,rk3128-power-controller",
+ .data = (void *)&rk3128_pmu,
+ },
+ {
+ .compatible = "rockchip,rk3228-power-controller",
+ .data = (void *)&rk3228_pmu,
+ },
+ {
.compatible = "rockchip,rk3288-power-controller",
.data = (void *)&rk3288_pmu,
},
diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c
index caf45cf..ab85829 100644
--- a/drivers/soc/samsung/pm_domains.c
+++ b/drivers/soc/samsung/pm_domains.c
@@ -13,14 +13,11 @@
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/pm_domain.h>
-#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/sched.h>
-#define MAX_CLK_PER_DOMAIN 4
-
struct exynos_pm_domain_config {
/* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
u32 local_pwr_cfg;
@@ -33,10 +30,6 @@ struct exynos_pm_domain {
void __iomem *base;
bool is_off;
struct generic_pm_domain pd;
- struct clk *oscclk;
- struct clk *clk[MAX_CLK_PER_DOMAIN];
- struct clk *pclk[MAX_CLK_PER_DOMAIN];
- struct clk *asb_clk[MAX_CLK_PER_DOMAIN];
u32 local_pwr_cfg;
};
@@ -46,29 +39,10 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
void __iomem *base;
u32 timeout, pwr;
char *op;
- int i;
pd = container_of(domain, struct exynos_pm_domain, pd);
base = pd->base;
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
- if (IS_ERR(pd->asb_clk[i]))
- break;
- clk_prepare_enable(pd->asb_clk[i]);
- }
-
- /* Set oscclk before powering off a domain*/
- if (!power_on) {
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
- if (IS_ERR(pd->clk[i]))
- break;
- pd->pclk[i] = clk_get_parent(pd->clk[i]);
- if (clk_set_parent(pd->clk[i], pd->oscclk))
- pr_err("%s: error setting oscclk as parent to clock %d\n",
- domain->name, i);
- }
- }
-
pwr = power_on ? pd->local_pwr_cfg : 0;
writel_relaxed(pwr, base);
@@ -86,26 +60,6 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
usleep_range(80, 100);
}
- /* Restore clocks after powering on a domain*/
- if (power_on) {
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
- if (IS_ERR(pd->clk[i]))
- break;
-
- if (IS_ERR(pd->pclk[i]))
- continue; /* Skip on first power up */
- if (clk_set_parent(pd->clk[i], pd->pclk[i]))
- pr_err("%s: error setting parent to clock%d\n",
- domain->name, i);
- }
- }
-
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
- if (IS_ERR(pd->asb_clk[i]))
- break;
- clk_disable_unprepare(pd->asb_clk[i]);
- }
-
return 0;
}
@@ -147,12 +101,6 @@ static __init const char *exynos_get_domain_name(struct device_node *node)
return kstrdup_const(name, GFP_KERNEL);
}
-static const char *soc_force_no_clk[] = {
- "samsung,exynos5250-clock",
- "samsung,exynos5420-clock",
- "samsung,exynos5800-clock",
-};
-
static __init int exynos4_pm_init_power_domain(void)
{
struct device_node *np;
@@ -161,7 +109,7 @@ static __init int exynos4_pm_init_power_domain(void)
for_each_matching_node_and_match(np, exynos_pm_domain_of_match, &match) {
const struct exynos_pm_domain_config *pm_domain_cfg;
struct exynos_pm_domain *pd;
- int on, i;
+ int on;
pm_domain_cfg = match->data;
@@ -189,42 +137,6 @@ static __init int exynos4_pm_init_power_domain(void)
pd->pd.power_on = exynos_pd_power_on;
pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
- for (i = 0; i < ARRAY_SIZE(soc_force_no_clk); i++)
- if (of_find_compatible_node(NULL, NULL,
- soc_force_no_clk[i]))
- goto no_clk;
-
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
- char clk_name[8];
-
- snprintf(clk_name, sizeof(clk_name), "asb%d", i);
- pd->asb_clk[i] = of_clk_get_by_name(np, clk_name);
- if (IS_ERR(pd->asb_clk[i]))
- break;
- }
-
- pd->oscclk = of_clk_get_by_name(np, "oscclk");
- if (IS_ERR(pd->oscclk))
- goto no_clk;
-
- for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
- char clk_name[8];
-
- snprintf(clk_name, sizeof(clk_name), "clk%d", i);
- pd->clk[i] = of_clk_get_by_name(np, clk_name);
- if (IS_ERR(pd->clk[i]))
- break;
- /*
- * Skip setting parent on first power up.
- * The parent at this time may not be useful at all.
- */
- pd->pclk[i] = ERR_PTR(-EINVAL);
- }
-
- if (IS_ERR(pd->clk[0]))
- clk_put(pd->oscclk);
-
-no_clk:
on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg;
pm_genpd_init(&pd->pd, NULL, !on);
diff --git a/drivers/soc/ti/knav_qmss.h b/drivers/soc/ti/knav_qmss.h
index 56866ba4..3efc47e 100644
--- a/drivers/soc/ti/knav_qmss.h
+++ b/drivers/soc/ti/knav_qmss.h
@@ -19,6 +19,8 @@
#ifndef __KNAV_QMSS_H__
#define __KNAV_QMSS_H__
+#include <linux/percpu.h>
+
#define THRESH_GTE BIT(7)
#define THRESH_LT 0
@@ -162,11 +164,11 @@ struct knav_qmgr_info {
* notifies: notifier counts
*/
struct knav_queue_stats {
- atomic_t pushes;
- atomic_t pops;
- atomic_t push_errors;
- atomic_t pop_errors;
- atomic_t notifies;
+ unsigned int pushes;
+ unsigned int pops;
+ unsigned int push_errors;
+ unsigned int pop_errors;
+ unsigned int notifies;
};
/**
@@ -283,7 +285,7 @@ struct knav_queue_inst {
struct knav_queue {
struct knav_reg_queue __iomem *reg_push, *reg_pop, *reg_peek;
struct knav_queue_inst *inst;
- struct knav_queue_stats stats;
+ struct knav_queue_stats __percpu *stats;
knav_queue_notify_fn notifier_fn;
void *notifier_fn_arg;
atomic_t notifier_enabled;
diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c
index 3d7225f..316e82e 100644
--- a/drivers/soc/ti/knav_qmss_acc.c
+++ b/drivers/soc/ti/knav_qmss_acc.c
@@ -405,8 +405,8 @@ static int knav_acc_init_queue(struct knav_range_info *range,
{
unsigned id = kq->id - range->queue_base;
- kq->descs = devm_kzalloc(range->kdev->dev,
- ACC_DESCS_MAX * sizeof(u32), GFP_KERNEL);
+ kq->descs = devm_kcalloc(range->kdev->dev,
+ ACC_DESCS_MAX, sizeof(u32), GFP_KERNEL);
if (!kq->descs)
return -ENOMEM;
@@ -552,7 +552,7 @@ int knav_init_acc_range(struct knav_device *kdev,
info->list_size = list_size;
mem_size = PAGE_ALIGN(list_size * 2);
info->mem_size = mem_size;
- range->acc = devm_kzalloc(kdev->dev, channels * sizeof(*range->acc),
+ range->acc = devm_kcalloc(kdev->dev, channels, sizeof(*range->acc),
GFP_KERNEL);
if (!range->acc)
return -ENOMEM;
diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c
index 419365a..6755f2a 100644
--- a/drivers/soc/ti/knav_qmss_queue.c
+++ b/drivers/soc/ti/knav_qmss_queue.c
@@ -99,7 +99,7 @@ void knav_queue_notify(struct knav_queue_inst *inst)
continue;
if (WARN_ON(!qh->notifier_fn))
continue;
- atomic_inc(&qh->stats.notifies);
+ this_cpu_inc(qh->stats->notifies);
qh->notifier_fn(qh->notifier_fn_arg);
}
rcu_read_unlock();
@@ -230,6 +230,12 @@ static struct knav_queue *__knav_queue_open(struct knav_queue_inst *inst,
if (!qh)
return ERR_PTR(-ENOMEM);
+ qh->stats = alloc_percpu(struct knav_queue_stats);
+ if (!qh->stats) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
qh->flags = flags;
qh->inst = inst;
id = inst->id - inst->qmgr->start_queue;
@@ -245,13 +251,17 @@ static struct knav_queue *__knav_queue_open(struct knav_queue_inst *inst,
if (range->ops && range->ops->open_queue)
ret = range->ops->open_queue(range, inst, flags);
- if (ret) {
- devm_kfree(inst->kdev->dev, qh);
- return ERR_PTR(ret);
- }
+ if (ret)
+ goto err;
}
list_add_tail_rcu(&qh->list, &inst->handles);
return qh;
+
+err:
+ if (qh->stats)
+ free_percpu(qh->stats);
+ devm_kfree(inst->kdev->dev, qh);
+ return ERR_PTR(ret);
}
static struct knav_queue *
@@ -427,6 +437,12 @@ static void knav_queue_debug_show_instance(struct seq_file *s,
{
struct knav_device *kdev = inst->kdev;
struct knav_queue *qh;
+ int cpu = 0;
+ int pushes = 0;
+ int pops = 0;
+ int push_errors = 0;
+ int pop_errors = 0;
+ int notifies = 0;
if (!knav_queue_is_busy(inst))
return;
@@ -434,19 +450,22 @@ static void knav_queue_debug_show_instance(struct seq_file *s,
seq_printf(s, "\tqueue id %d (%s)\n",
kdev->base_id + inst->id, inst->name);
for_each_handle_rcu(qh, inst) {
- seq_printf(s, "\t\thandle %p: ", qh);
- seq_printf(s, "pushes %8d, ",
- atomic_read(&qh->stats.pushes));
- seq_printf(s, "pops %8d, ",
- atomic_read(&qh->stats.pops));
- seq_printf(s, "count %8d, ",
- knav_queue_get_count(qh));
- seq_printf(s, "notifies %8d, ",
- atomic_read(&qh->stats.notifies));
- seq_printf(s, "push errors %8d, ",
- atomic_read(&qh->stats.push_errors));
- seq_printf(s, "pop errors %8d\n",
- atomic_read(&qh->stats.pop_errors));
+ for_each_possible_cpu(cpu) {
+ pushes += per_cpu_ptr(qh->stats, cpu)->pushes;
+ pops += per_cpu_ptr(qh->stats, cpu)->pops;
+ push_errors += per_cpu_ptr(qh->stats, cpu)->push_errors;
+ pop_errors += per_cpu_ptr(qh->stats, cpu)->pop_errors;
+ notifies += per_cpu_ptr(qh->stats, cpu)->notifies;
+ }
+
+ seq_printf(s, "\t\thandle %p: pushes %8d, pops %8d, count %8d, notifies %8d, push errors %8d, pop errors %8d\n",
+ qh,
+ pushes,
+ pops,
+ knav_queue_get_count(qh),
+ notifies,
+ push_errors,
+ pop_errors);
}
}
@@ -563,6 +582,7 @@ void knav_queue_close(void *qhandle)
if (range->ops && range->ops->close_queue)
range->ops->close_queue(range, inst);
}
+ free_percpu(qh->stats);
devm_kfree(inst->kdev->dev, qh);
}
EXPORT_SYMBOL_GPL(knav_queue_close);
@@ -636,7 +656,7 @@ int knav_queue_push(void *qhandle, dma_addr_t dma,
val = (u32)dma | ((size / 16) - 1);
writel_relaxed(val, &qh->reg_push[0].ptr_size_thresh);
- atomic_inc(&qh->stats.pushes);
+ this_cpu_inc(qh->stats->pushes);
return 0;
}
EXPORT_SYMBOL_GPL(knav_queue_push);
@@ -674,7 +694,7 @@ dma_addr_t knav_queue_pop(void *qhandle, unsigned *size)
if (size)
*size = ((val & DESC_SIZE_MASK) + 1) * 16;
- atomic_inc(&qh->stats.pops);
+ this_cpu_inc(qh->stats->pops);
return dma;
}
EXPORT_SYMBOL_GPL(knav_queue_pop);
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index 8974a0f..4b5e250 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -1291,7 +1291,7 @@ restore_params:
*
* @stream: Soundwire stream
*
- * Documentation/soundwire/stream.txt explains this API in detail
+ * Documentation/driver-api/soundwire/stream.rst explains this API in detail
*/
int sdw_prepare_stream(struct sdw_stream_runtime *stream)
{
@@ -1348,7 +1348,7 @@ static int _sdw_enable_stream(struct sdw_stream_runtime *stream)
*
* @stream: Soundwire stream
*
- * Documentation/soundwire/stream.txt explains this API in detail
+ * Documentation/driver-api/soundwire/stream.rst explains this API in detail
*/
int sdw_enable_stream(struct sdw_stream_runtime *stream)
{
@@ -1400,7 +1400,7 @@ static int _sdw_disable_stream(struct sdw_stream_runtime *stream)
*
* @stream: Soundwire stream
*
- * Documentation/soundwire/stream.txt explains this API in detail
+ * Documentation/driver-api/soundwire/stream.rst explains this API in detail
*/
int sdw_disable_stream(struct sdw_stream_runtime *stream)
{
@@ -1456,7 +1456,7 @@ static int _sdw_deprepare_stream(struct sdw_stream_runtime *stream)
*
* @stream: Soundwire stream
*
- * Documentation/soundwire/stream.txt explains this API in detail
+ * Documentation/driver-api/soundwire/stream.rst explains this API in detail
*/
int sdw_deprepare_stream(struct sdw_stream_runtime *stream)
{
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index 60d59b0..577084b 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -923,9 +923,10 @@ static int davinci_spi_probe(struct platform_device *pdev)
/* pdata in dspi is now updated and point pdata to that */
pdata = &dspi->pdata;
- dspi->bytes_per_word = devm_kzalloc(&pdev->dev,
- sizeof(*dspi->bytes_per_word) *
- pdata->num_chipselect, GFP_KERNEL);
+ dspi->bytes_per_word = devm_kcalloc(&pdev->dev,
+ pdata->num_chipselect,
+ sizeof(*dspi->bytes_per_word),
+ GFP_KERNEL);
if (dspi->bytes_per_word == NULL) {
ret = -ENOMEM;
goto free_master;
diff --git a/drivers/spi/spi-ep93xx.c b/drivers/spi/spi-ep93xx.c
index e5cc073..f152675 100644
--- a/drivers/spi/spi-ep93xx.c
+++ b/drivers/spi/spi-ep93xx.c
@@ -671,8 +671,8 @@ static int ep93xx_spi_probe(struct platform_device *pdev)
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 16);
master->num_chipselect = info->num_chipselect;
- master->cs_gpios = devm_kzalloc(&master->dev,
- sizeof(int) * master->num_chipselect,
+ master->cs_gpios = devm_kcalloc(&master->dev,
+ master->num_chipselect, sizeof(int),
GFP_KERNEL);
if (!master->cs_gpios) {
error = -ENOMEM;
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index b85a93c..6ae92d4 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -373,8 +373,9 @@ static int spi_gpio_probe(struct platform_device *pdev)
spi_gpio = spi_master_get_devdata(master);
- spi_gpio->cs_gpios = devm_kzalloc(&pdev->dev,
- pdata->num_chipselect * sizeof(*spi_gpio->cs_gpios),
+ spi_gpio->cs_gpios = devm_kcalloc(&pdev->dev,
+ pdata->num_chipselect,
+ sizeof(*spi_gpio->cs_gpios),
GFP_KERNEL);
if (!spi_gpio->cs_gpios)
return -ENOMEM;
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 866246f..d3b21fa 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1511,8 +1511,9 @@ static int spi_imx_probe(struct platform_device *pdev)
if (mxc_platform_info) {
master->num_chipselect = mxc_platform_info->num_chipselect;
if (mxc_platform_info->chipselect) {
- master->cs_gpios = devm_kzalloc(&master->dev,
- sizeof(int) * master->num_chipselect, GFP_KERNEL);
+ master->cs_gpios = devm_kcalloc(&master->dev,
+ master->num_chipselect, sizeof(int),
+ GFP_KERNEL);
if (!master->cs_gpios)
return -ENOMEM;
diff --git a/drivers/spi/spi-oc-tiny.c b/drivers/spi/spi-oc-tiny.c
index b591128..085f580 100644
--- a/drivers/spi/spi-oc-tiny.c
+++ b/drivers/spi/spi-oc-tiny.c
@@ -213,8 +213,8 @@ static int tiny_spi_of_probe(struct platform_device *pdev)
return 0;
hw->gpio_cs_count = of_gpio_count(np);
if (hw->gpio_cs_count > 0) {
- hw->gpio_cs = devm_kzalloc(&pdev->dev,
- hw->gpio_cs_count * sizeof(unsigned int),
+ hw->gpio_cs = devm_kcalloc(&pdev->dev,
+ hw->gpio_cs_count, sizeof(unsigned int),
GFP_KERNEL);
if (!hw->gpio_cs)
return -ENOMEM;
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 4797c57..1af8c96 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -2135,7 +2135,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
pl022->master_info = platform_info;
pl022->adev = adev;
pl022->vendor = id->data;
- pl022->chipselects = devm_kzalloc(dev, num_cs * sizeof(int),
+ pl022->chipselects = devm_kcalloc(dev, num_cs, sizeof(int),
GFP_KERNEL);
if (!pl022->chipselects) {
status = -ENOMEM;
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index efc624f..ec395a6 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2049,7 +2049,7 @@ static int of_spi_register_master(struct spi_controller *ctlr)
else if (nb < 0)
return nb;
- cs = devm_kzalloc(&ctlr->dev, sizeof(int) * ctlr->num_chipselect,
+ cs = devm_kcalloc(&ctlr->dev, ctlr->num_chipselect, sizeof(int),
GFP_KERNEL);
ctlr->cs_gpios = cs;
diff --git a/drivers/staging/android/ion/ion_heap.c b/drivers/staging/android/ion/ion_heap.c
index 772dad6..e8c4403 100644
--- a/drivers/staging/android/ion/ion_heap.c
+++ b/drivers/staging/android/ion/ion_heap.c
@@ -25,7 +25,8 @@ void *ion_heap_map_kernel(struct ion_heap *heap,
pgprot_t pgprot;
struct sg_table *table = buffer->sg_table;
int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE;
- struct page **pages = vmalloc(sizeof(struct page *) * npages);
+ struct page **pages = vmalloc(array_size(npages,
+ sizeof(struct page *)));
struct page **tmp = pages;
if (!pages)
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index 0e36b66..731e471 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -246,7 +246,7 @@ static int fbtft_request_gpios_dt(struct fbtft_par *par)
static int fbtft_backlight_update_status(struct backlight_device *bd)
{
struct fbtft_par *par = bl_get_data(bd);
- bool polarity = !!(bd->props.state & BL_CORE_DRIVER1);
+ bool polarity = par->polarity;
fbtft_par_dbg(DEBUG_BACKLIGHT, par,
"%s: polarity=%d, power=%d, fb_blank=%d\n",
@@ -296,7 +296,7 @@ void fbtft_register_backlight(struct fbtft_par *par)
/* Assume backlight is off, get polarity from current state of pin */
bl_props.power = FB_BLANK_POWERDOWN;
if (!gpio_get_value(par->gpio.led[0]))
- bl_props.state |= BL_CORE_DRIVER1;
+ par->polarity = true;
bd = backlight_device_register(dev_driver_string(par->info->device),
par->info->device, par,
diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h
index e19e64e..c7cb4a7 100644
--- a/drivers/staging/fbtft/fbtft.h
+++ b/drivers/staging/fbtft/fbtft.h
@@ -229,6 +229,7 @@ struct fbtft_par {
ktime_t update_time;
bool bgr;
void *extra;
+ bool polarity;
};
#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt
index 0ba6771..72ba9da 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt
+++ b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt
@@ -11,7 +11,7 @@ pool management for network interfaces.
This document provides an overview the Linux DPIO driver, its
subcomponents, and its APIs.
-See Documentation/dpaa2/overview.txt for a general overview of DPAA2
+See Documentation/networking/dpaa2/overview.rst for a general overview of DPAA2
and the general DPAA2 driver architecture in Linux.
Driver Overview
diff --git a/drivers/staging/greybus/audio_topology.c b/drivers/staging/greybus/audio_topology.c
index 15e57f7..b710783 100644
--- a/drivers/staging/greybus/audio_topology.c
+++ b/drivers/staging/greybus/audio_topology.c
@@ -144,7 +144,7 @@ static const char **gb_generate_enum_strings(struct gbaudio_module_info *gb,
__u8 *data;
items = le32_to_cpu(gbenum->items);
- strings = devm_kzalloc(gb->dev, sizeof(char *) * items, GFP_KERNEL);
+ strings = devm_kcalloc(gb->dev, items, sizeof(char *), GFP_KERNEL);
data = gbenum->names;
for (i = 0; i < items; i++) {
diff --git a/drivers/staging/greybus/camera.c b/drivers/staging/greybus/camera.c
index 341f729..6dded10 100644
--- a/drivers/staging/greybus/camera.c
+++ b/drivers/staging/greybus/camera.c
@@ -1175,8 +1175,9 @@ static int gb_camera_debugfs_init(struct gb_camera *gcam)
gcam->debugfs.root = debugfs_create_dir(dirname, gb_debugfs_get());
- gcam->debugfs.buffers = vmalloc(sizeof(*gcam->debugfs.buffers) *
- GB_CAMERA_DEBUGFS_BUFFER_MAX);
+ gcam->debugfs.buffers =
+ vmalloc(array_size(GB_CAMERA_DEBUGFS_BUFFER_MAX,
+ sizeof(*gcam->debugfs.buffers)));
if (!gcam->debugfs.buffers)
return -ENOMEM;
diff --git a/drivers/staging/media/bcm2048/TODO b/drivers/staging/media/bcm2048/TODO
index 051f85d..6bee2a2da 100644
--- a/drivers/staging/media/bcm2048/TODO
+++ b/drivers/staging/media/bcm2048/TODO
@@ -3,7 +3,7 @@ TODO:
From the initial code review:
The main thing you need to do is to implement all the controls using the
-control framework (see Documentation/video4linux/v4l2-controls.txt).
+control framework (see Documentation/media/kapi/v4l2-controls.rst).
Most drivers are by now converted to the control framework, so you will
find many examples of how to do this in drivers/media/radio.
diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index 289d775..b0be80f 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -303,9 +303,9 @@ static int imx_media_alloc_pad_vdev_lists(struct imx_media_dev *imxmd)
list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) {
entity = &sd->entity;
- vdev_lists = devm_kzalloc(
+ vdev_lists = devm_kcalloc(
imxmd->md.dev,
- entity->num_pads * sizeof(*vdev_lists),
+ entity->num_pads, sizeof(*vdev_lists),
GFP_KERNEL);
if (!vdev_lists)
return -ENOMEM;
@@ -544,7 +544,7 @@ static int imx_media_probe(struct platform_device *pdev)
goto unreg_dev;
}
- subdevs = devm_kzalloc(imxmd->md.dev, sizeof(*subdevs) * num_subdevs,
+ subdevs = devm_kcalloc(imxmd->md.dev, num_subdevs, sizeof(*subdevs),
GFP_KERNEL);
if (!subdevs) {
ret = -ENOMEM;
diff --git a/drivers/staging/media/zoran/Kconfig b/drivers/staging/media/zoran/Kconfig
index 63df5de..34a1813 100644
--- a/drivers/staging/media/zoran/Kconfig
+++ b/drivers/staging/media/zoran/Kconfig
@@ -7,7 +7,7 @@ config VIDEO_ZORAN
36057/36067 PCI controller chipset. This includes the Iomega
Buz, Pinnacle DC10+ and the Linux Media Labs LML33. There is
a driver homepage at <http://mjpeg.sf.net/driver-zoran/>. For
- more information, check <file:Documentation/video4linux/Zoran>.
+ more information, check <file:Documentation/media/v4l-drivers/zoran.rst>.
To compile this driver as a module, choose M here: the
module will be called zr36067.
diff --git a/drivers/staging/media/zoran/zoran_driver.c b/drivers/staging/media/zoran/zoran_driver.c
index d2e13ff..d784222 100644
--- a/drivers/staging/media/zoran/zoran_driver.c
+++ b/drivers/staging/media/zoran/zoran_driver.c
@@ -941,7 +941,7 @@ static int zoran_open(struct file *file)
/* used to be BUZ_MAX_WIDTH/HEIGHT, but that gives overflows
* on norm-change! */
fh->overlay_mask =
- kmalloc(((768 + 31) / 32) * 576 * 4, GFP_KERNEL);
+ kmalloc(array3_size((768 + 31) / 32, 576, 4), GFP_KERNEL);
if (!fh->overlay_mask) {
dprintk(1,
KERN_ERR
@@ -1220,7 +1220,8 @@ static int setup_window(struct zoran_fh *fh,
}
} else if (clipcount) {
/* write our own bitmap from the clips */
- vcp = vmalloc(sizeof(struct v4l2_clip) * (clipcount + 4));
+ vcp = vmalloc(array_size(sizeof(struct v4l2_clip),
+ clipcount + 4));
if (vcp == NULL) {
dprintk(1,
KERN_ERR
diff --git a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c
index 2d9ab26..0c3e498 100644
--- a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c
+++ b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c
@@ -143,7 +143,7 @@ static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev,
if (!max_maps)
return max_maps;
- *map = kzalloc(max_maps * sizeof(struct pinctrl_map), GFP_KERNEL);
+ *map = kcalloc(max_maps, sizeof(struct pinctrl_map), GFP_KERNEL);
if (!*map)
return -ENOMEM;
@@ -287,7 +287,8 @@ static int rt2880_pinmux_index(struct rt2880_priv *p)
}
/* allocate the group names array needed by the gpio function */
- p->group_names = devm_kzalloc(p->dev, sizeof(char *) * p->group_count, GFP_KERNEL);
+ p->group_names = devm_kcalloc(p->dev, p->group_count, sizeof(char *),
+ GFP_KERNEL);
if (!p->group_names)
return -1;
@@ -300,8 +301,12 @@ static int rt2880_pinmux_index(struct rt2880_priv *p)
p->func_count++;
/* allocate our function and group mapping index buffers */
- f = p->func = devm_kzalloc(p->dev, sizeof(struct rt2880_pmx_func) * p->func_count, GFP_KERNEL);
- gpio_func.groups = devm_kzalloc(p->dev, sizeof(int) * p->group_count, GFP_KERNEL);
+ f = p->func = devm_kcalloc(p->dev,
+ p->func_count,
+ sizeof(struct rt2880_pmx_func),
+ GFP_KERNEL);
+ gpio_func.groups = devm_kcalloc(p->dev, p->group_count, sizeof(int),
+ GFP_KERNEL);
if (!f || !gpio_func.groups)
return -1;
@@ -337,7 +342,10 @@ static int rt2880_pinmux_pins(struct rt2880_priv *p)
if (!p->func[i]->pin_count)
continue;
- p->func[i]->pins = devm_kzalloc(p->dev, sizeof(int) * p->func[i]->pin_count, GFP_KERNEL);
+ p->func[i]->pins = devm_kcalloc(p->dev,
+ p->func[i]->pin_count,
+ sizeof(int),
+ GFP_KERNEL);
for (j = 0; j < p->func[i]->pin_count; j++)
p->func[i]->pins[j] = p->func[i]->pin_first + j;
@@ -347,11 +355,11 @@ static int rt2880_pinmux_pins(struct rt2880_priv *p)
}
/* the buffer that tells us which pins are gpio */
- p->gpio = devm_kzalloc(p->dev,sizeof(uint8_t) * p->max_pins,
- GFP_KERNEL);
+ p->gpio = devm_kcalloc(p->dev,p->max_pins, sizeof(uint8_t),
+ GFP_KERNEL);
/* the pads needed to tell pinctrl about our pins */
- p->pads = devm_kzalloc(p->dev,
- sizeof(struct pinctrl_pin_desc) * p->max_pins,
+ p->pads = devm_kcalloc(p->dev,
+ p->max_pins, sizeof(struct pinctrl_pin_desc),
GFP_KERNEL);
if (!p->pads || !p->gpio ) {
dev_err(p->dev, "Failed to allocate gpio data\n");
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
index 24e9299..50e7cae 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
@@ -53,7 +53,7 @@ int rtw_init_mlme_priv(struct adapter *padapter)
memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
- pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
+ pbuf = vzalloc(array_size(MAX_BSS_CNT, sizeof(struct wlan_network)));
if (!pbuf) {
res = _FAIL;
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index 37a610d..f2cdcc2 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -597,8 +597,9 @@ static void RxReorderIndicatePacket(struct ieee80211_device *ieee,
bool bMatchWinStart = false, bPktInBuf = false;
IEEE80211_DEBUG(IEEE80211_DL_REORDER,"%s(): Seq is %d,pTS->RxIndicateSeq is %d, WinSize is %d\n",__func__,SeqNum,pTS->RxIndicateSeq,WinSize);
- prxbIndicateArray = kmalloc(sizeof(struct ieee80211_rxb *) *
- REORDER_WIN_SIZE, GFP_KERNEL);
+ prxbIndicateArray = kmalloc_array(REORDER_WIN_SIZE,
+ sizeof(struct ieee80211_rxb *),
+ GFP_KERNEL);
if (!prxbIndicateArray)
return;
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index a4df95c..8b17400 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -1640,8 +1640,8 @@ static short rtl8192_usb_initendpoints(struct net_device *dev)
{
struct r8192_priv *priv = ieee80211_priv(dev);
- priv->rx_urb = kmalloc(sizeof(struct urb *) * (MAX_RX_URB + 1),
- GFP_KERNEL);
+ priv->rx_urb = kmalloc_array(MAX_RX_URB + 1, sizeof(struct urb *),
+ GFP_KERNEL);
if (!priv->rx_urb)
return -ENOMEM;
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c
index cc4f115..f9392b8 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
@@ -37,7 +37,7 @@ sint _rtw_init_mlme_priv(struct adapter *padapter)
memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
- pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
+ pbuf = vzalloc(array_size(MAX_BSS_CNT, sizeof(struct wlan_network)));
if (pbuf == NULL) {
res = _FAIL;
diff --git a/drivers/staging/rtlwifi/efuse.c b/drivers/staging/rtlwifi/efuse.c
index d7c7d14..1dc7145 100644
--- a/drivers/staging/rtlwifi/efuse.c
+++ b/drivers/staging/rtlwifi/efuse.c
@@ -237,8 +237,8 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf)
}
/* allocate memory for efuse_tbl and efuse_word */
- efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE] *
- sizeof(u8), GFP_ATOMIC);
+ efuse_tbl = kzalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE],
+ GFP_ATOMIC);
if (!efuse_tbl)
return;
efuse_word = kcalloc(EFUSE_MAX_WORD_UNIT, sizeof(u16 *), GFP_ATOMIC);
diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c
index 821256b..b89ef15 100644
--- a/drivers/staging/rts5208/ms.c
+++ b/drivers/staging/rts5208/ms.c
@@ -2618,7 +2618,7 @@ static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
segment = &ms_card->segment[seg_no];
if (!segment->l2p_table) {
- segment->l2p_table = vmalloc(table_size * 2);
+ segment->l2p_table = vmalloc(array_size(table_size, 2));
if (!segment->l2p_table) {
rtsx_trace(chip);
goto BUILD_FAIL;
diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c
index 4ad472d..8a82346 100644
--- a/drivers/staging/rts5208/rtsx_chip.c
+++ b/drivers/staging/rts5208/rtsx_chip.c
@@ -1660,13 +1660,13 @@ int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
- data = vzalloc(dw_len * 4);
+ data = vzalloc(array_size(dw_len, 4));
if (!data) {
rtsx_trace(chip);
return STATUS_NOMEM;
}
- mask = vzalloc(dw_len * 4);
+ mask = vzalloc(array_size(dw_len, 4));
if (!mask) {
vfree(data);
rtsx_trace(chip);
@@ -1721,7 +1721,7 @@ int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
- data = vmalloc(dw_len * 4);
+ data = vmalloc(array_size(dw_len, 4));
if (!data) {
rtsx_trace(chip);
return STATUS_NOMEM;
diff --git a/drivers/staging/unisys/visorhba/visorhba_main.c b/drivers/staging/unisys/visorhba/visorhba_main.c
index 167e98f..4fc521c 100644
--- a/drivers/staging/unisys/visorhba/visorhba_main.c
+++ b/drivers/staging/unisys/visorhba/visorhba_main.c
@@ -865,7 +865,7 @@ static void do_scsi_nolinuxstat(struct uiscmdrsp *cmdrsp,
if (cmdrsp->scsi.no_disk_result == 0)
return;
- buf = kzalloc(sizeof(char) * 36, GFP_KERNEL);
+ buf = kzalloc(36, GFP_KERNEL);
if (!buf)
return;
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 3f4bf12..5ccef7d 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -155,6 +155,8 @@ static ssize_t target_core_item_dbroot_store(struct config_item *item,
mutex_unlock(&g_tf_lock);
+ pr_debug("Target_Core_ConfigFS: db_root set to %s\n", db_root);
+
return read_bytes;
}
@@ -3213,6 +3215,27 @@ void target_setup_backend_cits(struct target_backend *tb)
target_core_setup_dev_stat_cit(tb);
}
+static void target_init_dbroot(void)
+{
+ struct file *fp;
+
+ snprintf(db_root_stage, DB_ROOT_LEN, DB_ROOT_PREFERRED);
+ fp = filp_open(db_root_stage, O_RDONLY, 0);
+ if (IS_ERR(fp)) {
+ pr_err("db_root: cannot open: %s\n", db_root_stage);
+ return;
+ }
+ if (!S_ISDIR(file_inode(fp)->i_mode)) {
+ filp_close(fp, NULL);
+ pr_err("db_root: not a valid directory: %s\n", db_root_stage);
+ return;
+ }
+ filp_close(fp, NULL);
+
+ strncpy(db_root, db_root_stage, DB_ROOT_LEN);
+ pr_debug("Target_Core_ConfigFS: db_root set to %s\n", db_root);
+}
+
static int __init target_core_init_configfs(void)
{
struct configfs_subsystem *subsys = &target_core_fabrics;
@@ -3293,6 +3316,8 @@ static int __init target_core_init_configfs(void)
if (ret < 0)
goto out;
+ target_init_dbroot();
+
return 0;
out:
diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c
index 9b2c0c77..16751ae 100644
--- a/drivers/target/target_core_file.c
+++ b/drivers/target/target_core_file.c
@@ -250,6 +250,84 @@ static void fd_destroy_device(struct se_device *dev)
}
}
+struct target_core_file_cmd {
+ unsigned long len;
+ struct se_cmd *cmd;
+ struct kiocb iocb;
+};
+
+static void cmd_rw_aio_complete(struct kiocb *iocb, long ret, long ret2)
+{
+ struct target_core_file_cmd *cmd;
+
+ cmd = container_of(iocb, struct target_core_file_cmd, iocb);
+
+ if (ret != cmd->len)
+ target_complete_cmd(cmd->cmd, SAM_STAT_CHECK_CONDITION);
+ else
+ target_complete_cmd(cmd->cmd, SAM_STAT_GOOD);
+
+ kfree(cmd);
+}
+
+static sense_reason_t
+fd_execute_rw_aio(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
+ enum dma_data_direction data_direction)
+{
+ int is_write = !(data_direction == DMA_FROM_DEVICE);
+ struct se_device *dev = cmd->se_dev;
+ struct fd_dev *fd_dev = FD_DEV(dev);
+ struct file *file = fd_dev->fd_file;
+ struct target_core_file_cmd *aio_cmd;
+ struct iov_iter iter = {};
+ struct scatterlist *sg;
+ struct bio_vec *bvec;
+ ssize_t len = 0;
+ int ret = 0, i;
+
+ aio_cmd = kmalloc(sizeof(struct target_core_file_cmd), GFP_KERNEL);
+ if (!aio_cmd)
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+
+ bvec = kcalloc(sgl_nents, sizeof(struct bio_vec), GFP_KERNEL);
+ if (!bvec) {
+ kfree(aio_cmd);
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ }
+
+ for_each_sg(sgl, sg, sgl_nents, i) {
+ bvec[i].bv_page = sg_page(sg);
+ bvec[i].bv_len = sg->length;
+ bvec[i].bv_offset = sg->offset;
+
+ len += sg->length;
+ }
+
+ iov_iter_bvec(&iter, ITER_BVEC | is_write, bvec, sgl_nents, len);
+
+ aio_cmd->cmd = cmd;
+ aio_cmd->len = len;
+ aio_cmd->iocb.ki_pos = cmd->t_task_lba * dev->dev_attrib.block_size;
+ aio_cmd->iocb.ki_filp = file;
+ aio_cmd->iocb.ki_complete = cmd_rw_aio_complete;
+ aio_cmd->iocb.ki_flags = IOCB_DIRECT;
+
+ if (is_write && (cmd->se_cmd_flags & SCF_FUA))
+ aio_cmd->iocb.ki_flags |= IOCB_DSYNC;
+
+ if (is_write)
+ ret = call_write_iter(file, &aio_cmd->iocb, &iter);
+ else
+ ret = call_read_iter(file, &aio_cmd->iocb, &iter);
+
+ kfree(bvec);
+
+ if (ret != -EIOCBQUEUED)
+ cmd_rw_aio_complete(&aio_cmd->iocb, ret, 0);
+
+ return 0;
+}
+
static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
u32 block_size, struct scatterlist *sgl,
u32 sgl_nents, u32 data_length, int is_write)
@@ -527,7 +605,7 @@ fd_execute_unmap(struct se_cmd *cmd, sector_t lba, sector_t nolb)
}
static sense_reason_t
-fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
+fd_execute_rw_buffered(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
enum dma_data_direction data_direction)
{
struct se_device *dev = cmd->se_dev;
@@ -537,16 +615,6 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
sense_reason_t rc;
int ret = 0;
/*
- * We are currently limited by the number of iovecs (2048) per
- * single vfs_[writev,readv] call.
- */
- if (cmd->data_length > FD_MAX_BYTES) {
- pr_err("FILEIO: Not able to process I/O of %u bytes due to"
- "FD_MAX_BYTES: %u iovec count limitation\n",
- cmd->data_length, FD_MAX_BYTES);
- return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
- }
- /*
* Call vectorized fileio functions to map struct scatterlist
* physical memory addresses to struct iovec virtual memory.
*/
@@ -620,14 +688,39 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
return 0;
}
+static sense_reason_t
+fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
+ enum dma_data_direction data_direction)
+{
+ struct se_device *dev = cmd->se_dev;
+ struct fd_dev *fd_dev = FD_DEV(dev);
+
+ /*
+ * We are currently limited by the number of iovecs (2048) per
+ * single vfs_[writev,readv] call.
+ */
+ if (cmd->data_length > FD_MAX_BYTES) {
+ pr_err("FILEIO: Not able to process I/O of %u bytes due to"
+ "FD_MAX_BYTES: %u iovec count limitation\n",
+ cmd->data_length, FD_MAX_BYTES);
+ return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+ }
+
+ if (fd_dev->fbd_flags & FDBD_HAS_ASYNC_IO)
+ return fd_execute_rw_aio(cmd, sgl, sgl_nents, data_direction);
+ return fd_execute_rw_buffered(cmd, sgl, sgl_nents, data_direction);
+}
+
enum {
- Opt_fd_dev_name, Opt_fd_dev_size, Opt_fd_buffered_io, Opt_err
+ Opt_fd_dev_name, Opt_fd_dev_size, Opt_fd_buffered_io,
+ Opt_fd_async_io, Opt_err
};
static match_table_t tokens = {
{Opt_fd_dev_name, "fd_dev_name=%s"},
{Opt_fd_dev_size, "fd_dev_size=%s"},
{Opt_fd_buffered_io, "fd_buffered_io=%d"},
+ {Opt_fd_async_io, "fd_async_io=%d"},
{Opt_err, NULL}
};
@@ -693,6 +786,21 @@ static ssize_t fd_set_configfs_dev_params(struct se_device *dev,
fd_dev->fbd_flags |= FDBD_HAS_BUFFERED_IO_WCE;
break;
+ case Opt_fd_async_io:
+ ret = match_int(args, &arg);
+ if (ret)
+ goto out;
+ if (arg != 1) {
+ pr_err("bogus fd_async_io=%d value\n", arg);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pr_debug("FILEIO: Using async I/O"
+ " operations for struct fd_dev\n");
+
+ fd_dev->fbd_flags |= FDBD_HAS_ASYNC_IO;
+ break;
default:
break;
}
@@ -709,10 +817,11 @@ static ssize_t fd_show_configfs_dev_params(struct se_device *dev, char *b)
ssize_t bl = 0;
bl = sprintf(b + bl, "TCM FILEIO ID: %u", fd_dev->fd_dev_id);
- bl += sprintf(b + bl, " File: %s Size: %llu Mode: %s\n",
+ bl += sprintf(b + bl, " File: %s Size: %llu Mode: %s Async: %d\n",
fd_dev->fd_dev_name, fd_dev->fd_dev_size,
(fd_dev->fbd_flags & FDBD_HAS_BUFFERED_IO_WCE) ?
- "Buffered-WCE" : "O_DSYNC");
+ "Buffered-WCE" : "O_DSYNC",
+ !!(fd_dev->fbd_flags & FDBD_HAS_ASYNC_IO));
return bl;
}
diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core_file.h
index 53be5ff..929b1ec 100644
--- a/drivers/target/target_core_file.h
+++ b/drivers/target/target_core_file.h
@@ -22,6 +22,7 @@
#define FBDF_HAS_PATH 0x01
#define FBDF_HAS_SIZE 0x02
#define FDBD_HAS_BUFFERED_IO_WCE 0x04
+#define FDBD_HAS_ASYNC_IO 0x08
#define FDBD_FORMAT_UNIT_SIZE 2048
struct fd_dev {
diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h
index 1d5afc3..dead30b 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -166,6 +166,7 @@ extern struct se_portal_group xcopy_pt_tpg;
/* target_core_configfs.c */
#define DB_ROOT_LEN 4096
#define DB_ROOT_DEFAULT "/var/target"
+#define DB_ROOT_PREFERRED "/etc/target"
extern char db_root[];
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c
index 668934e..47d76c8 100644
--- a/drivers/target/target_core_pscsi.c
+++ b/drivers/target/target_core_pscsi.c
@@ -689,8 +689,29 @@ after_mode_sense:
}
after_mode_select:
- if (scsi_status == SAM_STAT_CHECK_CONDITION)
+ if (scsi_status == SAM_STAT_CHECK_CONDITION) {
transport_copy_sense_to_cmd(cmd, req_sense);
+
+ /*
+ * check for TAPE device reads with
+ * FM/EOM/ILI set, so that we can get data
+ * back despite framework assumption that a
+ * check condition means there is no data
+ */
+ if (sd->type == TYPE_TAPE &&
+ cmd->data_direction == DMA_FROM_DEVICE) {
+ /*
+ * is sense data valid, fixed format,
+ * and have FM, EOM, or ILI set?
+ */
+ if (req_sense[0] == 0xf0 && /* valid, fixed format */
+ req_sense[2] & 0xe0 && /* FM, EOM, or ILI */
+ (req_sense[2] & 0xf) == 0) { /* key==NO_SENSE */
+ pr_debug("Tape FM/EOM/ILI status detected. Treat as normal read.\n");
+ cmd->se_cmd_flags |= SCF_TREAT_READ_AS_NORMAL;
+ }
+ }
+ }
}
enum {
@@ -1062,7 +1083,8 @@ static void pscsi_req_done(struct request *req, blk_status_t status)
switch (host_byte(result)) {
case DID_OK:
- target_complete_cmd(cmd, scsi_status);
+ target_complete_cmd_with_length(cmd, scsi_status,
+ cmd->data_length - scsi_req(req)->resid_len);
break;
default:
pr_debug("PSCSI Host Byte exception at cmd: %p CDB:"
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 4558f2e..ee5081b 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -250,10 +250,10 @@ int transport_alloc_session_tags(struct se_session *se_sess,
{
int rc;
- se_sess->sess_cmd_map = kzalloc(tag_num * tag_size,
+ se_sess->sess_cmd_map = kcalloc(tag_size, tag_num,
GFP_KERNEL | __GFP_NOWARN | __GFP_RETRY_MAYFAIL);
if (!se_sess->sess_cmd_map) {
- se_sess->sess_cmd_map = vzalloc(tag_num * tag_size);
+ se_sess->sess_cmd_map = vzalloc(array_size(tag_size, tag_num));
if (!se_sess->sess_cmd_map) {
pr_err("Unable to allocate se_sess->sess_cmd_map\n");
return -ENOMEM;
@@ -779,7 +779,9 @@ EXPORT_SYMBOL(target_complete_cmd);
void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length)
{
- if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) {
+ if ((scsi_status == SAM_STAT_GOOD ||
+ cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) &&
+ length < cmd->data_length) {
if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
cmd->residual_count += cmd->data_length - length;
} else {
@@ -1431,7 +1433,7 @@ transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
return 0;
}
-/*
+/**
* target_submit_cmd_map_sgls - lookup unpacked lun and submit uninitialized
* se_cmd + use pre-allocated SGL memory.
*
@@ -1441,7 +1443,7 @@ transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
* @sense: pointer to SCSI sense buffer
* @unpacked_lun: unpacked LUN to reference for struct se_lun
* @data_length: fabric expected data transfer length
- * @task_addr: SAM task attribute
+ * @task_attr: SAM task attribute
* @data_dir: DMA data direction
* @flags: flags for command submission from target_sc_flags_tables
* @sgl: struct scatterlist memory for unidirectional mapping
@@ -1578,7 +1580,7 @@ int target_submit_cmd_map_sgls(struct se_cmd *se_cmd, struct se_session *se_sess
}
EXPORT_SYMBOL(target_submit_cmd_map_sgls);
-/*
+/**
* target_submit_cmd - lookup unpacked lun and submit uninitialized se_cmd
*
* @se_cmd: command descriptor to submit
@@ -1587,7 +1589,7 @@ EXPORT_SYMBOL(target_submit_cmd_map_sgls);
* @sense: pointer to SCSI sense buffer
* @unpacked_lun: unpacked LUN to reference for struct se_lun
* @data_length: fabric expected data transfer length
- * @task_addr: SAM task attribute
+ * @task_attr: SAM task attribute
* @data_dir: DMA data direction
* @flags: flags for command submission from target_sc_flags_tables
*
@@ -1654,7 +1656,7 @@ static bool target_lookup_lun_from_tag(struct se_session *se_sess, u64 tag,
* @se_sess: associated se_sess for endpoint
* @sense: pointer to SCSI sense buffer
* @unpacked_lun: unpacked LUN to reference for struct se_lun
- * @fabric_context: fabric context for TMR req
+ * @fabric_tmr_ptr: fabric context for TMR req
* @tm_type: Type of TM request
* @gfp: gfp type for caller
* @tag: referenced task tag for TMR_ABORT_TASK
@@ -2084,12 +2086,24 @@ static void transport_complete_qf(struct se_cmd *cmd)
goto queue_status;
}
- if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)
+ /*
+ * Check if we need to send a sense buffer from
+ * the struct se_cmd in question. We do NOT want
+ * to take this path of the IO has been marked as
+ * needing to be treated like a "normal read". This
+ * is the case if it's a tape read, and either the
+ * FM, EOM, or ILI bits are set, but there is no
+ * sense data.
+ */
+ if (!(cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) &&
+ cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)
goto queue_status;
switch (cmd->data_direction) {
case DMA_FROM_DEVICE:
- if (cmd->scsi_status)
+ /* queue status if not treating this as a normal read */
+ if (cmd->scsi_status &&
+ !(cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL))
goto queue_status;
trace_target_cmd_complete(cmd);
@@ -2194,9 +2208,15 @@ static void target_complete_ok_work(struct work_struct *work)
/*
* Check if we need to send a sense buffer from
- * the struct se_cmd in question.
+ * the struct se_cmd in question. We do NOT want
+ * to take this path of the IO has been marked as
+ * needing to be treated like a "normal read". This
+ * is the case if it's a tape read, and either the
+ * FM, EOM, or ILI bits are set, but there is no
+ * sense data.
*/
- if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) {
+ if (!(cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL) &&
+ cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) {
WARN_ON(!cmd->scsi_status);
ret = transport_send_check_condition_and_sense(
cmd, 0, 1);
@@ -2238,7 +2258,18 @@ static void target_complete_ok_work(struct work_struct *work)
queue_rsp:
switch (cmd->data_direction) {
case DMA_FROM_DEVICE:
- if (cmd->scsi_status)
+ /*
+ * if this is a READ-type IO, but SCSI status
+ * is set, then skip returning data and just
+ * return the status -- unless this IO is marked
+ * as needing to be treated as a normal read,
+ * in which case we want to go ahead and return
+ * the data. This happens, for example, for tape
+ * reads with the FM, EOM, or ILI bits set, with
+ * no sense data.
+ */
+ if (cmd->scsi_status &&
+ !(cmd->se_cmd_flags & SCF_TREAT_READ_AS_NORMAL))
goto queue_status;
atomic_long_add(cmd->data_length,
@@ -2606,7 +2637,8 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
}
EXPORT_SYMBOL(transport_generic_free_cmd);
-/* target_get_sess_cmd - Add command to active ->sess_cmd_list
+/**
+ * target_get_sess_cmd - Add command to active ->sess_cmd_list
* @se_cmd: command descriptor to add
* @ack_kref: Signal that fabric will perform an ack target_put_sess_cmd()
*/
@@ -2800,7 +2832,8 @@ void target_show_cmd(const char *pfx, struct se_cmd *cmd)
}
EXPORT_SYMBOL(target_show_cmd);
-/* target_sess_cmd_list_set_waiting - Flag all commands in
+/**
+ * target_sess_cmd_list_set_waiting - Flag all commands in
* sess_cmd_list to complete cmd_wait_comp. Set
* sess_tearing_down so no more commands are queued.
* @se_sess: session to flag
@@ -2835,7 +2868,8 @@ void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
}
EXPORT_SYMBOL(target_sess_cmd_list_set_waiting);
-/* target_wait_for_sess_cmds - Wait for outstanding descriptors
+/**
+ * target_wait_for_sess_cmds - Wait for outstanding descriptors
* @se_sess: session to wait for active I/O
*/
void target_wait_for_sess_cmds(struct se_session *se_sess)
@@ -3332,7 +3366,7 @@ static void target_tmr_work(struct work_struct *work)
tmr->response = TMR_FUNCTION_REJECTED;
break;
default:
- pr_err("Uknown TMR function: 0x%02x.\n",
+ pr_err("Unknown TMR function: 0x%02x.\n",
tmr->function);
tmr->response = TMR_FUNCTION_REJECTED;
break;
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 4f26bdc..7f96dfa 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -42,7 +42,11 @@
#include <linux/target_core_user.h>
-/*
+/**
+ * DOC: Userspace I/O
+ * Userspace I/O
+ * -------------
+ *
* Define a shared-memory interface for LIO to pass SCSI commands and
* data to userspace for processing. This is to allow backends that
* are too complex for in-kernel support to be possible.
@@ -53,7 +57,7 @@
* See the .h file for how the ring is laid out. Note that while the
* command ring is defined, the particulars of the data area are
* not. Offset values in the command entry point to other locations
- * internal to the mmap()ed area. There is separate space outside the
+ * internal to the mmap-ed area. There is separate space outside the
* command ring for data buffers. This leaves maximum flexibility for
* moving buffer allocations, or even page flipping or other
* allocation techniques, without altering the command ring layout.
@@ -1382,7 +1386,7 @@ static struct page *tcmu_try_get_block_page(struct tcmu_dev *udev, uint32_t dbi)
return page;
}
-static int tcmu_vma_fault(struct vm_fault *vmf)
+static vm_fault_t tcmu_vma_fault(struct vm_fault *vmf)
{
struct tcmu_dev *udev = vmf->vma->vm_private_data;
struct uio_info *info = &udev->uio_info;
@@ -1586,8 +1590,9 @@ static int tcmu_wait_genl_cmd_reply(struct tcmu_dev *udev)
return ret;
}
-static int tcmu_netlink_event(struct tcmu_dev *udev, enum tcmu_genl_cmd cmd,
- int reconfig_attr, const void *reconfig_data)
+static int tcmu_netlink_event_init(struct tcmu_dev *udev,
+ enum tcmu_genl_cmd cmd,
+ struct sk_buff **buf, void **hdr)
{
struct sk_buff *skb;
void *msg_header;
@@ -1613,46 +1618,66 @@ static int tcmu_netlink_event(struct tcmu_dev *udev, enum tcmu_genl_cmd cmd,
if (ret < 0)
goto free_skb;
- if (cmd == TCMU_CMD_RECONFIG_DEVICE) {
- switch (reconfig_attr) {
- case TCMU_ATTR_DEV_CFG:
- ret = nla_put_string(skb, reconfig_attr, reconfig_data);
- break;
- case TCMU_ATTR_DEV_SIZE:
- ret = nla_put_u64_64bit(skb, reconfig_attr,
- *((u64 *)reconfig_data),
- TCMU_ATTR_PAD);
- break;
- case TCMU_ATTR_WRITECACHE:
- ret = nla_put_u8(skb, reconfig_attr,
- *((u8 *)reconfig_data));
- break;
- default:
- BUG();
- }
+ *buf = skb;
+ *hdr = msg_header;
+ return ret;
- if (ret < 0)
- goto free_skb;
- }
+free_skb:
+ nlmsg_free(skb);
+ return ret;
+}
+
+static int tcmu_netlink_event_send(struct tcmu_dev *udev,
+ enum tcmu_genl_cmd cmd,
+ struct sk_buff **buf, void **hdr)
+{
+ int ret = 0;
+ struct sk_buff *skb = *buf;
+ void *msg_header = *hdr;
genlmsg_end(skb, msg_header);
tcmu_init_genl_cmd_reply(udev, cmd);
ret = genlmsg_multicast_allns(&tcmu_genl_family, skb, 0,
- TCMU_MCGRP_CONFIG, GFP_KERNEL);
- /* We don't care if no one is listening */
+ TCMU_MCGRP_CONFIG, GFP_KERNEL);
+ /* We don't care if no one is listening */
if (ret == -ESRCH)
ret = 0;
if (!ret)
ret = tcmu_wait_genl_cmd_reply(udev);
-
- return ret;
-free_skb:
- nlmsg_free(skb);
return ret;
}
+static int tcmu_send_dev_add_event(struct tcmu_dev *udev)
+{
+ struct sk_buff *skb = NULL;
+ void *msg_header = NULL;
+ int ret = 0;
+
+ ret = tcmu_netlink_event_init(udev, TCMU_CMD_ADDED_DEVICE, &skb,
+ &msg_header);
+ if (ret < 0)
+ return ret;
+ return tcmu_netlink_event_send(udev, TCMU_CMD_ADDED_DEVICE, &skb,
+ &msg_header);
+
+}
+
+static int tcmu_send_dev_remove_event(struct tcmu_dev *udev)
+{
+ struct sk_buff *skb = NULL;
+ void *msg_header = NULL;
+ int ret = 0;
+
+ ret = tcmu_netlink_event_init(udev, TCMU_CMD_REMOVED_DEVICE,
+ &skb, &msg_header);
+ if (ret < 0)
+ return ret;
+ return tcmu_netlink_event_send(udev, TCMU_CMD_REMOVED_DEVICE,
+ &skb, &msg_header);
+}
+
static int tcmu_update_uio_info(struct tcmu_dev *udev)
{
struct tcmu_hba *hba = udev->hba->hba_ptr;
@@ -1692,8 +1717,9 @@ static int tcmu_configure_device(struct se_device *dev)
info = &udev->uio_info;
- udev->data_bitmap = kzalloc(BITS_TO_LONGS(udev->max_blocks) *
- sizeof(unsigned long), GFP_KERNEL);
+ udev->data_bitmap = kcalloc(BITS_TO_LONGS(udev->max_blocks),
+ sizeof(unsigned long),
+ GFP_KERNEL);
if (!udev->data_bitmap) {
ret = -ENOMEM;
goto err_bitmap_alloc;
@@ -1762,7 +1788,7 @@ static int tcmu_configure_device(struct se_device *dev)
*/
kref_get(&udev->kref);
- ret = tcmu_netlink_event(udev, TCMU_CMD_ADDED_DEVICE, 0, NULL);
+ ret = tcmu_send_dev_add_event(udev);
if (ret)
goto err_netlink;
@@ -1812,7 +1838,7 @@ static void tcmu_destroy_device(struct se_device *dev)
list_del(&udev->node);
mutex_unlock(&root_udev_mutex);
- tcmu_netlink_event(udev, TCMU_CMD_REMOVED_DEVICE, 0, NULL);
+ tcmu_send_dev_remove_event(udev);
uio_unregister_device(&udev->uio_info);
@@ -2151,6 +2177,27 @@ static ssize_t tcmu_dev_config_show(struct config_item *item, char *page)
return snprintf(page, PAGE_SIZE, "%s\n", udev->dev_config);
}
+static int tcmu_send_dev_config_event(struct tcmu_dev *udev,
+ const char *reconfig_data)
+{
+ struct sk_buff *skb = NULL;
+ void *msg_header = NULL;
+ int ret = 0;
+
+ ret = tcmu_netlink_event_init(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+ if (ret < 0)
+ return ret;
+ ret = nla_put_string(skb, TCMU_ATTR_DEV_CFG, reconfig_data);
+ if (ret < 0) {
+ nlmsg_free(skb);
+ return ret;
+ }
+ return tcmu_netlink_event_send(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+}
+
+
static ssize_t tcmu_dev_config_store(struct config_item *item, const char *page,
size_t count)
{
@@ -2165,8 +2212,7 @@ static ssize_t tcmu_dev_config_store(struct config_item *item, const char *page,
/* Check if device has been configured before */
if (tcmu_dev_configured(udev)) {
- ret = tcmu_netlink_event(udev, TCMU_CMD_RECONFIG_DEVICE,
- TCMU_ATTR_DEV_CFG, page);
+ ret = tcmu_send_dev_config_event(udev, page);
if (ret) {
pr_err("Unable to reconfigure device\n");
return ret;
@@ -2193,6 +2239,26 @@ static ssize_t tcmu_dev_size_show(struct config_item *item, char *page)
return snprintf(page, PAGE_SIZE, "%zu\n", udev->dev_size);
}
+static int tcmu_send_dev_size_event(struct tcmu_dev *udev, u64 size)
+{
+ struct sk_buff *skb = NULL;
+ void *msg_header = NULL;
+ int ret = 0;
+
+ ret = tcmu_netlink_event_init(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+ if (ret < 0)
+ return ret;
+ ret = nla_put_u64_64bit(skb, TCMU_ATTR_DEV_SIZE,
+ size, TCMU_ATTR_PAD);
+ if (ret < 0) {
+ nlmsg_free(skb);
+ return ret;
+ }
+ return tcmu_netlink_event_send(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+}
+
static ssize_t tcmu_dev_size_store(struct config_item *item, const char *page,
size_t count)
{
@@ -2208,8 +2274,7 @@ static ssize_t tcmu_dev_size_store(struct config_item *item, const char *page,
/* Check if device has been configured before */
if (tcmu_dev_configured(udev)) {
- ret = tcmu_netlink_event(udev, TCMU_CMD_RECONFIG_DEVICE,
- TCMU_ATTR_DEV_SIZE, &val);
+ ret = tcmu_send_dev_size_event(udev, val);
if (ret) {
pr_err("Unable to reconfigure device\n");
return ret;
@@ -2257,6 +2322,25 @@ static ssize_t tcmu_emulate_write_cache_show(struct config_item *item,
return snprintf(page, PAGE_SIZE, "%i\n", da->emulate_write_cache);
}
+static int tcmu_send_emulate_write_cache(struct tcmu_dev *udev, u8 val)
+{
+ struct sk_buff *skb = NULL;
+ void *msg_header = NULL;
+ int ret = 0;
+
+ ret = tcmu_netlink_event_init(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+ if (ret < 0)
+ return ret;
+ ret = nla_put_u8(skb, TCMU_ATTR_WRITECACHE, val);
+ if (ret < 0) {
+ nlmsg_free(skb);
+ return ret;
+ }
+ return tcmu_netlink_event_send(udev, TCMU_CMD_RECONFIG_DEVICE,
+ &skb, &msg_header);
+}
+
static ssize_t tcmu_emulate_write_cache_store(struct config_item *item,
const char *page, size_t count)
{
@@ -2272,8 +2356,7 @@ static ssize_t tcmu_emulate_write_cache_store(struct config_item *item,
/* Check if device has been configured before */
if (tcmu_dev_configured(udev)) {
- ret = tcmu_netlink_event(udev, TCMU_CMD_RECONFIG_DEVICE,
- TCMU_ATTR_WRITECACHE, &val);
+ ret = tcmu_send_emulate_write_cache(udev, val);
if (ret) {
pr_err("Unable to reconfigure device\n");
return ret;
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index ee3a215..334d98b 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -1,11 +1,6 @@
-/*
- * Copyright 2013 Freescale Semiconductor, Inc.
- *
- * 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.
- *
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2013 Freescale Semiconductor, Inc.
#include <linux/clk.h>
#include <linux/cpufreq.h>
@@ -31,35 +26,57 @@
#define REG_CLR 0x8
#define REG_TOG 0xc
-#define MISC0 0x0150
-#define MISC0_REFTOP_SELBIASOFF (1 << 3)
-#define MISC1 0x0160
-#define MISC1_IRQ_TEMPHIGH (1 << 29)
+/* i.MX6 specific */
+#define IMX6_MISC0 0x0150
+#define IMX6_MISC0_REFTOP_SELBIASOFF (1 << 3)
+#define IMX6_MISC1 0x0160
+#define IMX6_MISC1_IRQ_TEMPHIGH (1 << 29)
/* Below LOW and PANIC bits are only for TEMPMON_IMX6SX */
-#define MISC1_IRQ_TEMPLOW (1 << 28)
-#define MISC1_IRQ_TEMPPANIC (1 << 27)
-
-#define TEMPSENSE0 0x0180
-#define TEMPSENSE0_ALARM_VALUE_SHIFT 20
-#define TEMPSENSE0_ALARM_VALUE_MASK (0xfff << TEMPSENSE0_ALARM_VALUE_SHIFT)
-#define TEMPSENSE0_TEMP_CNT_SHIFT 8
-#define TEMPSENSE0_TEMP_CNT_MASK (0xfff << TEMPSENSE0_TEMP_CNT_SHIFT)
-#define TEMPSENSE0_FINISHED (1 << 2)
-#define TEMPSENSE0_MEASURE_TEMP (1 << 1)
-#define TEMPSENSE0_POWER_DOWN (1 << 0)
-
-#define TEMPSENSE1 0x0190
-#define TEMPSENSE1_MEASURE_FREQ 0xffff
-/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
-#define TEMPSENSE2 0x0290
-#define TEMPSENSE2_LOW_VALUE_SHIFT 0
-#define TEMPSENSE2_LOW_VALUE_MASK 0xfff
-#define TEMPSENSE2_PANIC_VALUE_SHIFT 16
-#define TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000
+#define IMX6_MISC1_IRQ_TEMPLOW (1 << 28)
+#define IMX6_MISC1_IRQ_TEMPPANIC (1 << 27)
+
+#define IMX6_TEMPSENSE0 0x0180
+#define IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT 20
+#define IMX6_TEMPSENSE0_ALARM_VALUE_MASK (0xfff << 20)
+#define IMX6_TEMPSENSE0_TEMP_CNT_SHIFT 8
+#define IMX6_TEMPSENSE0_TEMP_CNT_MASK (0xfff << 8)
+#define IMX6_TEMPSENSE0_FINISHED (1 << 2)
+#define IMX6_TEMPSENSE0_MEASURE_TEMP (1 << 1)
+#define IMX6_TEMPSENSE0_POWER_DOWN (1 << 0)
+
+#define IMX6_TEMPSENSE1 0x0190
+#define IMX6_TEMPSENSE1_MEASURE_FREQ 0xffff
+#define IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT 0
#define OCOTP_MEM0 0x0480
#define OCOTP_ANA1 0x04e0
+/* Below TEMPSENSE2 is only for TEMPMON_IMX6SX */
+#define IMX6_TEMPSENSE2 0x0290
+#define IMX6_TEMPSENSE2_LOW_VALUE_SHIFT 0
+#define IMX6_TEMPSENSE2_LOW_VALUE_MASK 0xfff
+#define IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT 16
+#define IMX6_TEMPSENSE2_PANIC_VALUE_MASK 0xfff0000
+
+/* i.MX7 specific */
+#define IMX7_ANADIG_DIGPROG 0x800
+#define IMX7_TEMPSENSE0 0x300
+#define IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT 18
+#define IMX7_TEMPSENSE0_PANIC_ALARM_MASK (0x1ff << 18)
+#define IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT 9
+#define IMX7_TEMPSENSE0_HIGH_ALARM_MASK (0x1ff << 9)
+#define IMX7_TEMPSENSE0_LOW_ALARM_SHIFT 0
+#define IMX7_TEMPSENSE0_LOW_ALARM_MASK 0x1ff
+
+#define IMX7_TEMPSENSE1 0x310
+#define IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT 16
+#define IMX7_TEMPSENSE1_MEASURE_FREQ_MASK (0xffff << 16)
+#define IMX7_TEMPSENSE1_FINISHED (1 << 11)
+#define IMX7_TEMPSENSE1_MEASURE_TEMP (1 << 10)
+#define IMX7_TEMPSENSE1_POWER_DOWN (1 << 9)
+#define IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT 0
+#define IMX7_TEMPSENSE1_TEMP_VALUE_MASK 0x1ff
+
/* The driver supports 1 passive trip point and 1 critical trip point */
enum imx_thermal_trip {
IMX_TRIP_PASSIVE,
@@ -72,17 +89,114 @@ enum imx_thermal_trip {
#define TEMPMON_IMX6Q 1
#define TEMPMON_IMX6SX 2
+#define TEMPMON_IMX7D 3
struct thermal_soc_data {
u32 version;
+
+ u32 sensor_ctrl;
+ u32 power_down_mask;
+ u32 measure_temp_mask;
+
+ u32 measure_freq_ctrl;
+ u32 measure_freq_mask;
+ u32 measure_freq_shift;
+
+ u32 temp_data;
+ u32 temp_value_mask;
+ u32 temp_value_shift;
+ u32 temp_valid_mask;
+
+ u32 panic_alarm_ctrl;
+ u32 panic_alarm_mask;
+ u32 panic_alarm_shift;
+
+ u32 high_alarm_ctrl;
+ u32 high_alarm_mask;
+ u32 high_alarm_shift;
+
+ u32 low_alarm_ctrl;
+ u32 low_alarm_mask;
+ u32 low_alarm_shift;
};
static struct thermal_soc_data thermal_imx6q_data = {
.version = TEMPMON_IMX6Q,
+
+ .sensor_ctrl = IMX6_TEMPSENSE0,
+ .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
+ .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
+
+ .measure_freq_ctrl = IMX6_TEMPSENSE1,
+ .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
+ .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
+
+ .temp_data = IMX6_TEMPSENSE0,
+ .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
+ .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
+ .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
+
+ .high_alarm_ctrl = IMX6_TEMPSENSE0,
+ .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
+ .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
};
static struct thermal_soc_data thermal_imx6sx_data = {
.version = TEMPMON_IMX6SX,
+
+ .sensor_ctrl = IMX6_TEMPSENSE0,
+ .power_down_mask = IMX6_TEMPSENSE0_POWER_DOWN,
+ .measure_temp_mask = IMX6_TEMPSENSE0_MEASURE_TEMP,
+
+ .measure_freq_ctrl = IMX6_TEMPSENSE1,
+ .measure_freq_shift = IMX6_TEMPSENSE1_MEASURE_FREQ_SHIFT,
+ .measure_freq_mask = IMX6_TEMPSENSE1_MEASURE_FREQ,
+
+ .temp_data = IMX6_TEMPSENSE0,
+ .temp_value_mask = IMX6_TEMPSENSE0_TEMP_CNT_MASK,
+ .temp_value_shift = IMX6_TEMPSENSE0_TEMP_CNT_SHIFT,
+ .temp_valid_mask = IMX6_TEMPSENSE0_FINISHED,
+
+ .high_alarm_ctrl = IMX6_TEMPSENSE0,
+ .high_alarm_mask = IMX6_TEMPSENSE0_ALARM_VALUE_MASK,
+ .high_alarm_shift = IMX6_TEMPSENSE0_ALARM_VALUE_SHIFT,
+
+ .panic_alarm_ctrl = IMX6_TEMPSENSE2,
+ .panic_alarm_mask = IMX6_TEMPSENSE2_PANIC_VALUE_MASK,
+ .panic_alarm_shift = IMX6_TEMPSENSE2_PANIC_VALUE_SHIFT,
+
+ .low_alarm_ctrl = IMX6_TEMPSENSE2,
+ .low_alarm_mask = IMX6_TEMPSENSE2_LOW_VALUE_MASK,
+ .low_alarm_shift = IMX6_TEMPSENSE2_LOW_VALUE_SHIFT,
+};
+
+static struct thermal_soc_data thermal_imx7d_data = {
+ .version = TEMPMON_IMX7D,
+
+ .sensor_ctrl = IMX7_TEMPSENSE1,
+ .power_down_mask = IMX7_TEMPSENSE1_POWER_DOWN,
+ .measure_temp_mask = IMX7_TEMPSENSE1_MEASURE_TEMP,
+
+ .measure_freq_ctrl = IMX7_TEMPSENSE1,
+ .measure_freq_shift = IMX7_TEMPSENSE1_MEASURE_FREQ_SHIFT,
+ .measure_freq_mask = IMX7_TEMPSENSE1_MEASURE_FREQ_MASK,
+
+ .temp_data = IMX7_TEMPSENSE1,
+ .temp_value_mask = IMX7_TEMPSENSE1_TEMP_VALUE_MASK,
+ .temp_value_shift = IMX7_TEMPSENSE1_TEMP_VALUE_SHIFT,
+ .temp_valid_mask = IMX7_TEMPSENSE1_FINISHED,
+
+ .panic_alarm_ctrl = IMX7_TEMPSENSE1,
+ .panic_alarm_mask = IMX7_TEMPSENSE0_PANIC_ALARM_MASK,
+ .panic_alarm_shift = IMX7_TEMPSENSE0_PANIC_ALARM_SHIFT,
+
+ .high_alarm_ctrl = IMX7_TEMPSENSE0,
+ .high_alarm_mask = IMX7_TEMPSENSE0_HIGH_ALARM_MASK,
+ .high_alarm_shift = IMX7_TEMPSENSE0_HIGH_ALARM_SHIFT,
+
+ .low_alarm_ctrl = IMX7_TEMPSENSE0,
+ .low_alarm_mask = IMX7_TEMPSENSE0_LOW_ALARM_MASK,
+ .low_alarm_shift = IMX7_TEMPSENSE0_LOW_ALARM_SHIFT,
};
struct imx_thermal_data {
@@ -107,31 +221,42 @@ struct imx_thermal_data {
static void imx_set_panic_temp(struct imx_thermal_data *data,
int panic_temp)
{
+ const struct thermal_soc_data *soc_data = data->socdata;
struct regmap *map = data->tempmon;
int critical_value;
critical_value = (data->c2 - panic_temp) / data->c1;
- regmap_write(map, TEMPSENSE2 + REG_CLR, TEMPSENSE2_PANIC_VALUE_MASK);
- regmap_write(map, TEMPSENSE2 + REG_SET, critical_value <<
- TEMPSENSE2_PANIC_VALUE_SHIFT);
+
+ regmap_write(map, soc_data->panic_alarm_ctrl + REG_CLR,
+ soc_data->panic_alarm_mask);
+ regmap_write(map, soc_data->panic_alarm_ctrl + REG_SET,
+ critical_value << soc_data->panic_alarm_shift);
}
static void imx_set_alarm_temp(struct imx_thermal_data *data,
int alarm_temp)
{
struct regmap *map = data->tempmon;
+ const struct thermal_soc_data *soc_data = data->socdata;
int alarm_value;
data->alarm_temp = alarm_temp;
- alarm_value = (data->c2 - alarm_temp) / data->c1;
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_ALARM_VALUE_MASK);
- regmap_write(map, TEMPSENSE0 + REG_SET, alarm_value <<
- TEMPSENSE0_ALARM_VALUE_SHIFT);
+
+ if (data->socdata->version == TEMPMON_IMX7D)
+ alarm_value = alarm_temp / 1000 + data->c1 - 25;
+ else
+ alarm_value = (data->c2 - alarm_temp) / data->c1;
+
+ regmap_write(map, soc_data->high_alarm_ctrl + REG_CLR,
+ soc_data->high_alarm_mask);
+ regmap_write(map, soc_data->high_alarm_ctrl + REG_SET,
+ alarm_value << soc_data->high_alarm_shift);
}
static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
{
struct imx_thermal_data *data = tz->devdata;
+ const struct thermal_soc_data *soc_data = data->socdata;
struct regmap *map = data->tempmon;
unsigned int n_meas;
bool wait;
@@ -139,16 +264,18 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
if (data->mode == THERMAL_DEVICE_ENABLED) {
/* Check if a measurement is currently in progress */
- regmap_read(map, TEMPSENSE0, &val);
- wait = !(val & TEMPSENSE0_FINISHED);
+ regmap_read(map, soc_data->temp_data, &val);
+ wait = !(val & soc_data->temp_valid_mask);
} else {
/*
* Every time we measure the temperature, we will power on the
* temperature sensor, enable measurements, take a reading,
* disable measurements, power off the temperature sensor.
*/
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
+ regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
+ soc_data->power_down_mask);
+ regmap_write(map, soc_data->sensor_ctrl + REG_SET,
+ soc_data->measure_temp_mask);
wait = true;
}
@@ -160,22 +287,28 @@ static int imx_get_temp(struct thermal_zone_device *tz, int *temp)
if (wait)
usleep_range(20, 50);
- regmap_read(map, TEMPSENSE0, &val);
+ regmap_read(map, soc_data->temp_data, &val);
if (data->mode != THERMAL_DEVICE_ENABLED) {
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
+ regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
+ soc_data->measure_temp_mask);
+ regmap_write(map, soc_data->sensor_ctrl + REG_SET,
+ soc_data->power_down_mask);
}
- if ((val & TEMPSENSE0_FINISHED) == 0) {
+ if ((val & soc_data->temp_valid_mask) == 0) {
dev_dbg(&tz->device, "temp measurement never finished\n");
return -EAGAIN;
}
- n_meas = (val & TEMPSENSE0_TEMP_CNT_MASK) >> TEMPSENSE0_TEMP_CNT_SHIFT;
+ n_meas = (val & soc_data->temp_value_mask)
+ >> soc_data->temp_value_shift;
/* See imx_init_calib() for formula derivation */
- *temp = data->c2 - n_meas * data->c1;
+ if (data->socdata->version == TEMPMON_IMX7D)
+ *temp = (n_meas - data->c1 + 25) * 1000;
+ else
+ *temp = data->c2 - n_meas * data->c1;
/* Update alarm value to next higher trip point for TEMPMON_IMX6Q */
if (data->socdata->version == TEMPMON_IMX6Q) {
@@ -219,21 +352,26 @@ static int imx_set_mode(struct thermal_zone_device *tz,
{
struct imx_thermal_data *data = tz->devdata;
struct regmap *map = data->tempmon;
+ const struct thermal_soc_data *soc_data = data->socdata;
if (mode == THERMAL_DEVICE_ENABLED) {
tz->polling_delay = IMX_POLLING_DELAY;
tz->passive_delay = IMX_PASSIVE_DELAY;
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
+ regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
+ soc_data->power_down_mask);
+ regmap_write(map, soc_data->sensor_ctrl + REG_SET,
+ soc_data->measure_temp_mask);
if (!data->irq_enabled) {
data->irq_enabled = true;
enable_irq(data->irq);
}
} else {
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
+ regmap_write(map, soc_data->sensor_ctrl + REG_CLR,
+ soc_data->measure_temp_mask);
+ regmap_write(map, soc_data->sensor_ctrl + REG_SET,
+ soc_data->power_down_mask);
tz->polling_delay = 0;
tz->passive_delay = 0;
@@ -355,6 +493,15 @@ static int imx_init_calib(struct platform_device *pdev, u32 ocotp_ana1)
}
/*
+ * On i.MX7D, we only use the calibration data at 25C to get the temp,
+ * Tmeas = ( Nmeas - n1) + 25; n1 is the fuse value for 25C.
+ */
+ if (data->socdata->version == TEMPMON_IMX7D) {
+ data->c1 = (ocotp_ana1 >> 9) & 0x1ff;
+ return 0;
+ }
+
+ /*
* The sensor is calibrated at 25 °C (aka T1) and the value measured
* (aka N1) at this temperature is provided in bits [31:20] in the
* i.MX's OCOTP value ANA1.
@@ -492,6 +639,7 @@ static irqreturn_t imx_thermal_alarm_irq_thread(int irq, void *dev)
static const struct of_device_id of_imx_thermal_match[] = {
{ .compatible = "fsl,imx6q-tempmon", .data = &thermal_imx6q_data, },
{ .compatible = "fsl,imx6sx-tempmon", .data = &thermal_imx6sx_data, },
+ { .compatible = "fsl,imx7d-tempmon", .data = &thermal_imx7d_data, },
{ /* end */ }
};
MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
@@ -523,14 +671,15 @@ static int imx_thermal_probe(struct platform_device *pdev)
/* make sure the IRQ flag is clear before enabling irq on i.MX6SX */
if (data->socdata->version == TEMPMON_IMX6SX) {
- regmap_write(map, MISC1 + REG_CLR, MISC1_IRQ_TEMPHIGH |
- MISC1_IRQ_TEMPLOW | MISC1_IRQ_TEMPPANIC);
+ regmap_write(map, IMX6_MISC1 + REG_CLR,
+ IMX6_MISC1_IRQ_TEMPHIGH | IMX6_MISC1_IRQ_TEMPLOW
+ | IMX6_MISC1_IRQ_TEMPPANIC);
/*
* reset value of LOW ALARM is incorrect, set it to lowest
* value to avoid false trigger of low alarm.
*/
- regmap_write(map, TEMPSENSE2 + REG_SET,
- TEMPSENSE2_LOW_VALUE_MASK);
+ regmap_write(map, data->socdata->low_alarm_ctrl + REG_SET,
+ data->socdata->low_alarm_mask);
}
data->irq = platform_get_irq(pdev, 0);
@@ -557,11 +706,17 @@ static int imx_thermal_probe(struct platform_device *pdev)
}
/* Make sure sensor is in known good state for measurements */
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
- regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
- regmap_write(map, MISC0 + REG_SET, MISC0_REFTOP_SELBIASOFF);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
+ data->socdata->power_down_mask);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
+ data->socdata->measure_temp_mask);
+ regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
+ data->socdata->measure_freq_mask);
+ if (data->socdata->version != TEMPMON_IMX7D)
+ regmap_write(map, IMX6_MISC0 + REG_SET,
+ IMX6_MISC0_REFTOP_SELBIASOFF);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
+ data->socdata->power_down_mask);
data->policy = cpufreq_cpu_get(0);
if (!data->policy) {
@@ -626,16 +781,20 @@ static int imx_thermal_probe(struct platform_device *pdev)
data->temp_passive / 1000);
/* Enable measurements at ~ 10 Hz */
- regmap_write(map, TEMPSENSE1 + REG_CLR, TEMPSENSE1_MEASURE_FREQ);
+ regmap_write(map, data->socdata->measure_freq_ctrl + REG_CLR,
+ data->socdata->measure_freq_mask);
measure_freq = DIV_ROUND_UP(32768, 10); /* 10 Hz */
- regmap_write(map, TEMPSENSE1 + REG_SET, measure_freq);
+ regmap_write(map, data->socdata->measure_freq_ctrl + REG_SET,
+ measure_freq << data->socdata->measure_freq_shift);
imx_set_alarm_temp(data, data->temp_passive);
if (data->socdata->version == TEMPMON_IMX6SX)
imx_set_panic_temp(data, data->temp_critical);
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
+ data->socdata->power_down_mask);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
+ data->socdata->measure_temp_mask);
data->irq_enabled = true;
data->mode = THERMAL_DEVICE_ENABLED;
@@ -661,7 +820,8 @@ static int imx_thermal_remove(struct platform_device *pdev)
struct regmap *map = data->tempmon;
/* Disable measurements */
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
+ data->socdata->power_down_mask);
if (!IS_ERR(data->thermal_clk))
clk_disable_unprepare(data->thermal_clk);
@@ -684,8 +844,10 @@ static int imx_thermal_suspend(struct device *dev)
* temperature will be read as the thermal sensor is powered
* down.
*/
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_MEASURE_TEMP);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_POWER_DOWN);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
+ data->socdata->measure_temp_mask);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
+ data->socdata->power_down_mask);
data->mode = THERMAL_DEVICE_DISABLED;
clk_disable_unprepare(data->thermal_clk);
@@ -702,8 +864,10 @@ static int imx_thermal_resume(struct device *dev)
if (ret)
return ret;
/* Enabled thermal sensor after resume */
- regmap_write(map, TEMPSENSE0 + REG_CLR, TEMPSENSE0_POWER_DOWN);
- regmap_write(map, TEMPSENSE0 + REG_SET, TEMPSENSE0_MEASURE_TEMP);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_CLR,
+ data->socdata->power_down_mask);
+ regmap_write(map, data->socdata->sensor_ctrl + REG_SET,
+ data->socdata->measure_temp_mask);
data->mode = THERMAL_DEVICE_ENABLED;
return 0;
diff --git a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c b/drivers/thermal/int340x_thermal/acpi_thermal_rel.c
index c719167..45e7e5c 100644
--- a/drivers/thermal/int340x_thermal/acpi_thermal_rel.c
+++ b/drivers/thermal/int340x_thermal/acpi_thermal_rel.c
@@ -96,7 +96,7 @@ int acpi_parse_trt(acpi_handle handle, int *trt_count, struct trt **trtp,
}
*trt_count = p->package.count;
- trts = kzalloc(*trt_count * sizeof(struct trt), GFP_KERNEL);
+ trts = kcalloc(*trt_count, sizeof(struct trt), GFP_KERNEL);
if (!trts) {
result = -ENOMEM;
goto end;
@@ -178,7 +178,7 @@ int acpi_parse_art(acpi_handle handle, int *art_count, struct art **artp,
/* ignore p->package.elements[0], as this is _ART Revision field */
*art_count = p->package.count - 1;
- arts = kzalloc(*art_count * sizeof(struct art), GFP_KERNEL);
+ arts = kcalloc(*art_count, sizeof(struct art), GFP_KERNEL);
if (!arts) {
result = -ENOMEM;
goto end;
diff --git a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
index 145a5c53..9ec27ac 100644
--- a/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
+++ b/drivers/thermal/int340x_thermal/int340x_thermal_zone.c
@@ -147,9 +147,9 @@ static int int340x_thermal_get_trip_hyst(struct thermal_zone_device *zone,
status = acpi_evaluate_integer(d->adev->handle, "GTSH", NULL, &hyst);
if (ACPI_FAILURE(status))
- return -EIO;
-
- *temp = hyst * 100;
+ *temp = 0;
+ else
+ *temp = hyst * 100;
return 0;
}
@@ -239,9 +239,10 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
if (ACPI_FAILURE(status))
trip_cnt = 0;
else {
- int34x_thermal_zone->aux_trips = kzalloc(
- sizeof(*int34x_thermal_zone->aux_trips) *
- trip_cnt, GFP_KERNEL);
+ int34x_thermal_zone->aux_trips =
+ kcalloc(trip_cnt,
+ sizeof(*int34x_thermal_zone->aux_trips),
+ GFP_KERNEL);
if (!int34x_thermal_zone->aux_trips) {
ret = -ENOMEM;
goto err_trip_alloc;
diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c
index 80bbf9c..284cf2c 100644
--- a/drivers/thermal/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c
@@ -43,6 +43,9 @@
#define PCI_DEVICE_ID_PROC_BXTX_THERMAL 0x4A8C
#define PCI_DEVICE_ID_PROC_BXTP_THERMAL 0x5A8C
+/* GeminiLake thermal reporting device */
+#define PCI_DEVICE_ID_PROC_GLK_THERMAL 0x318C
+
struct power_config {
u32 index;
u32 min_uw;
@@ -467,6 +470,7 @@ static const struct pci_device_id proc_thermal_pci_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_BXTP_THERMAL)},
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CNL_THERMAL)},
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_CFL_THERMAL)},
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PROC_GLK_THERMAL)},
{ 0, },
};
diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c
index c75661a..0691f26 100644
--- a/drivers/thermal/mtk_thermal.c
+++ b/drivers/thermal/mtk_thermal.c
@@ -153,6 +153,12 @@
/* The number of sensing points per bank */
#define MT2712_NUM_SENSORS_PER_ZONE 4
+#define MT7622_TEMP_AUXADC_CHANNEL 11
+#define MT7622_NUM_SENSORS 1
+#define MT7622_NUM_ZONES 1
+#define MT7622_NUM_SENSORS_PER_ZONE 1
+#define MT7622_TS1 0
+
struct mtk_thermal;
struct thermal_bank_cfg {
@@ -242,6 +248,12 @@ static const int mt2712_adcpnp[MT2712_NUM_SENSORS_PER_ZONE] = {
static const int mt2712_mux_values[MT2712_NUM_SENSORS] = { 0, 1, 2, 3 };
+/* MT7622 thermal sensor data */
+static const int mt7622_bank_data[MT7622_NUM_SENSORS] = { MT7622_TS1, };
+static const int mt7622_msr[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_MSR0, };
+static const int mt7622_adcpnp[MT7622_NUM_SENSORS_PER_ZONE] = { TEMP_ADCPNP0, };
+static const int mt7622_mux_values[MT7622_NUM_SENSORS] = { 0, };
+
/**
* The MT8173 thermal controller has four banks. Each bank can read up to
* four temperature sensors simultaneously. The MT8173 has a total of 5
@@ -329,6 +341,25 @@ static const struct mtk_thermal_data mt2712_thermal_data = {
.sensor_mux_values = mt2712_mux_values,
};
+/*
+ * MT7622 have only one sensing point which uses AUXADC Channel 11 for raw data
+ * access.
+ */
+static const struct mtk_thermal_data mt7622_thermal_data = {
+ .auxadc_channel = MT7622_TEMP_AUXADC_CHANNEL,
+ .num_banks = MT7622_NUM_ZONES,
+ .num_sensors = MT7622_NUM_SENSORS,
+ .bank_data = {
+ {
+ .num_sensors = 1,
+ .sensors = mt7622_bank_data,
+ },
+ },
+ .msr = mt7622_msr,
+ .adcpnp = mt7622_adcpnp,
+ .sensor_mux_values = mt7622_mux_values,
+};
+
/**
* raw_to_mcelsius - convert a raw ADC value to mcelsius
* @mt: The thermal controller
@@ -631,6 +662,10 @@ static const struct of_device_id mtk_thermal_of_match[] = {
{
.compatible = "mediatek,mt2712-thermal",
.data = (void *)&mt2712_thermal_data,
+ },
+ {
+ .compatible = "mediatek,mt7622-thermal",
+ .data = (void *)&mt7622_thermal_data,
}, {
},
};
@@ -642,7 +677,6 @@ static int mtk_thermal_probe(struct platform_device *pdev)
struct device_node *auxadc, *apmixedsys, *np = pdev->dev.of_node;
struct mtk_thermal *mt;
struct resource *res;
- const struct of_device_id *of_id;
u64 auxadc_phys_base, apmixed_phys_base;
struct thermal_zone_device *tzdev;
@@ -650,9 +684,7 @@ static int mtk_thermal_probe(struct platform_device *pdev)
if (!mt)
return -ENOMEM;
- of_id = of_match_device(mtk_thermal_of_match, &pdev->dev);
- if (of_id)
- mt->conf = (const struct mtk_thermal_data *)of_id->data;
+ mt->conf = of_device_get_match_data(&pdev->dev);
mt->clk_peri_therm = devm_clk_get(&pdev->dev, "therm");
if (IS_ERR(mt->clk_peri_therm))
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index e09f035..977a830 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -1,26 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* of-thermal.c - Generic Thermal Management device tree support.
*
* Copyright (C) 2013 Texas Instruments
* Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@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; 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.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/thermal.h>
#include <linux/slab.h>
@@ -870,7 +853,7 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
if (tz->ntrips == 0) /* must have at least one child */
goto finish;
- tz->trips = kzalloc(tz->ntrips * sizeof(*tz->trips), GFP_KERNEL);
+ tz->trips = kcalloc(tz->ntrips, sizeof(*tz->trips), GFP_KERNEL);
if (!tz->trips) {
ret = -ENOMEM;
goto free_tz;
@@ -896,7 +879,7 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
if (tz->num_tbps == 0)
goto finish;
- tz->tbps = kzalloc(tz->num_tbps * sizeof(*tz->tbps), GFP_KERNEL);
+ tz->tbps = kcalloc(tz->num_tbps, sizeof(*tz->tbps), GFP_KERNEL);
if (!tz->tbps) {
ret = -ENOMEM;
goto free_trips;
diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom-spmi-temp-alarm.c
index 95f987d..ad4f3a8 100644
--- a/drivers/thermal/qcom-spmi-temp-alarm.c
+++ b/drivers/thermal/qcom-spmi-temp-alarm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, 2017, The Linux Foundation. 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 and
@@ -11,6 +11,7 @@
* GNU General Public License for more details.
*/
+#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/iio/consumer.h>
@@ -29,13 +30,17 @@
#define QPNP_TM_REG_ALARM_CTRL 0x46
#define QPNP_TM_TYPE 0x09
-#define QPNP_TM_SUBTYPE 0x08
+#define QPNP_TM_SUBTYPE_GEN1 0x08
+#define QPNP_TM_SUBTYPE_GEN2 0x09
-#define STATUS_STAGE_MASK 0x03
+#define STATUS_GEN1_STAGE_MASK GENMASK(1, 0)
+#define STATUS_GEN2_STATE_MASK GENMASK(6, 4)
+#define STATUS_GEN2_STATE_SHIFT 4
-#define SHUTDOWN_CTRL1_THRESHOLD_MASK 0x03
+#define SHUTDOWN_CTRL1_OVERRIDE_MASK GENMASK(7, 6)
+#define SHUTDOWN_CTRL1_THRESHOLD_MASK GENMASK(1, 0)
-#define ALARM_CTRL_FORCE_ENABLE 0x80
+#define ALARM_CTRL_FORCE_ENABLE BIT(7)
/*
* Trip point values based on threshold control
@@ -58,6 +63,7 @@
struct qpnp_tm_chip {
struct regmap *map;
struct thermal_zone_device *tz_dev;
+ unsigned int subtype;
long temp;
unsigned int thresh;
unsigned int stage;
@@ -66,6 +72,9 @@ struct qpnp_tm_chip {
struct iio_channel *adc;
};
+/* This array maps from GEN2 alarm state to GEN1 alarm stage */
+static const unsigned int alarm_state_map[8] = {0, 1, 1, 2, 2, 3, 3, 3};
+
static int qpnp_tm_read(struct qpnp_tm_chip *chip, u16 addr, u8 *data)
{
unsigned int val;
@@ -84,30 +93,59 @@ static int qpnp_tm_write(struct qpnp_tm_chip *chip, u16 addr, u8 data)
return regmap_write(chip->map, chip->base + addr, data);
}
+/**
+ * qpnp_tm_get_temp_stage() - return over-temperature stage
+ * @chip: Pointer to the qpnp_tm chip
+ *
+ * Return: stage (GEN1) or state (GEN2) on success, or errno on failure.
+ */
+static int qpnp_tm_get_temp_stage(struct qpnp_tm_chip *chip)
+{
+ int ret;
+ u8 reg = 0;
+
+ ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg);
+ if (ret < 0)
+ return ret;
+
+ if (chip->subtype == QPNP_TM_SUBTYPE_GEN1)
+ ret = reg & STATUS_GEN1_STAGE_MASK;
+ else
+ ret = (reg & STATUS_GEN2_STATE_MASK) >> STATUS_GEN2_STATE_SHIFT;
+
+ return ret;
+}
+
/*
* This function updates the internal temp value based on the
* current thermal stage and threshold as well as the previous stage
*/
static int qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
{
- unsigned int stage;
+ unsigned int stage, stage_new, stage_old;
int ret;
- u8 reg = 0;
- ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg);
+ ret = qpnp_tm_get_temp_stage(chip);
if (ret < 0)
return ret;
+ stage = ret;
- stage = reg & STATUS_STAGE_MASK;
+ if (chip->subtype == QPNP_TM_SUBTYPE_GEN1) {
+ stage_new = stage;
+ stage_old = chip->stage;
+ } else {
+ stage_new = alarm_state_map[stage];
+ stage_old = alarm_state_map[chip->stage];
+ }
- if (stage > chip->stage) {
+ if (stage_new > stage_old) {
/* increasing stage, use lower bound */
- chip->temp = (stage - 1) * TEMP_STAGE_STEP +
+ chip->temp = (stage_new - 1) * TEMP_STAGE_STEP +
chip->thresh * TEMP_THRESH_STEP +
TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
- } else if (stage < chip->stage) {
+ } else if (stage_new < stage_old) {
/* decreasing stage, use upper bound */
- chip->temp = stage * TEMP_STAGE_STEP +
+ chip->temp = stage_new * TEMP_STAGE_STEP +
chip->thresh * TEMP_THRESH_STEP -
TEMP_STAGE_HYSTERESIS + TEMP_THRESH_MIN;
}
@@ -162,28 +200,37 @@ static irqreturn_t qpnp_tm_isr(int irq, void *data)
*/
static int qpnp_tm_init(struct qpnp_tm_chip *chip)
{
+ unsigned int stage;
int ret;
- u8 reg;
+ u8 reg = 0;
- chip->thresh = THRESH_MIN;
+ ret = qpnp_tm_read(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, &reg);
+ if (ret < 0)
+ return ret;
+
+ chip->thresh = reg & SHUTDOWN_CTRL1_THRESHOLD_MASK;
chip->temp = DEFAULT_TEMP;
- ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, &reg);
+ ret = qpnp_tm_get_temp_stage(chip);
if (ret < 0)
return ret;
+ chip->stage = ret;
- chip->stage = reg & STATUS_STAGE_MASK;
+ stage = chip->subtype == QPNP_TM_SUBTYPE_GEN1
+ ? chip->stage : alarm_state_map[chip->stage];
- if (chip->stage)
+ if (stage)
chip->temp = chip->thresh * TEMP_THRESH_STEP +
- (chip->stage - 1) * TEMP_STAGE_STEP +
+ (stage - 1) * TEMP_STAGE_STEP +
TEMP_THRESH_MIN;
/*
* Set threshold and disable software override of stage 2 and 3
* shutdowns.
*/
- reg = chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK;
+ chip->thresh = THRESH_MIN;
+ reg &= ~(SHUTDOWN_CTRL1_OVERRIDE_MASK | SHUTDOWN_CTRL1_THRESHOLD_MASK);
+ reg |= chip->thresh & SHUTDOWN_CTRL1_THRESHOLD_MASK;
ret = qpnp_tm_write(chip, QPNP_TM_REG_SHUTDOWN_CTRL1, reg);
if (ret < 0)
return ret;
@@ -246,12 +293,15 @@ static int qpnp_tm_probe(struct platform_device *pdev)
return ret;
}
- if (type != QPNP_TM_TYPE || subtype != QPNP_TM_SUBTYPE) {
+ if (type != QPNP_TM_TYPE || (subtype != QPNP_TM_SUBTYPE_GEN1
+ && subtype != QPNP_TM_SUBTYPE_GEN2)) {
dev_err(&pdev->dev, "invalid type 0x%02x or subtype 0x%02x\n",
type, subtype);
return -ENODEV;
}
+ chip->subtype = subtype;
+
ret = qpnp_tm_init(chip);
if (ret < 0) {
dev_err(&pdev->dev, "init failed\n");
diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c
index c2c3442..3440166 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -115,6 +115,7 @@ static int tsens_probe(struct platform_device *pdev)
struct tsens_device *tmdev;
const struct tsens_data *data;
const struct of_device_id *id;
+ u32 num_sensors;
if (pdev->dev.of_node)
dev = &pdev->dev;
@@ -129,19 +130,24 @@ static int tsens_probe(struct platform_device *pdev)
else
data = &data_8960;
- if (data->num_sensors <= 0) {
+ num_sensors = data->num_sensors;
+
+ if (np)
+ of_property_read_u32(np, "#qcom,sensors", &num_sensors);
+
+ if (num_sensors <= 0) {
dev_err(dev, "invalid number of sensors\n");
return -EINVAL;
}
tmdev = devm_kzalloc(dev,
- struct_size(tmdev, sensor, data->num_sensors),
+ struct_size(tmdev, sensor, num_sensors),
GFP_KERNEL);
if (!tmdev)
return -ENOMEM;
tmdev->dev = dev;
- tmdev->num_sensors = data->num_sensors;
+ tmdev->num_sensors = num_sensors;
tmdev->ops = data->ops;
for (i = 0; i < tmdev->num_sensors; i++) {
if (data->hw_ids)
diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c
index 561a0a3..766521e 100644
--- a/drivers/thermal/rcar_gen3_thermal.c
+++ b/drivers/thermal/rcar_gen3_thermal.c
@@ -132,7 +132,7 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
#define RCAR3_THERMAL_GRAN 500 /* mili Celsius */
/* no idea where these constants come from */
-#define TJ_1 96
+#define TJ_1 116
#define TJ_3 -41
static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef,
@@ -146,7 +146,7 @@ static void rcar_gen3_thermal_calc_coefs(struct equation_coefs *coef,
* Division is not scaled in BSP and if scaled it might overflow
* the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled
*/
- tj_2 = (FIXPT_INT((ptat[1] - ptat[2]) * 137)
+ tj_2 = (FIXPT_INT((ptat[1] - ptat[2]) * 157)
/ (ptat[0] - ptat[2])) - FIXPT_INT(41);
coef->a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]),
@@ -207,8 +207,8 @@ 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);
+ low = clamp_val(low, -40000, 120000);
+ high = clamp_val(high, -40000, 120000);
rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1,
rcar_gen3_thermal_mcelsius_to_temp(tsc, low));
@@ -329,6 +329,7 @@ static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
static const struct of_device_id rcar_gen3_thermal_dt_ids[] = {
{ .compatible = "renesas,r8a7795-thermal", },
{ .compatible = "renesas,r8a7796-thermal", },
+ { .compatible = "renesas,r8a77965-thermal", },
{},
};
MODULE_DEVICE_TABLE(of, rcar_gen3_thermal_dt_ids);
@@ -354,11 +355,11 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
/* default values if FUSEs are missing */
/* TODO: Read values from hardware on supported platforms */
- int ptat[3] = { 2351, 1509, 435 };
+ int ptat[3] = { 2631, 1509, 435 };
int thcode[TSC_MAX_NUM][3] = {
- { 3248, 2800, 2221 },
- { 3245, 2795, 2216 },
- { 3250, 2805, 2237 },
+ { 3397, 2800, 2221 },
+ { 3393, 2795, 2216 },
+ { 3389, 2805, 2237 },
};
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c
index 73e5fee..45fb284 100644
--- a/drivers/thermal/rcar_thermal.c
+++ b/drivers/thermal/rcar_thermal.c
@@ -58,10 +58,47 @@ struct rcar_thermal_common {
spinlock_t lock;
};
+struct rcar_thermal_chip {
+ unsigned int use_of_thermal : 1;
+ unsigned int has_filonoff : 1;
+ unsigned int irq_per_ch : 1;
+ unsigned int needs_suspend_resume : 1;
+ unsigned int nirqs;
+};
+
+static const struct rcar_thermal_chip rcar_thermal = {
+ .use_of_thermal = 0,
+ .has_filonoff = 1,
+ .irq_per_ch = 0,
+ .needs_suspend_resume = 0,
+ .nirqs = 1,
+};
+
+static const struct rcar_thermal_chip rcar_gen2_thermal = {
+ .use_of_thermal = 1,
+ .has_filonoff = 1,
+ .irq_per_ch = 0,
+ .needs_suspend_resume = 0,
+ .nirqs = 1,
+};
+
+static const struct rcar_thermal_chip rcar_gen3_thermal = {
+ .use_of_thermal = 1,
+ .has_filonoff = 0,
+ .irq_per_ch = 1,
+ .needs_suspend_resume = 1,
+ /*
+ * The Gen3 chip has 3 interrupts, but this driver uses only 2
+ * interrupts to detect a temperature change, rise or fall.
+ */
+ .nirqs = 2,
+};
+
struct rcar_thermal_priv {
void __iomem *base;
struct rcar_thermal_common *common;
struct thermal_zone_device *zone;
+ const struct rcar_thermal_chip *chip;
struct delayed_work work;
struct mutex lock;
struct list_head list;
@@ -77,13 +114,20 @@ struct rcar_thermal_priv {
#define rcar_priv_to_dev(priv) ((priv)->common->dev)
#define rcar_has_irq_support(priv) ((priv)->common->base)
#define rcar_id_to_shift(priv) ((priv)->id * 8)
-#define rcar_of_data(dev) ((unsigned long)of_device_get_match_data(dev))
-#define rcar_use_of_thermal(dev) (rcar_of_data(dev) == USE_OF_THERMAL)
-#define USE_OF_THERMAL 1
static const struct of_device_id rcar_thermal_dt_ids[] = {
- { .compatible = "renesas,rcar-thermal", },
- { .compatible = "renesas,rcar-gen2-thermal", .data = (void *)USE_OF_THERMAL },
+ {
+ .compatible = "renesas,rcar-thermal",
+ .data = &rcar_thermal,
+ },
+ {
+ .compatible = "renesas,rcar-gen2-thermal",
+ .data = &rcar_gen2_thermal,
+ },
+ {
+ .compatible = "renesas,thermal-r8a77995",
+ .data = &rcar_gen3_thermal,
+ },
{},
};
MODULE_DEVICE_TABLE(of, rcar_thermal_dt_ids);
@@ -190,7 +234,8 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)
* enable IRQ
*/
if (rcar_has_irq_support(priv)) {
- rcar_thermal_write(priv, FILONOFF, 0);
+ if (priv->chip->has_filonoff)
+ rcar_thermal_write(priv, FILONOFF, 0);
/* enable Rising/Falling edge interrupt */
rcar_thermal_write(priv, POSNEG, 0x1);
@@ -420,7 +465,7 @@ static int rcar_thermal_remove(struct platform_device *pdev)
rcar_thermal_for_each_priv(priv, common) {
rcar_thermal_irq_disable(priv);
- if (rcar_use_of_thermal(dev))
+ if (priv->chip->use_of_thermal)
thermal_remove_hwmon_sysfs(priv->zone);
else
thermal_zone_device_unregister(priv->zone);
@@ -438,6 +483,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
struct rcar_thermal_priv *priv;
struct device *dev = &pdev->dev;
struct resource *res, *irq;
+ const struct rcar_thermal_chip *chip = of_device_get_match_data(dev);
int mres = 0;
int i;
int ret = -ENODEV;
@@ -457,19 +503,35 @@ static int rcar_thermal_probe(struct platform_device *pdev)
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (irq) {
- /*
- * platform has IRQ support.
- * Then, driver uses common registers
- * rcar_has_irq_support() will be enabled
- */
- res = platform_get_resource(pdev, IORESOURCE_MEM, mres++);
- common->base = devm_ioremap_resource(dev, res);
- if (IS_ERR(common->base))
- return PTR_ERR(common->base);
+ for (i = 0; i < chip->nirqs; i++) {
+ irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!irq)
+ continue;
+ if (!common->base) {
+ /*
+ * platform has IRQ support.
+ * Then, driver uses common registers
+ * rcar_has_irq_support() will be enabled
+ */
+ res = platform_get_resource(pdev, IORESOURCE_MEM,
+ mres++);
+ common->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(common->base))
+ return PTR_ERR(common->base);
+
+ idle = 0; /* polling delay is not needed */
+ }
- idle = 0; /* polling delay is not needed */
+ ret = devm_request_irq(dev, irq->start, rcar_thermal_irq,
+ IRQF_SHARED, dev_name(dev), common);
+ if (ret) {
+ dev_err(dev, "irq request failed\n ");
+ goto error_unregister;
+ }
+
+ /* update ENR bits */
+ if (chip->irq_per_ch)
+ enr_bits |= 1 << i;
}
for (i = 0;; i++) {
@@ -491,6 +553,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
priv->common = common;
priv->id = i;
+ priv->chip = chip;
mutex_init(&priv->lock);
INIT_LIST_HEAD(&priv->list);
INIT_DELAYED_WORK(&priv->work, rcar_thermal_work);
@@ -498,7 +561,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
if (ret < 0)
goto error_unregister;
- if (rcar_use_of_thermal(dev))
+ if (chip->use_of_thermal)
priv->zone = devm_thermal_zone_of_sensor_register(
dev, i, priv,
&rcar_thermal_zone_of_ops);
@@ -515,7 +578,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
goto error_unregister;
}
- if (rcar_use_of_thermal(dev)) {
+ if (chip->use_of_thermal) {
/*
* thermal_zone doesn't enable hwmon as default,
* but, enable it here to keep compatible
@@ -531,20 +594,12 @@ static int rcar_thermal_probe(struct platform_device *pdev)
list_move_tail(&priv->list, &common->head);
/* update ENR bits */
- enr_bits |= 3 << (i * 8);
+ if (!chip->irq_per_ch)
+ enr_bits |= 3 << (i * 8);
}
- /* enable temperature comparation */
- if (irq) {
- ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0,
- dev_name(dev), common);
- if (ret) {
- dev_err(dev, "irq request failed\n ");
- goto error_unregister;
- }
-
+ if (enr_bits)
rcar_thermal_common_write(common, ENR, enr_bits);
- }
dev_info(dev, "%d sensor probed\n", i);
@@ -556,9 +611,48 @@ error_unregister:
return ret;
}
+#ifdef CONFIG_PM_SLEEP
+static int rcar_thermal_suspend(struct device *dev)
+{
+ struct rcar_thermal_common *common = dev_get_drvdata(dev);
+ struct rcar_thermal_priv *priv = list_first_entry(&common->head,
+ typeof(*priv), list);
+
+ if (priv->chip->needs_suspend_resume) {
+ rcar_thermal_common_write(common, ENR, 0);
+ rcar_thermal_irq_disable(priv);
+ rcar_thermal_bset(priv, THSCR, CPCTL, 0);
+ }
+
+ return 0;
+}
+
+static int rcar_thermal_resume(struct device *dev)
+{
+ struct rcar_thermal_common *common = dev_get_drvdata(dev);
+ struct rcar_thermal_priv *priv = list_first_entry(&common->head,
+ typeof(*priv), list);
+ int ret;
+
+ if (priv->chip->needs_suspend_resume) {
+ ret = rcar_thermal_update_temp(priv);
+ if (ret < 0)
+ return ret;
+ rcar_thermal_irq_enable(priv);
+ rcar_thermal_common_write(common, ENR, 0x03);
+ }
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(rcar_thermal_pm_ops, rcar_thermal_suspend,
+ rcar_thermal_resume);
+
static struct platform_driver rcar_thermal_driver = {
.driver = {
.name = "rcar_thermal",
+ .pm = &rcar_thermal_pm_ops,
.of_match_table = rcar_thermal_dt_ids,
},
.probe = rcar_thermal_probe,
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index ac83f72..a992e51 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -29,13 +29,14 @@
#include <linux/io.h>
#include <linux/interrupt.h>
#include <linux/module.h>
-#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
-#include "exynos_tmu.h"
+#include <dt-bindings/thermal/thermal_exynos.h>
+
#include "../thermal_core.h"
/* Exynos generic registers */
@@ -75,9 +76,6 @@
#define EXYNOS_TMU_THERM_TRIP_EN_SHIFT 12
#define EXYNOS_TMU_INTEN_RISE0_SHIFT 0
-#define EXYNOS_TMU_INTEN_RISE1_SHIFT 4
-#define EXYNOS_TMU_INTEN_RISE2_SHIFT 8
-#define EXYNOS_TMU_INTEN_RISE3_SHIFT 12
#define EXYNOS_TMU_INTEN_FALL0_SHIFT 16
#define EXYNOS_EMUL_TIME 0x57F0
@@ -98,11 +96,6 @@
#define EXYNOS4412_MUX_ADDR_SHIFT 20
/* Exynos5433 specific registers */
-#define EXYNOS5433_TMU_REG_CONTROL1 0x024
-#define EXYNOS5433_TMU_SAMPLING_INTERVAL 0x02c
-#define EXYNOS5433_TMU_COUNTER_VALUE0 0x030
-#define EXYNOS5433_TMU_COUNTER_VALUE1 0x034
-#define EXYNOS5433_TMU_REG_CURRENT_TEMP1 0x044
#define EXYNOS5433_THD_TEMP_RISE3_0 0x050
#define EXYNOS5433_THD_TEMP_RISE7_4 0x054
#define EXYNOS5433_THD_TEMP_FALL3_0 0x060
@@ -123,27 +116,7 @@
#define EXYNOS5433_PD_DET_EN 1
-/*exynos5440 specific registers*/
-#define EXYNOS5440_TMU_S0_7_TRIM 0x000
-#define EXYNOS5440_TMU_S0_7_CTRL 0x020
-#define EXYNOS5440_TMU_S0_7_DEBUG 0x040
-#define EXYNOS5440_TMU_S0_7_TEMP 0x0f0
-#define EXYNOS5440_TMU_S0_7_TH0 0x110
-#define EXYNOS5440_TMU_S0_7_TH1 0x130
-#define EXYNOS5440_TMU_S0_7_TH2 0x150
-#define EXYNOS5440_TMU_S0_7_IRQEN 0x210
-#define EXYNOS5440_TMU_S0_7_IRQ 0x230
-/* exynos5440 common registers */
-#define EXYNOS5440_TMU_IRQ_STATUS 0x000
-#define EXYNOS5440_TMU_PMIN 0x004
-
-#define EXYNOS5440_TMU_INTEN_RISE0_SHIFT 0
-#define EXYNOS5440_TMU_INTEN_RISE1_SHIFT 1
-#define EXYNOS5440_TMU_INTEN_RISE2_SHIFT 2
-#define EXYNOS5440_TMU_INTEN_RISE3_SHIFT 3
-#define EXYNOS5440_TMU_INTEN_FALL0_SHIFT 4
-#define EXYNOS5440_TMU_TH_RISE4_SHIFT 24
-#define EXYNOS5440_EFUSE_SWAP_OFFSET 8
+#define EXYNOS5433_G3D_BASE 0x10070000
/* Exynos7 specific registers */
#define EXYNOS7_THD_TEMP_RISE7_6 0x50
@@ -155,22 +128,32 @@
#define EXYNOS7_TMU_TEMP_MASK 0x1ff
#define EXYNOS7_PD_DET_EN_SHIFT 23
#define EXYNOS7_TMU_INTEN_RISE0_SHIFT 0
-#define EXYNOS7_TMU_INTEN_RISE1_SHIFT 1
-#define EXYNOS7_TMU_INTEN_RISE2_SHIFT 2
-#define EXYNOS7_TMU_INTEN_RISE3_SHIFT 3
-#define EXYNOS7_TMU_INTEN_RISE4_SHIFT 4
-#define EXYNOS7_TMU_INTEN_RISE5_SHIFT 5
-#define EXYNOS7_TMU_INTEN_RISE6_SHIFT 6
-#define EXYNOS7_TMU_INTEN_RISE7_SHIFT 7
#define EXYNOS7_EMUL_DATA_SHIFT 7
#define EXYNOS7_EMUL_DATA_MASK 0x1ff
+#define EXYNOS_FIRST_POINT_TRIM 25
+#define EXYNOS_SECOND_POINT_TRIM 85
+
+#define EXYNOS_NOISE_CANCEL_MODE 4
+
#define MCELSIUS 1000
+
+enum soc_type {
+ SOC_ARCH_EXYNOS3250 = 1,
+ SOC_ARCH_EXYNOS4210,
+ SOC_ARCH_EXYNOS4412,
+ SOC_ARCH_EXYNOS5250,
+ SOC_ARCH_EXYNOS5260,
+ SOC_ARCH_EXYNOS5420,
+ SOC_ARCH_EXYNOS5420_TRIMINFO,
+ SOC_ARCH_EXYNOS5433,
+ SOC_ARCH_EXYNOS7,
+};
+
/**
* struct exynos_tmu_data : A structure to hold the private data of the TMU
driver
* @id: identifier of the one instance of the TMU controller.
- * @pdata: pointer to the tmu platform/configuration data
* @base: base address of the single instance of the TMU controller.
* @base_second: base address of the common registers of the TMU controller.
* @irq: irq number of the TMU controller.
@@ -180,8 +163,17 @@
* @clk: pointer to the clock structure.
* @clk_sec: pointer to the clock structure for accessing the base_second.
* @sclk: pointer to the clock structure for accessing the tmu special clk.
+ * @cal_type: calibration type for temperature
+ * @efuse_value: SoC defined fuse value
+ * @min_efuse_value: minimum valid trimming data
+ * @max_efuse_value: maximum valid trimming data
* @temp_error1: fused value of the first point trim.
* @temp_error2: fused value of the second point trim.
+ * @gain: gain of amplifier in the positive-TC generator block
+ * 0 < gain <= 15
+ * @reference_voltage: reference voltage of amplifier
+ * in the positive-TC generator block
+ * 0 < reference_voltage <= 31
* @regulator: pointer to the TMU regulator structure.
* @reg_conf: pointer to structure to register with core thermal.
* @ntrip: number of supported trip points.
@@ -194,7 +186,6 @@
*/
struct exynos_tmu_data {
int id;
- struct exynos_tmu_platform_data *pdata;
void __iomem *base;
void __iomem *base_second;
int irq;
@@ -202,71 +193,42 @@ struct exynos_tmu_data {
struct work_struct irq_work;
struct mutex lock;
struct clk *clk, *clk_sec, *sclk;
+ u32 cal_type;
+ u32 efuse_value;
+ u32 min_efuse_value;
+ u32 max_efuse_value;
u16 temp_error1, temp_error2;
+ u8 gain;
+ u8 reference_voltage;
struct regulator *regulator;
struct thermal_zone_device *tzd;
unsigned int ntrip;
bool enabled;
- int (*tmu_initialize)(struct platform_device *pdev);
+ void (*tmu_set_trip_temp)(struct exynos_tmu_data *data, int trip,
+ u8 temp);
+ void (*tmu_set_trip_hyst)(struct exynos_tmu_data *data, int trip,
+ u8 temp, u8 hyst);
+ void (*tmu_initialize)(struct platform_device *pdev);
void (*tmu_control)(struct platform_device *pdev, bool on);
int (*tmu_read)(struct exynos_tmu_data *data);
void (*tmu_set_emulation)(struct exynos_tmu_data *data, int temp);
void (*tmu_clear_irqs)(struct exynos_tmu_data *data);
};
-static void exynos_report_trigger(struct exynos_tmu_data *p)
-{
- char data[10], *envp[] = { data, NULL };
- struct thermal_zone_device *tz = p->tzd;
- int temp;
- unsigned int i;
-
- if (!tz) {
- pr_err("No thermal zone device defined\n");
- return;
- }
-
- thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
-
- mutex_lock(&tz->lock);
- /* Find the level for which trip happened */
- for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
- tz->ops->get_trip_temp(tz, i, &temp);
- if (tz->last_temperature < temp)
- break;
- }
-
- snprintf(data, sizeof(data), "%u", i);
- kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, envp);
- mutex_unlock(&tz->lock);
-}
-
/*
* TMU treats temperature as a mapped temperature code.
* The temperature is converted differently depending on the calibration type.
*/
static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
{
- struct exynos_tmu_platform_data *pdata = data->pdata;
- int temp_code;
-
- switch (pdata->cal_type) {
- case TYPE_TWO_POINT_TRIMMING:
- temp_code = (temp - pdata->first_point_trim) *
- (data->temp_error2 - data->temp_error1) /
- (pdata->second_point_trim - pdata->first_point_trim) +
- data->temp_error1;
- break;
- case TYPE_ONE_POINT_TRIMMING:
- temp_code = temp + data->temp_error1 - pdata->first_point_trim;
- break;
- default:
- temp_code = temp + pdata->default_temp_offset;
- break;
- }
+ if (data->cal_type == TYPE_ONE_POINT_TRIMMING)
+ return temp + data->temp_error1 - EXYNOS_FIRST_POINT_TRIM;
- return temp_code;
+ return (temp - EXYNOS_FIRST_POINT_TRIM) *
+ (data->temp_error2 - data->temp_error1) /
+ (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) +
+ data->temp_error1;
}
/*
@@ -275,120 +237,123 @@ static int temp_to_code(struct exynos_tmu_data *data, u8 temp)
*/
static int code_to_temp(struct exynos_tmu_data *data, u16 temp_code)
{
- struct exynos_tmu_platform_data *pdata = data->pdata;
- int temp;
-
- switch (pdata->cal_type) {
- case TYPE_TWO_POINT_TRIMMING:
- temp = (temp_code - data->temp_error1) *
- (pdata->second_point_trim - pdata->first_point_trim) /
- (data->temp_error2 - data->temp_error1) +
- pdata->first_point_trim;
- break;
- case TYPE_ONE_POINT_TRIMMING:
- temp = temp_code - data->temp_error1 + pdata->first_point_trim;
- break;
- default:
- temp = temp_code - pdata->default_temp_offset;
- break;
- }
+ if (data->cal_type == TYPE_ONE_POINT_TRIMMING)
+ return temp_code - data->temp_error1 + EXYNOS_FIRST_POINT_TRIM;
- return temp;
+ return (temp_code - data->temp_error1) *
+ (EXYNOS_SECOND_POINT_TRIM - EXYNOS_FIRST_POINT_TRIM) /
+ (data->temp_error2 - data->temp_error1) +
+ EXYNOS_FIRST_POINT_TRIM;
}
static void sanitize_temp_error(struct exynos_tmu_data *data, u32 trim_info)
{
- struct exynos_tmu_platform_data *pdata = data->pdata;
+ u16 tmu_temp_mask =
+ (data->soc == SOC_ARCH_EXYNOS7) ? EXYNOS7_TMU_TEMP_MASK
+ : EXYNOS_TMU_TEMP_MASK;
- data->temp_error1 = trim_info & EXYNOS_TMU_TEMP_MASK;
+ data->temp_error1 = trim_info & tmu_temp_mask;
data->temp_error2 = ((trim_info >> EXYNOS_TRIMINFO_85_SHIFT) &
EXYNOS_TMU_TEMP_MASK);
if (!data->temp_error1 ||
- (pdata->min_efuse_value > data->temp_error1) ||
- (data->temp_error1 > pdata->max_efuse_value))
- data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
+ (data->min_efuse_value > data->temp_error1) ||
+ (data->temp_error1 > data->max_efuse_value))
+ data->temp_error1 = data->efuse_value & EXYNOS_TMU_TEMP_MASK;
if (!data->temp_error2)
data->temp_error2 =
- (pdata->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) &
+ (data->efuse_value >> EXYNOS_TRIMINFO_85_SHIFT) &
EXYNOS_TMU_TEMP_MASK;
}
-static u32 get_th_reg(struct exynos_tmu_data *data, u32 threshold, bool falling)
+static int exynos_tmu_initialize(struct platform_device *pdev)
{
- struct thermal_zone_device *tz = data->tzd;
+ struct exynos_tmu_data *data = platform_get_drvdata(pdev);
+ struct thermal_zone_device *tzd = data->tzd;
const struct thermal_trip * const trips =
- of_thermal_get_trip_points(tz);
- unsigned long temp;
- int i;
+ of_thermal_get_trip_points(tzd);
+ unsigned int status;
+ int ret = 0, temp, hyst;
if (!trips) {
- pr_err("%s: Cannot get trip points from of-thermal.c!\n",
- __func__);
- return 0;
+ dev_err(&pdev->dev,
+ "Cannot get trip points from device tree!\n");
+ return -ENODEV;
}
- for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
- if (trips[i].type == THERMAL_TRIP_CRITICAL)
- continue;
-
- temp = trips[i].temperature / MCELSIUS;
- if (falling)
- temp -= (trips[i].hysteresis / MCELSIUS);
- else
- threshold &= ~(0xff << 8 * i);
-
- threshold |= temp_to_code(data, temp) << 8 * i;
+ if (data->soc != SOC_ARCH_EXYNOS5433) /* FIXME */
+ ret = tzd->ops->get_crit_temp(tzd, &temp);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "No CRITICAL trip point defined in device tree!\n");
+ goto out;
}
- return threshold;
-}
-
-static int exynos_tmu_initialize(struct platform_device *pdev)
-{
- struct exynos_tmu_data *data = platform_get_drvdata(pdev);
- int ret;
-
- if (of_thermal_get_ntrips(data->tzd) > data->ntrip) {
+ if (of_thermal_get_ntrips(tzd) > data->ntrip) {
dev_info(&pdev->dev,
"More trip points than supported by this TMU.\n");
dev_info(&pdev->dev,
"%d trip points should be configured in polling mode.\n",
- (of_thermal_get_ntrips(data->tzd) - data->ntrip));
+ (of_thermal_get_ntrips(tzd) - data->ntrip));
}
mutex_lock(&data->lock);
clk_enable(data->clk);
if (!IS_ERR(data->clk_sec))
clk_enable(data->clk_sec);
- ret = data->tmu_initialize(pdev);
+
+ status = readb(data->base + EXYNOS_TMU_REG_STATUS);
+ if (!status) {
+ ret = -EBUSY;
+ } else {
+ int i, ntrips =
+ min_t(int, of_thermal_get_ntrips(tzd), data->ntrip);
+
+ data->tmu_initialize(pdev);
+
+ /* Write temperature code for rising and falling threshold */
+ for (i = 0; i < ntrips; i++) {
+ /* Write temperature code for rising threshold */
+ ret = tzd->ops->get_trip_temp(tzd, i, &temp);
+ if (ret)
+ goto err;
+ temp /= MCELSIUS;
+ data->tmu_set_trip_temp(data, i, temp);
+
+ /* Write temperature code for falling threshold */
+ ret = tzd->ops->get_trip_hyst(tzd, i, &hyst);
+ if (ret)
+ goto err;
+ hyst /= MCELSIUS;
+ data->tmu_set_trip_hyst(data, i, temp, hyst);
+ }
+
+ data->tmu_clear_irqs(data);
+ }
+err:
clk_disable(data->clk);
mutex_unlock(&data->lock);
if (!IS_ERR(data->clk_sec))
clk_disable(data->clk_sec);
-
+out:
return ret;
}
static u32 get_con_reg(struct exynos_tmu_data *data, u32 con)
{
- struct exynos_tmu_platform_data *pdata = data->pdata;
-
if (data->soc == SOC_ARCH_EXYNOS4412 ||
data->soc == SOC_ARCH_EXYNOS3250)
con |= (EXYNOS4412_MUX_ADDR_VALUE << EXYNOS4412_MUX_ADDR_SHIFT);
con &= ~(EXYNOS_TMU_REF_VOLTAGE_MASK << EXYNOS_TMU_REF_VOLTAGE_SHIFT);
- con |= pdata->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
+ con |= data->reference_voltage << EXYNOS_TMU_REF_VOLTAGE_SHIFT;
con &= ~(EXYNOS_TMU_BUF_SLOPE_SEL_MASK << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
- con |= (pdata->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
+ con |= (data->gain << EXYNOS_TMU_BUF_SLOPE_SEL_SHIFT);
- if (pdata->noise_cancel_mode) {
- con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT);
- con |= (pdata->noise_cancel_mode << EXYNOS_TMU_TRIP_MODE_SHIFT);
- }
+ con &= ~(EXYNOS_TMU_TRIP_MODE_MASK << EXYNOS_TMU_TRIP_MODE_SHIFT);
+ con |= (EXYNOS_NOISE_CANCEL_MODE << EXYNOS_TMU_TRIP_MODE_SHIFT);
return con;
}
@@ -405,65 +370,70 @@ static void exynos_tmu_control(struct platform_device *pdev, bool on)
mutex_unlock(&data->lock);
}
-static int exynos4210_tmu_initialize(struct platform_device *pdev)
+static void exynos4210_tmu_set_trip_temp(struct exynos_tmu_data *data,
+ int trip, u8 temp)
{
- struct exynos_tmu_data *data = platform_get_drvdata(pdev);
- struct thermal_zone_device *tz = data->tzd;
const struct thermal_trip * const trips =
- of_thermal_get_trip_points(tz);
- int ret = 0, threshold_code, i;
- unsigned long reference, temp;
- unsigned int status;
+ of_thermal_get_trip_points(data->tzd);
+ u8 ref, th_code;
- if (!trips) {
- pr_err("%s: Cannot get trip points from of-thermal.c!\n",
- __func__);
- ret = -ENODEV;
- goto out;
- }
+ ref = trips[0].temperature / MCELSIUS;
- status = readb(data->base + EXYNOS_TMU_REG_STATUS);
- if (!status) {
- ret = -EBUSY;
- goto out;
+ if (trip == 0) {
+ th_code = temp_to_code(data, ref);
+ writeb(th_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
}
+ temp -= ref;
+ writeb(temp, data->base + EXYNOS4210_TMU_REG_TRIG_LEVEL0 + trip * 4);
+}
+
+/* failing thresholds are not supported on Exynos4210 */
+static void exynos4210_tmu_set_trip_hyst(struct exynos_tmu_data *data,
+ int trip, u8 temp, u8 hyst)
+{
+}
+
+static void exynos4210_tmu_initialize(struct platform_device *pdev)
+{
+ struct exynos_tmu_data *data = platform_get_drvdata(pdev);
+
sanitize_temp_error(data, readl(data->base + EXYNOS_TMU_REG_TRIMINFO));
+}
- /* Write temperature code for threshold */
- reference = trips[0].temperature / MCELSIUS;
- threshold_code = temp_to_code(data, reference);
- if (threshold_code < 0) {
- ret = threshold_code;
- goto out;
- }
- writeb(threshold_code, data->base + EXYNOS4210_TMU_REG_THRESHOLD_TEMP);
+static void exynos4412_tmu_set_trip_temp(struct exynos_tmu_data *data,
+ int trip, u8 temp)
+{
+ u32 th, con;
- for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
- temp = trips[i].temperature / MCELSIUS;
- writeb(temp - reference, data->base +
- EXYNOS4210_TMU_REG_TRIG_LEVEL0 + i * 4);
+ th = readl(data->base + EXYNOS_THD_TEMP_RISE);
+ th &= ~(0xff << 8 * trip);
+ th |= temp_to_code(data, temp) << 8 * trip;
+ writel(th, data->base + EXYNOS_THD_TEMP_RISE);
+
+ if (trip == 3) {
+ con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
+ con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
+ writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
}
+}
- data->tmu_clear_irqs(data);
-out:
- return ret;
+static void exynos4412_tmu_set_trip_hyst(struct exynos_tmu_data *data,
+ int trip, u8 temp, u8 hyst)
+{
+ u32 th;
+
+ th = readl(data->base + EXYNOS_THD_TEMP_FALL);
+ th &= ~(0xff << 8 * trip);
+ if (hyst)
+ th |= temp_to_code(data, temp - hyst) << 8 * trip;
+ writel(th, data->base + EXYNOS_THD_TEMP_FALL);
}
-static int exynos4412_tmu_initialize(struct platform_device *pdev)
+static void exynos4412_tmu_initialize(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
- const struct thermal_trip * const trips =
- of_thermal_get_trip_points(data->tzd);
- unsigned int status, trim_info, con, ctrl, rising_threshold;
- int ret = 0, threshold_code, i;
- unsigned long crit_temp = 0;
-
- status = readb(data->base + EXYNOS_TMU_REG_STATUS);
- if (!status) {
- ret = -EBUSY;
- goto out;
- }
+ unsigned int trim_info, ctrl;
if (data->soc == SOC_ARCH_EXYNOS3250 ||
data->soc == SOC_ARCH_EXYNOS4412 ||
@@ -485,58 +455,53 @@ static int exynos4412_tmu_initialize(struct platform_device *pdev)
trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
sanitize_temp_error(data, trim_info);
+}
- /* Write temperature code for rising and falling threshold */
- rising_threshold = readl(data->base + EXYNOS_THD_TEMP_RISE);
- rising_threshold = get_th_reg(data, rising_threshold, false);
- writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
- writel(get_th_reg(data, 0, true), data->base + EXYNOS_THD_TEMP_FALL);
-
- data->tmu_clear_irqs(data);
+static void exynos5433_tmu_set_trip_temp(struct exynos_tmu_data *data,
+ int trip, u8 temp)
+{
+ unsigned int reg_off, j;
+ u32 th;
- /* if last threshold limit is also present */
- for (i = 0; i < of_thermal_get_ntrips(data->tzd); i++) {
- if (trips[i].type == THERMAL_TRIP_CRITICAL) {
- crit_temp = trips[i].temperature;
- break;
- }
+ if (trip > 3) {
+ reg_off = EXYNOS5433_THD_TEMP_RISE7_4;
+ j = trip - 4;
+ } else {
+ reg_off = EXYNOS5433_THD_TEMP_RISE3_0;
+ j = trip;
}
- if (i == of_thermal_get_ntrips(data->tzd)) {
- pr_err("%s: No CRITICAL trip point defined at of-thermal.c!\n",
- __func__);
- ret = -EINVAL;
- goto out;
- }
+ th = readl(data->base + reg_off);
+ th &= ~(0xff << j * 8);
+ th |= (temp_to_code(data, temp) << j * 8);
+ writel(th, data->base + reg_off);
+}
- threshold_code = temp_to_code(data, crit_temp / MCELSIUS);
- /* 1-4 level to be assigned in th0 reg */
- rising_threshold &= ~(0xff << 8 * i);
- rising_threshold |= threshold_code << 8 * i;
- writel(rising_threshold, data->base + EXYNOS_THD_TEMP_RISE);
- con = readl(data->base + EXYNOS_TMU_REG_CONTROL);
- con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
- writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
+static void exynos5433_tmu_set_trip_hyst(struct exynos_tmu_data *data,
+ int trip, u8 temp, u8 hyst)
+{
+ unsigned int reg_off, j;
+ u32 th;
-out:
- return ret;
+ if (trip > 3) {
+ reg_off = EXYNOS5433_THD_TEMP_FALL7_4;
+ j = trip - 4;
+ } else {
+ reg_off = EXYNOS5433_THD_TEMP_FALL3_0;
+ j = trip;
+ }
+
+ th = readl(data->base + reg_off);
+ th &= ~(0xff << j * 8);
+ th |= (temp_to_code(data, temp - hyst) << j * 8);
+ writel(th, data->base + reg_off);
}
-static int exynos5433_tmu_initialize(struct platform_device *pdev)
+static void exynos5433_tmu_initialize(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
- struct exynos_tmu_platform_data *pdata = data->pdata;
- struct thermal_zone_device *tz = data->tzd;
- unsigned int status, trim_info;
- unsigned int rising_threshold = 0, falling_threshold = 0;
- int temp, temp_hist;
- int ret = 0, threshold_code, i, sensor_id, cal_type;
-
- status = readb(data->base + EXYNOS_TMU_REG_STATUS);
- if (!status) {
- ret = -EBUSY;
- goto out;
- }
+ unsigned int trim_info;
+ int sensor_id, cal_type;
trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
sanitize_temp_error(data, trim_info);
@@ -552,227 +517,84 @@ static int exynos5433_tmu_initialize(struct platform_device *pdev)
>> EXYNOS5433_TRIMINFO_CALIB_SEL_SHIFT;
switch (cal_type) {
- case EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING:
- pdata->cal_type = TYPE_ONE_POINT_TRIMMING;
- break;
case EXYNOS5433_TRIMINFO_TWO_POINT_TRIMMING:
- pdata->cal_type = TYPE_TWO_POINT_TRIMMING;
+ data->cal_type = TYPE_TWO_POINT_TRIMMING;
break;
+ case EXYNOS5433_TRIMINFO_ONE_POINT_TRIMMING:
default:
- pdata->cal_type = TYPE_ONE_POINT_TRIMMING;
+ data->cal_type = TYPE_ONE_POINT_TRIMMING;
break;
}
dev_info(&pdev->dev, "Calibration type is %d-point calibration\n",
cal_type ? 2 : 1);
-
- /* Write temperature code for rising and falling threshold */
- for (i = 0; i < of_thermal_get_ntrips(tz); i++) {
- int rising_reg_offset, falling_reg_offset;
- int j = 0;
-
- switch (i) {
- case 0:
- case 1:
- case 2:
- case 3:
- rising_reg_offset = EXYNOS5433_THD_TEMP_RISE3_0;
- falling_reg_offset = EXYNOS5433_THD_TEMP_FALL3_0;
- j = i;
- break;
- case 4:
- case 5:
- case 6:
- case 7:
- rising_reg_offset = EXYNOS5433_THD_TEMP_RISE7_4;
- falling_reg_offset = EXYNOS5433_THD_TEMP_FALL7_4;
- j = i - 4;
- break;
- default:
- continue;
- }
-
- /* Write temperature code for rising threshold */
- tz->ops->get_trip_temp(tz, i, &temp);
- temp /= MCELSIUS;
- threshold_code = temp_to_code(data, temp);
-
- rising_threshold = readl(data->base + rising_reg_offset);
- rising_threshold |= (threshold_code << j * 8);
- writel(rising_threshold, data->base + rising_reg_offset);
-
- /* Write temperature code for falling threshold */
- tz->ops->get_trip_hyst(tz, i, &temp_hist);
- temp_hist = temp - (temp_hist / MCELSIUS);
- threshold_code = temp_to_code(data, temp_hist);
-
- falling_threshold = readl(data->base + falling_reg_offset);
- falling_threshold &= ~(0xff << j * 8);
- falling_threshold |= (threshold_code << j * 8);
- writel(falling_threshold, data->base + falling_reg_offset);
- }
-
- data->tmu_clear_irqs(data);
-out:
- return ret;
}
-static int exynos5440_tmu_initialize(struct platform_device *pdev)
+static void exynos7_tmu_set_trip_temp(struct exynos_tmu_data *data,
+ int trip, u8 temp)
{
- struct exynos_tmu_data *data = platform_get_drvdata(pdev);
- unsigned int trim_info = 0, con, rising_threshold;
- int threshold_code;
- int crit_temp = 0;
+ unsigned int reg_off, bit_off;
+ u32 th;
- /*
- * For exynos5440 soc triminfo value is swapped between TMU0 and
- * TMU2, so the below logic is needed.
- */
- switch (data->id) {
- case 0:
- trim_info = readl(data->base + EXYNOS5440_EFUSE_SWAP_OFFSET +
- EXYNOS5440_TMU_S0_7_TRIM);
- break;
- case 1:
- trim_info = readl(data->base + EXYNOS5440_TMU_S0_7_TRIM);
- break;
- case 2:
- trim_info = readl(data->base - EXYNOS5440_EFUSE_SWAP_OFFSET +
- EXYNOS5440_TMU_S0_7_TRIM);
- }
- sanitize_temp_error(data, trim_info);
+ reg_off = ((7 - trip) / 2) * 4;
+ bit_off = ((8 - trip) % 2);
- /* Write temperature code for rising and falling threshold */
- rising_threshold = readl(data->base + EXYNOS5440_TMU_S0_7_TH0);
- rising_threshold = get_th_reg(data, rising_threshold, false);
- writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH0);
- writel(0, data->base + EXYNOS5440_TMU_S0_7_TH1);
+ th = readl(data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
+ th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
+ th |= temp_to_code(data, temp) << (16 * bit_off);
+ writel(th, data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
+}
- data->tmu_clear_irqs(data);
+static void exynos7_tmu_set_trip_hyst(struct exynos_tmu_data *data,
+ int trip, u8 temp, u8 hyst)
+{
+ unsigned int reg_off, bit_off;
+ u32 th;
- /* if last threshold limit is also present */
- if (!data->tzd->ops->get_crit_temp(data->tzd, &crit_temp)) {
- threshold_code = temp_to_code(data, crit_temp / MCELSIUS);
- /* 5th level to be assigned in th2 reg */
- rising_threshold =
- threshold_code << EXYNOS5440_TMU_TH_RISE4_SHIFT;
- writel(rising_threshold, data->base + EXYNOS5440_TMU_S0_7_TH2);
- con = readl(data->base + EXYNOS5440_TMU_S0_7_CTRL);
- con |= (1 << EXYNOS_TMU_THERM_TRIP_EN_SHIFT);
- writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
- }
- /* Clear the PMIN in the common TMU register */
- if (!data->id)
- writel(0, data->base_second + EXYNOS5440_TMU_PMIN);
+ reg_off = ((7 - trip) / 2) * 4;
+ bit_off = ((8 - trip) % 2);
- return 0;
+ th = readl(data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
+ th &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
+ th |= temp_to_code(data, temp - hyst) << (16 * bit_off);
+ writel(th, data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
}
-static int exynos7_tmu_initialize(struct platform_device *pdev)
+static void exynos7_tmu_initialize(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
- struct thermal_zone_device *tz = data->tzd;
- struct exynos_tmu_platform_data *pdata = data->pdata;
- unsigned int status, trim_info;
- unsigned int rising_threshold = 0, falling_threshold = 0;
- int ret = 0, threshold_code, i;
- int temp, temp_hist;
- unsigned int reg_off, bit_off;
-
- status = readb(data->base + EXYNOS_TMU_REG_STATUS);
- if (!status) {
- ret = -EBUSY;
- goto out;
- }
+ unsigned int trim_info;
trim_info = readl(data->base + EXYNOS_TMU_REG_TRIMINFO);
-
- data->temp_error1 = trim_info & EXYNOS7_TMU_TEMP_MASK;
- if (!data->temp_error1 ||
- (pdata->min_efuse_value > data->temp_error1) ||
- (data->temp_error1 > pdata->max_efuse_value))
- data->temp_error1 = pdata->efuse_value & EXYNOS_TMU_TEMP_MASK;
-
- /* Write temperature code for rising and falling threshold */
- for (i = (of_thermal_get_ntrips(tz) - 1); i >= 0; i--) {
- /*
- * On exynos7 there are 4 rising and 4 falling threshold
- * registers (0x50-0x5c and 0x60-0x6c respectively). Each
- * register holds the value of two threshold levels (at bit
- * offsets 0 and 16). Based on the fact that there are atmost
- * eight possible trigger levels, calculate the register and
- * bit offsets where the threshold levels are to be written.
- *
- * e.g. EXYNOS7_THD_TEMP_RISE7_6 (0x50)
- * [24:16] - Threshold level 7
- * [8:0] - Threshold level 6
- * e.g. EXYNOS7_THD_TEMP_RISE5_4 (0x54)
- * [24:16] - Threshold level 5
- * [8:0] - Threshold level 4
- *
- * and similarly for falling thresholds.
- *
- * Based on the above, calculate the register and bit offsets
- * for rising/falling threshold levels and populate them.
- */
- reg_off = ((7 - i) / 2) * 4;
- bit_off = ((8 - i) % 2);
-
- tz->ops->get_trip_temp(tz, i, &temp);
- temp /= MCELSIUS;
-
- tz->ops->get_trip_hyst(tz, i, &temp_hist);
- temp_hist = temp - (temp_hist / MCELSIUS);
-
- /* Set 9-bit temperature code for rising threshold levels */
- threshold_code = temp_to_code(data, temp);
- rising_threshold = readl(data->base +
- EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
- rising_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
- rising_threshold |= threshold_code << (16 * bit_off);
- writel(rising_threshold,
- data->base + EXYNOS7_THD_TEMP_RISE7_6 + reg_off);
-
- /* Set 9-bit temperature code for falling threshold levels */
- threshold_code = temp_to_code(data, temp_hist);
- falling_threshold &= ~(EXYNOS7_TMU_TEMP_MASK << (16 * bit_off));
- falling_threshold |= threshold_code << (16 * bit_off);
- writel(falling_threshold,
- data->base + EXYNOS7_THD_TEMP_FALL7_6 + reg_off);
- }
-
- data->tmu_clear_irqs(data);
-out:
- return ret;
+ sanitize_temp_error(data, trim_info);
}
static void exynos4210_tmu_control(struct platform_device *pdev, bool on)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tz = data->tzd;
- unsigned int con, interrupt_en;
+ unsigned int con, interrupt_en = 0, i;
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
if (on) {
- con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
- interrupt_en =
- (of_thermal_is_trip_valid(tz, 3)
- << EXYNOS_TMU_INTEN_RISE3_SHIFT) |
- (of_thermal_is_trip_valid(tz, 2)
- << EXYNOS_TMU_INTEN_RISE2_SHIFT) |
- (of_thermal_is_trip_valid(tz, 1)
- << EXYNOS_TMU_INTEN_RISE1_SHIFT) |
- (of_thermal_is_trip_valid(tz, 0)
- << EXYNOS_TMU_INTEN_RISE0_SHIFT);
+ for (i = 0; i < data->ntrip; i++) {
+ if (!of_thermal_is_trip_valid(tz, i))
+ continue;
+
+ interrupt_en |=
+ (1 << (EXYNOS_TMU_INTEN_RISE0_SHIFT + i * 4));
+ }
if (data->soc != SOC_ARCH_EXYNOS4210)
interrupt_en |=
interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
+
+ con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
} else {
con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
- interrupt_en = 0; /* Disable all interrupts */
}
+
writel(interrupt_en, data->base + EXYNOS_TMU_REG_INTEN);
writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
}
@@ -781,36 +603,25 @@ static void exynos5433_tmu_control(struct platform_device *pdev, bool on)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tz = data->tzd;
- unsigned int con, interrupt_en, pd_det_en;
+ unsigned int con, interrupt_en = 0, pd_det_en, i;
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
if (on) {
- con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
- interrupt_en =
- (of_thermal_is_trip_valid(tz, 7)
- << EXYNOS7_TMU_INTEN_RISE7_SHIFT) |
- (of_thermal_is_trip_valid(tz, 6)
- << EXYNOS7_TMU_INTEN_RISE6_SHIFT) |
- (of_thermal_is_trip_valid(tz, 5)
- << EXYNOS7_TMU_INTEN_RISE5_SHIFT) |
- (of_thermal_is_trip_valid(tz, 4)
- << EXYNOS7_TMU_INTEN_RISE4_SHIFT) |
- (of_thermal_is_trip_valid(tz, 3)
- << EXYNOS7_TMU_INTEN_RISE3_SHIFT) |
- (of_thermal_is_trip_valid(tz, 2)
- << EXYNOS7_TMU_INTEN_RISE2_SHIFT) |
- (of_thermal_is_trip_valid(tz, 1)
- << EXYNOS7_TMU_INTEN_RISE1_SHIFT) |
- (of_thermal_is_trip_valid(tz, 0)
- << EXYNOS7_TMU_INTEN_RISE0_SHIFT);
+ for (i = 0; i < data->ntrip; i++) {
+ if (!of_thermal_is_trip_valid(tz, i))
+ continue;
+
+ interrupt_en |=
+ (1 << (EXYNOS7_TMU_INTEN_RISE0_SHIFT + i));
+ }
interrupt_en |=
interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
- } else {
+
+ con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
+ } else
con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
- interrupt_en = 0; /* Disable all interrupts */
- }
pd_det_en = on ? EXYNOS5433_PD_DET_EN : 0;
@@ -819,70 +630,31 @@ static void exynos5433_tmu_control(struct platform_device *pdev, bool on)
writel(con, data->base + EXYNOS_TMU_REG_CONTROL);
}
-static void exynos5440_tmu_control(struct platform_device *pdev, bool on)
-{
- struct exynos_tmu_data *data = platform_get_drvdata(pdev);
- struct thermal_zone_device *tz = data->tzd;
- unsigned int con, interrupt_en;
-
- con = get_con_reg(data, readl(data->base + EXYNOS5440_TMU_S0_7_CTRL));
-
- if (on) {
- con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
- interrupt_en =
- (of_thermal_is_trip_valid(tz, 3)
- << EXYNOS5440_TMU_INTEN_RISE3_SHIFT) |
- (of_thermal_is_trip_valid(tz, 2)
- << EXYNOS5440_TMU_INTEN_RISE2_SHIFT) |
- (of_thermal_is_trip_valid(tz, 1)
- << EXYNOS5440_TMU_INTEN_RISE1_SHIFT) |
- (of_thermal_is_trip_valid(tz, 0)
- << EXYNOS5440_TMU_INTEN_RISE0_SHIFT);
- interrupt_en |=
- interrupt_en << EXYNOS5440_TMU_INTEN_FALL0_SHIFT;
- } else {
- con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
- interrupt_en = 0; /* Disable all interrupts */
- }
- writel(interrupt_en, data->base + EXYNOS5440_TMU_S0_7_IRQEN);
- writel(con, data->base + EXYNOS5440_TMU_S0_7_CTRL);
-}
-
static void exynos7_tmu_control(struct platform_device *pdev, bool on)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
struct thermal_zone_device *tz = data->tzd;
- unsigned int con, interrupt_en;
+ unsigned int con, interrupt_en = 0, i;
con = get_con_reg(data, readl(data->base + EXYNOS_TMU_REG_CONTROL));
if (on) {
- con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
- con |= (1 << EXYNOS7_PD_DET_EN_SHIFT);
- interrupt_en =
- (of_thermal_is_trip_valid(tz, 7)
- << EXYNOS7_TMU_INTEN_RISE7_SHIFT) |
- (of_thermal_is_trip_valid(tz, 6)
- << EXYNOS7_TMU_INTEN_RISE6_SHIFT) |
- (of_thermal_is_trip_valid(tz, 5)
- << EXYNOS7_TMU_INTEN_RISE5_SHIFT) |
- (of_thermal_is_trip_valid(tz, 4)
- << EXYNOS7_TMU_INTEN_RISE4_SHIFT) |
- (of_thermal_is_trip_valid(tz, 3)
- << EXYNOS7_TMU_INTEN_RISE3_SHIFT) |
- (of_thermal_is_trip_valid(tz, 2)
- << EXYNOS7_TMU_INTEN_RISE2_SHIFT) |
- (of_thermal_is_trip_valid(tz, 1)
- << EXYNOS7_TMU_INTEN_RISE1_SHIFT) |
- (of_thermal_is_trip_valid(tz, 0)
- << EXYNOS7_TMU_INTEN_RISE0_SHIFT);
+ for (i = 0; i < data->ntrip; i++) {
+ if (!of_thermal_is_trip_valid(tz, i))
+ continue;
+
+ interrupt_en |=
+ (1 << (EXYNOS7_TMU_INTEN_RISE0_SHIFT + i));
+ }
interrupt_en |=
interrupt_en << EXYNOS_TMU_INTEN_FALL0_SHIFT;
+
+ con |= (1 << EXYNOS_TMU_CORE_EN_SHIFT);
+ con |= (1 << EXYNOS7_PD_DET_EN_SHIFT);
} else {
con &= ~(1 << EXYNOS_TMU_CORE_EN_SHIFT);
con &= ~(1 << EXYNOS7_PD_DET_EN_SHIFT);
- interrupt_en = 0; /* Disable all interrupts */
}
writel(interrupt_en, data->base + EXYNOS7_TMU_REG_INTEN);
@@ -896,6 +668,12 @@ static int exynos_get_temp(void *p, int *temp)
if (!data || !data->tmu_read || !data->enabled)
return -EINVAL;
+ else if (!data->enabled)
+ /*
+ * Called too early, probably
+ * from thermal_zone_of_sensor_register().
+ */
+ return -EAGAIN;
mutex_lock(&data->lock);
clk_enable(data->clk);
@@ -919,10 +697,8 @@ static u32 get_emul_con_reg(struct exynos_tmu_data *data, unsigned int val,
if (temp) {
temp /= MCELSIUS;
- if (data->soc != SOC_ARCH_EXYNOS5440) {
- val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
- val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
- }
+ val &= ~(EXYNOS_EMUL_TIME_MASK << EXYNOS_EMUL_TIME_SHIFT);
+ val |= (EXYNOS_EMUL_TIME << EXYNOS_EMUL_TIME_SHIFT);
if (data->soc == SOC_ARCH_EXYNOS7) {
val &= ~(EXYNOS7_EMUL_DATA_MASK <<
EXYNOS7_EMUL_DATA_SHIFT);
@@ -963,16 +739,6 @@ static void exynos4412_tmu_set_emulation(struct exynos_tmu_data *data,
writel(val, data->base + emul_con);
}
-static void exynos5440_tmu_set_emulation(struct exynos_tmu_data *data,
- int temp)
-{
- unsigned int val;
-
- val = readl(data->base + EXYNOS5440_TMU_S0_7_DEBUG);
- val = get_emul_con_reg(data, val, temp);
- writel(val, data->base + EXYNOS5440_TMU_S0_7_DEBUG);
-}
-
static int exynos_tmu_set_emulation(void *drv_data, int temp)
{
struct exynos_tmu_data *data = drv_data;
@@ -995,7 +761,6 @@ out:
}
#else
#define exynos4412_tmu_set_emulation NULL
-#define exynos5440_tmu_set_emulation NULL
static int exynos_tmu_set_emulation(void *drv_data, int temp)
{ return -EINVAL; }
#endif /* CONFIG_THERMAL_EMULATION */
@@ -1013,11 +778,6 @@ static int exynos4412_tmu_read(struct exynos_tmu_data *data)
return readb(data->base + EXYNOS_TMU_REG_CURRENT_TEMP);
}
-static int exynos5440_tmu_read(struct exynos_tmu_data *data)
-{
- return readb(data->base + EXYNOS5440_TMU_S0_7_TEMP);
-}
-
static int exynos7_tmu_read(struct exynos_tmu_data *data)
{
return readw(data->base + EXYNOS_TMU_REG_CURRENT_TEMP) &
@@ -1028,20 +788,14 @@ static void exynos_tmu_work(struct work_struct *work)
{
struct exynos_tmu_data *data = container_of(work,
struct exynos_tmu_data, irq_work);
- unsigned int val_type;
if (!IS_ERR(data->clk_sec))
clk_enable(data->clk_sec);
- /* Find which sensor generated this interrupt */
- if (data->soc == SOC_ARCH_EXYNOS5440) {
- val_type = readl(data->base_second + EXYNOS5440_TMU_IRQ_STATUS);
- if (!((val_type >> data->id) & 0x1))
- goto out;
- }
if (!IS_ERR(data->clk_sec))
clk_disable(data->clk_sec);
- exynos_report_trigger(data);
+ thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED);
+
mutex_lock(&data->lock);
clk_enable(data->clk);
@@ -1050,7 +804,6 @@ static void exynos_tmu_work(struct work_struct *work)
clk_disable(data->clk);
mutex_unlock(&data->lock);
-out:
enable_irq(data->irq);
}
@@ -1085,15 +838,6 @@ static void exynos4210_tmu_clear_irqs(struct exynos_tmu_data *data)
writel(val_irq, data->base + tmu_intclear);
}
-static void exynos5440_tmu_clear_irqs(struct exynos_tmu_data *data)
-{
- unsigned int val_irq;
-
- val_irq = readl(data->base + EXYNOS5440_TMU_S0_7_IRQ);
- /* clear the interrupts */
- writel(val_irq, data->base + EXYNOS5440_TMU_S0_7_IRQ);
-}
-
static irqreturn_t exynos_tmu_irq(int irq, void *id)
{
struct exynos_tmu_data *data = id;
@@ -1105,86 +849,41 @@ static irqreturn_t exynos_tmu_irq(int irq, void *id)
}
static const struct of_device_id exynos_tmu_match[] = {
- { .compatible = "samsung,exynos3250-tmu", },
- { .compatible = "samsung,exynos4210-tmu", },
- { .compatible = "samsung,exynos4412-tmu", },
- { .compatible = "samsung,exynos5250-tmu", },
- { .compatible = "samsung,exynos5260-tmu", },
- { .compatible = "samsung,exynos5420-tmu", },
- { .compatible = "samsung,exynos5420-tmu-ext-triminfo", },
- { .compatible = "samsung,exynos5433-tmu", },
- { .compatible = "samsung,exynos5440-tmu", },
- { .compatible = "samsung,exynos7-tmu", },
- { /* sentinel */ },
+ {
+ .compatible = "samsung,exynos3250-tmu",
+ .data = (const void *)SOC_ARCH_EXYNOS3250,
+ }, {
+ .compatible = "samsung,exynos4210-tmu",
+ .data = (const void *)SOC_ARCH_EXYNOS4210,
+ }, {
+ .compatible = "samsung,exynos4412-tmu",
+ .data = (const void *)SOC_ARCH_EXYNOS4412,
+ }, {
+ .compatible = "samsung,exynos5250-tmu",
+ .data = (const void *)SOC_ARCH_EXYNOS5250,
+ }, {
+ .compatible = "samsung,exynos5260-tmu",
+ .data = (const void *)SOC_ARCH_EXYNOS5260,
+ }, {
+ .compatible = "samsung,exynos5420-tmu",
+ .data = (const void *)SOC_ARCH_EXYNOS5420,
+ }, {
+ .compatible = "samsung,exynos5420-tmu-ext-triminfo",
+ .data = (const void *)SOC_ARCH_EXYNOS5420_TRIMINFO,
+ }, {
+ .compatible = "samsung,exynos5433-tmu",
+ .data = (const void *)SOC_ARCH_EXYNOS5433,
+ }, {
+ .compatible = "samsung,exynos7-tmu",
+ .data = (const void *)SOC_ARCH_EXYNOS7,
+ },
+ { },
};
MODULE_DEVICE_TABLE(of, exynos_tmu_match);
-static int exynos_of_get_soc_type(struct device_node *np)
-{
- if (of_device_is_compatible(np, "samsung,exynos3250-tmu"))
- return SOC_ARCH_EXYNOS3250;
- else if (of_device_is_compatible(np, "samsung,exynos4210-tmu"))
- return SOC_ARCH_EXYNOS4210;
- else if (of_device_is_compatible(np, "samsung,exynos4412-tmu"))
- return SOC_ARCH_EXYNOS4412;
- else if (of_device_is_compatible(np, "samsung,exynos5250-tmu"))
- return SOC_ARCH_EXYNOS5250;
- else if (of_device_is_compatible(np, "samsung,exynos5260-tmu"))
- return SOC_ARCH_EXYNOS5260;
- else if (of_device_is_compatible(np, "samsung,exynos5420-tmu"))
- return SOC_ARCH_EXYNOS5420;
- else if (of_device_is_compatible(np,
- "samsung,exynos5420-tmu-ext-triminfo"))
- return SOC_ARCH_EXYNOS5420_TRIMINFO;
- else if (of_device_is_compatible(np, "samsung,exynos5433-tmu"))
- return SOC_ARCH_EXYNOS5433;
- else if (of_device_is_compatible(np, "samsung,exynos5440-tmu"))
- return SOC_ARCH_EXYNOS5440;
- else if (of_device_is_compatible(np, "samsung,exynos7-tmu"))
- return SOC_ARCH_EXYNOS7;
-
- return -EINVAL;
-}
-
-static int exynos_of_sensor_conf(struct device_node *np,
- struct exynos_tmu_platform_data *pdata)
-{
- u32 value;
- int ret;
-
- of_node_get(np);
-
- ret = of_property_read_u32(np, "samsung,tmu_gain", &value);
- pdata->gain = (u8)value;
- of_property_read_u32(np, "samsung,tmu_reference_voltage", &value);
- pdata->reference_voltage = (u8)value;
- of_property_read_u32(np, "samsung,tmu_noise_cancel_mode", &value);
- pdata->noise_cancel_mode = (u8)value;
-
- of_property_read_u32(np, "samsung,tmu_efuse_value",
- &pdata->efuse_value);
- of_property_read_u32(np, "samsung,tmu_min_efuse_value",
- &pdata->min_efuse_value);
- of_property_read_u32(np, "samsung,tmu_max_efuse_value",
- &pdata->max_efuse_value);
-
- of_property_read_u32(np, "samsung,tmu_first_point_trim", &value);
- pdata->first_point_trim = (u8)value;
- of_property_read_u32(np, "samsung,tmu_second_point_trim", &value);
- pdata->second_point_trim = (u8)value;
- of_property_read_u32(np, "samsung,tmu_default_temp_offset", &value);
- pdata->default_temp_offset = (u8)value;
-
- of_property_read_u32(np, "samsung,tmu_cal_type", &pdata->cal_type);
-
- of_node_put(np);
- return 0;
-}
-
static int exynos_map_dt_data(struct platform_device *pdev)
{
struct exynos_tmu_data *data = platform_get_drvdata(pdev);
- struct exynos_tmu_platform_data *pdata;
struct resource res;
if (!data || !pdev->dev.of_node)
@@ -1211,23 +910,22 @@ static int exynos_map_dt_data(struct platform_device *pdev)
return -EADDRNOTAVAIL;
}
- pdata = devm_kzalloc(&pdev->dev,
- sizeof(struct exynos_tmu_platform_data),
- GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
-
- exynos_of_sensor_conf(pdev->dev.of_node, pdata);
- data->pdata = pdata;
- data->soc = exynos_of_get_soc_type(pdev->dev.of_node);
+ data->soc = (enum soc_type)of_device_get_match_data(&pdev->dev);
switch (data->soc) {
case SOC_ARCH_EXYNOS4210:
+ data->tmu_set_trip_temp = exynos4210_tmu_set_trip_temp;
+ data->tmu_set_trip_hyst = exynos4210_tmu_set_trip_hyst;
data->tmu_initialize = exynos4210_tmu_initialize;
data->tmu_control = exynos4210_tmu_control;
data->tmu_read = exynos4210_tmu_read;
data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
data->ntrip = 4;
+ data->gain = 15;
+ data->reference_voltage = 7;
+ data->efuse_value = 55;
+ data->min_efuse_value = 40;
+ data->max_efuse_value = 100;
break;
case SOC_ARCH_EXYNOS3250:
case SOC_ARCH_EXYNOS4412:
@@ -1235,48 +933,69 @@ static int exynos_map_dt_data(struct platform_device *pdev)
case SOC_ARCH_EXYNOS5260:
case SOC_ARCH_EXYNOS5420:
case SOC_ARCH_EXYNOS5420_TRIMINFO:
+ data->tmu_set_trip_temp = exynos4412_tmu_set_trip_temp;
+ data->tmu_set_trip_hyst = exynos4412_tmu_set_trip_hyst;
data->tmu_initialize = exynos4412_tmu_initialize;
data->tmu_control = exynos4210_tmu_control;
data->tmu_read = exynos4412_tmu_read;
data->tmu_set_emulation = exynos4412_tmu_set_emulation;
data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
data->ntrip = 4;
+ data->gain = 8;
+ data->reference_voltage = 16;
+ data->efuse_value = 55;
+ if (data->soc != SOC_ARCH_EXYNOS5420 &&
+ data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO)
+ data->min_efuse_value = 40;
+ else
+ data->min_efuse_value = 0;
+ data->max_efuse_value = 100;
break;
case SOC_ARCH_EXYNOS5433:
+ data->tmu_set_trip_temp = exynos5433_tmu_set_trip_temp;
+ data->tmu_set_trip_hyst = exynos5433_tmu_set_trip_hyst;
data->tmu_initialize = exynos5433_tmu_initialize;
data->tmu_control = exynos5433_tmu_control;
data->tmu_read = exynos4412_tmu_read;
data->tmu_set_emulation = exynos4412_tmu_set_emulation;
data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
data->ntrip = 8;
- break;
- case SOC_ARCH_EXYNOS5440:
- data->tmu_initialize = exynos5440_tmu_initialize;
- data->tmu_control = exynos5440_tmu_control;
- data->tmu_read = exynos5440_tmu_read;
- data->tmu_set_emulation = exynos5440_tmu_set_emulation;
- data->tmu_clear_irqs = exynos5440_tmu_clear_irqs;
- data->ntrip = 4;
+ data->gain = 8;
+ if (res.start == EXYNOS5433_G3D_BASE)
+ data->reference_voltage = 23;
+ else
+ data->reference_voltage = 16;
+ data->efuse_value = 75;
+ data->min_efuse_value = 40;
+ data->max_efuse_value = 150;
break;
case SOC_ARCH_EXYNOS7:
+ data->tmu_set_trip_temp = exynos7_tmu_set_trip_temp;
+ data->tmu_set_trip_hyst = exynos7_tmu_set_trip_hyst;
data->tmu_initialize = exynos7_tmu_initialize;
data->tmu_control = exynos7_tmu_control;
data->tmu_read = exynos7_tmu_read;
data->tmu_set_emulation = exynos4412_tmu_set_emulation;
data->tmu_clear_irqs = exynos4210_tmu_clear_irqs;
data->ntrip = 8;
+ data->gain = 9;
+ data->reference_voltage = 17;
+ data->efuse_value = 75;
+ data->min_efuse_value = 15;
+ data->max_efuse_value = 100;
break;
default:
dev_err(&pdev->dev, "Platform not supported\n");
return -EINVAL;
}
+ data->cal_type = TYPE_ONE_POINT_TRIMMING;
+
/*
* Check if the TMU shares some registers and then try to map the
* memory of common registers.
*/
- if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO &&
- data->soc != SOC_ARCH_EXYNOS5440)
+ if (data->soc != SOC_ARCH_EXYNOS5420_TRIMINFO)
return 0;
if (of_address_to_resource(pdev->dev.of_node, 1, &res)) {
diff --git a/drivers/thermal/samsung/exynos_tmu.h b/drivers/thermal/samsung/exynos_tmu.h
deleted file mode 100644
index 5149c2a..0000000
--- a/drivers/thermal/samsung/exynos_tmu.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * exynos_tmu.h - Samsung EXYNOS TMU (Thermal Management Unit)
- *
- * Copyright (C) 2011 Samsung Electronics
- * Donggeun Kim <dg77.kim@samsung.com>
- * Amit Daniel Kachhap <amit.daniel@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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _EXYNOS_TMU_H
-#define _EXYNOS_TMU_H
-#include <linux/cpu_cooling.h>
-#include <dt-bindings/thermal/thermal_exynos.h>
-
-enum soc_type {
- SOC_ARCH_EXYNOS3250 = 1,
- SOC_ARCH_EXYNOS4210,
- SOC_ARCH_EXYNOS4412,
- SOC_ARCH_EXYNOS5250,
- SOC_ARCH_EXYNOS5260,
- SOC_ARCH_EXYNOS5420,
- SOC_ARCH_EXYNOS5420_TRIMINFO,
- SOC_ARCH_EXYNOS5433,
- SOC_ARCH_EXYNOS5440,
- SOC_ARCH_EXYNOS7,
-};
-
-/**
- * struct exynos_tmu_platform_data
- * @gain: gain of amplifier in the positive-TC generator block
- * 0 < gain <= 15
- * @reference_voltage: reference voltage of amplifier
- * in the positive-TC generator block
- * 0 < reference_voltage <= 31
- * @noise_cancel_mode: noise cancellation mode
- * 000, 100, 101, 110 and 111 can be different modes
- * @type: determines the type of SOC
- * @efuse_value: platform defined fuse value
- * @min_efuse_value: minimum valid trimming data
- * @max_efuse_value: maximum valid trimming data
- * @default_temp_offset: default temperature offset in case of no trimming
- * @cal_type: calibration type for temperature
- *
- * This structure is required for configuration of exynos_tmu driver.
- */
-struct exynos_tmu_platform_data {
- u8 gain;
- u8 reference_voltage;
- u8 noise_cancel_mode;
-
- u32 efuse_value;
- u32 min_efuse_value;
- u32 max_efuse_value;
- u8 first_point_trim;
- u8 second_point_trim;
- u8 default_temp_offset;
-
- enum soc_type type;
- u32 cal_type;
-};
-
-#endif /* _EXYNOS_TMU_H */
diff --git a/drivers/thermal/tegra/soctherm.c b/drivers/thermal/tegra/soctherm.c
index 455b58c..ed28110 100644
--- a/drivers/thermal/tegra/soctherm.c
+++ b/drivers/thermal/tegra/soctherm.c
@@ -241,31 +241,6 @@ struct tegra_soctherm {
};
/**
- * clk_writel() - writes a value to a CAR register
- * @ts: pointer to a struct tegra_soctherm
- * @v: the value to write
- * @reg: the register offset
- *
- * Writes @v to @reg. No return value.
- */
-static inline void clk_writel(struct tegra_soctherm *ts, u32 value, u32 reg)
-{
- writel(value, (ts->clk_regs + reg));
-}
-
-/**
- * clk_readl() - reads specified register from CAR IP block
- * @ts: pointer to a struct tegra_soctherm
- * @reg: register address to be read
- *
- * Return: the value of the register
- */
-static inline u32 clk_readl(struct tegra_soctherm *ts, u32 reg)
-{
- return readl(ts->clk_regs + reg);
-}
-
-/**
* ccroc_writel() - writes a value to a CCROC register
* @ts: pointer to a struct tegra_soctherm
* @v: the value to write
@@ -926,7 +901,7 @@ static int throt_set_cdev_state(struct thermal_cooling_device *cdev,
return 0;
}
-static struct thermal_cooling_device_ops throt_cooling_ops = {
+static const struct thermal_cooling_device_ops throt_cooling_ops = {
.get_max_state = throt_get_cdev_max_state,
.get_cur_state = throt_get_cdev_cur_state,
.set_cur_state = throt_set_cdev_state,
@@ -1207,9 +1182,9 @@ static void tegra_soctherm_throttle(struct device *dev)
} else {
writel(v, ts->regs + THROT_GLOBAL_CFG);
- v = clk_readl(ts, CAR_SUPER_CCLKG_DIVIDER);
+ v = readl(ts->clk_regs + CAR_SUPER_CCLKG_DIVIDER);
v = REG_SET_MASK(v, CDIVG_USE_THERM_CONTROLS_MASK, 1);
- clk_writel(ts, v, CAR_SUPER_CCLKG_DIVIDER);
+ writel(v, ts->clk_regs + CAR_SUPER_CCLKG_DIVIDER);
}
/* initialize stats collection */
@@ -1343,8 +1318,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
return PTR_ERR(tegra->clock_soctherm);
}
- tegra->calib = devm_kzalloc(&pdev->dev,
- sizeof(u32) * soc->num_tsensors,
+ tegra->calib = devm_kcalloc(&pdev->dev,
+ soc->num_tsensors, sizeof(u32),
GFP_KERNEL);
if (!tegra->calib)
return -ENOMEM;
@@ -1363,8 +1338,8 @@ static int tegra_soctherm_probe(struct platform_device *pdev)
return err;
}
- tegra->thermctl_tzs = devm_kzalloc(&pdev->dev,
- sizeof(*z) * soc->num_ttgs,
+ tegra->thermctl_tzs = devm_kcalloc(&pdev->dev,
+ soc->num_ttgs, sizeof(*z),
GFP_KERNEL);
if (!tegra->thermctl_tzs)
return -ENOMEM;
diff --git a/drivers/thermal/thermal-generic-adc.c b/drivers/thermal/thermal-generic-adc.c
index 46d3005..bf1c628 100644
--- a/drivers/thermal/thermal-generic-adc.c
+++ b/drivers/thermal/thermal-generic-adc.c
@@ -87,8 +87,9 @@ static int gadc_thermal_read_linear_lookup_table(struct device *dev,
return -EINVAL;
}
- gti->lookup_table = devm_kzalloc(dev, sizeof(*gti->lookup_table) *
- ntable, GFP_KERNEL);
+ gti->lookup_table = devm_kcalloc(dev,
+ ntable, sizeof(*gti->lookup_table),
+ GFP_KERNEL);
if (!gti->lookup_table)
return -ENOMEM;
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index d64325e..6ab9823 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1,13 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* thermal.c - Generic Thermal Management Sysfs support.
*
* Copyright (C) 2008 Intel Corp
* Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
* Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.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.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -736,7 +733,7 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
sysfs_attr_init(&dev->attr.attr);
dev->attr.attr.name = dev->attr_name;
dev->attr.attr.mode = 0444;
- dev->attr.show = thermal_cooling_device_trip_point_show;
+ dev->attr.show = trip_point_show;
result = device_create_file(&tz->device, &dev->attr);
if (result)
goto remove_symbol_link;
@@ -745,8 +742,8 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz,
sysfs_attr_init(&dev->weight_attr.attr);
dev->weight_attr.attr.name = dev->weight_attr_name;
dev->weight_attr.attr.mode = S_IWUSR | S_IRUGO;
- dev->weight_attr.show = thermal_cooling_device_weight_show;
- dev->weight_attr.store = thermal_cooling_device_weight_store;
+ dev->weight_attr.show = weight_show;
+ dev->weight_attr.store = weight_store;
result = device_create_file(&tz->device, &dev->weight_attr);
if (result)
goto remove_trip_file;
diff --git a/drivers/thermal/thermal_core.h b/drivers/thermal/thermal_core.h
index 5e41502..0df190e 100644
--- a/drivers/thermal/thermal_core.h
+++ b/drivers/thermal/thermal_core.h
@@ -1,24 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* thermal_core.h
*
* Copyright (C) 2012 Intel Corp
* Author: Durgadoss R <durgadoss.r@intel.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.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifndef __THERMAL_CORE_H__
@@ -75,15 +60,10 @@ void thermal_zone_destroy_device_groups(struct thermal_zone_device *);
void thermal_cooling_device_setup_sysfs(struct thermal_cooling_device *);
void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev);
/* used only at binding time */
-ssize_t
-thermal_cooling_device_trip_point_show(struct device *,
- struct device_attribute *, char *);
-ssize_t thermal_cooling_device_weight_show(struct device *,
- struct device_attribute *, char *);
-
-ssize_t thermal_cooling_device_weight_store(struct device *,
- struct device_attribute *,
- const char *, size_t);
+ssize_t trip_point_show(struct device *, struct device_attribute *, char *);
+ssize_t weight_show(struct device *, struct device_attribute *, char *);
+ssize_t weight_store(struct device *, struct device_attribute *, const char *,
+ size_t);
#ifdef CONFIG_THERMAL_STATISTICS
void thermal_cooling_device_stats_update(struct thermal_cooling_device *cdev,
diff --git a/drivers/thermal/thermal_helpers.c b/drivers/thermal/thermal_helpers.c
index eb03d7e..2ba756a 100644
--- a/drivers/thermal/thermal_helpers.c
+++ b/drivers/thermal/thermal_helpers.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* thermal_helpers.c - helper functions to handle thermal devices
*
@@ -7,10 +8,6 @@
* Copyright (C) 2008 Intel Corp
* Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
* Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.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.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
index c4a508a..1127883 100644
--- a/drivers/thermal/thermal_hwmon.c
+++ b/drivers/thermal/thermal_hwmon.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* thermal_hwmon.c - Generic Thermal Management hwmon support.
*
@@ -8,22 +9,6 @@
*
* Copyright (C) 2013 Texas Instruments
* Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@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; 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.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#include <linux/hwmon.h>
#include <linux/thermal.h>
diff --git a/drivers/thermal/thermal_hwmon.h b/drivers/thermal/thermal_hwmon.h
index c798fdb..019f6f8 100644
--- a/drivers/thermal/thermal_hwmon.h
+++ b/drivers/thermal/thermal_hwmon.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* thermal_hwmon.h - Generic Thermal Management hwmon support.
*
@@ -8,22 +9,6 @@
*
* Copyright (C) 2013 Texas Instruments
* Copyright (C) 2013 Eduardo Valentin <eduardo.valentin@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; 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.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifndef __THERMAL_HWMON_H__
#define __THERMAL_HWMON_H__
diff --git a/drivers/thermal/thermal_sysfs.c b/drivers/thermal/thermal_sysfs.c
index 23b5e0a..2241cea 100644
--- a/drivers/thermal/thermal_sysfs.c
+++ b/drivers/thermal/thermal_sysfs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* thermal.c - sysfs interface of thermal devices
*
@@ -7,10 +8,6 @@
* Copyright (C) 2008 Intel Corp
* Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
* Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.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.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -381,7 +378,7 @@ sustainable_power_store(struct device *dev, struct device_attribute *devattr,
\
return count; \
} \
- static DEVICE_ATTR(name, S_IWUSR | S_IRUGO, name##_show, name##_store)
+ static DEVICE_ATTR_RW(name)
create_s32_tzp_attr(k_po);
create_s32_tzp_attr(k_pu);
@@ -668,17 +665,15 @@ void thermal_zone_destroy_device_groups(struct thermal_zone_device *tz)
/* sys I/F for cooling device */
static ssize_t
-thermal_cooling_device_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+cdev_type_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct thermal_cooling_device *cdev = to_cooling_device(dev);
return sprintf(buf, "%s\n", cdev->type);
}
-static ssize_t
-thermal_cooling_device_max_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t max_state_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct thermal_cooling_device *cdev = to_cooling_device(dev);
unsigned long state;
@@ -690,9 +685,8 @@ thermal_cooling_device_max_state_show(struct device *dev,
return sprintf(buf, "%ld\n", state);
}
-static ssize_t
-thermal_cooling_device_cur_state_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static ssize_t cur_state_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct thermal_cooling_device *cdev = to_cooling_device(dev);
unsigned long state;
@@ -705,9 +699,8 @@ thermal_cooling_device_cur_state_show(struct device *dev,
}
static ssize_t
-thermal_cooling_device_cur_state_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+cur_state_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct thermal_cooling_device *cdev = to_cooling_device(dev);
unsigned long state;
@@ -726,13 +719,10 @@ thermal_cooling_device_cur_state_store(struct device *dev,
return count;
}
-static struct device_attribute dev_attr_cdev_type =
-__ATTR(type, 0444, thermal_cooling_device_type_show, NULL);
-static DEVICE_ATTR(max_state, 0444,
- thermal_cooling_device_max_state_show, NULL);
-static DEVICE_ATTR(cur_state, 0644,
- thermal_cooling_device_cur_state_show,
- thermal_cooling_device_cur_state_store);
+static struct device_attribute
+dev_attr_cdev_type = __ATTR(type, 0444, cdev_type_show, NULL);
+static DEVICE_ATTR_RO(max_state);
+static DEVICE_ATTR_RW(cur_state);
static struct attribute *cooling_device_attrs[] = {
&dev_attr_cdev_type.attr,
@@ -791,10 +781,8 @@ unlock:
spin_unlock(&stats->lock);
}
-static ssize_t
-thermal_cooling_device_total_trans_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t total_trans_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct thermal_cooling_device *cdev = to_cooling_device(dev);
struct cooling_dev_stats *stats = cdev->stats;
@@ -808,9 +796,8 @@ thermal_cooling_device_total_trans_show(struct device *dev,
}
static ssize_t
-thermal_cooling_device_time_in_state_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+time_in_state_ms_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
{
struct thermal_cooling_device *cdev = to_cooling_device(dev);
struct cooling_dev_stats *stats = cdev->stats;
@@ -830,9 +817,8 @@ thermal_cooling_device_time_in_state_show(struct device *dev,
}
static ssize_t
-thermal_cooling_device_reset_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+reset_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
{
struct thermal_cooling_device *cdev = to_cooling_device(dev);
struct cooling_dev_stats *stats = cdev->stats;
@@ -853,10 +839,8 @@ thermal_cooling_device_reset_store(struct device *dev,
return count;
}
-static ssize_t
-thermal_cooling_device_trans_table_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+static ssize_t trans_table_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct thermal_cooling_device *cdev = to_cooling_device(dev);
struct cooling_dev_stats *stats = cdev->stats;
@@ -899,13 +883,10 @@ thermal_cooling_device_trans_table_show(struct device *dev,
return len;
}
-static DEVICE_ATTR(total_trans, 0444, thermal_cooling_device_total_trans_show,
- NULL);
-static DEVICE_ATTR(time_in_state_ms, 0444,
- thermal_cooling_device_time_in_state_show, NULL);
-static DEVICE_ATTR(reset, 0200, NULL, thermal_cooling_device_reset_store);
-static DEVICE_ATTR(trans_table, 0444,
- thermal_cooling_device_trans_table_show, NULL);
+static DEVICE_ATTR_RO(total_trans);
+static DEVICE_ATTR_RO(time_in_state_ms);
+static DEVICE_ATTR_WO(reset);
+static DEVICE_ATTR_RO(trans_table);
static struct attribute *cooling_device_stats_attrs[] = {
&dev_attr_total_trans.attr,
@@ -980,8 +961,7 @@ void thermal_cooling_device_destroy_sysfs(struct thermal_cooling_device *cdev)
/* these helper will be used only at the time of bindig */
ssize_t
-thermal_cooling_device_trip_point_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+trip_point_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct thermal_instance *instance;
@@ -995,8 +975,7 @@ thermal_cooling_device_trip_point_show(struct device *dev,
}
ssize_t
-thermal_cooling_device_weight_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+weight_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct thermal_instance *instance;
@@ -1005,10 +984,8 @@ thermal_cooling_device_weight_show(struct device *dev,
return sprintf(buf, "%d\n", instance->weight);
}
-ssize_t
-thermal_cooling_device_weight_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+ssize_t weight_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct thermal_instance *instance;
int ret, weight;
diff --git a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
index cd9a304..6ac0370 100644
--- a/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
+++ b/drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
@@ -310,7 +310,7 @@ omap5430_adc_to_temp[
119800, 120200, 120600, 121000, 121400, 121800, 122400, 122600, 123000,
123400,
/* Index 940 - 945 */
- 123800, 1242000, 124600, 124900, 125000, 125000,
+ 123800, 124200, 124600, 124900, 125000, 125000,
};
/* OMAP54xx ES2.0 data */
diff --git a/drivers/thermal/uniphier_thermal.c b/drivers/thermal/uniphier_thermal.c
index 9570473..55477d7 100644
--- a/drivers/thermal/uniphier_thermal.c
+++ b/drivers/thermal/uniphier_thermal.c
@@ -365,6 +365,10 @@ static const struct of_device_id uniphier_tm_dt_ids[] = {
.compatible = "socionext,uniphier-ld20-thermal",
.data = &uniphier_ld20_tm_data,
},
+ {
+ .compatible = "socionext,uniphier-pxs3-thermal",
+ .data = &uniphier_ld20_tm_data,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, uniphier_tm_dt_ids);
diff --git a/drivers/thermal/x86_pkg_temp_thermal.c b/drivers/thermal/x86_pkg_temp_thermal.c
index 1a6c88b..1ef937d 100644
--- a/drivers/thermal/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/x86_pkg_temp_thermal.c
@@ -516,7 +516,8 @@ static int __init pkg_temp_thermal_init(void)
return -ENODEV;
max_packages = topology_max_packages();
- packages = kzalloc(max_packages * sizeof(struct pkg_device *), GFP_KERNEL);
+ packages = kcalloc(max_packages, sizeof(struct pkg_device *),
+ GFP_KERNEL);
if (!packages)
return -ENOMEM;
diff --git a/drivers/tty/ehv_bytechan.c b/drivers/tty/ehv_bytechan.c
index 47ac568..eea4049 100644
--- a/drivers/tty/ehv_bytechan.c
+++ b/drivers/tty/ehv_bytechan.c
@@ -754,7 +754,7 @@ static int __init ehv_bc_init(void)
* array, then you can use pointer math (e.g. "bc - bcs") to get its
* tty index.
*/
- bcs = kzalloc(count * sizeof(struct ehv_bc_data), GFP_KERNEL);
+ bcs = kcalloc(count, sizeof(struct ehv_bc_data), GFP_KERNEL);
if (!bcs)
return -ENOMEM;
diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c
index 1c1bd0a..37caba7 100644
--- a/drivers/tty/goldfish.c
+++ b/drivers/tty/goldfish.c
@@ -245,8 +245,9 @@ static int goldfish_tty_create_driver(void)
int ret;
struct tty_driver *tty;
- goldfish_ttys = kzalloc(sizeof(*goldfish_ttys) *
- goldfish_tty_line_count, GFP_KERNEL);
+ goldfish_ttys = kcalloc(goldfish_tty_line_count,
+ sizeof(*goldfish_ttys),
+ GFP_KERNEL);
if (goldfish_ttys == NULL) {
ret = -ENOMEM;
goto err_alloc_goldfish_ttys_failed;
diff --git a/drivers/tty/hvc/hvc_iucv.c b/drivers/tty/hvc/hvc_iucv.c
index a746807..2af1e57 100644
--- a/drivers/tty/hvc/hvc_iucv.c
+++ b/drivers/tty/hvc/hvc_iucv.c
@@ -1252,7 +1252,7 @@ static int hvc_iucv_setup_filter(const char *val)
if (size > MAX_VMID_FILTER)
return -ENOSPC;
- array = kzalloc(size * 8, GFP_KERNEL);
+ array = kcalloc(size, 8, GFP_KERNEL);
if (!array)
return -ENOMEM;
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c
index 1db1d97..cb4db1b 100644
--- a/drivers/tty/hvc/hvcs.c
+++ b/drivers/tty/hvc/hvcs.c
@@ -1441,7 +1441,8 @@ static int hvcs_alloc_index_list(int n)
{
int i;
- hvcs_index_list = kmalloc(n * sizeof(hvcs_index_count),GFP_KERNEL);
+ hvcs_index_list = kmalloc_array(n, sizeof(hvcs_index_count),
+ GFP_KERNEL);
if (!hvcs_index_list)
return -ENOMEM;
hvcs_index_count = n;
diff --git a/drivers/tty/isicom.c b/drivers/tty/isicom.c
index bdd3027..8d96e86 100644
--- a/drivers/tty/isicom.c
+++ b/drivers/tty/isicom.c
@@ -1477,7 +1477,7 @@ static int load_firmware(struct pci_dev *pdev,
goto errrelfw;
}
- data = kmalloc(word_count * 2, GFP_KERNEL);
+ data = kmalloc_array(word_count, 2, GFP_KERNEL);
if (data == NULL) {
dev_err(&pdev->dev, "Card%d, firmware upload "
"failed, not enough memory\n", index + 1);
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 55b3eff..8e44287 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -2738,8 +2738,9 @@ static int atmel_serial_probe(struct platform_device *pdev)
if (!atmel_use_pdc_rx(&atmel_port->uart)) {
ret = -ENOMEM;
- data = kmalloc(sizeof(struct atmel_uart_char)
- * ATMEL_SERIAL_RINGSIZE, GFP_KERNEL);
+ data = kmalloc_array(ATMEL_SERIAL_RINGSIZE,
+ sizeof(struct atmel_uart_char),
+ GFP_KERNEL);
if (!data)
goto err_alloc_ring;
atmel_port->rx_ring.buf = data;
diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
index 760d5dd..cb85002 100644
--- a/drivers/tty/serial/pch_uart.c
+++ b/drivers/tty/serial/pch_uart.c
@@ -991,7 +991,7 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv)
priv->tx_dma_use = 1;
- priv->sg_tx_p = kzalloc(sizeof(struct scatterlist)*num, GFP_ATOMIC);
+ priv->sg_tx_p = kcalloc(num, sizeof(struct scatterlist), GFP_ATOMIC);
if (!priv->sg_tx_p) {
dev_err(priv->port.dev, "%s:kzalloc Failed\n", __func__);
return 0;
diff --git a/drivers/tty/serial/rp2.c b/drivers/tty/serial/rp2.c
index 520b43b..5690c09 100644
--- a/drivers/tty/serial/rp2.c
+++ b/drivers/tty/serial/rp2.c
@@ -774,7 +774,7 @@ static int rp2_probe(struct pci_dev *pdev,
rp2_init_card(card);
- ports = devm_kzalloc(&pdev->dev, sizeof(*ports) * card->n_ports,
+ ports = devm_kcalloc(&pdev->dev, card->n_ports, sizeof(*ports),
GFP_KERNEL);
if (!ports)
return -ENOMEM;
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 890b883..9c14a45 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2445,7 +2445,7 @@ int uart_register_driver(struct uart_driver *drv)
* Maybe we should be using a slab cache for this, especially if
* we have a large number of ports to handle.
*/
- drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);
+ drv->state = kcalloc(drv->nr, sizeof(struct uart_state), GFP_KERNEL);
if (!drv->state)
goto out;
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
index b93d022..72131b5 100644
--- a/drivers/tty/serial/sunsab.c
+++ b/drivers/tty/serial/sunsab.c
@@ -1125,8 +1125,9 @@ static int __init sunsab_init(void)
}
if (num_channels) {
- sunsab_ports = kzalloc(sizeof(struct uart_sunsab_port) *
- num_channels, GFP_KERNEL);
+ sunsab_ports = kcalloc(num_channels,
+ sizeof(struct uart_sunsab_port),
+ GFP_KERNEL);
if (!sunsab_ports)
return -ENOMEM;
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 7c838b9..aba5952 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -867,8 +867,13 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
i = -EIO;
tty_ldisc_deref(ld);
- if (i > 0)
- tty_update_time(&inode->i_atime);
+ if (i > 0) {
+ struct timespec ts;
+
+ ts = timespec64_to_timespec(inode->i_atime);
+ tty_update_time(&ts);
+ inode->i_atime = timespec_to_timespec64(ts);
+ }
return i;
}
@@ -969,7 +974,11 @@ static inline ssize_t do_tty_write(
cond_resched();
}
if (written) {
- tty_update_time(&file_inode(file)->i_mtime);
+ struct timespec ts;
+
+ ts = timespec64_to_timespec(file_inode(file)->i_mtime);
+ tty_update_time(&ts);
+ file_inode(file)->i_mtime = timespec_to_timespec64(ts);
ret = written;
}
out:
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index 722a669..7c7ada0 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -231,7 +231,7 @@ static void set_inverse_trans_unicode(struct vc_data *conp,
q = p->inverse_trans_unicode;
if (!q) {
q = p->inverse_trans_unicode =
- kmalloc(MAX_GLYPH * sizeof(u16), GFP_KERNEL);
+ kmalloc_array(MAX_GLYPH, sizeof(u16), GFP_KERNEL);
if (!q)
return;
}
@@ -479,7 +479,8 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
p1 = p->uni_pgdir[n = unicode >> 11];
if (!p1) {
- p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
+ p1 = p->uni_pgdir[n] = kmalloc_array(32, sizeof(u16 *),
+ GFP_KERNEL);
if (!p1) return -ENOMEM;
for (i = 0; i < 32; i++)
p1[i] = NULL;
@@ -487,7 +488,7 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
p2 = p1[n = (unicode >> 6) & 0x1f];
if (!p2) {
- p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
+ p2 = p1[n] = kmalloc_array(64, sizeof(u16), GFP_KERNEL);
if (!p2) return -ENOMEM;
memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
}
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 5d412df..d5b4a2b 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1624,7 +1624,7 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
struct kbdiacr *dia;
int i;
- dia = kmalloc(MAX_DIACR * sizeof(struct kbdiacr),
+ dia = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacr),
GFP_KERNEL);
if (!dia)
return -ENOMEM;
@@ -1657,7 +1657,7 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
struct kbdiacrsuc __user *a = udp;
void *buf;
- buf = kmalloc(MAX_DIACR * sizeof(struct kbdiacruc),
+ buf = kmalloc_array(MAX_DIACR, sizeof(struct kbdiacruc),
GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index 7851383..90ea1cc 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -280,7 +280,8 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t
/* Allocate a new buffer before freeing the old one ... */
multiplier = use_unicode ? 3 : 1; /* chars can take up to 3 bytes */
- bp = kmalloc(((sel_end-sel_start)/2+1)*multiplier, GFP_KERNEL);
+ bp = kmalloc_array((sel_end - sel_start) / 2 + 1, multiplier,
+ GFP_KERNEL);
if (!bp) {
printk(KERN_WARNING "selection: kmalloc() failed\n");
clear_selection();
diff --git a/drivers/uio/uio_pruss.c b/drivers/uio/uio_pruss.c
index 31d5b1d..91aea88 100644
--- a/drivers/uio/uio_pruss.c
+++ b/drivers/uio/uio_pruss.c
@@ -129,7 +129,7 @@ static int pruss_probe(struct platform_device *pdev)
if (!gdev)
return -ENOMEM;
- gdev->info = kzalloc(sizeof(*p) * MAX_PRUSS_EVT, GFP_KERNEL);
+ gdev->info = kcalloc(MAX_PRUSS_EVT, sizeof(*p), GFP_KERNEL);
if (!gdev->info) {
kfree(gdev);
return -ENOMEM;
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 76e16c5..476dcc5 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -897,7 +897,7 @@ static int parse_usbdevfs_streams(struct usb_dev_state *ps,
if (num_streams_ret && (num_streams < 2 || num_streams > 65536))
return -EINVAL;
- eps = kmalloc(num_eps * sizeof(*eps), GFP_KERNEL);
+ eps = kmalloc_array(num_eps, sizeof(*eps), GFP_KERNEL);
if (!eps)
return -ENOMEM;
@@ -1602,8 +1602,9 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
as->mem_usage = u;
if (num_sgs) {
- as->urb->sg = kmalloc(num_sgs * sizeof(struct scatterlist),
- GFP_KERNEL);
+ as->urb->sg = kmalloc_array(num_sgs,
+ sizeof(struct scatterlist),
+ GFP_KERNEL);
if (!as->urb->sg) {
ret = -ENOMEM;
goto error;
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 26c2438..fcae521 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1376,7 +1376,7 @@ static int hub_configure(struct usb_hub *hub,
dev_info(hub_dev, "%d port%s detected\n", maxchild,
(maxchild == 1) ? "" : "s");
- hub->ports = kzalloc(maxchild * sizeof(struct usb_port *), GFP_KERNEL);
+ hub->ports = kcalloc(maxchild, sizeof(struct usb_port *), GFP_KERNEL);
if (!hub->ports) {
ret = -ENOMEM;
goto fail;
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 7b13700..1a15392 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -390,7 +390,7 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev,
}
/* initialize all the urbs we'll use */
- io->urbs = kmalloc(io->entries * sizeof(*io->urbs), mem_flags);
+ io->urbs = kmalloc_array(io->entries, sizeof(*io->urbs), mem_flags);
if (!io->urbs)
goto nomem;
@@ -1824,8 +1824,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
n = nintf = 0;
if (cp) {
nintf = cp->desc.bNumInterfaces;
- new_interfaces = kmalloc(nintf * sizeof(*new_interfaces),
- GFP_NOIO);
+ new_interfaces = kmalloc_array(nintf, sizeof(*new_interfaces),
+ GFP_NOIO);
if (!new_interfaces)
return -ENOMEM;
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 1faefea..edaf0b6 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -5079,13 +5079,14 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg);
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
- hsotg->frame_num_array = kzalloc(sizeof(*hsotg->frame_num_array) *
- FRAME_NUM_ARRAY_SIZE, GFP_KERNEL);
+ hsotg->frame_num_array = kcalloc(FRAME_NUM_ARRAY_SIZE,
+ sizeof(*hsotg->frame_num_array),
+ GFP_KERNEL);
if (!hsotg->frame_num_array)
goto error1;
- hsotg->last_frame_num_array = kzalloc(
- sizeof(*hsotg->last_frame_num_array) *
- FRAME_NUM_ARRAY_SIZE, GFP_KERNEL);
+ hsotg->last_frame_num_array =
+ kcalloc(FRAME_NUM_ARRAY_SIZE,
+ sizeof(*hsotg->last_frame_num_array), GFP_KERNEL);
if (!hsotg->last_frame_num_array)
goto error1;
#endif
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 199d257..dce9d12 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1308,7 +1308,7 @@ ffs_sb_make_inode(struct super_block *sb, void *data,
inode = new_inode(sb);
if (likely(inode)) {
- struct timespec ts = current_time(inode);
+ struct timespec64 ts = current_time(inode);
inode->i_ino = get_next_ino();
inode->i_mode = perms->mode;
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index a4d99bf..17147b8 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -2036,7 +2036,7 @@ static struct usba_ep * atmel_udc_of_init(struct platform_device *pdev,
udc->num_ep = usba_config_fifo_table(udc);
}
- eps = devm_kzalloc(&pdev->dev, sizeof(struct usba_ep) * udc->num_ep,
+ eps = devm_kcalloc(&pdev->dev, udc->num_ep, sizeof(struct usba_ep),
GFP_KERNEL);
if (!eps)
return ERR_PTR(-ENOMEM);
diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c
index 03149b9d..a4d9b5e 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_ep.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c
@@ -138,9 +138,9 @@ static int ep_bd_list_alloc(struct bdc_ep *ep)
__func__, ep, num_tabs);
/* Allocate memory for table array */
- ep->bd_list.bd_table_array = kzalloc(
- num_tabs * sizeof(struct bd_table *),
- GFP_ATOMIC);
+ ep->bd_list.bd_table_array = kcalloc(num_tabs,
+ sizeof(struct bd_table *),
+ GFP_ATOMIC);
if (!ep->bd_list.bd_table_array)
return -ENOMEM;
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index 9a3f7db..be59309 100644
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -2246,7 +2246,7 @@ static int struct_udc_setup(struct fsl_udc *udc,
pdata = dev_get_platdata(&pdev->dev);
udc->phy_mode = pdata->phy_mode;
- udc->eps = kzalloc(sizeof(struct fsl_ep) * udc->max_ep, GFP_KERNEL);
+ udc->eps = kcalloc(udc->max_ep, sizeof(struct fsl_ep), GFP_KERNEL);
if (!udc->eps)
return -1;
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index 977ea1a0..7cf98c7 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -2427,7 +2427,8 @@ static int renesas_usb3_init_ep(struct renesas_usb3 *usb3, struct device *dev,
if (usb3->num_usb3_eps > USB3_MAX_NUM_PIPES)
usb3->num_usb3_eps = USB3_MAX_NUM_PIPES;
- usb3->usb3_ep = devm_kzalloc(dev, sizeof(*usb3_ep) * usb3->num_usb3_eps,
+ usb3->usb3_ep = devm_kcalloc(dev,
+ usb3->num_usb3_eps, sizeof(*usb3_ep),
GFP_KERNEL);
if (!usb3->usb3_ep)
return -ENOMEM;
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index e56db44..1d87295 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -117,8 +117,9 @@ static struct ehci_tt *find_tt(struct usb_device *udev)
if (utt->multi) {
tt_index = utt->hcpriv;
if (!tt_index) { /* Create the index array */
- tt_index = kzalloc(utt->hub->maxchild *
- sizeof(*tt_index), GFP_ATOMIC);
+ tt_index = kcalloc(utt->hub->maxchild,
+ sizeof(*tt_index),
+ GFP_ATOMIC);
if (!tt_index)
return ERR_PTR(-ENOMEM);
utt->hcpriv = tt_index;
diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c
index 3a4e8f6..f3308ce 100644
--- a/drivers/usb/host/fhci-tds.c
+++ b/drivers/usb/host/fhci-tds.c
@@ -189,7 +189,7 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem,
goto err;
}
- buff = kmalloc(1028 * sizeof(*buff), GFP_KERNEL);
+ buff = kmalloc_array(1028, sizeof(*buff), GFP_KERNEL);
if (!buff) {
kfree(pkt);
err_for = "buffer";
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index 3a8bbfe..6e3dad1 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -741,8 +741,8 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd,
if (urb_priv == NULL)
return -ENOMEM;
- urb_priv->isoc_td = kzalloc(
- sizeof(struct td) * urb->number_of_packets, mem_flags);
+ urb_priv->isoc_td = kcalloc(urb->number_of_packets, sizeof(struct td),
+ mem_flags);
if (urb_priv->isoc_td == NULL) {
ret = -ENOMEM;
goto alloc_td_failed;
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index d3ee1f52a..4f267dc 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -492,7 +492,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf)
char *next;
unsigned i;
- seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC);
+ seen = kmalloc_array(DBG_SCHED_LIMIT, sizeof(*seen), GFP_ATOMIC);
if (!seen)
return 0;
seen_count = 0;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 4fe7471..acbd3d7 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2274,8 +2274,8 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
xhci->hw_ports[i].hw_portnum = i;
}
- xhci->rh_bw = kzalloc_node(sizeof(*xhci->rh_bw)*num_ports, flags,
- dev_to_node(dev));
+ xhci->rh_bw = kcalloc_node(num_ports, sizeof(*xhci->rh_bw), flags,
+ dev_to_node(dev));
if (!xhci->rh_bw)
return -ENOMEM;
for (i = 0; i < num_ports; i++) {
diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c
index 236a60f..c2e255f 100644
--- a/drivers/usb/misc/ldusb.c
+++ b/drivers/usb/misc/ldusb.c
@@ -695,7 +695,10 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n");
dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint);
- dev->ring_buffer = kmalloc(ring_buffer_size*(sizeof(size_t)+dev->interrupt_in_endpoint_size), GFP_KERNEL);
+ dev->ring_buffer =
+ kmalloc_array(ring_buffer_size,
+ sizeof(size_t) + dev->interrupt_in_endpoint_size,
+ GFP_KERNEL);
if (!dev->ring_buffer)
goto error;
dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
@@ -706,7 +709,9 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *
goto error;
dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? usb_endpoint_maxp(dev->interrupt_out_endpoint) :
udev->descriptor.bMaxPacketSize0;
- dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL);
+ dev->interrupt_out_buffer =
+ kmalloc_array(write_buffer_size,
+ dev->interrupt_out_endpoint_size, GFP_KERNEL);
if (!dev->interrupt_out_buffer)
goto error;
dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c
index a0d6e0a..c4f017e 100644
--- a/drivers/usb/misc/sisusbvga/sisusb_con.c
+++ b/drivers/usb/misc/sisusbvga/sisusb_con.c
@@ -1243,7 +1243,7 @@ sisusbcon_font_set(struct vc_data *c, struct console_font *font,
}
if (!sisusb->font_backup)
- sisusb->font_backup = vmalloc(charcount * 32);
+ sisusb->font_backup = vmalloc(array_size(charcount, 32));
if (sisusb->font_backup) {
memcpy(sisusb->font_backup, font->data, charcount * 32);
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index 34e866ad..ad2c082 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -1024,7 +1024,8 @@ static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg
return -EINVAL;
size = CHUNK_ALIGN(arg);
- vec = kzalloc(sizeof(struct mon_pgmap) * (size / CHUNK_SIZE), GFP_KERNEL);
+ vec = kcalloc(size / CHUNK_SIZE, sizeof(struct mon_pgmap),
+ GFP_KERNEL);
if (vec == NULL) {
ret = -ENOMEM;
break;
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index 34ee9eb..33d059c 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -1068,7 +1068,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
if (!gpriv)
return -ENOMEM;
- uep = kzalloc(sizeof(struct usbhsg_uep) * pipe_size, GFP_KERNEL);
+ uep = kcalloc(pipe_size, sizeof(struct usbhsg_uep), GFP_KERNEL);
if (!uep) {
ret = -ENOMEM;
goto usbhs_mod_gadget_probe_err_gpriv;
diff --git a/drivers/usb/renesas_usbhs/pipe.c b/drivers/usb/renesas_usbhs/pipe.c
index 9677e0e..c4922b9 100644
--- a/drivers/usb/renesas_usbhs/pipe.c
+++ b/drivers/usb/renesas_usbhs/pipe.c
@@ -803,7 +803,8 @@ int usbhs_pipe_probe(struct usbhs_priv *priv)
return -EINVAL;
}
- info->pipe = kzalloc(sizeof(struct usbhs_pipe) * pipe_size, GFP_KERNEL);
+ info->pipe = kcalloc(pipe_size, sizeof(struct usbhs_pipe),
+ GFP_KERNEL);
if (!info->pipe)
return -ENOMEM;
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c
index 62c91e3..2fb7130 100644
--- a/drivers/usb/serial/iuu_phoenix.c
+++ b/drivers/usb/serial/iuu_phoenix.c
@@ -736,7 +736,7 @@ static int iuu_uart_on(struct usb_serial_port *port)
int status;
u8 *buf;
- buf = kmalloc(sizeof(u8) * 4, GFP_KERNEL);
+ buf = kmalloc(4, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -790,7 +790,7 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base,
unsigned int T1FrekvensHZ = 0;
dev_dbg(&port->dev, "%s - enter baud_base=%d\n", __func__, baud_base);
- dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL);
+ dataout = kmalloc(5, GFP_KERNEL);
if (!dataout)
return -ENOMEM;
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
index 900591d..6b8edf6 100644
--- a/drivers/usb/storage/alauda.c
+++ b/drivers/usb/storage/alauda.c
@@ -1025,7 +1025,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address,
* We also need a temporary block buffer, where we read in the old data,
* overwrite parts with the new data, and manipulate the redundancy data
*/
- blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO);
+ blockbuffer = kmalloc_array(pagesize + 64, blocksize, GFP_NOIO);
if (!blockbuffer) {
kfree(buffer);
return USB_STOR_TRANSPORT_ERROR;
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
index 93cf57a..4d261e4 100644
--- a/drivers/usb/storage/ene_ub6250.c
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -807,8 +807,12 @@ static int ms_lib_alloc_logicalmap(struct us_data *us)
u32 i;
struct ene_ub6250_info *info = (struct ene_ub6250_info *) us->extra;
- info->MS_Lib.Phy2LogMap = kmalloc(info->MS_Lib.NumberOfPhyBlock * sizeof(u16), GFP_KERNEL);
- info->MS_Lib.Log2PhyMap = kmalloc(info->MS_Lib.NumberOfLogBlock * sizeof(u16), GFP_KERNEL);
+ info->MS_Lib.Phy2LogMap = kmalloc_array(info->MS_Lib.NumberOfPhyBlock,
+ sizeof(u16),
+ GFP_KERNEL);
+ info->MS_Lib.Log2PhyMap = kmalloc_array(info->MS_Lib.NumberOfLogBlock,
+ sizeof(u16),
+ GFP_KERNEL);
if ((info->MS_Lib.Phy2LogMap == NULL) || (info->MS_Lib.Log2PhyMap == NULL)) {
ms_lib_free_logicalmap(us);
@@ -1113,8 +1117,12 @@ static int ms_lib_alloc_writebuf(struct us_data *us)
info->MS_Lib.wrtblk = (u16)-1;
- info->MS_Lib.blkpag = kmalloc(info->MS_Lib.PagesPerBlock * info->MS_Lib.BytesPerSector, GFP_KERNEL);
- info->MS_Lib.blkext = kmalloc(info->MS_Lib.PagesPerBlock * sizeof(struct ms_lib_type_extdat), GFP_KERNEL);
+ info->MS_Lib.blkpag = kmalloc_array(info->MS_Lib.PagesPerBlock,
+ info->MS_Lib.BytesPerSector,
+ GFP_KERNEL);
+ info->MS_Lib.blkext = kmalloc_array(info->MS_Lib.PagesPerBlock,
+ sizeof(struct ms_lib_type_extdat),
+ GFP_KERNEL);
if ((info->MS_Lib.blkpag == NULL) || (info->MS_Lib.blkext == NULL)) {
ms_lib_free_writebuf(us);
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 1cf7dbf..bc9da73 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -1231,8 +1231,8 @@ sddr09_read_map(struct us_data *us) {
kfree(info->lba_to_pba);
kfree(info->pba_to_lba);
- info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
- info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
+ info->lba_to_pba = kmalloc_array(numblocks, sizeof(int), GFP_NOIO);
+ info->pba_to_lba = kmalloc_array(numblocks, sizeof(int), GFP_NOIO);
if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) {
printk(KERN_WARNING "sddr09_read_map: out of memory\n");
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index 8c814b2..b8527c5 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -651,7 +651,7 @@ static int sddr55_read_map(struct us_data *us) {
numblocks = info->capacity >> (info->blockshift + info->pageshift);
- buffer = kmalloc( numblocks * 2, GFP_NOIO );
+ buffer = kmalloc_array(numblocks, 2, GFP_NOIO );
if (!buffer)
return -1;
@@ -684,8 +684,8 @@ static int sddr55_read_map(struct us_data *us) {
kfree(info->lba_to_pba);
kfree(info->pba_to_lba);
- info->lba_to_pba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
- info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO);
+ info->lba_to_pba = kmalloc_array(numblocks, sizeof(int), GFP_NOIO);
+ info->pba_to_lba = kmalloc_array(numblocks, sizeof(int), GFP_NOIO);
if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) {
kfree(info->lba_to_pba);
diff --git a/drivers/usb/wusbcore/wa-rpipe.c b/drivers/usb/wusbcore/wa-rpipe.c
index d0f1a66..38884aa 100644
--- a/drivers/usb/wusbcore/wa-rpipe.c
+++ b/drivers/usb/wusbcore/wa-rpipe.c
@@ -470,7 +470,8 @@ error:
int wa_rpipes_create(struct wahc *wa)
{
wa->rpipes = le16_to_cpu(wa->wa_descr->wNumRPipes);
- wa->rpipe_bm = kzalloc(BITS_TO_LONGS(wa->rpipes)*sizeof(unsigned long),
+ wa->rpipe_bm = kcalloc(BITS_TO_LONGS(wa->rpipes),
+ sizeof(unsigned long),
GFP_KERNEL);
if (wa->rpipe_bm == NULL)
return -ENOMEM;
diff --git a/drivers/uwb/est.c b/drivers/uwb/est.c
index f3e2325..ad30ddf 100644
--- a/drivers/uwb/est.c
+++ b/drivers/uwb/est.c
@@ -217,7 +217,7 @@ static
int uwb_est_grow(void)
{
size_t actual_size = uwb_est_size * sizeof(uwb_est[0]);
- void *new = kmalloc(2 * actual_size, GFP_ATOMIC);
+ void *new = kmalloc_array(2, actual_size, GFP_ATOMIC);
if (new == NULL)
return -ENOMEM;
memcpy(new, uwb_est, actual_size);
diff --git a/drivers/uwb/i1480/dfu/usb.c b/drivers/uwb/i1480/dfu/usb.c
index a50cf45..c0430a4 100644
--- a/drivers/uwb/i1480/dfu/usb.c
+++ b/drivers/uwb/i1480/dfu/usb.c
@@ -376,7 +376,7 @@ int i1480_usb_probe(struct usb_interface *iface, const struct usb_device_id *id)
i1480 = &i1480_usb->i1480;
i1480->buf_size = 512;
- i1480->cmd_buf = kmalloc(2 * i1480->buf_size, GFP_KERNEL);
+ i1480->cmd_buf = kmalloc_array(2, i1480->buf_size, GFP_KERNEL);
if (i1480->cmd_buf == NULL) {
dev_err(dev, "Cannot allocate transfer buffers\n");
result = -ENOMEM;
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 1269910..0212f0e 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -66,34 +66,6 @@ uuid_le mdev_uuid(struct mdev_device *mdev)
}
EXPORT_SYMBOL(mdev_uuid);
-static int _find_mdev_device(struct device *dev, void *data)
-{
- struct mdev_device *mdev;
-
- if (!dev_is_mdev(dev))
- return 0;
-
- mdev = to_mdev_device(dev);
-
- if (uuid_le_cmp(mdev->uuid, *(uuid_le *)data) == 0)
- return 1;
-
- return 0;
-}
-
-static bool mdev_device_exist(struct mdev_parent *parent, uuid_le uuid)
-{
- struct device *dev;
-
- dev = device_find_child(parent->dev, &uuid, _find_mdev_device);
- if (dev) {
- put_device(dev);
- return true;
- }
-
- return false;
-}
-
/* Should be called holding parent_list_lock */
static struct mdev_parent *__find_parent_device(struct device *dev)
{
@@ -221,7 +193,6 @@ int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops)
}
kref_init(&parent->ref);
- mutex_init(&parent->lock);
parent->dev = dev;
parent->ops = ops;
@@ -297,6 +268,10 @@ static void mdev_device_release(struct device *dev)
{
struct mdev_device *mdev = to_mdev_device(dev);
+ mutex_lock(&mdev_list_lock);
+ list_del(&mdev->next);
+ mutex_unlock(&mdev_list_lock);
+
dev_dbg(&mdev->dev, "MDEV: destroying\n");
kfree(mdev);
}
@@ -304,7 +279,7 @@ static void mdev_device_release(struct device *dev)
int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
{
int ret;
- struct mdev_device *mdev;
+ struct mdev_device *mdev, *tmp;
struct mdev_parent *parent;
struct mdev_type *type = to_mdev_type(kobj);
@@ -312,21 +287,28 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
if (!parent)
return -EINVAL;
- mutex_lock(&parent->lock);
+ mutex_lock(&mdev_list_lock);
/* Check for duplicate */
- if (mdev_device_exist(parent, uuid)) {
- ret = -EEXIST;
- goto create_err;
+ list_for_each_entry(tmp, &mdev_list, next) {
+ if (!uuid_le_cmp(tmp->uuid, uuid)) {
+ mutex_unlock(&mdev_list_lock);
+ ret = -EEXIST;
+ goto mdev_fail;
+ }
}
mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
if (!mdev) {
+ mutex_unlock(&mdev_list_lock);
ret = -ENOMEM;
- goto create_err;
+ goto mdev_fail;
}
memcpy(&mdev->uuid, &uuid, sizeof(uuid_le));
+ list_add(&mdev->next, &mdev_list);
+ mutex_unlock(&mdev_list_lock);
+
mdev->parent = parent;
kref_init(&mdev->ref);
@@ -338,35 +320,28 @@ int mdev_device_create(struct kobject *kobj, struct device *dev, uuid_le uuid)
ret = device_register(&mdev->dev);
if (ret) {
put_device(&mdev->dev);
- goto create_err;
+ goto mdev_fail;
}
ret = mdev_device_create_ops(kobj, mdev);
if (ret)
- goto create_failed;
+ goto create_fail;
ret = mdev_create_sysfs_files(&mdev->dev, type);
if (ret) {
mdev_device_remove_ops(mdev, true);
- goto create_failed;
+ goto create_fail;
}
mdev->type_kobj = kobj;
+ mdev->active = true;
dev_dbg(&mdev->dev, "MDEV: created\n");
- mutex_unlock(&parent->lock);
-
- mutex_lock(&mdev_list_lock);
- list_add(&mdev->next, &mdev_list);
- mutex_unlock(&mdev_list_lock);
-
- return ret;
+ return 0;
-create_failed:
+create_fail:
device_unregister(&mdev->dev);
-
-create_err:
- mutex_unlock(&parent->lock);
+mdev_fail:
mdev_put_parent(parent);
return ret;
}
@@ -377,44 +352,39 @@ int mdev_device_remove(struct device *dev, bool force_remove)
struct mdev_parent *parent;
struct mdev_type *type;
int ret;
- bool found = false;
mdev = to_mdev_device(dev);
mutex_lock(&mdev_list_lock);
list_for_each_entry(tmp, &mdev_list, next) {
- if (tmp == mdev) {
- found = true;
+ if (tmp == mdev)
break;
- }
}
- if (found)
- list_del(&mdev->next);
+ if (tmp != mdev) {
+ mutex_unlock(&mdev_list_lock);
+ return -ENODEV;
+ }
- mutex_unlock(&mdev_list_lock);
+ if (!mdev->active) {
+ mutex_unlock(&mdev_list_lock);
+ return -EAGAIN;
+ }
- if (!found)
- return -ENODEV;
+ mdev->active = false;
+ mutex_unlock(&mdev_list_lock);
type = to_mdev_type(mdev->type_kobj);
parent = mdev->parent;
- mutex_lock(&parent->lock);
ret = mdev_device_remove_ops(mdev, force_remove);
if (ret) {
- mutex_unlock(&parent->lock);
-
- mutex_lock(&mdev_list_lock);
- list_add(&mdev->next, &mdev_list);
- mutex_unlock(&mdev_list_lock);
-
+ mdev->active = true;
return ret;
}
mdev_remove_sysfs_files(dev, type);
device_unregister(dev);
- mutex_unlock(&parent->lock);
mdev_put_parent(parent);
return 0;
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index a9cefd7..b5819b7 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -20,7 +20,6 @@ struct mdev_parent {
struct device *dev;
const struct mdev_parent_ops *ops;
struct kref ref;
- struct mutex lock;
struct list_head next;
struct kset *mdev_types_kset;
struct list_head type_list;
@@ -34,6 +33,7 @@ struct mdev_device {
struct kref ref;
struct list_head next;
struct kobject *type_kobj;
+ bool active;
};
#define to_mdev_device(dev) container_of(dev, struct mdev_device, dev)
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index 802df21..249472f 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -257,24 +257,24 @@ int mdev_create_sysfs_files(struct device *dev, struct mdev_type *type)
{
int ret;
- ret = sysfs_create_files(&dev->kobj, mdev_device_attrs);
- if (ret)
- return ret;
-
ret = sysfs_create_link(type->devices_kobj, &dev->kobj, dev_name(dev));
if (ret)
- goto device_link_failed;
+ return ret;
ret = sysfs_create_link(&dev->kobj, &type->kobj, "mdev_type");
if (ret)
goto type_link_failed;
+ ret = sysfs_create_files(&dev->kobj, mdev_device_attrs);
+ if (ret)
+ goto create_files_failed;
+
return ret;
+create_files_failed:
+ sysfs_remove_link(&dev->kobj, "mdev_type");
type_link_failed:
sysfs_remove_link(type->devices_kobj, dev_name(dev));
-device_link_failed:
- sysfs_remove_files(&dev->kobj, mdev_device_attrs);
return ret;
}
diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c
index 4c27f4b..c0cd824 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -17,6 +17,7 @@
#include <linux/iommu.h>
#include <linux/module.h>
#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/uaccess.h>
@@ -239,6 +240,7 @@ static void vfio_platform_release(void *device_data)
ret, extra_dbg ? extra_dbg : "");
WARN_ON(1);
}
+ pm_runtime_put(vdev->device);
vfio_platform_regions_cleanup(vdev);
vfio_platform_irq_cleanup(vdev);
}
@@ -269,6 +271,10 @@ static int vfio_platform_open(void *device_data)
if (ret)
goto err_irq;
+ ret = pm_runtime_get_sync(vdev->device);
+ if (ret < 0)
+ goto err_pm;
+
ret = vfio_platform_call_reset(vdev, &extra_dbg);
if (ret && vdev->reset_required) {
dev_warn(vdev->device, "reset driver is required and reset call failed in open (%d) %s\n",
@@ -283,6 +289,8 @@ static int vfio_platform_open(void *device_data)
return 0;
err_rst:
+ pm_runtime_put(vdev->device);
+err_pm:
vfio_platform_irq_cleanup(vdev);
err_irq:
vfio_platform_regions_cleanup(vdev);
@@ -630,8 +638,7 @@ static int vfio_platform_of_probe(struct vfio_platform_device *vdev,
ret = device_property_read_string(dev, "compatible",
&vdev->compat);
if (ret)
- pr_err("VFIO: cannot retrieve compat for %s\n",
- vdev->name);
+ pr_err("VFIO: Cannot retrieve compat for %s\n", vdev->name);
return ret;
}
@@ -673,7 +680,7 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
ret = vfio_platform_get_reset(vdev);
if (ret && vdev->reset_required) {
- pr_err("vfio: no reset function found for device %s\n",
+ pr_err("VFIO: No reset function found for device %s\n",
vdev->name);
return ret;
}
@@ -681,18 +688,24 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
group = vfio_iommu_group_get(dev);
if (!group) {
pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
- return -EINVAL;
+ ret = -EINVAL;
+ goto put_reset;
}
ret = vfio_add_group_dev(dev, &vfio_platform_ops, vdev);
- if (ret) {
- vfio_iommu_group_put(group, dev);
- return ret;
- }
+ if (ret)
+ goto put_iommu;
mutex_init(&vdev->igate);
+ pm_runtime_enable(vdev->device);
return 0;
+
+put_iommu:
+ vfio_iommu_group_put(group, dev);
+put_reset:
+ vfio_platform_put_reset(vdev);
+ return ret;
}
EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
@@ -703,6 +716,7 @@ struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
vdev = vfio_del_group_dev(dev);
if (vdev) {
+ pm_runtime_disable(vdev->device);
vfio_platform_put_reset(vdev);
vfio_iommu_group_put(dev->iommu_group, dev);
}
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 721f97f..6483387 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -630,8 +630,6 @@ static const char * const vfio_driver_whitelist[] = { "pci-stub" };
static bool vfio_dev_whitelisted(struct device *dev, struct device_driver *drv)
{
- int i;
-
if (dev_is_pci(dev)) {
struct pci_dev *pdev = to_pci_dev(dev);
@@ -639,12 +637,9 @@ static bool vfio_dev_whitelisted(struct device *dev, struct device_driver *drv)
return true;
}
- for (i = 0; i < ARRAY_SIZE(vfio_driver_whitelist); i++) {
- if (!strcmp(drv->name, vfio_driver_whitelist[i]))
- return true;
- }
-
- return false;
+ return match_string(vfio_driver_whitelist,
+ ARRAY_SIZE(vfio_driver_whitelist),
+ drv->name) >= 0;
}
/*
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 3c082451..2c75b33 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -83,6 +83,7 @@ struct vfio_dma {
size_t size; /* Map size (bytes) */
int prot; /* IOMMU_READ/WRITE */
bool iommu_mapped;
+ bool lock_cap; /* capable(CAP_IPC_LOCK) */
struct task_struct *task;
struct rb_root pfn_list; /* Ex-user pinned pfn list */
};
@@ -253,29 +254,25 @@ static int vfio_iova_put_vfio_pfn(struct vfio_dma *dma, struct vfio_pfn *vpfn)
return ret;
}
-static int vfio_lock_acct(struct task_struct *task, long npage, bool *lock_cap)
+static int vfio_lock_acct(struct vfio_dma *dma, long npage, bool async)
{
struct mm_struct *mm;
- bool is_current;
int ret;
if (!npage)
return 0;
- is_current = (task->mm == current->mm);
-
- mm = is_current ? task->mm : get_task_mm(task);
+ mm = async ? get_task_mm(dma->task) : dma->task->mm;
if (!mm)
return -ESRCH; /* process exited */
ret = down_write_killable(&mm->mmap_sem);
if (!ret) {
if (npage > 0) {
- if (lock_cap ? !*lock_cap :
- !has_capability(task, CAP_IPC_LOCK)) {
+ if (!dma->lock_cap) {
unsigned long limit;
- limit = task_rlimit(task,
+ limit = task_rlimit(dma->task,
RLIMIT_MEMLOCK) >> PAGE_SHIFT;
if (mm->locked_vm + npage > limit)
@@ -289,7 +286,7 @@ static int vfio_lock_acct(struct task_struct *task, long npage, bool *lock_cap)
up_write(&mm->mmap_sem);
}
- if (!is_current)
+ if (async)
mmput(mm);
return ret;
@@ -400,7 +397,7 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
*/
static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
long npage, unsigned long *pfn_base,
- bool lock_cap, unsigned long limit)
+ unsigned long limit)
{
unsigned long pfn = 0;
long ret, pinned = 0, lock_acct = 0;
@@ -423,7 +420,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
* pages are already counted against the user.
*/
if (!rsvd && !vfio_find_vpfn(dma, iova)) {
- if (!lock_cap && current->mm->locked_vm + 1 > limit) {
+ if (!dma->lock_cap && current->mm->locked_vm + 1 > limit) {
put_pfn(*pfn_base, dma->prot);
pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n", __func__,
limit << PAGE_SHIFT);
@@ -449,7 +446,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
}
if (!rsvd && !vfio_find_vpfn(dma, iova)) {
- if (!lock_cap &&
+ if (!dma->lock_cap &&
current->mm->locked_vm + lock_acct + 1 > limit) {
put_pfn(pfn, dma->prot);
pr_warn("%s: RLIMIT_MEMLOCK (%ld) exceeded\n",
@@ -462,7 +459,7 @@ static long vfio_pin_pages_remote(struct vfio_dma *dma, unsigned long vaddr,
}
out:
- ret = vfio_lock_acct(current, lock_acct, &lock_cap);
+ ret = vfio_lock_acct(dma, lock_acct, false);
unpin_out:
if (ret) {
@@ -493,7 +490,7 @@ static long vfio_unpin_pages_remote(struct vfio_dma *dma, dma_addr_t iova,
}
if (do_accounting)
- vfio_lock_acct(dma->task, locked - unlocked, NULL);
+ vfio_lock_acct(dma, locked - unlocked, true);
return unlocked;
}
@@ -510,7 +507,7 @@ static int vfio_pin_page_external(struct vfio_dma *dma, unsigned long vaddr,
ret = vaddr_get_pfn(mm, vaddr, dma->prot, pfn_base);
if (!ret && do_accounting && !is_invalid_reserved_pfn(*pfn_base)) {
- ret = vfio_lock_acct(dma->task, 1, NULL);
+ ret = vfio_lock_acct(dma, 1, true);
if (ret) {
put_pfn(*pfn_base, dma->prot);
if (ret == -ENOMEM)
@@ -537,7 +534,7 @@ static int vfio_unpin_page_external(struct vfio_dma *dma, dma_addr_t iova,
unlocked = vfio_iova_put_vfio_pfn(dma, vpfn);
if (do_accounting)
- vfio_lock_acct(dma->task, -unlocked, NULL);
+ vfio_lock_acct(dma, -unlocked, true);
return unlocked;
}
@@ -829,7 +826,7 @@ static long vfio_unmap_unpin(struct vfio_iommu *iommu, struct vfio_dma *dma,
unlocked += vfio_sync_unpin(dma, domain, &unmapped_region_list);
if (do_accounting) {
- vfio_lock_acct(dma->task, -unlocked, NULL);
+ vfio_lock_acct(dma, -unlocked, true);
return 0;
}
return unlocked;
@@ -1044,14 +1041,12 @@ static int vfio_pin_map_dma(struct vfio_iommu *iommu, struct vfio_dma *dma,
size_t size = map_size;
long npage;
unsigned long pfn, limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
- bool lock_cap = capable(CAP_IPC_LOCK);
int ret = 0;
while (size) {
/* Pin a contiguous chunk of memory */
npage = vfio_pin_pages_remote(dma, vaddr + dma->size,
- size >> PAGE_SHIFT, &pfn,
- lock_cap, limit);
+ size >> PAGE_SHIFT, &pfn, limit);
if (npage <= 0) {
WARN_ON(!npage);
ret = (int)npage;
@@ -1126,8 +1121,36 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
dma->iova = iova;
dma->vaddr = vaddr;
dma->prot = prot;
- get_task_struct(current);
- dma->task = current;
+
+ /*
+ * We need to be able to both add to a task's locked memory and test
+ * against the locked memory limit and we need to be able to do both
+ * outside of this call path as pinning can be asynchronous via the
+ * external interfaces for mdev devices. RLIMIT_MEMLOCK requires a
+ * task_struct and VM locked pages requires an mm_struct, however
+ * holding an indefinite mm reference is not recommended, therefore we
+ * only hold a reference to a task. We could hold a reference to
+ * current, however QEMU uses this call path through vCPU threads,
+ * which can be killed resulting in a NULL mm and failure in the unmap
+ * path when called via a different thread. Avoid this problem by
+ * using the group_leader as threads within the same group require
+ * both CLONE_THREAD and CLONE_VM and will therefore use the same
+ * mm_struct.
+ *
+ * Previously we also used the task for testing CAP_IPC_LOCK at the
+ * time of pinning and accounting, however has_capability() makes use
+ * of real_cred, a copy-on-write field, so we can't guarantee that it
+ * matches group_leader, or in fact that it might not change by the
+ * time it's evaluated. If a process were to call MAP_DMA with
+ * CAP_IPC_LOCK but later drop it, it doesn't make sense that they
+ * possibly see different results for an iommu_mapped vfio_dma vs
+ * externally mapped. Therefore track CAP_IPC_LOCK in vfio_dma at the
+ * time of calling MAP_DMA.
+ */
+ get_task_struct(current->group_leader);
+ dma->task = current->group_leader;
+ dma->lock_cap = capable(CAP_IPC_LOCK);
+
dma->pfn_list = RB_ROOT;
/* Insert zero-sized and grow as we map chunks of it */
@@ -1162,7 +1185,6 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
struct vfio_domain *d;
struct rb_node *n;
unsigned long limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
- bool lock_cap = capable(CAP_IPC_LOCK);
int ret;
/* Arbitrarily pick the first domain in the list for lookups */
@@ -1209,8 +1231,7 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
npage = vfio_pin_pages_remote(dma, vaddr,
n >> PAGE_SHIFT,
- &pfn, lock_cap,
- limit);
+ &pfn, limit);
if (npage <= 0) {
WARN_ON(!npage);
ret = (int)npage;
@@ -1487,7 +1508,7 @@ static void vfio_iommu_unmap_unpin_reaccount(struct vfio_iommu *iommu)
if (!is_invalid_reserved_pfn(vpfn->pfn))
locked++;
}
- vfio_lock_acct(dma->task, locked - unlocked, NULL);
+ vfio_lock_acct(dma, locked - unlocked, true);
}
}
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index e7cf7d2..686dc67 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -274,8 +274,10 @@ static int vhost_net_set_ubuf_info(struct vhost_net *n)
zcopy = vhost_net_zcopy_mask & (0x1 << i);
if (!zcopy)
continue;
- n->vqs[i].ubuf_info = kmalloc(sizeof(*n->vqs[i].ubuf_info) *
- UIO_MAXIOV, GFP_KERNEL);
+ n->vqs[i].ubuf_info =
+ kmalloc_array(UIO_MAXIOV,
+ sizeof(*n->vqs[i].ubuf_info),
+ GFP_KERNEL);
if (!n->vqs[i].ubuf_info)
goto err;
}
@@ -943,7 +945,7 @@ static int vhost_net_open(struct inode *inode, struct file *f)
n = kvmalloc(sizeof *n, GFP_KERNEL | __GFP_RETRY_MAYFAIL);
if (!n)
return -ENOMEM;
- vqs = kmalloc(VHOST_NET_VQ_MAX * sizeof(*vqs), GFP_KERNEL);
+ vqs = kmalloc_array(VHOST_NET_VQ_MAX, sizeof(*vqs), GFP_KERNEL);
if (!vqs) {
kvfree(n);
return -ENOMEM;
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 7ad5709..17fcd3b 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1378,7 +1378,7 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
goto err_vs;
}
- vqs = kmalloc(VHOST_SCSI_MAX_VQ * sizeof(*vqs), GFP_KERNEL);
+ vqs = kmalloc_array(VHOST_SCSI_MAX_VQ, sizeof(*vqs), GFP_KERNEL);
if (!vqs)
goto err_vqs;
@@ -1685,22 +1685,25 @@ static int vhost_scsi_nexus_cb(struct se_portal_group *se_tpg,
for (i = 0; i < VHOST_SCSI_DEFAULT_TAGS; i++) {
tv_cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[i];
- tv_cmd->tvc_sgl = kzalloc(sizeof(struct scatterlist) *
- VHOST_SCSI_PREALLOC_SGLS, GFP_KERNEL);
+ tv_cmd->tvc_sgl = kcalloc(VHOST_SCSI_PREALLOC_SGLS,
+ sizeof(struct scatterlist),
+ GFP_KERNEL);
if (!tv_cmd->tvc_sgl) {
pr_err("Unable to allocate tv_cmd->tvc_sgl\n");
goto out;
}
- tv_cmd->tvc_upages = kzalloc(sizeof(struct page *) *
- VHOST_SCSI_PREALLOC_UPAGES, GFP_KERNEL);
+ tv_cmd->tvc_upages = kcalloc(VHOST_SCSI_PREALLOC_UPAGES,
+ sizeof(struct page *),
+ GFP_KERNEL);
if (!tv_cmd->tvc_upages) {
pr_err("Unable to allocate tv_cmd->tvc_upages\n");
goto out;
}
- tv_cmd->tvc_prot_sgl = kzalloc(sizeof(struct scatterlist) *
- VHOST_SCSI_PREALLOC_PROT_SGLS, GFP_KERNEL);
+ tv_cmd->tvc_prot_sgl = kcalloc(VHOST_SCSI_PREALLOC_PROT_SGLS,
+ sizeof(struct scatterlist),
+ GFP_KERNEL);
if (!tv_cmd->tvc_prot_sgl) {
pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n");
goto out;
diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c
index 906b8f0..4058985 100644
--- a/drivers/vhost/test.c
+++ b/drivers/vhost/test.c
@@ -107,7 +107,7 @@ static int vhost_test_open(struct inode *inode, struct file *f)
if (!n)
return -ENOMEM;
- vqs = kmalloc(VHOST_TEST_VQ_MAX * sizeof(*vqs), GFP_KERNEL);
+ vqs = kmalloc_array(VHOST_TEST_VQ_MAX, sizeof(*vqs), GFP_KERNEL);
if (!vqs) {
kfree(n);
return -ENOMEM;
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 895eaa2..a502f1a 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -385,10 +385,13 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
for (i = 0; i < dev->nvqs; ++i) {
vq = dev->vqs[i];
- vq->indirect = kmalloc(sizeof *vq->indirect * UIO_MAXIOV,
- GFP_KERNEL);
- vq->log = kmalloc(sizeof *vq->log * UIO_MAXIOV, GFP_KERNEL);
- vq->heads = kmalloc(sizeof *vq->heads * UIO_MAXIOV, GFP_KERNEL);
+ vq->indirect = kmalloc_array(UIO_MAXIOV,
+ sizeof(*vq->indirect),
+ GFP_KERNEL);
+ vq->log = kmalloc_array(UIO_MAXIOV, sizeof(*vq->log),
+ GFP_KERNEL);
+ vq->heads = kmalloc_array(UIO_MAXIOV, sizeof(*vq->heads),
+ GFP_KERNEL);
if (!vq->indirect || !vq->log || !vq->heads)
goto err_nomem;
}
@@ -1286,7 +1289,8 @@ 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 = kvzalloc(size + mem.nregions * sizeof(*m->regions), GFP_KERNEL);
+ newmem = kvzalloc(struct_size(newmem, regions, mem.nregions),
+ GFP_KERNEL);
if (!newmem)
return -ENOMEM;
@@ -2345,6 +2349,9 @@ struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type)
struct vhost_msg_node *node = kmalloc(sizeof *node, GFP_KERNEL);
if (!node)
return NULL;
+
+ /* Make sure all padding within the structure is initialized. */
+ memset(&node->msg, 0, sizeof node->msg);
node->vq = vq;
node->msg.type = type;
return node;
diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c
index bb8971f..a94d700 100644
--- a/drivers/vhost/vringh.c
+++ b/drivers/vhost/vringh.c
@@ -191,7 +191,7 @@ static int resize_iovec(struct vringh_kiov *iov, gfp_t gfp)
if (flag)
new = krealloc(iov->iov, new_num * sizeof(struct iovec), gfp);
else {
- new = kmalloc(new_num * sizeof(struct iovec), gfp);
+ new = kmalloc_array(new_num, sizeof(struct iovec), gfp);
if (new) {
memcpy(new, iov->iov,
iov->max_num * sizeof(struct iovec));
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
index 4e1d2ad..2919e23 100644
--- a/drivers/video/backlight/Kconfig
+++ b/drivers/video/backlight/Kconfig
@@ -150,6 +150,13 @@ config LCD_HX8357
If you have a HX-8357 LCD panel, say Y to enable its LCD control
driver.
+ config LCD_OTM3225A
+ tristate "ORISE Technology OTM3225A support"
+ depends on SPI
+ help
+ If you have a panel based on the OTM3225A controller
+ chip then say y to include a driver for it.
+
endif # LCD_CLASS_DEVICE
#
@@ -467,6 +474,12 @@ config BACKLIGHT_ARCXCNN
If you have an ARCxCnnnn family backlight say Y to enable
the backlight driver.
+config BACKLIGHT_RAVE_SP
+ tristate "RAVE SP Backlight driver"
+ depends on RAVE_SP_CORE
+ help
+ Support for backlight control on RAVE SP device.
+
endif # BACKLIGHT_CLASS_DEVICE
endif # BACKLIGHT_LCD_SUPPORT
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
index 5e28f01..0dcc2c7 100644
--- a/drivers/video/backlight/Makefile
+++ b/drivers/video/backlight/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_LCD_LD9040) += ld9040.o
obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o
obj-$(CONFIG_LCD_LMS501KF03) += lms501kf03.o
obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
+obj-$(CONFIG_LCD_OTM3225A) += otm3225a.o
obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o
obj-$(CONFIG_LCD_TDO24M) += tdo24m.o
@@ -57,3 +58,4 @@ obj-$(CONFIG_BACKLIGHT_TOSA) += tosa_bl.o
obj-$(CONFIG_BACKLIGHT_TPS65217) += tps65217_bl.o
obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o
obj-$(CONFIG_BACKLIGHT_ARCXCNN) += arcxcnn_bl.o
+obj-$(CONFIG_BACKLIGHT_RAVE_SP) += rave-sp-backlight.o
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c
index e7315bf..16119bd 100644
--- a/drivers/video/backlight/adp8860_bl.c
+++ b/drivers/video/backlight/adp8860_bl.c
@@ -223,7 +223,7 @@ static int adp8860_led_probe(struct i2c_client *client)
struct led_info *cur_led;
int ret, i;
- led = devm_kzalloc(&client->dev, sizeof(*led) * pdata->num_leds,
+ led = devm_kcalloc(&client->dev, pdata->num_leds, sizeof(*led),
GFP_KERNEL);
if (led == NULL)
return -ENOMEM;
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
index 058d1de..4fec9aa 100644
--- a/drivers/video/backlight/adp8870_bl.c
+++ b/drivers/video/backlight/adp8870_bl.c
@@ -246,7 +246,7 @@ static int adp8870_led_probe(struct i2c_client *client)
struct led_info *cur_led;
int ret, i;
- led = devm_kzalloc(&client->dev, pdata->num_leds * sizeof(*led),
+ led = devm_kcalloc(&client->dev, pdata->num_leds, sizeof(*led),
GFP_KERNEL);
if (led == NULL)
return -ENOMEM;
diff --git a/drivers/video/backlight/as3711_bl.c b/drivers/video/backlight/as3711_bl.c
index 734a915..ca544aa 100644
--- a/drivers/video/backlight/as3711_bl.c
+++ b/drivers/video/backlight/as3711_bl.c
@@ -28,8 +28,6 @@ enum as3711_bl_type {
struct as3711_bl_data {
bool powered;
- const char *fb_name;
- struct device *fb_dev;
enum as3711_bl_type type;
int brightness;
struct backlight_device *bl;
@@ -262,10 +260,10 @@ static int as3711_bl_register(struct platform_device *pdev,
static int as3711_backlight_parse_dt(struct device *dev)
{
struct as3711_bl_pdata *pdata = dev_get_platdata(dev);
- struct device_node *bl =
- of_find_node_by_name(dev->parent->of_node, "backlight"), *fb;
+ struct device_node *bl, *fb;
int ret;
+ bl = of_get_child_by_name(dev->parent->of_node, "backlight");
if (!bl) {
dev_dbg(dev, "backlight node not found\n");
return -ENODEV;
@@ -273,26 +271,30 @@ static int as3711_backlight_parse_dt(struct device *dev)
fb = of_parse_phandle(bl, "su1-dev", 0);
if (fb) {
- pdata->su1_fb = fb->full_name;
+ of_node_put(fb);
+
+ pdata->su1_fb = true;
ret = of_property_read_u32(bl, "su1-max-uA", &pdata->su1_max_uA);
if (pdata->su1_max_uA <= 0)
ret = -EINVAL;
if (ret < 0)
- return ret;
+ goto err_put_bl;
}
fb = of_parse_phandle(bl, "su2-dev", 0);
if (fb) {
int count = 0;
- pdata->su2_fb = fb->full_name;
+ of_node_put(fb);
+
+ pdata->su2_fb = true;
ret = of_property_read_u32(bl, "su2-max-uA", &pdata->su2_max_uA);
if (pdata->su2_max_uA <= 0)
ret = -EINVAL;
if (ret < 0)
- return ret;
+ goto err_put_bl;
if (of_find_property(bl, "su2-feedback-voltage", NULL)) {
pdata->su2_feedback = AS3711_SU2_VOLTAGE;
@@ -314,8 +316,10 @@ static int as3711_backlight_parse_dt(struct device *dev)
pdata->su2_feedback = AS3711_SU2_CURR_AUTO;
count++;
}
- if (count != 1)
- return -EINVAL;
+ if (count != 1) {
+ ret = -EINVAL;
+ goto err_put_bl;
+ }
count = 0;
if (of_find_property(bl, "su2-fbprot-lx-sd4", NULL)) {
@@ -334,8 +338,10 @@ static int as3711_backlight_parse_dt(struct device *dev)
pdata->su2_fbprot = AS3711_SU2_GPIO4;
count++;
}
- if (count != 1)
- return -EINVAL;
+ if (count != 1) {
+ ret = -EINVAL;
+ goto err_put_bl;
+ }
count = 0;
if (of_find_property(bl, "su2-auto-curr1", NULL)) {
@@ -355,11 +361,20 @@ static int as3711_backlight_parse_dt(struct device *dev)
* At least one su2-auto-curr* must be specified iff
* AS3711_SU2_CURR_AUTO is used
*/
- if (!count ^ (pdata->su2_feedback != AS3711_SU2_CURR_AUTO))
- return -EINVAL;
+ if (!count ^ (pdata->su2_feedback != AS3711_SU2_CURR_AUTO)) {
+ ret = -EINVAL;
+ goto err_put_bl;
+ }
}
+ of_node_put(bl);
+
return 0;
+
+err_put_bl:
+ of_node_put(bl);
+
+ return ret;
}
static int as3711_backlight_probe(struct platform_device *pdev)
@@ -412,7 +427,6 @@ static int as3711_backlight_probe(struct platform_device *pdev)
if (pdata->su1_fb) {
su = &supply->su1;
- su->fb_name = pdata->su1_fb;
su->type = AS3711_BL_SU1;
max_brightness = min(pdata->su1_max_uA, 31);
@@ -423,7 +437,6 @@ static int as3711_backlight_probe(struct platform_device *pdev)
if (pdata->su2_fb) {
su = &supply->su2;
- su->fb_name = pdata->su2_fb;
su->type = AS3711_BL_SU2;
switch (pdata->su2_fbprot) {
diff --git a/drivers/video/backlight/generic_bl.c b/drivers/video/backlight/generic_bl.c
index 67dfb93..4dea91a 100644
--- a/drivers/video/backlight/generic_bl.c
+++ b/drivers/video/backlight/generic_bl.c
@@ -21,9 +21,6 @@ static int genericbl_intensity;
static struct backlight_device *generic_backlight_device;
static struct generic_bl_info *bl_machinfo;
-/* Flag to signal when the battery is low */
-#define GENERICBL_BATTLOW BL_CORE_DRIVER1
-
static int genericbl_send_intensity(struct backlight_device *bd)
{
int intensity = bd->props.brightness;
@@ -34,8 +31,6 @@ static int genericbl_send_intensity(struct backlight_device *bd)
intensity = 0;
if (bd->props.state & BL_CORE_SUSPENDED)
intensity = 0;
- if (bd->props.state & GENERICBL_BATTLOW)
- intensity &= bl_machinfo->limit_mask;
bl_machinfo->set_bl_intensity(intensity);
diff --git a/drivers/video/backlight/lp855x_bl.c b/drivers/video/backlight/lp855x_bl.c
index 939f057..7361248 100644
--- a/drivers/video/backlight/lp855x_bl.c
+++ b/drivers/video/backlight/lp855x_bl.c
@@ -374,7 +374,7 @@ static int lp855x_parse_dt(struct lp855x *lp)
struct device_node *child;
int i = 0;
- rom = devm_kzalloc(dev, sizeof(*rom) * rom_length, GFP_KERNEL);
+ rom = devm_kcalloc(dev, rom_length, sizeof(*rom), GFP_KERNEL);
if (!rom)
return -ENOMEM;
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c
index 7b738d6..f3aa608 100644
--- a/drivers/video/backlight/max8925_bl.c
+++ b/drivers/video/backlight/max8925_bl.c
@@ -116,7 +116,7 @@ static void max8925_backlight_dt_init(struct platform_device *pdev)
if (!pdata)
return;
- np = of_find_node_by_name(nproot, "backlight");
+ np = of_get_child_by_name(nproot, "backlight");
if (!np) {
dev_err(&pdev->dev, "failed to find backlight node\n");
return;
@@ -125,6 +125,8 @@ static void max8925_backlight_dt_init(struct platform_device *pdev)
if (!of_property_read_u32(np, "maxim,max8925-dual-string", &val))
pdata->dual_string = val;
+ of_node_put(np);
+
pdev->dev.platform_data = pdata;
}
diff --git a/drivers/video/backlight/otm3225a.c b/drivers/video/backlight/otm3225a.c
new file mode 100644
index 0000000..2472e21
--- /dev/null
+++ b/drivers/video/backlight/otm3225a.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Driver for ORISE Technology OTM3225A SOC for TFT LCD
+ * Copyright (C) 2017, EETS GmbH, Felix Brack <fb@ltec.ch>
+ *
+ * This driver implements a lcd device for the ORISE OTM3225A display
+ * controller. The control interface to the display is SPI and the display's
+ * memory is updated over the 16-bit RGB interface.
+ * The main source of information for writing this driver was provided by the
+ * OTM3225A datasheet from ORISE Technology. Some information arise from the
+ * ILI9328 datasheet from ILITEK as well as from the datasheets and sample code
+ * provided by Crystalfontz America Inc. who sells the CFAF240320A-032T, a 3.2"
+ * TFT LC display using the OTM3225A controller.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/lcd.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+
+#define OTM3225A_INDEX_REG 0x70
+#define OTM3225A_DATA_REG 0x72
+
+/* instruction register list */
+#define DRIVER_OUTPUT_CTRL_1 0x01
+#define DRIVER_WAVEFORM_CTRL 0x02
+#define ENTRY_MODE 0x03
+#define SCALING_CTRL 0x04
+#define DISPLAY_CTRL_1 0x07
+#define DISPLAY_CTRL_2 0x08
+#define DISPLAY_CTRL_3 0x09
+#define FRAME_CYCLE_CTRL 0x0A
+#define EXT_DISP_IFACE_CTRL_1 0x0C
+#define FRAME_MAKER_POS 0x0D
+#define EXT_DISP_IFACE_CTRL_2 0x0F
+#define POWER_CTRL_1 0x10
+#define POWER_CTRL_2 0x11
+#define POWER_CTRL_3 0x12
+#define POWER_CTRL_4 0x13
+#define GRAM_ADDR_HORIZ_SET 0x20
+#define GRAM_ADDR_VERT_SET 0x21
+#define GRAM_READ_WRITE 0x22
+#define POWER_CTRL_7 0x29
+#define FRAME_RATE_CTRL 0x2B
+#define GAMMA_CTRL_1 0x30
+#define GAMMA_CTRL_2 0x31
+#define GAMMA_CTRL_3 0x32
+#define GAMMA_CTRL_4 0x35
+#define GAMMA_CTRL_5 0x36
+#define GAMMA_CTRL_6 0x37
+#define GAMMA_CTRL_7 0x38
+#define GAMMA_CTRL_8 0x39
+#define GAMMA_CTRL_9 0x3C
+#define GAMMA_CTRL_10 0x3D
+#define WINDOW_HORIZ_RAM_START 0x50
+#define WINDOW_HORIZ_RAM_END 0x51
+#define WINDOW_VERT_RAM_START 0x52
+#define WINDOW_VERT_RAM_END 0x53
+#define DRIVER_OUTPUT_CTRL_2 0x60
+#define BASE_IMG_DISPLAY_CTRL 0x61
+#define VERT_SCROLL_CTRL 0x6A
+#define PD1_DISPLAY_POS 0x80
+#define PD1_RAM_START 0x81
+#define PD1_RAM_END 0x82
+#define PD2_DISPLAY_POS 0x83
+#define PD2_RAM_START 0x84
+#define PD2_RAM_END 0x85
+#define PANEL_IFACE_CTRL_1 0x90
+#define PANEL_IFACE_CTRL_2 0x92
+#define PANEL_IFACE_CTRL_4 0x95
+#define PANEL_IFACE_CTRL_5 0x97
+
+struct otm3225a_data {
+ struct spi_device *spi;
+ struct lcd_device *ld;
+ int power;
+};
+
+struct otm3225a_spi_instruction {
+ unsigned char reg; /* register to write */
+ unsigned short value; /* data to write to 'reg' */
+ unsigned short delay; /* delay in ms after write */
+};
+
+static struct otm3225a_spi_instruction display_init[] = {
+ { DRIVER_OUTPUT_CTRL_1, 0x0000, 0 },
+ { DRIVER_WAVEFORM_CTRL, 0x0700, 0 },
+ { ENTRY_MODE, 0x50A0, 0 },
+ { SCALING_CTRL, 0x0000, 0 },
+ { DISPLAY_CTRL_2, 0x0606, 0 },
+ { DISPLAY_CTRL_3, 0x0000, 0 },
+ { FRAME_CYCLE_CTRL, 0x0000, 0 },
+ { EXT_DISP_IFACE_CTRL_1, 0x0000, 0 },
+ { FRAME_MAKER_POS, 0x0000, 0 },
+ { EXT_DISP_IFACE_CTRL_2, 0x0002, 0 },
+ { POWER_CTRL_2, 0x0007, 0 },
+ { POWER_CTRL_3, 0x0000, 0 },
+ { POWER_CTRL_4, 0x0000, 200 },
+ { DISPLAY_CTRL_1, 0x0101, 0 },
+ { POWER_CTRL_1, 0x12B0, 0 },
+ { POWER_CTRL_2, 0x0007, 0 },
+ { POWER_CTRL_3, 0x01BB, 50 },
+ { POWER_CTRL_4, 0x0013, 0 },
+ { POWER_CTRL_7, 0x0010, 50 },
+ { GAMMA_CTRL_1, 0x000A, 0 },
+ { GAMMA_CTRL_2, 0x1326, 0 },
+ { GAMMA_CTRL_3, 0x0A29, 0 },
+ { GAMMA_CTRL_4, 0x0A0A, 0 },
+ { GAMMA_CTRL_5, 0x1E03, 0 },
+ { GAMMA_CTRL_6, 0x031E, 0 },
+ { GAMMA_CTRL_7, 0x0706, 0 },
+ { GAMMA_CTRL_8, 0x0303, 0 },
+ { GAMMA_CTRL_9, 0x010E, 0 },
+ { GAMMA_CTRL_10, 0x040E, 0 },
+ { WINDOW_HORIZ_RAM_START, 0x0000, 0 },
+ { WINDOW_HORIZ_RAM_END, 0x00EF, 0 },
+ { WINDOW_VERT_RAM_START, 0x0000, 0 },
+ { WINDOW_VERT_RAM_END, 0x013F, 0 },
+ { DRIVER_OUTPUT_CTRL_2, 0x2700, 0 },
+ { BASE_IMG_DISPLAY_CTRL, 0x0001, 0 },
+ { VERT_SCROLL_CTRL, 0x0000, 0 },
+ { PD1_DISPLAY_POS, 0x0000, 0 },
+ { PD1_RAM_START, 0x0000, 0 },
+ { PD1_RAM_END, 0x0000, 0 },
+ { PD2_DISPLAY_POS, 0x0000, 0 },
+ { PD2_RAM_START, 0x0000, 0 },
+ { PD2_RAM_END, 0x0000, 0 },
+ { PANEL_IFACE_CTRL_1, 0x0010, 0 },
+ { PANEL_IFACE_CTRL_2, 0x0000, 0 },
+ { PANEL_IFACE_CTRL_4, 0x0210, 0 },
+ { PANEL_IFACE_CTRL_5, 0x0000, 0 },
+ { DISPLAY_CTRL_1, 0x0133, 0 },
+};
+
+static struct otm3225a_spi_instruction display_enable_rgb_interface[] = {
+ { ENTRY_MODE, 0x1080, 0 },
+ { GRAM_ADDR_HORIZ_SET, 0x0000, 0 },
+ { GRAM_ADDR_VERT_SET, 0x0000, 0 },
+ { EXT_DISP_IFACE_CTRL_1, 0x0111, 500 },
+};
+
+static struct otm3225a_spi_instruction display_off[] = {
+ { DISPLAY_CTRL_1, 0x0131, 100 },
+ { DISPLAY_CTRL_1, 0x0130, 100 },
+ { DISPLAY_CTRL_1, 0x0100, 0 },
+ { POWER_CTRL_1, 0x0280, 0 },
+ { POWER_CTRL_3, 0x018B, 0 },
+};
+
+static struct otm3225a_spi_instruction display_on[] = {
+ { POWER_CTRL_1, 0x1280, 0 },
+ { DISPLAY_CTRL_1, 0x0101, 100 },
+ { DISPLAY_CTRL_1, 0x0121, 0 },
+ { DISPLAY_CTRL_1, 0x0123, 100 },
+ { DISPLAY_CTRL_1, 0x0133, 10 },
+};
+
+static void otm3225a_write(struct spi_device *spi,
+ struct otm3225a_spi_instruction *instruction,
+ unsigned int count)
+{
+ unsigned char buf[3];
+
+ while (count--) {
+ /* address register using index register */
+ buf[0] = OTM3225A_INDEX_REG;
+ buf[1] = 0x00;
+ buf[2] = instruction->reg;
+ spi_write(spi, buf, 3);
+
+ /* write data to addressed register */
+ buf[0] = OTM3225A_DATA_REG;
+ buf[1] = (instruction->value >> 8) & 0xff;
+ buf[2] = instruction->value & 0xff;
+ spi_write(spi, buf, 3);
+
+ /* execute delay if any */
+ if (instruction->delay)
+ msleep(instruction->delay);
+ instruction++;
+ }
+}
+
+static int otm3225a_set_power(struct lcd_device *ld, int power)
+{
+ struct otm3225a_data *dd = lcd_get_data(ld);
+
+ if (power == dd->power)
+ return 0;
+
+ if (power > FB_BLANK_UNBLANK)
+ otm3225a_write(dd->spi, display_off, ARRAY_SIZE(display_off));
+ else
+ otm3225a_write(dd->spi, display_on, ARRAY_SIZE(display_on));
+ dd->power = power;
+
+ return 0;
+}
+
+static int otm3225a_get_power(struct lcd_device *ld)
+{
+ struct otm3225a_data *dd = lcd_get_data(ld);
+
+ return dd->power;
+}
+
+static struct lcd_ops otm3225a_ops = {
+ .set_power = otm3225a_set_power,
+ .get_power = otm3225a_get_power,
+};
+
+static int otm3225a_probe(struct spi_device *spi)
+{
+ struct otm3225a_data *dd;
+ struct lcd_device *ld;
+ struct device *dev = &spi->dev;
+
+ dd = devm_kzalloc(dev, sizeof(struct otm3225a_data), GFP_KERNEL);
+ if (dd == NULL)
+ return -ENOMEM;
+
+ ld = devm_lcd_device_register(dev, dev_name(dev), dev, dd,
+ &otm3225a_ops);
+ if (IS_ERR(ld))
+ return PTR_ERR(ld);
+
+ dd->spi = spi;
+ dd->ld = ld;
+ dev_set_drvdata(dev, dd);
+
+ dev_info(dev, "Initializing and switching to RGB interface");
+ otm3225a_write(spi, display_init, ARRAY_SIZE(display_init));
+ otm3225a_write(spi, display_enable_rgb_interface,
+ ARRAY_SIZE(display_enable_rgb_interface));
+ return 0;
+}
+
+static struct spi_driver otm3225a_driver = {
+ .driver = {
+ .name = "otm3225a",
+ .owner = THIS_MODULE,
+ },
+ .probe = otm3225a_probe,
+};
+
+module_spi_driver(otm3225a_driver);
+
+MODULE_AUTHOR("Felix Brack <fb@ltec.ch>");
+MODULE_DESCRIPTION("OTM3225A TFT LCD driver");
+MODULE_VERSION("1.0.0");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/pandora_bl.c b/drivers/video/backlight/pandora_bl.c
index a186bc6..9618766 100644
--- a/drivers/video/backlight/pandora_bl.c
+++ b/drivers/video/backlight/pandora_bl.c
@@ -35,11 +35,15 @@
#define MAX_VALUE 63
#define MAX_USER_VALUE (MAX_VALUE - MIN_VALUE)
-#define PANDORABL_WAS_OFF BL_CORE_DRIVER1
+struct pandora_private {
+ unsigned old_state;
+#define PANDORABL_WAS_OFF 1
+};
static int pandora_backlight_update_status(struct backlight_device *bl)
{
int brightness = bl->props.brightness;
+ struct pandora_private *priv = bl_get_data(bl);
u8 r;
if (bl->props.power != FB_BLANK_UNBLANK)
@@ -53,7 +57,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl)
brightness = MAX_USER_VALUE;
if (brightness == 0) {
- if (bl->props.state & PANDORABL_WAS_OFF)
+ if (priv->old_state == PANDORABL_WAS_OFF)
goto done;
/* first disable PWM0 output, then clock */
@@ -66,7 +70,7 @@ static int pandora_backlight_update_status(struct backlight_device *bl)
goto done;
}
- if (bl->props.state & PANDORABL_WAS_OFF) {
+ if (priv->old_state == PANDORABL_WAS_OFF) {
/*
* set PWM duty cycle to max. TPS61161 seems to use this
* to calibrate it's PWM sensitivity when it starts.
@@ -93,9 +97,9 @@ static int pandora_backlight_update_status(struct backlight_device *bl)
done:
if (brightness != 0)
- bl->props.state &= ~PANDORABL_WAS_OFF;
+ priv->old_state = 0;
else
- bl->props.state |= PANDORABL_WAS_OFF;
+ priv->old_state = PANDORABL_WAS_OFF;
return 0;
}
@@ -109,13 +113,20 @@ static int pandora_backlight_probe(struct platform_device *pdev)
{
struct backlight_properties props;
struct backlight_device *bl;
+ struct pandora_private *priv;
u8 r;
+ priv = devm_kmalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&pdev->dev, "failed to allocate driver private data\n");
+ return -ENOMEM;
+ }
+
memset(&props, 0, sizeof(props));
props.max_brightness = MAX_USER_VALUE;
props.type = BACKLIGHT_RAW;
bl = devm_backlight_device_register(&pdev->dev, pdev->name, &pdev->dev,
- NULL, &pandora_backlight_ops, &props);
+ priv, &pandora_backlight_ops, &props);
if (IS_ERR(bl)) {
dev_err(&pdev->dev, "failed to register backlight\n");
return PTR_ERR(bl);
@@ -126,7 +137,7 @@ static int pandora_backlight_probe(struct platform_device *pdev)
/* 64 cycle period, ON position 0 */
twl_i2c_write_u8(TWL_MODULE_PWM, 0x80, TWL_PWM0_ON);
- bl->props.state |= PANDORABL_WAS_OFF;
+ priv->old_state = PANDORABL_WAS_OFF;
bl->props.brightness = MAX_USER_VALUE;
backlight_update_status(bl);
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index 1c2289d..44ac5bd 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio.h>
#include <linux/module.h>
@@ -35,6 +36,8 @@ struct pwm_bl_data {
struct gpio_desc *enable_gpio;
unsigned int scale;
bool legacy;
+ unsigned int post_pwm_on_delay;
+ unsigned int pwm_off_delay;
int (*notify)(struct device *,
int brightness);
void (*notify_after)(struct device *,
@@ -54,10 +57,14 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb, int brightness)
if (err < 0)
dev_err(pb->dev, "failed to enable power supply\n");
+ pwm_enable(pb->pwm);
+
+ if (pb->post_pwm_on_delay)
+ msleep(pb->post_pwm_on_delay);
+
if (pb->enable_gpio)
gpiod_set_value_cansleep(pb->enable_gpio, 1);
- pwm_enable(pb->pwm);
pb->enabled = true;
}
@@ -66,12 +73,15 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
if (!pb->enabled)
return;
- pwm_config(pb->pwm, 0, pb->period);
- pwm_disable(pb->pwm);
-
if (pb->enable_gpio)
gpiod_set_value_cansleep(pb->enable_gpio, 0);
+ if (pb->pwm_off_delay)
+ msleep(pb->pwm_off_delay);
+
+ pwm_config(pb->pwm, 0, pb->period);
+ pwm_disable(pb->pwm);
+
regulator_disable(pb->power_supply);
pb->enabled = false;
}
@@ -177,6 +187,14 @@ static int pwm_backlight_parse_dt(struct device *dev,
data->max_brightness--;
}
+ /*
+ * These values are optional and set as 0 by default, the out values
+ * are modified only if a valid u32 value can be decoded.
+ */
+ of_property_read_u32(node, "post-pwm-on-delay-ms",
+ &data->post_pwm_on_delay);
+ of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
+
data->enable_gpio = -EINVAL;
return 0;
}
@@ -275,6 +293,8 @@ static int pwm_backlight_probe(struct platform_device *pdev)
pb->exit = data->exit;
pb->dev = &pdev->dev;
pb->enabled = false;
+ pb->post_pwm_on_delay = data->post_pwm_on_delay;
+ pb->pwm_off_delay = data->pwm_off_delay;
pb->enable_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
GPIOD_ASIS);
@@ -301,14 +321,14 @@ static int pwm_backlight_probe(struct platform_device *pdev)
/*
* If the GPIO is not known to be already configured as output, that
- * is, if gpiod_get_direction returns either GPIOF_DIR_IN or -EINVAL,
- * change the direction to output and set the GPIO as active.
+ * is, if gpiod_get_direction returns either 1 or -EINVAL, change the
+ * direction to output and set the GPIO as active.
* Do not force the GPIO to active when it was already output as it
* could cause backlight flickering or we would enable the backlight too
* early. Leave the decision of the initial backlight state for later.
*/
if (pb->enable_gpio &&
- gpiod_get_direction(pb->enable_gpio) != GPIOF_DIR_OUT)
+ gpiod_get_direction(pb->enable_gpio) != 0)
gpiod_direction_output(pb->enable_gpio, 1);
pb->power_supply = devm_regulator_get(&pdev->dev, "power");
diff --git a/drivers/video/backlight/rave-sp-backlight.c b/drivers/video/backlight/rave-sp-backlight.c
new file mode 100644
index 0000000..462f14a
--- /dev/null
+++ b/drivers/video/backlight/rave-sp-backlight.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+/*
+ * LCD Backlight driver for RAVE SP
+ *
+ * Copyright (C) 2018 Zodiac Inflight Innovations
+ *
+ */
+
+#include <linux/backlight.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/rave-sp.h>
+#include <linux/platform_device.h>
+
+#define RAVE_SP_BACKLIGHT_LCD_EN BIT(7)
+
+static int rave_sp_backlight_update_status(struct backlight_device *bd)
+{
+ const struct backlight_properties *p = &bd->props;
+ const u8 intensity =
+ (p->power == FB_BLANK_UNBLANK) ? p->brightness : 0;
+ struct rave_sp *sp = dev_get_drvdata(&bd->dev);
+ u8 cmd[] = {
+ [0] = RAVE_SP_CMD_SET_BACKLIGHT,
+ [1] = 0,
+ [2] = intensity ? RAVE_SP_BACKLIGHT_LCD_EN | intensity : 0,
+ [3] = 0,
+ [4] = 0,
+ };
+
+ return rave_sp_exec(sp, cmd, sizeof(cmd), NULL, 0);
+}
+
+static const struct backlight_ops rave_sp_backlight_ops = {
+ .options = BL_CORE_SUSPENDRESUME,
+ .update_status = rave_sp_backlight_update_status,
+};
+
+static struct backlight_properties rave_sp_backlight_props = {
+ .type = BACKLIGHT_PLATFORM,
+ .max_brightness = 100,
+ .brightness = 50,
+};
+
+static int rave_sp_backlight_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct backlight_device *bd;
+
+ bd = devm_backlight_device_register(dev, pdev->name, dev->parent,
+ dev_get_drvdata(dev->parent),
+ &rave_sp_backlight_ops,
+ &rave_sp_backlight_props);
+ if (IS_ERR(bd))
+ return PTR_ERR(bd);
+
+ backlight_update_status(bd);
+
+ return 0;
+}
+
+static const struct of_device_id rave_sp_backlight_of_match[] = {
+ { .compatible = "zii,rave-sp-backlight" },
+ {}
+};
+
+static struct platform_driver rave_sp_backlight_driver = {
+ .probe = rave_sp_backlight_probe,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .of_match_table = rave_sp_backlight_of_match,
+ },
+};
+module_platform_driver(rave_sp_backlight_driver);
+
+MODULE_DEVICE_TABLE(of, rave_sp_backlight_of_match);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
+MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
+MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
+MODULE_DESCRIPTION("RAVE SP Backlight driver");
diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
index 380917c..762e3fe 100644
--- a/drivers/video/backlight/tps65217_bl.c
+++ b/drivers/video/backlight/tps65217_bl.c
@@ -184,11 +184,11 @@ static struct tps65217_bl_pdata *
tps65217_bl_parse_dt(struct platform_device *pdev)
{
struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
- struct device_node *node = of_node_get(tps->dev->of_node);
+ struct device_node *node;
struct tps65217_bl_pdata *pdata, *err;
u32 val;
- node = of_find_node_by_name(node, "backlight");
+ node = of_get_child_by_name(tps->dev->of_node, "backlight");
if (!node)
return ERR_PTR(-ENODEV);
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c
index 08b8226..ff45dca 100644
--- a/drivers/video/console/sticore.c
+++ b/drivers/video/console/sticore.c
@@ -649,7 +649,7 @@ static void *sti_bmode_font_raw(struct sti_cooked_font *f)
unsigned char *n, *p, *q;
int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font);
- n = kzalloc(4*size, STI_LOWMEM);
+ n = kcalloc(4, size, STI_LOWMEM);
if (!n)
return NULL;
p = n + 3;
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index d942542..591a13a 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -1437,7 +1437,7 @@ config FB_SIS_315
config FB_VIA
tristate "VIA UniChrome (Pro) and Chrome9 display support"
- depends on FB && PCI && X86 && GPIOLIB && I2C
+ depends on FB && PCI && GPIOLIB && I2C && (X86 || COMPILE_TEST)
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -1888,7 +1888,6 @@ config FB_W100
config FB_SH_MOBILE_LCDC
tristate "SuperH Mobile LCDC framebuffer support"
depends on FB && (SUPERH || ARCH_RENESAS) && HAVE_CLK
- depends on FB_SH_MOBILE_MERAM || !FB_SH_MOBILE_MERAM
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
@@ -2253,39 +2252,6 @@ config FB_BROADSHEET
and could also have been called by other names when coupled with
a bridge adapter.
-config FB_AUO_K190X
- tristate "AUO-K190X EPD controller support"
- depends on FB
- select FB_SYS_FILLRECT
- select FB_SYS_COPYAREA
- select FB_SYS_IMAGEBLIT
- select FB_SYS_FOPS
- select FB_DEFERRED_IO
- help
- Provides support for epaper controllers from the K190X series
- of AUO. These controllers can be used to drive epaper displays
- from Sipix.
-
- This option enables the common support, shared by the individual
- controller drivers. You will also have to enable the driver
- for the controller type used in your device.
-
-config FB_AUO_K1900
- tristate "AUO-K1900 EPD controller support"
- depends on FB && FB_AUO_K190X
- help
- This driver implements support for the AUO K1900 epd-controller.
- This controller can drive Sipix epaper displays but can only do
- serial updates, reducing the number of possible frames per second.
-
-config FB_AUO_K1901
- tristate "AUO-K1901 EPD controller support"
- depends on FB && FB_AUO_K190X
- help
- This driver implements support for the AUO K1901 epd-controller.
- This controller can drive Sipix epaper displays and supports
- concurrent updates, making higher frames per second possible.
-
config FB_JZ4740
tristate "JZ4740 LCD framebuffer support"
depends on FB && MACH_JZ4740
@@ -2346,18 +2312,6 @@ source "drivers/video/fbdev/omap/Kconfig"
source "drivers/video/fbdev/omap2/Kconfig"
source "drivers/video/fbdev/mmp/Kconfig"
-config FB_SH_MOBILE_MERAM
- tristate "SuperH Mobile MERAM read ahead support"
- depends on (SUPERH || ARCH_SHMOBILE)
- select GENERIC_ALLOCATOR
- ---help---
- Enable MERAM support for the SuperH controller.
-
- This will allow for caching of the framebuffer to provide more
- reliable access under heavy main memory bus traffic situations.
- Up to 4 memory channels can be configured, allowing 4 RGB or
- 2 YCbCr framebuffers to be configured.
-
config FB_SSD1307
tristate "Solomon SSD1307 framebuffer support"
depends on FB && I2C
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index 55282a2..13c9003 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -100,9 +100,6 @@ obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o
obj-$(CONFIG_FB_METRONOME) += metronomefb.o
obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o
-obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o
-obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o
-obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o
obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
obj-$(CONFIG_FB_SH7760) += sh7760fb.o
obj-$(CONFIG_FB_IMX) += imxfb.o
@@ -116,7 +113,6 @@ obj-$(CONFIG_FB_SM501) += sm501fb.o
obj-$(CONFIG_FB_UDL) += udlfb.o
obj-$(CONFIG_FB_SMSCUFX) += smscufx.o
obj-$(CONFIG_FB_XILINX) += xilinxfb.o
-obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o
obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o
obj-$(CONFIG_FB_OMAP) += omap/
obj-y += omap2/
diff --git a/drivers/video/fbdev/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c
index 09b0e55..6cc4686 100644
--- a/drivers/video/fbdev/aty/aty128fb.c
+++ b/drivers/video/fbdev/aty/aty128fb.c
@@ -2442,7 +2442,7 @@ static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
(void)aty_ld_pll(POWER_MANAGEMENT);
aty_st_le32(BUS_CNTL1, 0x00000010);
aty_st_le32(MEM_POWER_MISC, 0x0c830000);
- mdelay(100);
+ msleep(100);
/* Switch PCI power management to D2 */
pci_set_power_state(pdev, PCI_D2);
diff --git a/drivers/video/fbdev/aty/radeon_pm.c b/drivers/video/fbdev/aty/radeon_pm.c
index 7137c12..e695adb 100644
--- a/drivers/video/fbdev/aty/radeon_pm.c
+++ b/drivers/video/fbdev/aty/radeon_pm.c
@@ -2678,17 +2678,17 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg)
* it, we'll restore the dynamic clocks state on wakeup
*/
radeon_pm_disable_dynamic_mode(rinfo);
- mdelay(50);
+ msleep(50);
radeon_pm_save_regs(rinfo, 1);
if (rinfo->is_mobility && !(rinfo->pm_mode & radeon_pm_d2)) {
/* Switch off LVDS interface */
- mdelay(1);
+ usleep_range(1000, 2000);
OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_BL_MOD_EN));
- mdelay(1);
+ usleep_range(1000, 2000);
OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_EN | LVDS_ON));
OUTREG(LVDS_PLL_CNTL, (INREG(LVDS_PLL_CNTL) & ~30000) | 0x20000);
- mdelay(20);
+ msleep(20);
OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
}
pci_disable_device(pdev);
diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c
index 7c9a672..0adf068 100644
--- a/drivers/video/fbdev/au1100fb.c
+++ b/drivers/video/fbdev/au1100fb.c
@@ -464,7 +464,7 @@ static int au1100fb_drv_probe(struct platform_device *dev)
PAGE_ALIGN(fbdev->fb_len),
&fbdev->fb_phys, GFP_KERNEL);
if (!fbdev->fb_mem) {
- print_err("fail to allocate frambuffer (size: %dK))",
+ print_err("fail to allocate framebuffer (size: %dK))",
fbdev->fb_len / 1024);
return -ENOMEM;
}
@@ -501,7 +501,7 @@ static int au1100fb_drv_probe(struct platform_device *dev)
fbdev->info.fix = au1100fb_fix;
fbdev->info.pseudo_palette =
- devm_kzalloc(&dev->dev, sizeof(u32) * 16, GFP_KERNEL);
+ devm_kcalloc(&dev->dev, 16, sizeof(u32), GFP_KERNEL);
if (!fbdev->info.pseudo_palette)
return -ENOMEM;
diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c
index 87d5a62..3872cce 100644
--- a/drivers/video/fbdev/au1200fb.c
+++ b/drivers/video/fbdev/au1200fb.c
@@ -1696,7 +1696,7 @@ static int au1200fb_drv_probe(struct platform_device *dev)
&fbdev->fb_phys, GFP_KERNEL,
DMA_ATTR_NON_CONSISTENT);
if (!fbdev->fb_mem) {
- print_err("fail to allocate frambuffer (size: %dK))",
+ print_err("fail to allocate framebuffer (size: %dK))",
fbdev->fb_len / 1024);
ret = -ENOMEM;
goto failed;
diff --git a/drivers/video/fbdev/auo_k1900fb.c b/drivers/video/fbdev/auo_k1900fb.c
deleted file mode 100644
index 7637c60..0000000
--- a/drivers/video/fbdev/auo_k1900fb.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * auok190xfb.c -- FB driver for AUO-K1900 controllers
- *
- * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de>
- *
- * based on broadsheetfb.c
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * 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.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This driver is written to be used with the AUO-K1900 display controller.
- *
- * It is intended to be architecture independent. A board specific driver
- * must be used to perform all the physical IO interactions.
- *
- * The controller supports different update modes:
- * mode0+1 16 step gray (4bit)
- * mode2 4 step gray (2bit) - FIXME: add strange refresh
- * mode3 2 step gray (1bit) - FIXME: add strange refresh
- * mode4 handwriting mode (strange behaviour)
- * mode5 automatic selection of update mode
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/firmware.h>
-#include <linux/gpio.h>
-#include <linux/pm_runtime.h>
-
-#include <video/auo_k190xfb.h>
-
-#include "auo_k190x.h"
-
-/*
- * AUO-K1900 specific commands
- */
-
-#define AUOK1900_CMD_PARTIALDISP 0x1001
-#define AUOK1900_CMD_ROTATION 0x1006
-#define AUOK1900_CMD_LUT_STOP 0x1009
-
-#define AUOK1900_INIT_TEMP_AVERAGE (1 << 13)
-#define AUOK1900_INIT_ROTATE(_x) ((_x & 0x3) << 10)
-#define AUOK1900_INIT_RESOLUTION(_res) ((_res & 0x7) << 2)
-
-static void auok1900_init(struct auok190xfb_par *par)
-{
- struct device *dev = par->info->device;
- struct auok190x_board *board = par->board;
- u16 init_param = 0;
-
- pm_runtime_get_sync(dev);
-
- init_param |= AUOK1900_INIT_TEMP_AVERAGE;
- init_param |= AUOK1900_INIT_ROTATE(par->rotation);
- init_param |= AUOK190X_INIT_INVERSE_WHITE;
- init_param |= AUOK190X_INIT_FORMAT0;
- init_param |= AUOK1900_INIT_RESOLUTION(par->resolution);
- init_param |= AUOK190X_INIT_SHIFT_RIGHT;
-
- auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param);
-
- /* let the controller finish */
- board->wait_for_rdy(par);
-
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-}
-
-static void auok1900_update_region(struct auok190xfb_par *par, int mode,
- u16 y1, u16 y2)
-{
- struct device *dev = par->info->device;
- unsigned char *buf = (unsigned char *)par->info->screen_base;
- int xres = par->info->var.xres;
- int line_length = par->info->fix.line_length;
- u16 args[4];
-
- pm_runtime_get_sync(dev);
-
- mutex_lock(&(par->io_lock));
-
- /* y1 and y2 must be a multiple of 2 so drop the lowest bit */
- y1 &= 0xfffe;
- y2 &= 0xfffe;
-
- dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n",
- 1, y1+1, xres, y2-y1, mode);
-
- /* to FIX handle different partial update modes */
- args[0] = mode | 1;
- args[1] = y1 + 1;
- args[2] = xres;
- args[3] = y2 - y1;
- buf += y1 * line_length;
- auok190x_send_cmdargs_pixels(par, AUOK1900_CMD_PARTIALDISP, 4, args,
- ((y2 - y1) * line_length)/2, (u16 *) buf);
- auok190x_send_command(par, AUOK190X_CMD_DATA_STOP);
-
- par->update_cnt++;
-
- mutex_unlock(&(par->io_lock));
-
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-}
-
-static void auok1900fb_dpy_update_pages(struct auok190xfb_par *par,
- u16 y1, u16 y2)
-{
- int mode;
-
- if (par->update_mode < 0) {
- mode = AUOK190X_UPDATE_MODE(1);
- par->last_mode = -1;
- } else {
- mode = AUOK190X_UPDATE_MODE(par->update_mode);
- par->last_mode = par->update_mode;
- }
-
- if (par->flash)
- mode |= AUOK190X_UPDATE_NONFLASH;
-
- auok1900_update_region(par, mode, y1, y2);
-}
-
-static void auok1900fb_dpy_update(struct auok190xfb_par *par)
-{
- int mode;
-
- if (par->update_mode < 0) {
- mode = AUOK190X_UPDATE_MODE(0);
- par->last_mode = -1;
- } else {
- mode = AUOK190X_UPDATE_MODE(par->update_mode);
- par->last_mode = par->update_mode;
- }
-
- if (par->flash)
- mode |= AUOK190X_UPDATE_NONFLASH;
-
- auok1900_update_region(par, mode, 0, par->info->var.yres);
- par->update_cnt = 0;
-}
-
-static bool auok1900fb_need_refresh(struct auok190xfb_par *par)
-{
- return (par->update_cnt > 10);
-}
-
-static int auok1900fb_probe(struct platform_device *pdev)
-{
- struct auok190x_init_data init;
- struct auok190x_board *board;
-
- /* pick up board specific routines */
- board = pdev->dev.platform_data;
- if (!board)
- return -EINVAL;
-
- /* fill temporary init struct for common init */
- init.id = "auo_k1900fb";
- init.board = board;
- init.update_partial = auok1900fb_dpy_update_pages;
- init.update_all = auok1900fb_dpy_update;
- init.need_refresh = auok1900fb_need_refresh;
- init.init = auok1900_init;
-
- return auok190x_common_probe(pdev, &init);
-}
-
-static int auok1900fb_remove(struct platform_device *pdev)
-{
- return auok190x_common_remove(pdev);
-}
-
-static struct platform_driver auok1900fb_driver = {
- .probe = auok1900fb_probe,
- .remove = auok1900fb_remove,
- .driver = {
- .name = "auo_k1900fb",
- .pm = &auok190x_pm,
- },
-};
-module_platform_driver(auok1900fb_driver);
-
-MODULE_DESCRIPTION("framebuffer driver for the AUO-K1900 EPD controller");
-MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/auo_k1901fb.c b/drivers/video/fbdev/auo_k1901fb.c
deleted file mode 100644
index 681fe61..0000000
--- a/drivers/video/fbdev/auo_k1901fb.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * auok190xfb.c -- FB driver for AUO-K1901 controllers
- *
- * Copyright (C) 2011, 2012 Heiko Stuebner <heiko@sntech.de>
- *
- * based on broadsheetfb.c
- *
- * Copyright (C) 2008, Jaya Kumar
- *
- * 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.
- *
- * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
- *
- * This driver is written to be used with the AUO-K1901 display controller.
- *
- * It is intended to be architecture independent. A board specific driver
- * must be used to perform all the physical IO interactions.
- *
- * The controller supports different update modes:
- * mode0+1 16 step gray (4bit)
- * mode2+3 4 step gray (2bit)
- * mode4+5 2 step gray (1bit)
- * - mode4 is described as "without LUT"
- * mode7 automatic selection of update mode
- *
- * The most interesting difference to the K1900 is the ability to do screen
- * updates in an asynchronous fashion. Where the K1900 needs to wait for the
- * current update to complete, the K1901 can process later updates already.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/list.h>
-#include <linux/firmware.h>
-#include <linux/gpio.h>
-#include <linux/pm_runtime.h>
-
-#include <video/auo_k190xfb.h>
-
-#include "auo_k190x.h"
-
-/*
- * AUO-K1901 specific commands
- */
-
-#define AUOK1901_CMD_LUT_INTERFACE 0x0005
-#define AUOK1901_CMD_DMA_START 0x1001
-#define AUOK1901_CMD_CURSOR_START 0x1007
-#define AUOK1901_CMD_CURSOR_STOP AUOK190X_CMD_DATA_STOP
-#define AUOK1901_CMD_DDMA_START 0x1009
-
-#define AUOK1901_INIT_GATE_PULSE_LOW (0 << 14)
-#define AUOK1901_INIT_GATE_PULSE_HIGH (1 << 14)
-#define AUOK1901_INIT_SINGLE_GATE (0 << 13)
-#define AUOK1901_INIT_DOUBLE_GATE (1 << 13)
-
-/* Bits to pixels
- * Mode 15-12 11-8 7-4 3-0
- * format2 2 T 1 T
- * format3 1 T 2 T
- * format4 T 2 T 1
- * format5 T 1 T 2
- *
- * halftone modes:
- * format6 2 2 1 1
- * format7 1 1 2 2
- */
-#define AUOK1901_INIT_FORMAT2 (1 << 7)
-#define AUOK1901_INIT_FORMAT3 ((1 << 7) | (1 << 6))
-#define AUOK1901_INIT_FORMAT4 (1 << 8)
-#define AUOK1901_INIT_FORMAT5 ((1 << 8) | (1 << 6))
-#define AUOK1901_INIT_FORMAT6 ((1 << 8) | (1 << 7))
-#define AUOK1901_INIT_FORMAT7 ((1 << 8) | (1 << 7) | (1 << 6))
-
-/* res[4] to bit 10
- * res[3-0] to bits 5-2
- */
-#define AUOK1901_INIT_RESOLUTION(_res) (((_res & (1 << 4)) << 6) \
- | ((_res & 0xf) << 2))
-
-/*
- * portrait / landscape orientation in AUOK1901_CMD_DMA_START
- */
-#define AUOK1901_DMA_ROTATE90(_rot) ((_rot & 1) << 13)
-
-/*
- * equivalent to 1 << 11, needs the ~ to have same rotation like K1900
- */
-#define AUOK1901_DDMA_ROTATE180(_rot) ((~_rot & 2) << 10)
-
-static void auok1901_init(struct auok190xfb_par *par)
-{
- struct device *dev = par->info->device;
- struct auok190x_board *board = par->board;
- u16 init_param = 0;
-
- pm_runtime_get_sync(dev);
-
- init_param |= AUOK190X_INIT_INVERSE_WHITE;
- init_param |= AUOK190X_INIT_FORMAT0;
- init_param |= AUOK1901_INIT_RESOLUTION(par->resolution);
- init_param |= AUOK190X_INIT_SHIFT_LEFT;
-
- auok190x_send_cmdargs(par, AUOK190X_CMD_INIT, 1, &init_param);
-
- /* let the controller finish */
- board->wait_for_rdy(par);
-
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-}
-
-static void auok1901_update_region(struct auok190xfb_par *par, int mode,
- u16 y1, u16 y2)
-{
- struct device *dev = par->info->device;
- unsigned char *buf = (unsigned char *)par->info->screen_base;
- int xres = par->info->var.xres;
- int line_length = par->info->fix.line_length;
- u16 args[5];
-
- pm_runtime_get_sync(dev);
-
- mutex_lock(&(par->io_lock));
-
- /* y1 and y2 must be a multiple of 2 so drop the lowest bit */
- y1 &= 0xfffe;
- y2 &= 0xfffe;
-
- dev_dbg(dev, "update (x,y,w,h,mode)=(%d,%d,%d,%d,%d)\n",
- 1, y1+1, xres, y2-y1, mode);
-
- /* K1901: first transfer the region data */
- args[0] = AUOK1901_DMA_ROTATE90(par->rotation) | 1;
- args[1] = y1 + 1;
- args[2] = xres;
- args[3] = y2 - y1;
- buf += y1 * line_length;
- auok190x_send_cmdargs_pixels_nowait(par, AUOK1901_CMD_DMA_START, 4,
- args, ((y2 - y1) * line_length)/2,
- (u16 *) buf);
- auok190x_send_command_nowait(par, AUOK190X_CMD_DATA_STOP);
-
- /* K1901: second tell the controller to update the region with mode */
- args[0] = mode | AUOK1901_DDMA_ROTATE180(par->rotation);
- args[1] = 1;
- args[2] = y1 + 1;
- args[3] = xres;
- args[4] = y2 - y1;
- auok190x_send_cmdargs_nowait(par, AUOK1901_CMD_DDMA_START, 5, args);
-
- par->update_cnt++;
-
- mutex_unlock(&(par->io_lock));
-
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-}
-
-static void auok1901fb_dpy_update_pages(struct auok190xfb_par *par,
- u16 y1, u16 y2)
-{
- int mode;
-
- if (par->update_mode < 0) {
- mode = AUOK190X_UPDATE_MODE(1);
- par->last_mode = -1;
- } else {
- mode = AUOK190X_UPDATE_MODE(par->update_mode);
- par->last_mode = par->update_mode;
- }
-
- if (par->flash)
- mode |= AUOK190X_UPDATE_NONFLASH;
-
- auok1901_update_region(par, mode, y1, y2);
-}
-
-static void auok1901fb_dpy_update(struct auok190xfb_par *par)
-{
- int mode;
-
- /* When doing full updates, wait for the controller to be ready
- * This will hopefully catch some hangs of the K1901
- */
- par->board->wait_for_rdy(par);
-
- if (par->update_mode < 0) {
- mode = AUOK190X_UPDATE_MODE(0);
- par->last_mode = -1;
- } else {
- mode = AUOK190X_UPDATE_MODE(par->update_mode);
- par->last_mode = par->update_mode;
- }
-
- if (par->flash)
- mode |= AUOK190X_UPDATE_NONFLASH;
-
- auok1901_update_region(par, mode, 0, par->info->var.yres);
- par->update_cnt = 0;
-}
-
-static bool auok1901fb_need_refresh(struct auok190xfb_par *par)
-{
- return (par->update_cnt > 10);
-}
-
-static int auok1901fb_probe(struct platform_device *pdev)
-{
- struct auok190x_init_data init;
- struct auok190x_board *board;
-
- /* pick up board specific routines */
- board = pdev->dev.platform_data;
- if (!board)
- return -EINVAL;
-
- /* fill temporary init struct for common init */
- init.id = "auo_k1901fb";
- init.board = board;
- init.update_partial = auok1901fb_dpy_update_pages;
- init.update_all = auok1901fb_dpy_update;
- init.need_refresh = auok1901fb_need_refresh;
- init.init = auok1901_init;
-
- return auok190x_common_probe(pdev, &init);
-}
-
-static int auok1901fb_remove(struct platform_device *pdev)
-{
- return auok190x_common_remove(pdev);
-}
-
-static struct platform_driver auok1901fb_driver = {
- .probe = auok1901fb_probe,
- .remove = auok1901fb_remove,
- .driver = {
- .name = "auo_k1901fb",
- .pm = &auok190x_pm,
- },
-};
-module_platform_driver(auok1901fb_driver);
-
-MODULE_DESCRIPTION("framebuffer driver for the AUO-K1901 EPD controller");
-MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/auo_k190x.c b/drivers/video/fbdev/auo_k190x.c
deleted file mode 100644
index 9d24d1b..0000000
--- a/drivers/video/fbdev/auo_k190x.c
+++ /dev/null
@@ -1,1195 +0,0 @@
-/*
- * Common code for AUO-K190X framebuffer drivers
- *
- * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
- *
- * 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/sched/mm.h>
-#include <linux/kernel.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/fb.h>
-#include <linux/delay.h>
-#include <linux/uaccess.h>
-#include <linux/vmalloc.h>
-#include <linux/regulator/consumer.h>
-
-#include <video/auo_k190xfb.h>
-
-#include "auo_k190x.h"
-
-struct panel_info {
- int w;
- int h;
-};
-
-/* table of panel specific parameters to be indexed into by the board drivers */
-static struct panel_info panel_table[] = {
- /* standard 6" */
- [AUOK190X_RESOLUTION_800_600] = {
- .w = 800,
- .h = 600,
- },
- /* standard 9" */
- [AUOK190X_RESOLUTION_1024_768] = {
- .w = 1024,
- .h = 768,
- },
- [AUOK190X_RESOLUTION_600_800] = {
- .w = 600,
- .h = 800,
- },
- [AUOK190X_RESOLUTION_768_1024] = {
- .w = 768,
- .h = 1024,
- },
-};
-
-/*
- * private I80 interface to the board driver
- */
-
-static void auok190x_issue_data(struct auok190xfb_par *par, u16 data)
-{
- par->board->set_ctl(par, AUOK190X_I80_WR, 0);
- par->board->set_hdb(par, data);
- par->board->set_ctl(par, AUOK190X_I80_WR, 1);
-}
-
-static void auok190x_issue_cmd(struct auok190xfb_par *par, u16 data)
-{
- par->board->set_ctl(par, AUOK190X_I80_DC, 0);
- auok190x_issue_data(par, data);
- par->board->set_ctl(par, AUOK190X_I80_DC, 1);
-}
-
-/**
- * Conversion of 16bit color to 4bit grayscale
- * does roughly (0.3 * R + 0.6 G + 0.1 B) / 2
- */
-static inline int rgb565_to_gray4(u16 data, struct fb_var_screeninfo *var)
-{
- return ((((data & 0xF800) >> var->red.offset) * 77 +
- ((data & 0x07E0) >> (var->green.offset + 1)) * 151 +
- ((data & 0x1F) >> var->blue.offset) * 28) >> 8 >> 1);
-}
-
-static int auok190x_issue_pixels_rgb565(struct auok190xfb_par *par, int size,
- u16 *data)
-{
- struct fb_var_screeninfo *var = &par->info->var;
- struct device *dev = par->info->device;
- int i;
- u16 tmp;
-
- if (size & 7) {
- dev_err(dev, "issue_pixels: size %d must be a multiple of 8\n",
- size);
- return -EINVAL;
- }
-
- for (i = 0; i < (size >> 2); i++) {
- par->board->set_ctl(par, AUOK190X_I80_WR, 0);
-
- tmp = (rgb565_to_gray4(data[4*i], var) & 0x000F);
- tmp |= (rgb565_to_gray4(data[4*i+1], var) << 4) & 0x00F0;
- tmp |= (rgb565_to_gray4(data[4*i+2], var) << 8) & 0x0F00;
- tmp |= (rgb565_to_gray4(data[4*i+3], var) << 12) & 0xF000;
-
- par->board->set_hdb(par, tmp);
- par->board->set_ctl(par, AUOK190X_I80_WR, 1);
- }
-
- return 0;
-}
-
-static int auok190x_issue_pixels_gray8(struct auok190xfb_par *par, int size,
- u16 *data)
-{
- struct device *dev = par->info->device;
- int i;
- u16 tmp;
-
- if (size & 3) {
- dev_err(dev, "issue_pixels: size %d must be a multiple of 4\n",
- size);
- return -EINVAL;
- }
-
- for (i = 0; i < (size >> 1); i++) {
- par->board->set_ctl(par, AUOK190X_I80_WR, 0);
-
- /* simple reduction of 8bit staticgray to 4bit gray
- * combines 4 * 4bit pixel values into a 16bit value
- */
- tmp = (data[2*i] & 0xF0) >> 4;
- tmp |= (data[2*i] & 0xF000) >> 8;
- tmp |= (data[2*i+1] & 0xF0) << 4;
- tmp |= (data[2*i+1] & 0xF000);
-
- par->board->set_hdb(par, tmp);
- par->board->set_ctl(par, AUOK190X_I80_WR, 1);
- }
-
- return 0;
-}
-
-static int auok190x_issue_pixels(struct auok190xfb_par *par, int size,
- u16 *data)
-{
- struct fb_info *info = par->info;
- struct device *dev = par->info->device;
-
- if (info->var.bits_per_pixel == 8 && info->var.grayscale)
- auok190x_issue_pixels_gray8(par, size, data);
- else if (info->var.bits_per_pixel == 16)
- auok190x_issue_pixels_rgb565(par, size, data);
- else
- dev_err(dev, "unsupported color mode (bits: %d, gray: %d)\n",
- info->var.bits_per_pixel, info->var.grayscale);
-
- return 0;
-}
-
-static u16 auok190x_read_data(struct auok190xfb_par *par)
-{
- u16 data;
-
- par->board->set_ctl(par, AUOK190X_I80_OE, 0);
- data = par->board->get_hdb(par);
- par->board->set_ctl(par, AUOK190X_I80_OE, 1);
-
- return data;
-}
-
-/*
- * Command interface for the controller drivers
- */
-
-void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data)
-{
- par->board->set_ctl(par, AUOK190X_I80_CS, 0);
- auok190x_issue_cmd(par, data);
- par->board->set_ctl(par, AUOK190X_I80_CS, 1);
-}
-EXPORT_SYMBOL_GPL(auok190x_send_command_nowait);
-
-void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd,
- int argc, u16 *argv)
-{
- int i;
-
- par->board->set_ctl(par, AUOK190X_I80_CS, 0);
- auok190x_issue_cmd(par, cmd);
-
- for (i = 0; i < argc; i++)
- auok190x_issue_data(par, argv[i]);
- par->board->set_ctl(par, AUOK190X_I80_CS, 1);
-}
-EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_nowait);
-
-int auok190x_send_command(struct auok190xfb_par *par, u16 data)
-{
- int ret;
-
- ret = par->board->wait_for_rdy(par);
- if (ret)
- return ret;
-
- auok190x_send_command_nowait(par, data);
- return 0;
-}
-EXPORT_SYMBOL_GPL(auok190x_send_command);
-
-int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd,
- int argc, u16 *argv)
-{
- int ret;
-
- ret = par->board->wait_for_rdy(par);
- if (ret)
- return ret;
-
- auok190x_send_cmdargs_nowait(par, cmd, argc, argv);
- return 0;
-}
-EXPORT_SYMBOL_GPL(auok190x_send_cmdargs);
-
-int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd,
- int argc, u16 *argv)
-{
- int i, ret;
-
- ret = par->board->wait_for_rdy(par);
- if (ret)
- return ret;
-
- par->board->set_ctl(par, AUOK190X_I80_CS, 0);
- auok190x_issue_cmd(par, cmd);
-
- for (i = 0; i < argc; i++)
- argv[i] = auok190x_read_data(par);
- par->board->set_ctl(par, AUOK190X_I80_CS, 1);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(auok190x_read_cmdargs);
-
-void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par, u16 cmd,
- int argc, u16 *argv, int size, u16 *data)
-{
- int i;
-
- par->board->set_ctl(par, AUOK190X_I80_CS, 0);
-
- auok190x_issue_cmd(par, cmd);
-
- for (i = 0; i < argc; i++)
- auok190x_issue_data(par, argv[i]);
-
- auok190x_issue_pixels(par, size, data);
-
- par->board->set_ctl(par, AUOK190X_I80_CS, 1);
-}
-EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels_nowait);
-
-int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd,
- int argc, u16 *argv, int size, u16 *data)
-{
- int ret;
-
- ret = par->board->wait_for_rdy(par);
- if (ret)
- return ret;
-
- auok190x_send_cmdargs_pixels_nowait(par, cmd, argc, argv, size, data);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(auok190x_send_cmdargs_pixels);
-
-/*
- * fbdefio callbacks - common on both controllers.
- */
-
-static void auok190xfb_dpy_first_io(struct fb_info *info)
-{
- /* tell runtime-pm that we wish to use the device in a short time */
- pm_runtime_get(info->device);
-}
-
-/* this is called back from the deferred io workqueue */
-static void auok190xfb_dpy_deferred_io(struct fb_info *info,
- struct list_head *pagelist)
-{
- struct fb_deferred_io *fbdefio = info->fbdefio;
- struct auok190xfb_par *par = info->par;
- u16 line_length = info->fix.line_length;
- u16 yres = info->var.yres;
- u16 y1 = 0, h = 0;
- int prev_index = -1;
- struct page *cur;
- int h_inc;
- int threshold;
-
- if (!list_empty(pagelist))
- /* the device resume should've been requested through first_io,
- * if the resume did not finish until now, wait for it.
- */
- pm_runtime_barrier(info->device);
- else
- /* We reached this via the fsync or some other way.
- * In either case the first_io function did not run,
- * so we runtime_resume the device here synchronously.
- */
- pm_runtime_get_sync(info->device);
-
- /* Do a full screen update every n updates to prevent
- * excessive darkening of the Sipix display.
- * If we do this, there is no need to walk the pages.
- */
- if (par->need_refresh(par)) {
- par->update_all(par);
- goto out;
- }
-
- /* height increment is fixed per page */
- h_inc = DIV_ROUND_UP(PAGE_SIZE , line_length);
-
- /* calculate number of pages from pixel height */
- threshold = par->consecutive_threshold / h_inc;
- if (threshold < 1)
- threshold = 1;
-
- /* walk the written page list and swizzle the data */
- list_for_each_entry(cur, &fbdefio->pagelist, lru) {
- if (prev_index < 0) {
- /* just starting so assign first page */
- y1 = (cur->index << PAGE_SHIFT) / line_length;
- h = h_inc;
- } else if ((cur->index - prev_index) <= threshold) {
- /* page is within our threshold for single updates */
- h += h_inc * (cur->index - prev_index);
- } else {
- /* page not consecutive, issue previous update first */
- par->update_partial(par, y1, y1 + h);
-
- /* start over with our non consecutive page */
- y1 = (cur->index << PAGE_SHIFT) / line_length;
- h = h_inc;
- }
- prev_index = cur->index;
- }
-
- /* if we still have any pages to update we do so now */
- if (h >= yres)
- /* its a full screen update, just do it */
- par->update_all(par);
- else
- par->update_partial(par, y1, min((u16) (y1 + h), yres));
-
-out:
- pm_runtime_mark_last_busy(info->device);
- pm_runtime_put_autosuspend(info->device);
-}
-
-/*
- * framebuffer operations
- */
-
-/*
- * this is the slow path from userspace. they can seek and write to
- * the fb. it's inefficient to do anything less than a full screen draw
- */
-static ssize_t auok190xfb_write(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- struct auok190xfb_par *par = info->par;
- unsigned long p = *ppos;
- void *dst;
- int err = 0;
- unsigned long total_size;
-
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
-
- total_size = info->fix.smem_len;
-
- if (p > total_size)
- return -EFBIG;
-
- if (count > total_size) {
- err = -EFBIG;
- count = total_size;
- }
-
- if (count + p > total_size) {
- if (!err)
- err = -ENOSPC;
-
- count = total_size - p;
- }
-
- dst = (void *)(info->screen_base + p);
-
- if (copy_from_user(dst, buf, count))
- err = -EFAULT;
-
- if (!err)
- *ppos += count;
-
- par->update_all(par);
-
- return (err) ? err : count;
-}
-
-static void auok190xfb_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect)
-{
- struct auok190xfb_par *par = info->par;
-
- sys_fillrect(info, rect);
-
- par->update_all(par);
-}
-
-static void auok190xfb_copyarea(struct fb_info *info,
- const struct fb_copyarea *area)
-{
- struct auok190xfb_par *par = info->par;
-
- sys_copyarea(info, area);
-
- par->update_all(par);
-}
-
-static void auok190xfb_imageblit(struct fb_info *info,
- const struct fb_image *image)
-{
- struct auok190xfb_par *par = info->par;
-
- sys_imageblit(info, image);
-
- par->update_all(par);
-}
-
-static int auok190xfb_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- struct device *dev = info->device;
- struct auok190xfb_par *par = info->par;
- struct panel_info *panel = &panel_table[par->resolution];
- int size;
-
- /*
- * Color depth
- */
-
- if (var->bits_per_pixel == 8 && var->grayscale == 1) {
- /*
- * For 8-bit grayscale, R, G, and B offset are equal.
- */
- var->red.length = 8;
- var->red.offset = 0;
- var->red.msb_right = 0;
-
- var->green.length = 8;
- var->green.offset = 0;
- var->green.msb_right = 0;
-
- var->blue.length = 8;
- var->blue.offset = 0;
- var->blue.msb_right = 0;
-
- var->transp.length = 0;
- var->transp.offset = 0;
- var->transp.msb_right = 0;
- } else if (var->bits_per_pixel == 16) {
- var->red.length = 5;
- var->red.offset = 11;
- var->red.msb_right = 0;
-
- var->green.length = 6;
- var->green.offset = 5;
- var->green.msb_right = 0;
-
- var->blue.length = 5;
- var->blue.offset = 0;
- var->blue.msb_right = 0;
-
- var->transp.length = 0;
- var->transp.offset = 0;
- var->transp.msb_right = 0;
- } else {
- dev_warn(dev, "unsupported color mode (bits: %d, grayscale: %d)\n",
- info->var.bits_per_pixel, info->var.grayscale);
- return -EINVAL;
- }
-
- /*
- * Dimensions
- */
-
- switch (var->rotate) {
- case FB_ROTATE_UR:
- case FB_ROTATE_UD:
- var->xres = panel->w;
- var->yres = panel->h;
- break;
- case FB_ROTATE_CW:
- case FB_ROTATE_CCW:
- var->xres = panel->h;
- var->yres = panel->w;
- break;
- default:
- dev_dbg(dev, "Invalid rotation request\n");
- return -EINVAL;
- }
-
- var->xres_virtual = var->xres;
- var->yres_virtual = var->yres;
-
- /*
- * Memory limit
- */
-
- size = var->xres_virtual * var->yres_virtual * var->bits_per_pixel / 8;
- if (size > info->fix.smem_len) {
- dev_err(dev, "Memory limit exceeded, requested %dK\n",
- size >> 10);
- return -ENOMEM;
- }
-
- return 0;
-}
-
-static int auok190xfb_set_fix(struct fb_info *info)
-{
- struct fb_fix_screeninfo *fix = &info->fix;
- struct fb_var_screeninfo *var = &info->var;
-
- fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
-
- fix->type = FB_TYPE_PACKED_PIXELS;
- fix->accel = FB_ACCEL_NONE;
- fix->visual = (var->grayscale) ? FB_VISUAL_STATIC_PSEUDOCOLOR
- : FB_VISUAL_TRUECOLOR;
- fix->xpanstep = 0;
- fix->ypanstep = 0;
- fix->ywrapstep = 0;
-
- return 0;
-}
-
-static int auok190xfb_set_par(struct fb_info *info)
-{
- struct auok190xfb_par *par = info->par;
-
- par->rotation = info->var.rotate;
- auok190xfb_set_fix(info);
-
- /* reinit the controller to honor the rotation */
- par->init(par);
-
- /* wait for init to complete */
- par->board->wait_for_rdy(par);
-
- return 0;
-}
-
-static struct fb_ops auok190xfb_ops = {
- .owner = THIS_MODULE,
- .fb_read = fb_sys_read,
- .fb_write = auok190xfb_write,
- .fb_fillrect = auok190xfb_fillrect,
- .fb_copyarea = auok190xfb_copyarea,
- .fb_imageblit = auok190xfb_imageblit,
- .fb_check_var = auok190xfb_check_var,
- .fb_set_par = auok190xfb_set_par,
-};
-
-/*
- * Controller-functions common to both K1900 and K1901
- */
-
-static int auok190x_read_temperature(struct auok190xfb_par *par)
-{
- struct device *dev = par->info->device;
- u16 data[4];
- int temp;
-
- pm_runtime_get_sync(dev);
-
- mutex_lock(&(par->io_lock));
-
- auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data);
-
- mutex_unlock(&(par->io_lock));
-
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-
- /* sanitize and split of half-degrees for now */
- temp = ((data[0] & AUOK190X_VERSION_TEMP_MASK) >> 1);
-
- /* handle positive and negative temperatures */
- if (temp >= 201)
- return (255 - temp + 1) * (-1);
- else
- return temp;
-}
-
-static void auok190x_identify(struct auok190xfb_par *par)
-{
- struct device *dev = par->info->device;
- u16 data[4];
-
- pm_runtime_get_sync(dev);
-
- mutex_lock(&(par->io_lock));
-
- auok190x_read_cmdargs(par, AUOK190X_CMD_READ_VERSION, 4, data);
-
- mutex_unlock(&(par->io_lock));
-
- par->epd_type = data[1] & AUOK190X_VERSION_TEMP_MASK;
-
- par->panel_size_int = AUOK190X_VERSION_SIZE_INT(data[2]);
- par->panel_size_float = AUOK190X_VERSION_SIZE_FLOAT(data[2]);
- par->panel_model = AUOK190X_VERSION_MODEL(data[2]);
-
- par->tcon_version = AUOK190X_VERSION_TCON(data[3]);
- par->lut_version = AUOK190X_VERSION_LUT(data[3]);
-
- dev_dbg(dev, "panel %d.%din, model 0x%x, EPD 0x%x TCON-rev 0x%x, LUT-rev 0x%x",
- par->panel_size_int, par->panel_size_float, par->panel_model,
- par->epd_type, par->tcon_version, par->lut_version);
-
- pm_runtime_mark_last_busy(dev);
- pm_runtime_put_autosuspend(dev);
-}
-
-/*
- * Sysfs functions
- */
-
-static ssize_t update_mode_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct auok190xfb_par *par = info->par;
-
- return sprintf(buf, "%d\n", par->update_mode);
-}
-
-static ssize_t update_mode_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct auok190xfb_par *par = info->par;
- int mode, ret;
-
- ret = kstrtoint(buf, 10, &mode);
- if (ret)
- return ret;
-
- par->update_mode = mode;
-
- /* if we enter a better mode, do a full update */
- if (par->last_mode > 1 && mode < par->last_mode)
- par->update_all(par);
-
- return count;
-}
-
-static ssize_t flash_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct auok190xfb_par *par = info->par;
-
- return sprintf(buf, "%d\n", par->flash);
-}
-
-static ssize_t flash_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct auok190xfb_par *par = info->par;
- int flash, ret;
-
- ret = kstrtoint(buf, 10, &flash);
- if (ret)
- return ret;
-
- if (flash > 0)
- par->flash = 1;
- else
- par->flash = 0;
-
- return count;
-}
-
-static ssize_t temp_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fb_info *info = dev_get_drvdata(dev);
- struct auok190xfb_par *par = info->par;
- int temp;
-
- temp = auok190x_read_temperature(par);
- return sprintf(buf, "%d\n", temp);
-}
-
-static DEVICE_ATTR_RW(update_mode);
-static DEVICE_ATTR_RW(flash);
-static DEVICE_ATTR(temp, 0644, temp_show, NULL);
-
-static struct attribute *auok190x_attributes[] = {
- &dev_attr_update_mode.attr,
- &dev_attr_flash.attr,
- &dev_attr_temp.attr,
- NULL
-};
-
-static const struct attribute_group auok190x_attr_group = {
- .attrs = auok190x_attributes,
-};
-
-static int auok190x_power(struct auok190xfb_par *par, bool on)
-{
- struct auok190x_board *board = par->board;
- int ret;
-
- if (on) {
- /* We should maintain POWER up for at least 80ms before set
- * RST_N and SLP_N to high (TCON spec 20100803_v35 p59)
- */
- ret = regulator_enable(par->regulator);
- if (ret)
- return ret;
-
- msleep(200);
- gpio_set_value(board->gpio_nrst, 1);
- gpio_set_value(board->gpio_nsleep, 1);
- msleep(200);
- } else {
- regulator_disable(par->regulator);
- gpio_set_value(board->gpio_nrst, 0);
- gpio_set_value(board->gpio_nsleep, 0);
- }
-
- return 0;
-}
-
-/*
- * Recovery - powercycle the controller
- */
-
-static void auok190x_recover(struct auok190xfb_par *par)
-{
- struct device *dev = par->info->device;
-
- auok190x_power(par, 0);
- msleep(100);
- auok190x_power(par, 1);
-
- /* after powercycling the device, it's always active */
- pm_runtime_set_active(dev);
- par->standby = 0;
-
- par->init(par);
-
- /* wait for init to complete */
- par->board->wait_for_rdy(par);
-}
-
-/*
- * Power-management
- */
-static int __maybe_unused auok190x_runtime_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct fb_info *info = platform_get_drvdata(pdev);
- struct auok190xfb_par *par = info->par;
- struct auok190x_board *board = par->board;
- u16 standby_param;
-
- /* take and keep the lock until we are resumed, as the controller
- * will never reach the non-busy state when in standby mode
- */
- mutex_lock(&(par->io_lock));
-
- if (par->standby) {
- dev_warn(dev, "already in standby, runtime-pm pairing mismatch\n");
- mutex_unlock(&(par->io_lock));
- return 0;
- }
-
- /* according to runtime_pm.txt runtime_suspend only means, that the
- * device will not process data and will not communicate with the CPU
- * As we hold the lock, this stays true even without standby
- */
- if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
- dev_dbg(dev, "runtime suspend without standby\n");
- goto finish;
- } else if (board->quirks & AUOK190X_QUIRK_STANDBYPARAM) {
- /* for some TCON versions STANDBY expects a parameter (0) but
- * it seems the real tcon version has to be determined yet.
- */
- dev_dbg(dev, "runtime suspend with additional empty param\n");
- standby_param = 0;
- auok190x_send_cmdargs(par, AUOK190X_CMD_STANDBY, 1,
- &standby_param);
- } else {
- dev_dbg(dev, "runtime suspend without param\n");
- auok190x_send_command(par, AUOK190X_CMD_STANDBY);
- }
-
- msleep(64);
-
-finish:
- par->standby = 1;
-
- return 0;
-}
-
-static int __maybe_unused auok190x_runtime_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct fb_info *info = platform_get_drvdata(pdev);
- struct auok190xfb_par *par = info->par;
- struct auok190x_board *board = par->board;
-
- if (!par->standby) {
- dev_warn(dev, "not in standby, runtime-pm pairing mismatch\n");
- return 0;
- }
-
- if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
- dev_dbg(dev, "runtime resume without standby\n");
- } else {
- /* when in standby, controller is always busy
- * and only accepts the wakeup command
- */
- dev_dbg(dev, "runtime resume from standby\n");
- auok190x_send_command_nowait(par, AUOK190X_CMD_WAKEUP);
-
- msleep(160);
-
- /* wait for the controller to be ready and release the lock */
- board->wait_for_rdy(par);
- }
-
- par->standby = 0;
-
- mutex_unlock(&(par->io_lock));
-
- return 0;
-}
-
-static int __maybe_unused auok190x_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct fb_info *info = platform_get_drvdata(pdev);
- struct auok190xfb_par *par = info->par;
- struct auok190x_board *board = par->board;
- int ret;
-
- dev_dbg(dev, "suspend\n");
- if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
- /* suspend via powering off the ic */
- dev_dbg(dev, "suspend with broken standby\n");
-
- auok190x_power(par, 0);
- } else {
- dev_dbg(dev, "suspend using sleep\n");
-
- /* the sleep state can only be entered from the standby state.
- * pm_runtime_get_noresume gets called before the suspend call.
- * So the devices usage count is >0 but it is not necessarily
- * active.
- */
- if (!pm_runtime_status_suspended(dev)) {
- ret = auok190x_runtime_suspend(dev);
- if (ret < 0) {
- dev_err(dev, "auok190x_runtime_suspend failed with %d\n",
- ret);
- return ret;
- }
- par->manual_standby = 1;
- }
-
- gpio_direction_output(board->gpio_nsleep, 0);
- }
-
- msleep(100);
-
- return 0;
-}
-
-static int __maybe_unused auok190x_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct fb_info *info = platform_get_drvdata(pdev);
- struct auok190xfb_par *par = info->par;
- struct auok190x_board *board = par->board;
-
- dev_dbg(dev, "resume\n");
- if (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN) {
- dev_dbg(dev, "resume with broken standby\n");
-
- auok190x_power(par, 1);
-
- par->init(par);
- } else {
- dev_dbg(dev, "resume from sleep\n");
-
- /* device should be in runtime suspend when we were suspended
- * and pm_runtime_put_sync gets called after this function.
- * So there is no need to touch the standby mode here at all.
- */
- gpio_direction_output(board->gpio_nsleep, 1);
- msleep(100);
-
- /* an additional init call seems to be necessary after sleep */
- auok190x_runtime_resume(dev);
- par->init(par);
-
- /* if we were runtime-suspended before, suspend again*/
- if (!par->manual_standby)
- auok190x_runtime_suspend(dev);
- else
- par->manual_standby = 0;
- }
-
- return 0;
-}
-
-const struct dev_pm_ops auok190x_pm = {
- SET_RUNTIME_PM_OPS(auok190x_runtime_suspend, auok190x_runtime_resume,
- NULL)
- SET_SYSTEM_SLEEP_PM_OPS(auok190x_suspend, auok190x_resume)
-};
-EXPORT_SYMBOL_GPL(auok190x_pm);
-
-/*
- * Common probe and remove code
- */
-
-int auok190x_common_probe(struct platform_device *pdev,
- struct auok190x_init_data *init)
-{
- struct auok190x_board *board = init->board;
- struct auok190xfb_par *par;
- struct fb_info *info;
- struct panel_info *panel;
- int videomemorysize, ret;
- unsigned char *videomemory;
-
- /* check board contents */
- if (!board->init || !board->cleanup || !board->wait_for_rdy
- || !board->set_ctl || !board->set_hdb || !board->get_hdb
- || !board->setup_irq)
- return -EINVAL;
-
- info = framebuffer_alloc(sizeof(struct auok190xfb_par), &pdev->dev);
- if (!info)
- return -ENOMEM;
-
- par = info->par;
- par->info = info;
- par->board = board;
- par->recover = auok190x_recover;
- par->update_partial = init->update_partial;
- par->update_all = init->update_all;
- par->need_refresh = init->need_refresh;
- par->init = init->init;
-
- /* init update modes */
- par->update_cnt = 0;
- par->update_mode = -1;
- par->last_mode = -1;
- par->flash = 0;
-
- par->regulator = regulator_get(info->device, "vdd");
- if (IS_ERR(par->regulator)) {
- ret = PTR_ERR(par->regulator);
- dev_err(info->device, "Failed to get regulator: %d\n", ret);
- goto err_reg;
- }
-
- ret = board->init(par);
- if (ret) {
- dev_err(info->device, "board init failed, %d\n", ret);
- goto err_board;
- }
-
- ret = gpio_request(board->gpio_nsleep, "AUOK190x sleep");
- if (ret) {
- dev_err(info->device, "could not request sleep gpio, %d\n",
- ret);
- goto err_gpio1;
- }
-
- ret = gpio_direction_output(board->gpio_nsleep, 0);
- if (ret) {
- dev_err(info->device, "could not set sleep gpio, %d\n", ret);
- goto err_gpio2;
- }
-
- ret = gpio_request(board->gpio_nrst, "AUOK190x reset");
- if (ret) {
- dev_err(info->device, "could not request reset gpio, %d\n",
- ret);
- goto err_gpio2;
- }
-
- ret = gpio_direction_output(board->gpio_nrst, 0);
- if (ret) {
- dev_err(info->device, "could not set reset gpio, %d\n", ret);
- goto err_gpio3;
- }
-
- ret = auok190x_power(par, 1);
- if (ret) {
- dev_err(info->device, "could not power on the device, %d\n",
- ret);
- goto err_gpio3;
- }
-
- mutex_init(&par->io_lock);
-
- init_waitqueue_head(&par->waitq);
-
- ret = par->board->setup_irq(par->info);
- if (ret) {
- dev_err(info->device, "could not setup ready-irq, %d\n", ret);
- goto err_irq;
- }
-
- /* wait for init to complete */
- par->board->wait_for_rdy(par);
-
- /*
- * From here on the controller can talk to us
- */
-
- /* initialise fix, var, resolution and rotation */
-
- strlcpy(info->fix.id, init->id, 16);
- info->var.bits_per_pixel = 8;
- info->var.grayscale = 1;
-
- panel = &panel_table[board->resolution];
-
- par->resolution = board->resolution;
- par->rotation = 0;
-
- /* videomemory handling */
-
- videomemorysize = roundup((panel->w * panel->h) * 2, PAGE_SIZE);
- videomemory = vzalloc(videomemorysize);
- if (!videomemory) {
- ret = -ENOMEM;
- goto err_irq;
- }
-
- info->screen_base = (char *)videomemory;
- info->fix.smem_len = videomemorysize;
-
- info->flags = FBINFO_FLAG_DEFAULT | FBINFO_VIRTFB;
- info->fbops = &auok190xfb_ops;
-
- ret = auok190xfb_check_var(&info->var, info);
- if (ret)
- goto err_defio;
-
- auok190xfb_set_fix(info);
-
- /* deferred io init */
-
- info->fbdefio = devm_kzalloc(info->device,
- sizeof(struct fb_deferred_io),
- GFP_KERNEL);
- if (!info->fbdefio) {
- dev_err(info->device, "Failed to allocate memory\n");
- ret = -ENOMEM;
- goto err_defio;
- }
-
- dev_dbg(info->device, "targeting %d frames per second\n", board->fps);
- info->fbdefio->delay = HZ / board->fps;
- info->fbdefio->first_io = auok190xfb_dpy_first_io,
- info->fbdefio->deferred_io = auok190xfb_dpy_deferred_io,
- fb_deferred_io_init(info);
-
- /* color map */
-
- ret = fb_alloc_cmap(&info->cmap, 256, 0);
- if (ret < 0) {
- dev_err(info->device, "Failed to allocate colormap\n");
- goto err_cmap;
- }
-
- /* controller init */
-
- par->consecutive_threshold = 100;
- par->init(par);
- auok190x_identify(par);
-
- platform_set_drvdata(pdev, info);
-
- ret = register_framebuffer(info);
- if (ret < 0)
- goto err_regfb;
-
- ret = sysfs_create_group(&info->device->kobj, &auok190x_attr_group);
- if (ret)
- goto err_sysfs;
-
- dev_info(info->device, "fb%d: %dx%d using %dK of video memory\n",
- info->node, info->var.xres, info->var.yres,
- videomemorysize >> 10);
-
- /* increase autosuspend_delay when we use alternative methods
- * for runtime_pm
- */
- par->autosuspend_delay = (board->quirks & AUOK190X_QUIRK_STANDBYBROKEN)
- ? 1000 : 200;
-
- pm_runtime_set_active(info->device);
- pm_runtime_enable(info->device);
- pm_runtime_set_autosuspend_delay(info->device, par->autosuspend_delay);
- pm_runtime_use_autosuspend(info->device);
-
- return 0;
-
-err_sysfs:
- unregister_framebuffer(info);
-err_regfb:
- fb_dealloc_cmap(&info->cmap);
-err_cmap:
- fb_deferred_io_cleanup(info);
-err_defio:
- vfree((void *)info->screen_base);
-err_irq:
- auok190x_power(par, 0);
-err_gpio3:
- gpio_free(board->gpio_nrst);
-err_gpio2:
- gpio_free(board->gpio_nsleep);
-err_gpio1:
- board->cleanup(par);
-err_board:
- regulator_put(par->regulator);
-err_reg:
- framebuffer_release(info);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(auok190x_common_probe);
-
-int auok190x_common_remove(struct platform_device *pdev)
-{
- struct fb_info *info = platform_get_drvdata(pdev);
- struct auok190xfb_par *par = info->par;
- struct auok190x_board *board = par->board;
-
- pm_runtime_disable(info->device);
-
- sysfs_remove_group(&info->device->kobj, &auok190x_attr_group);
-
- unregister_framebuffer(info);
-
- fb_dealloc_cmap(&info->cmap);
-
- fb_deferred_io_cleanup(info);
-
- vfree((void *)info->screen_base);
-
- auok190x_power(par, 0);
-
- gpio_free(board->gpio_nrst);
- gpio_free(board->gpio_nsleep);
-
- board->cleanup(par);
-
- regulator_put(par->regulator);
-
- framebuffer_release(info);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(auok190x_common_remove);
-
-MODULE_DESCRIPTION("Common code for AUO-K190X controllers");
-MODULE_AUTHOR("Heiko Stuebner <heiko@sntech.de>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/auo_k190x.h b/drivers/video/fbdev/auo_k190x.h
deleted file mode 100644
index e35af1f..0000000
--- a/drivers/video/fbdev/auo_k190x.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Private common definitions for AUO-K190X framebuffer drivers
- *
- * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
- *
- * 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.
- */
-
-/*
- * I80 interface specific defines
- */
-
-#define AUOK190X_I80_CS 0x01
-#define AUOK190X_I80_DC 0x02
-#define AUOK190X_I80_WR 0x03
-#define AUOK190X_I80_OE 0x04
-
-/*
- * AUOK190x commands, common to both controllers
- */
-
-#define AUOK190X_CMD_INIT 0x0000
-#define AUOK190X_CMD_STANDBY 0x0001
-#define AUOK190X_CMD_WAKEUP 0x0002
-#define AUOK190X_CMD_TCON_RESET 0x0003
-#define AUOK190X_CMD_DATA_STOP 0x1002
-#define AUOK190X_CMD_LUT_START 0x1003
-#define AUOK190X_CMD_DISP_REFRESH 0x1004
-#define AUOK190X_CMD_DISP_RESET 0x1005
-#define AUOK190X_CMD_PRE_DISPLAY_START 0x100D
-#define AUOK190X_CMD_PRE_DISPLAY_STOP 0x100F
-#define AUOK190X_CMD_FLASH_W 0x2000
-#define AUOK190X_CMD_FLASH_E 0x2001
-#define AUOK190X_CMD_FLASH_STS 0x2002
-#define AUOK190X_CMD_FRAMERATE 0x3000
-#define AUOK190X_CMD_READ_VERSION 0x4000
-#define AUOK190X_CMD_READ_STATUS 0x4001
-#define AUOK190X_CMD_READ_LUT 0x4003
-#define AUOK190X_CMD_DRIVERTIMING 0x5000
-#define AUOK190X_CMD_LBALANCE 0x5001
-#define AUOK190X_CMD_AGINGMODE 0x6000
-#define AUOK190X_CMD_AGINGEXIT 0x6001
-
-/*
- * Common settings for AUOK190X_CMD_INIT
- */
-
-#define AUOK190X_INIT_DATA_FILTER (0 << 12)
-#define AUOK190X_INIT_DATA_BYPASS (1 << 12)
-#define AUOK190X_INIT_INVERSE_WHITE (0 << 9)
-#define AUOK190X_INIT_INVERSE_BLACK (1 << 9)
-#define AUOK190X_INIT_SCAN_DOWN (0 << 1)
-#define AUOK190X_INIT_SCAN_UP (1 << 1)
-#define AUOK190X_INIT_SHIFT_LEFT (0 << 0)
-#define AUOK190X_INIT_SHIFT_RIGHT (1 << 0)
-
-/* Common bits to pixels
- * Mode 15-12 11-8 7-4 3-0
- * format0 4 3 2 1
- * format1 3 4 1 2
- */
-
-#define AUOK190X_INIT_FORMAT0 0
-#define AUOK190X_INIT_FORMAT1 (1 << 6)
-
-/*
- * settings for AUOK190X_CMD_RESET
- */
-
-#define AUOK190X_RESET_TCON (0 << 0)
-#define AUOK190X_RESET_NORMAL (1 << 0)
-#define AUOK190X_RESET_PON (1 << 1)
-
-/*
- * AUOK190X_CMD_VERSION
- */
-
-#define AUOK190X_VERSION_TEMP_MASK (0x1ff)
-#define AUOK190X_VERSION_EPD_MASK (0xff)
-#define AUOK190X_VERSION_SIZE_INT(_val) ((_val & 0xfc00) >> 10)
-#define AUOK190X_VERSION_SIZE_FLOAT(_val) ((_val & 0x3c0) >> 6)
-#define AUOK190X_VERSION_MODEL(_val) (_val & 0x3f)
-#define AUOK190X_VERSION_LUT(_val) (_val & 0xff)
-#define AUOK190X_VERSION_TCON(_val) ((_val & 0xff00) >> 8)
-
-/*
- * update modes for CMD_PARTIALDISP on K1900 and CMD_DDMA on K1901
- */
-
-#define AUOK190X_UPDATE_MODE(_res) ((_res & 0x7) << 12)
-#define AUOK190X_UPDATE_NONFLASH (1 << 15)
-
-/*
- * track panel specific parameters for common init
- */
-
-struct auok190x_init_data {
- char *id;
- struct auok190x_board *board;
-
- void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2);
- void (*update_all)(struct auok190xfb_par *par);
- bool (*need_refresh)(struct auok190xfb_par *par);
- void (*init)(struct auok190xfb_par *par);
-};
-
-
-extern void auok190x_send_command_nowait(struct auok190xfb_par *par, u16 data);
-extern int auok190x_send_command(struct auok190xfb_par *par, u16 data);
-extern void auok190x_send_cmdargs_nowait(struct auok190xfb_par *par, u16 cmd,
- int argc, u16 *argv);
-extern int auok190x_send_cmdargs(struct auok190xfb_par *par, u16 cmd,
- int argc, u16 *argv);
-extern void auok190x_send_cmdargs_pixels_nowait(struct auok190xfb_par *par,
- u16 cmd, int argc, u16 *argv,
- int size, u16 *data);
-extern int auok190x_send_cmdargs_pixels(struct auok190xfb_par *par, u16 cmd,
- int argc, u16 *argv, int size,
- u16 *data);
-extern int auok190x_read_cmdargs(struct auok190xfb_par *par, u16 cmd,
- int argc, u16 *argv);
-
-extern int auok190x_common_probe(struct platform_device *pdev,
- struct auok190x_init_data *init);
-extern int auok190x_common_remove(struct platform_device *pdev);
-
-extern const struct dev_pm_ops auok190x_pm;
diff --git a/drivers/video/fbdev/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c
index 9f9a7be..d6ba348 100644
--- a/drivers/video/fbdev/broadsheetfb.c
+++ b/drivers/video/fbdev/broadsheetfb.c
@@ -617,7 +617,7 @@ static int broadsheet_spiflash_rewrite_sector(struct broadsheetfb_par *par,
int tail_start_addr;
int start_sector_addr;
- sector_buffer = kzalloc(sizeof(char)*sector_size, GFP_KERNEL);
+ sector_buffer = kzalloc(sector_size, GFP_KERNEL);
if (!sector_buffer)
return -ENOMEM;
diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c
index 790900d..ca935c0 100644
--- a/drivers/video/fbdev/core/bitblit.c
+++ b/drivers/video/fbdev/core/bitblit.c
@@ -269,7 +269,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
if (attribute) {
u8 *dst;
- dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC);
+ dst = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
if (!dst)
return;
kfree(ops->cursor_data);
@@ -312,7 +312,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode,
vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
- char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
+ char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
int cur_height, size, i = 0;
u8 msk = 0xff;
diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c
index 487d5e3..82c20c6 100644
--- a/drivers/video/fbdev/core/fb_defio.c
+++ b/drivers/video/fbdev/core/fb_defio.c
@@ -37,7 +37,7 @@ static struct page *fb_deferred_io_page(struct fb_info *info, unsigned long offs
}
/* this is to find and return the vmalloc-ed fb pages */
-static int fb_deferred_io_fault(struct vm_fault *vmf)
+static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf)
{
unsigned long offset;
struct page *page;
@@ -90,7 +90,7 @@ int fb_deferred_io_fsync(struct file *file, loff_t start, loff_t end, int datasy
EXPORT_SYMBOL_GPL(fb_deferred_io_fsync);
/* vm_ops->page_mkwrite handler */
-static int fb_deferred_io_mkwrite(struct vm_fault *vmf)
+static vm_fault_t fb_deferred_io_mkwrite(struct vm_fault *vmf)
{
struct page *page = vmf->page;
struct fb_info *info = vmf->vma->vm_private_data;
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 3e330e0..c910e74 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -591,7 +591,8 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info,
if (scr_readw(r) != vc->vc_video_erase_char)
break;
if (r != q && new_rows >= rows + logo_lines) {
- save = kmalloc(logo_lines * new_cols * 2, GFP_KERNEL);
+ save = kmalloc(array3_size(logo_lines, new_cols, 2),
+ GFP_KERNEL);
if (save) {
int i = cols < new_cols ? cols : new_cols;
scr_memsetw(save, erase, logo_lines * new_cols * 2);
diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c
index 37a8b0b2..dfa9a8a 100644
--- a/drivers/video/fbdev/core/fbcon_ccw.c
+++ b/drivers/video/fbdev/core/fbcon_ccw.c
@@ -258,7 +258,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
if (attribute) {
u8 *dst;
- dst = kmalloc(w * vc->vc_font.width, GFP_ATOMIC);
+ dst = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC);
if (!dst)
return;
kfree(ops->cursor_data);
@@ -304,14 +304,15 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
- char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC);
+ char *tmp, *mask = kmalloc_array(w, vc->vc_font.width,
+ GFP_ATOMIC);
int cur_height, size, i = 0;
int width = (vc->vc_font.width + 7)/8;
if (!mask)
return;
- tmp = kmalloc(width * vc->vc_font.height, GFP_ATOMIC);
+ tmp = kmalloc_array(width, vc->vc_font.height, GFP_ATOMIC);
if (!tmp) {
kfree(mask);
diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c
index 1888f8c..ce08251 100644
--- a/drivers/video/fbdev/core/fbcon_cw.c
+++ b/drivers/video/fbdev/core/fbcon_cw.c
@@ -241,7 +241,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
if (attribute) {
u8 *dst;
- dst = kmalloc(w * vc->vc_font.width, GFP_ATOMIC);
+ dst = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC);
if (!dst)
return;
kfree(ops->cursor_data);
@@ -287,14 +287,15 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode,
vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
- char *tmp, *mask = kmalloc(w*vc->vc_font.width, GFP_ATOMIC);
+ char *tmp, *mask = kmalloc_array(w, vc->vc_font.width,
+ GFP_ATOMIC);
int cur_height, size, i = 0;
int width = (vc->vc_font.width + 7)/8;
if (!mask)
return;
- tmp = kmalloc(width * vc->vc_font.height, GFP_ATOMIC);
+ tmp = kmalloc_array(width, vc->vc_font.height, GFP_ATOMIC);
if (!tmp) {
kfree(mask);
diff --git a/drivers/video/fbdev/core/fbcon_rotate.c b/drivers/video/fbdev/core/fbcon_rotate.c
index 8a51e4d..c0d4452 100644
--- a/drivers/video/fbdev/core/fbcon_rotate.c
+++ b/drivers/video/fbdev/core/fbcon_rotate.c
@@ -46,7 +46,7 @@ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
info->fbops->fb_sync(info);
if (ops->fd_size < d_cellsize * len) {
- dst = kmalloc(d_cellsize * len, GFP_KERNEL);
+ dst = kmalloc_array(len, d_cellsize, GFP_KERNEL);
if (dst == NULL) {
err = -ENOMEM;
diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c
index f98eee2..1936afc 100644
--- a/drivers/video/fbdev/core/fbcon_ud.c
+++ b/drivers/video/fbdev/core/fbcon_ud.c
@@ -289,7 +289,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
if (attribute) {
u8 *dst;
- dst = kmalloc(w * vc->vc_font.height, GFP_ATOMIC);
+ dst = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
if (!dst)
return;
kfree(ops->cursor_data);
@@ -335,7 +335,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode,
vc->vc_cursor_type != ops->p->cursor_shape ||
ops->cursor_state.mask == NULL ||
ops->cursor_reset) {
- char *mask = kmalloc(w*vc->vc_font.height, GFP_ATOMIC);
+ char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
int cur_height, size, i = 0;
u8 msk = 0xff;
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 924d073..609438d 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -489,7 +489,8 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
}
if (fb_logo.depth <= 4) {
- logo_new = kmalloc(logo->width * logo->height, GFP_KERNEL);
+ logo_new = kmalloc_array(logo->width, logo->height,
+ GFP_KERNEL);
if (logo_new == NULL) {
kfree(palette);
if (saved_pseudo_palette)
@@ -506,8 +507,8 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
image.height = logo->height;
if (rotate) {
- logo_rotate = kmalloc(logo->width *
- logo->height, GFP_KERNEL);
+ logo_rotate = kmalloc_array(logo->width, logo->height,
+ GFP_KERNEL);
if (logo_rotate)
fb_rotate_logo(info, logo_rotate, &image, rotate);
}
diff --git a/drivers/video/fbdev/core/fbmon.c b/drivers/video/fbdev/core/fbmon.c
index 2b2d673..852d86c 100644
--- a/drivers/video/fbdev/core/fbmon.c
+++ b/drivers/video/fbdev/core/fbmon.c
@@ -620,7 +620,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize,
int num = 0, i, first = 1;
int ver, rev;
- mode = kzalloc(50 * sizeof(struct fb_videomode), GFP_KERNEL);
+ mode = kcalloc(50, sizeof(struct fb_videomode), GFP_KERNEL);
if (mode == NULL)
return NULL;
@@ -671,7 +671,7 @@ static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize,
}
*dbsize = num;
- m = kmalloc(num * sizeof(struct fb_videomode), GFP_KERNEL);
+ m = kmalloc_array(num, sizeof(struct fb_videomode), GFP_KERNEL);
if (!m)
return mode;
memmove(m, mode, num * sizeof(struct fb_videomode));
@@ -1055,8 +1055,9 @@ void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
if (!(num + svd_n))
return;
- m = kzalloc((specs->modedb_len + num + svd_n) *
- sizeof(struct fb_videomode), GFP_KERNEL);
+ m = kcalloc(specs->modedb_len + num + svd_n,
+ sizeof(struct fb_videomode),
+ GFP_KERNEL);
if (!m)
return;
diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c
index ba82f97..c4eb866 100644
--- a/drivers/video/fbdev/imxfb.c
+++ b/drivers/video/fbdev/imxfb.c
@@ -662,7 +662,7 @@ static int imxfb_init_fbinfo(struct platform_device *pdev)
pr_debug("%s\n",__func__);
- info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
+ info->pseudo_palette = kmalloc_array(16, sizeof(u32), GFP_KERNEL);
if (!info->pseudo_palette)
return -ENOMEM;
diff --git a/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
index fe92eed..8dd296d 100644
--- a/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
+++ b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
@@ -245,7 +245,7 @@ static void mb86290fb_imageblit(struct fb_info *info,
return;
}
- cmd = kmalloc(cmdlen * 4, GFP_DMA);
+ cmd = kmalloc_array(cmdlen, 4, GFP_DMA);
if (!cmd)
return cfb_imageblit(info, image);
cmdfn(cmd, step, dx, dy, width, height, fgcolor, bgcolor, image, info);
diff --git a/drivers/video/fbdev/mmp/fb/mmpfb.c b/drivers/video/fbdev/mmp/fb/mmpfb.c
index 92279e0..ee212be 100644
--- a/drivers/video/fbdev/mmp/fb/mmpfb.c
+++ b/drivers/video/fbdev/mmp/fb/mmpfb.c
@@ -493,12 +493,11 @@ static int modes_setup(struct mmpfb_info *fbi)
return 0;
}
/* put videomode list to info structure */
- videomodes = kzalloc(sizeof(struct fb_videomode) * videomode_num,
- GFP_KERNEL);
- if (!videomodes) {
- dev_err(fbi->dev, "can't malloc video modes\n");
+ videomodes = kcalloc(videomode_num, sizeof(struct fb_videomode),
+ GFP_KERNEL);
+ if (!videomodes)
return -ENOMEM;
- }
+
for (i = 0; i < videomode_num; i++)
mmpmode_to_fbmode(&videomodes[i], &mmp_modes[i]);
fb_videomode_to_modelist(videomodes, videomode_num, &info->modelist);
diff --git a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
index b6f83d5..fcdbb2d 100644
--- a/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
+++ b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c
@@ -406,12 +406,10 @@ static int path_init(struct mmphw_path_plat *path_plat,
dev_info(ctrl->dev, "%s: %s\n", __func__, config->name);
/* init driver data */
- path_info = kzalloc(sizeof(struct mmp_path_info), GFP_KERNEL);
- if (!path_info) {
- dev_err(ctrl->dev, "%s: unable to alloc path_info for %s\n",
- __func__, config->name);
+ path_info = kzalloc(sizeof(*path_info), GFP_KERNEL);
+ if (!path_info)
return 0;
- }
+
path_info->name = config->name;
path_info->id = path_plat->id;
path_info->dev = ctrl->dev;
diff --git a/drivers/video/fbdev/mxsfb.c b/drivers/video/fbdev/mxsfb.c
index 246bea3..12c8bd1 100644
--- a/drivers/video/fbdev/mxsfb.c
+++ b/drivers/video/fbdev/mxsfb.c
@@ -931,7 +931,7 @@ static int mxsfb_probe(struct platform_device *pdev)
if (IS_ERR(host->reg_lcd))
host->reg_lcd = NULL;
- fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,
+ fb_info->pseudo_palette = devm_kcalloc(&pdev->dev, 16, sizeof(u32),
GFP_KERNEL);
if (!fb_info->pseudo_palette) {
ret = -ENOMEM;
diff --git a/drivers/video/fbdev/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c
index 418a2d0..fbeeed5 100644
--- a/drivers/video/fbdev/nvidia/nvidia.c
+++ b/drivers/video/fbdev/nvidia/nvidia.c
@@ -566,7 +566,7 @@ static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
u8 *msk = (u8 *) cursor->mask;
u8 *src;
- src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
+ src = kmalloc_array(s_pitch, cursor->image.height, GFP_ATOMIC);
if (src) {
switch (cursor->rop) {
@@ -1548,7 +1548,7 @@ MODULE_PARM_DESC(noaccel,
"(default=0)");
module_param(noscale, int, 0);
MODULE_PARM_DESC(noscale,
- "Disables screen scaleing. (0 or 1=disable) "
+ "Disables screen scaling. (0 or 1=disable) "
"(default=0, do scaling)");
module_param(paneltweak, int, 0);
MODULE_PARM_DESC(paneltweak,
diff --git a/drivers/video/fbdev/omap/lcd_ams_delta.c b/drivers/video/fbdev/omap/lcd_ams_delta.c
index a4ee947..e8c748a 100644
--- a/drivers/video/fbdev/omap/lcd_ams_delta.c
+++ b/drivers/video/fbdev/omap/lcd_ams_delta.c
@@ -197,3 +197,7 @@ static struct platform_driver ams_delta_panel_driver = {
};
module_platform_driver(ams_delta_panel_driver);
+
+MODULE_AUTHOR("Jonathan McDowell <noodles@earth.li>");
+MODULE_DESCRIPTION("LCD panel support for the Amstrad E3 (Delta) videophone");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap/lcd_h3.c b/drivers/video/fbdev/omap/lcd_h3.c
index 796f463..fd0ac99 100644
--- a/drivers/video/fbdev/omap/lcd_h3.c
+++ b/drivers/video/fbdev/omap/lcd_h3.c
@@ -89,3 +89,7 @@ static struct platform_driver h3_panel_driver = {
};
module_platform_driver(h3_panel_driver);
+
+MODULE_AUTHOR("Imre Deak");
+MODULE_DESCRIPTION("LCD panel support for the TI OMAP H3 board");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap/lcd_htcherald.c b/drivers/video/fbdev/omap/lcd_htcherald.c
index 9d692f5b..db4ff1c 100644
--- a/drivers/video/fbdev/omap/lcd_htcherald.c
+++ b/drivers/video/fbdev/omap/lcd_htcherald.c
@@ -66,3 +66,7 @@ static struct platform_driver htcherald_panel_driver = {
};
module_platform_driver(htcherald_panel_driver);
+
+MODULE_AUTHOR("Cory Maccarrone");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LCD panel support for the HTC Herald");
diff --git a/drivers/video/fbdev/omap/lcd_inn1510.c b/drivers/video/fbdev/omap/lcd_inn1510.c
index b284050..1ea775f 100644
--- a/drivers/video/fbdev/omap/lcd_inn1510.c
+++ b/drivers/video/fbdev/omap/lcd_inn1510.c
@@ -73,3 +73,7 @@ static struct platform_driver innovator1510_panel_driver = {
};
module_platform_driver(innovator1510_panel_driver);
+
+MODULE_AUTHOR("Imre Deak");
+MODULE_DESCRIPTION("LCD panel support for the TI OMAP1510 Innovator board");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap/lcd_inn1610.c b/drivers/video/fbdev/omap/lcd_inn1610.c
index 1841710..8d0cf68 100644
--- a/drivers/video/fbdev/omap/lcd_inn1610.c
+++ b/drivers/video/fbdev/omap/lcd_inn1610.c
@@ -106,3 +106,7 @@ static struct platform_driver innovator1610_panel_driver = {
};
module_platform_driver(innovator1610_panel_driver);
+
+MODULE_AUTHOR("Imre Deak");
+MODULE_DESCRIPTION("LCD panel support for the TI OMAP1610 Innovator board");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap/lcd_osk.c b/drivers/video/fbdev/omap/lcd_osk.c
index b0be577..9fc43a1 100644
--- a/drivers/video/fbdev/omap/lcd_osk.c
+++ b/drivers/video/fbdev/omap/lcd_osk.c
@@ -93,3 +93,7 @@ static struct platform_driver osk_panel_driver = {
};
module_platform_driver(osk_panel_driver);
+
+MODULE_AUTHOR("Imre Deak");
+MODULE_DESCRIPTION("LCD panel support for the TI OMAP OSK board");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap/lcd_palmte.c b/drivers/video/fbdev/omap/lcd_palmte.c
index cef9638..a0e8886 100644
--- a/drivers/video/fbdev/omap/lcd_palmte.c
+++ b/drivers/video/fbdev/omap/lcd_palmte.c
@@ -59,3 +59,7 @@ static struct platform_driver palmte_panel_driver = {
};
module_platform_driver(palmte_panel_driver);
+
+MODULE_AUTHOR("Romain Goyet <r.goyet@gmail.com>, Laurent Gonzalez <palmte.linux@free.fr>");
+MODULE_DESCRIPTION("LCD panel support for the Palm Tungsten E");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap/lcd_palmtt.c b/drivers/video/fbdev/omap/lcd_palmtt.c
index 627f13d..2c45375 100644
--- a/drivers/video/fbdev/omap/lcd_palmtt.c
+++ b/drivers/video/fbdev/omap/lcd_palmtt.c
@@ -72,3 +72,7 @@ static struct platform_driver palmtt_panel_driver = {
};
module_platform_driver(palmtt_panel_driver);
+
+MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
+MODULE_DESCRIPTION("LCD panel support for Palm Tungsten|T");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/omap/lcd_palmz71.c b/drivers/video/fbdev/omap/lcd_palmz71.c
index c46d4db..c99a15a 100644
--- a/drivers/video/fbdev/omap/lcd_palmz71.c
+++ b/drivers/video/fbdev/omap/lcd_palmz71.c
@@ -66,3 +66,7 @@ static struct platform_driver palmz71_panel_driver = {
};
module_platform_driver(palmz71_panel_driver);
+
+MODULE_AUTHOR("Romain Goyet, Laurent Gonzalez, Marek Vasut");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LCD panel support for the Palm Zire71");
diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c
index 3479a47..585f39e 100644
--- a/drivers/video/fbdev/omap/omapfb_main.c
+++ b/drivers/video/fbdev/omap/omapfb_main.c
@@ -1645,7 +1645,7 @@ static int omapfb_do_probe(struct platform_device *pdev,
goto cleanup;
}
- fbdev = kzalloc(sizeof(struct omapfb_device), GFP_KERNEL);
+ fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
if (fbdev == NULL) {
dev_err(&pdev->dev,
"unable to allocate memory for device info\n");
diff --git a/drivers/video/fbdev/omap2/omapfb/Kconfig b/drivers/video/fbdev/omap2/omapfb/Kconfig
index e6226ae..3bf154e 100644
--- a/drivers/video/fbdev/omap2/omapfb/Kconfig
+++ b/drivers/video/fbdev/omap2/omapfb/Kconfig
@@ -5,6 +5,7 @@ menuconfig FB_OMAP2
tristate "OMAP2+ frame buffer support"
depends on FB
depends on DRM_OMAP = n
+ depends on GPIOLIB
select FB_OMAP2_DSS
select OMAP2_VRFB if ARCH_OMAP2 || ARCH_OMAP3
diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
index bef4315..87497a0 100644
--- a/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
+++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
@@ -387,8 +387,7 @@ static void dsicm_get_resolution(struct omap_dss_device *dssdev,
static ssize_t dsicm_num_errors_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+ struct panel_drv_data *ddata = dev_get_drvdata(dev);
struct omap_dss_device *in = ddata->in;
u8 errors = 0;
int r;
@@ -419,8 +418,7 @@ static ssize_t dsicm_num_errors_show(struct device *dev,
static ssize_t dsicm_hw_revision_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+ struct panel_drv_data *ddata = dev_get_drvdata(dev);
struct omap_dss_device *in = ddata->in;
u8 id1, id2, id3;
int r;
@@ -451,8 +449,7 @@ static ssize_t dsicm_store_ulps(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+ struct panel_drv_data *ddata = dev_get_drvdata(dev);
struct omap_dss_device *in = ddata->in;
unsigned long t;
int r;
@@ -486,8 +483,7 @@ static ssize_t dsicm_show_ulps(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+ struct panel_drv_data *ddata = dev_get_drvdata(dev);
unsigned t;
mutex_lock(&ddata->lock);
@@ -501,8 +497,7 @@ static ssize_t dsicm_store_ulps_timeout(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+ struct panel_drv_data *ddata = dev_get_drvdata(dev);
struct omap_dss_device *in = ddata->in;
unsigned long t;
int r;
@@ -533,8 +528,7 @@ static ssize_t dsicm_show_ulps_timeout(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct panel_drv_data *ddata = platform_get_drvdata(pdev);
+ struct panel_drv_data *ddata = dev_get_drvdata(dev);
unsigned t;
mutex_lock(&ddata->lock);
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/manager.c b/drivers/video/fbdev/omap2/omapfb/dss/manager.c
index 69f86d2..d21c641 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/manager.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/manager.c
@@ -42,8 +42,8 @@ int dss_init_overlay_managers(void)
num_managers = dss_feat_get_num_mgrs();
- managers = kzalloc(sizeof(struct omap_overlay_manager) * num_managers,
- GFP_KERNEL);
+ managers = kcalloc(num_managers, sizeof(struct omap_overlay_manager),
+ GFP_KERNEL);
BUG_ON(managers == NULL);
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/overlay.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay.c
index d6c5d75..be17a47 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/overlay.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay.c
@@ -59,8 +59,8 @@ void dss_init_overlays(struct platform_device *pdev)
num_overlays = dss_feat_get_num_ovls();
- overlays = kzalloc(sizeof(struct omap_overlay) * num_overlays,
- GFP_KERNEL);
+ overlays = kcalloc(num_overlays, sizeof(struct omap_overlay),
+ GFP_KERNEL);
BUG_ON(overlays == NULL);
diff --git a/drivers/video/fbdev/omap2/omapfb/vrfb.c b/drivers/video/fbdev/omap2/omapfb/vrfb.c
index f346b02..f355ecf 100644
--- a/drivers/video/fbdev/omap2/omapfb/vrfb.c
+++ b/drivers/video/fbdev/omap2/omapfb/vrfb.c
@@ -359,8 +359,8 @@ static int __init vrfb_probe(struct platform_device *pdev)
num_ctxs = pdev->num_resources - 1;
- ctxs = devm_kzalloc(&pdev->dev,
- sizeof(struct vrfb_ctx) * num_ctxs,
+ ctxs = devm_kcalloc(&pdev->dev,
+ num_ctxs, sizeof(struct vrfb_ctx),
GFP_KERNEL);
if (!ctxs)
diff --git a/drivers/video/fbdev/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c
index a582d3a..8a53d1d 100644
--- a/drivers/video/fbdev/pvr2fb.c
+++ b/drivers/video/fbdev/pvr2fb.c
@@ -682,7 +682,7 @@ static ssize_t pvr2fb_write(struct fb_info *info, const char *buf,
nr_pages = (count + PAGE_SIZE - 1) >> PAGE_SHIFT;
- pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+ pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL);
if (!pages)
return -ENOMEM;
diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c
index c3d49e1..76722a5 100644
--- a/drivers/video/fbdev/pxafb.c
+++ b/drivers/video/fbdev/pxafb.c
@@ -2115,12 +2115,10 @@ static int of_get_pxafb_display(struct device *dev, struct device_node *disp,
if (ret)
s = "color-tft";
- for (i = 0; lcd_types[i]; i++)
- if (!strcmp(s, lcd_types[i]))
- break;
- if (!i || !lcd_types[i]) {
+ i = match_string(lcd_types, -1, s);
+ if (i < 0) {
dev_err(dev, "lcd-type %s is unknown\n", s);
- return -EINVAL;
+ return i;
}
info->lcd_conn |= LCD_CONN_TYPE(i);
info->lcd_conn |= LCD_CONN_WIDTH(bus_width);
diff --git a/drivers/video/fbdev/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c
index ff82823..cc242ba 100644
--- a/drivers/video/fbdev/riva/fbdev.c
+++ b/drivers/video/fbdev/riva/fbdev.c
@@ -1615,7 +1615,7 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
u8 *msk = (u8 *) cursor->mask;
u8 *src;
- src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
+ src = kmalloc_array(s_pitch, cursor->image.height, GFP_ATOMIC);
if (src) {
switch (cursor->rop) {
diff --git a/drivers/video/fbdev/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c
index c204683..c09d742 100644
--- a/drivers/video/fbdev/savage/savagefb_driver.c
+++ b/drivers/video/fbdev/savage/savagefb_driver.c
@@ -1892,11 +1892,11 @@ static int savage_init_hw(struct savagefb_par *par)
vga_out8(0x3d4, 0x66, par);
cr66 = vga_in8(0x3d5, par);
vga_out8(0x3d5, cr66 | 0x02, par);
- mdelay(10);
+ usleep_range(10000, 11000);
vga_out8(0x3d4, 0x66, par);
vga_out8(0x3d5, cr66 & ~0x02, par); /* clear reset flag */
- mdelay(10);
+ usleep_range(10000, 11000);
/*
@@ -1906,11 +1906,11 @@ static int savage_init_hw(struct savagefb_par *par)
vga_out8(0x3d4, 0x3f, par);
cr3f = vga_in8(0x3d5, par);
vga_out8(0x3d5, cr3f | 0x08, par);
- mdelay(10);
+ usleep_range(10000, 11000);
vga_out8(0x3d4, 0x3f, par);
vga_out8(0x3d5, cr3f & ~0x08, par); /* clear reset flags */
- mdelay(10);
+ usleep_range(10000, 11000);
/* Savage ramdac speeds */
par->numClocks = 4;
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c
index c3a4650..dc46be3 100644
--- a/drivers/video/fbdev/sh_mobile_lcdcfb.c
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.c
@@ -29,7 +29,6 @@
#include <linux/vmalloc.h>
#include <video/sh_mobile_lcdc.h>
-#include <video/sh_mobile_meram.h>
#include "sh_mobile_lcdcfb.h"
@@ -217,7 +216,6 @@ struct sh_mobile_lcdc_priv {
struct notifier_block notifier;
int started;
int forced_fourcc; /* 2 channel LCDC must share fourcc setting */
- struct sh_mobile_meram_info *meram_dev;
};
/* -----------------------------------------------------------------------------
@@ -346,16 +344,12 @@ static void sh_mobile_lcdc_clk_on(struct sh_mobile_lcdc_priv *priv)
if (priv->dot_clk)
clk_prepare_enable(priv->dot_clk);
pm_runtime_get_sync(priv->dev);
- if (priv->meram_dev && priv->meram_dev->pdev)
- pm_runtime_get_sync(&priv->meram_dev->pdev->dev);
}
}
static void sh_mobile_lcdc_clk_off(struct sh_mobile_lcdc_priv *priv)
{
if (atomic_sub_return(1, &priv->hw_usecnt) == -1) {
- if (priv->meram_dev && priv->meram_dev->pdev)
- pm_runtime_put_sync(&priv->meram_dev->pdev->dev);
pm_runtime_put(priv->dev);
if (priv->dot_clk)
clk_disable_unprepare(priv->dot_clk);
@@ -1073,7 +1067,6 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
{
- struct sh_mobile_meram_info *mdev = priv->meram_dev;
struct sh_mobile_lcdc_chan *ch;
unsigned long tmp;
int ret;
@@ -1106,9 +1099,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
/* Compute frame buffer base address and pitch for each channel. */
for (k = 0; k < ARRAY_SIZE(priv->ch); k++) {
- int pixelformat;
- void *cache;
-
ch = &priv->ch[k];
if (!ch->enabled)
continue;
@@ -1117,45 +1107,6 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv)
ch->base_addr_c = ch->dma_handle
+ ch->xres_virtual * ch->yres_virtual;
ch->line_size = ch->pitch;
-
- /* Enable MERAM if possible. */
- if (mdev == NULL || ch->cfg->meram_cfg == NULL)
- continue;
-
- /* Free the allocated MERAM cache. */
- if (ch->cache) {
- sh_mobile_meram_cache_free(mdev, ch->cache);
- ch->cache = NULL;
- }
-
- switch (ch->format->fourcc) {
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_NV21:
- case V4L2_PIX_FMT_NV16:
- case V4L2_PIX_FMT_NV61:
- pixelformat = SH_MOBILE_MERAM_PF_NV;
- break;
- case V4L2_PIX_FMT_NV24:
- case V4L2_PIX_FMT_NV42:
- pixelformat = SH_MOBILE_MERAM_PF_NV24;
- break;
- case V4L2_PIX_FMT_RGB565:
- case V4L2_PIX_FMT_BGR24:
- case V4L2_PIX_FMT_BGR32:
- default:
- pixelformat = SH_MOBILE_MERAM_PF_RGB;
- break;
- }
-
- cache = sh_mobile_meram_cache_alloc(mdev, ch->cfg->meram_cfg,
- ch->pitch, ch->yres, pixelformat,
- &ch->line_size);
- if (!IS_ERR(cache)) {
- sh_mobile_meram_cache_update(mdev, cache,
- ch->base_addr_y, ch->base_addr_c,
- &ch->base_addr_y, &ch->base_addr_c);
- ch->cache = cache;
- }
}
for (k = 0; k < ARRAY_SIZE(priv->overlays); ++k) {
@@ -1223,13 +1174,6 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv)
}
sh_mobile_lcdc_display_off(ch);
-
- /* Free the MERAM cache. */
- if (ch->cache) {
- sh_mobile_meram_cache_free(priv->meram_dev, ch->cache);
- ch->cache = NULL;
- }
-
}
/* stop the lcdc */
@@ -1851,11 +1795,6 @@ static int sh_mobile_lcdc_pan(struct fb_var_screeninfo *var,
base_addr_c = ch->dma_handle + ch->xres_virtual * ch->yres_virtual
+ c_offset;
- if (ch->cache)
- sh_mobile_meram_cache_update(priv->meram_dev, ch->cache,
- base_addr_y, base_addr_c,
- &base_addr_y, &base_addr_c);
-
ch->base_addr_y = base_addr_y;
ch->base_addr_c = base_addr_c;
ch->pan_y_offset = y_offset;
@@ -2149,10 +2088,8 @@ sh_mobile_lcdc_channel_fb_register(struct sh_mobile_lcdc_chan *ch)
if (info->fbdefio) {
ch->sglist = vmalloc(sizeof(struct scatterlist) *
ch->fb_size >> PAGE_SHIFT);
- if (!ch->sglist) {
- dev_err(ch->lcdc->dev, "cannot allocate sglist\n");
+ if (!ch->sglist)
return -ENOMEM;
- }
}
info->bl_dev = ch->bl;
@@ -2354,8 +2291,7 @@ static int sh_mobile_lcdc_resume(struct device *dev)
static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
+ struct sh_mobile_lcdc_priv *priv = dev_get_drvdata(dev);
/* turn off LCDC hardware */
lcdc_write(priv, _LDCNT1R, 0);
@@ -2365,8 +2301,7 @@ static int sh_mobile_lcdc_runtime_suspend(struct device *dev)
static int sh_mobile_lcdc_runtime_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct sh_mobile_lcdc_priv *priv = platform_get_drvdata(pdev);
+ struct sh_mobile_lcdc_priv *priv = dev_get_drvdata(dev);
__sh_mobile_lcdc_start(priv);
@@ -2718,13 +2653,11 @@ static int sh_mobile_lcdc_probe(struct platform_device *pdev)
}
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(&pdev->dev, "cannot allocate device data\n");
+ if (!priv)
return -ENOMEM;
- }
priv->dev = &pdev->dev;
- priv->meram_dev = pdata->meram_dev;
+
for (i = 0; i < ARRAY_SIZE(priv->ch); i++)
mutex_init(&priv->ch[i].open_lock);
platform_set_drvdata(pdev, priv);
diff --git a/drivers/video/fbdev/sh_mobile_lcdcfb.h b/drivers/video/fbdev/sh_mobile_lcdcfb.h
index cc52c74..b8e47a8 100644
--- a/drivers/video/fbdev/sh_mobile_lcdcfb.h
+++ b/drivers/video/fbdev/sh_mobile_lcdcfb.h
@@ -61,7 +61,6 @@ struct sh_mobile_lcdc_chan {
unsigned long *reg_offs;
unsigned long ldmt1r_value;
unsigned long enabled; /* ME and SE in LDCNT2R */
- void *cache;
struct mutex open_lock; /* protects the use counter */
int use_count;
diff --git a/drivers/video/fbdev/sh_mobile_meram.c b/drivers/video/fbdev/sh_mobile_meram.c
deleted file mode 100644
index baadfb2..0000000
--- a/drivers/video/fbdev/sh_mobile_meram.c
+++ /dev/null
@@ -1,758 +0,0 @@
-/*
- * SuperH Mobile MERAM Driver for SuperH Mobile LCDC Driver
- *
- * Copyright (c) 2011 Damian Hobson-Garcia <dhobsong@igel.co.jp>
- * Takanari Hayama <taki@igel.co.jp>
- *
- * 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/device.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/genalloc.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/slab.h>
-
-#include <video/sh_mobile_meram.h>
-
-/* -----------------------------------------------------------------------------
- * MERAM registers
- */
-
-#define MEVCR1 0x4
-#define MEVCR1_RST (1 << 31)
-#define MEVCR1_WD (1 << 30)
-#define MEVCR1_AMD1 (1 << 29)
-#define MEVCR1_AMD0 (1 << 28)
-#define MEQSEL1 0x40
-#define MEQSEL2 0x44
-
-#define MExxCTL 0x400
-#define MExxCTL_BV (1 << 31)
-#define MExxCTL_BSZ_SHIFT 28
-#define MExxCTL_MSAR_MASK (0x7ff << MExxCTL_MSAR_SHIFT)
-#define MExxCTL_MSAR_SHIFT 16
-#define MExxCTL_NXT_MASK (0x1f << MExxCTL_NXT_SHIFT)
-#define MExxCTL_NXT_SHIFT 11
-#define MExxCTL_WD1 (1 << 10)
-#define MExxCTL_WD0 (1 << 9)
-#define MExxCTL_WS (1 << 8)
-#define MExxCTL_CB (1 << 7)
-#define MExxCTL_WBF (1 << 6)
-#define MExxCTL_WF (1 << 5)
-#define MExxCTL_RF (1 << 4)
-#define MExxCTL_CM (1 << 3)
-#define MExxCTL_MD_READ (1 << 0)
-#define MExxCTL_MD_WRITE (2 << 0)
-#define MExxCTL_MD_ICB_WB (3 << 0)
-#define MExxCTL_MD_ICB (4 << 0)
-#define MExxCTL_MD_FB (7 << 0)
-#define MExxCTL_MD_MASK (7 << 0)
-#define MExxBSIZE 0x404
-#define MExxBSIZE_RCNT_SHIFT 28
-#define MExxBSIZE_YSZM1_SHIFT 16
-#define MExxBSIZE_XSZM1_SHIFT 0
-#define MExxMNCF 0x408
-#define MExxMNCF_KWBNM_SHIFT 28
-#define MExxMNCF_KRBNM_SHIFT 24
-#define MExxMNCF_BNM_SHIFT 16
-#define MExxMNCF_XBV (1 << 15)
-#define MExxMNCF_CPL_YCBCR444 (1 << 12)
-#define MExxMNCF_CPL_YCBCR420 (2 << 12)
-#define MExxMNCF_CPL_YCBCR422 (3 << 12)
-#define MExxMNCF_CPL_MSK (3 << 12)
-#define MExxMNCF_BL (1 << 2)
-#define MExxMNCF_LNM_SHIFT 0
-#define MExxSARA 0x410
-#define MExxSARB 0x414
-#define MExxSBSIZE 0x418
-#define MExxSBSIZE_HDV (1 << 31)
-#define MExxSBSIZE_HSZ16 (0 << 28)
-#define MExxSBSIZE_HSZ32 (1 << 28)
-#define MExxSBSIZE_HSZ64 (2 << 28)
-#define MExxSBSIZE_HSZ128 (3 << 28)
-#define MExxSBSIZE_SBSIZZ_SHIFT 0
-
-#define MERAM_MExxCTL_VAL(next, addr) \
- ((((next) << MExxCTL_NXT_SHIFT) & MExxCTL_NXT_MASK) | \
- (((addr) << MExxCTL_MSAR_SHIFT) & MExxCTL_MSAR_MASK))
-#define MERAM_MExxBSIZE_VAL(rcnt, yszm1, xszm1) \
- (((rcnt) << MExxBSIZE_RCNT_SHIFT) | \
- ((yszm1) << MExxBSIZE_YSZM1_SHIFT) | \
- ((xszm1) << MExxBSIZE_XSZM1_SHIFT))
-
-static const unsigned long common_regs[] = {
- MEVCR1,
- MEQSEL1,
- MEQSEL2,
-};
-#define MERAM_REGS_SIZE ARRAY_SIZE(common_regs)
-
-static const unsigned long icb_regs[] = {
- MExxCTL,
- MExxBSIZE,
- MExxMNCF,
- MExxSARA,
- MExxSARB,
- MExxSBSIZE,
-};
-#define ICB_REGS_SIZE ARRAY_SIZE(icb_regs)
-
-/*
- * sh_mobile_meram_icb - MERAM ICB information
- * @regs: Registers cache
- * @index: ICB index
- * @offset: MERAM block offset
- * @size: MERAM block size in KiB
- * @cache_unit: Bytes to cache per ICB
- * @pixelformat: Video pixel format of the data stored in the ICB
- * @current_reg: Which of Start Address Register A (0) or B (1) is in use
- */
-struct sh_mobile_meram_icb {
- unsigned long regs[ICB_REGS_SIZE];
- unsigned int index;
- unsigned long offset;
- unsigned int size;
-
- unsigned int cache_unit;
- unsigned int pixelformat;
- unsigned int current_reg;
-};
-
-#define MERAM_ICB_NUM 32
-
-struct sh_mobile_meram_fb_plane {
- struct sh_mobile_meram_icb *marker;
- struct sh_mobile_meram_icb *cache;
-};
-
-struct sh_mobile_meram_fb_cache {
- unsigned int nplanes;
- struct sh_mobile_meram_fb_plane planes[2];
-};
-
-/*
- * sh_mobile_meram_priv - MERAM device
- * @base: Registers base address
- * @meram: MERAM physical address
- * @regs: Registers cache
- * @lock: Protects used_icb and icbs
- * @used_icb: Bitmask of used ICBs
- * @icbs: ICBs
- * @pool: Allocation pool to manage the MERAM
- */
-struct sh_mobile_meram_priv {
- void __iomem *base;
- unsigned long meram;
- unsigned long regs[MERAM_REGS_SIZE];
-
- struct mutex lock;
- unsigned long used_icb;
- struct sh_mobile_meram_icb icbs[MERAM_ICB_NUM];
-
- struct gen_pool *pool;
-};
-
-/* settings */
-#define MERAM_GRANULARITY 1024
-#define MERAM_SEC_LINE 15
-#define MERAM_LINE_WIDTH 2048
-
-/* -----------------------------------------------------------------------------
- * Registers access
- */
-
-#define MERAM_ICB_OFFSET(base, idx, off) ((base) + (off) + (idx) * 0x20)
-
-static inline void meram_write_icb(void __iomem *base, unsigned int idx,
- unsigned int off, unsigned long val)
-{
- iowrite32(val, MERAM_ICB_OFFSET(base, idx, off));
-}
-
-static inline unsigned long meram_read_icb(void __iomem *base, unsigned int idx,
- unsigned int off)
-{
- return ioread32(MERAM_ICB_OFFSET(base, idx, off));
-}
-
-static inline void meram_write_reg(void __iomem *base, unsigned int off,
- unsigned long val)
-{
- iowrite32(val, base + off);
-}
-
-static inline unsigned long meram_read_reg(void __iomem *base, unsigned int off)
-{
- return ioread32(base + off);
-}
-
-/* -----------------------------------------------------------------------------
- * MERAM allocation and free
- */
-
-static unsigned long meram_alloc(struct sh_mobile_meram_priv *priv, size_t size)
-{
- return gen_pool_alloc(priv->pool, size);
-}
-
-static void meram_free(struct sh_mobile_meram_priv *priv, unsigned long mem,
- size_t size)
-{
- gen_pool_free(priv->pool, mem, size);
-}
-
-/* -----------------------------------------------------------------------------
- * LCDC cache planes allocation, init, cleanup and free
- */
-
-/* Allocate ICBs and MERAM for a plane. */
-static int meram_plane_alloc(struct sh_mobile_meram_priv *priv,
- struct sh_mobile_meram_fb_plane *plane,
- size_t size)
-{
- unsigned long mem;
- unsigned long idx;
-
- idx = find_first_zero_bit(&priv->used_icb, 28);
- if (idx == 28)
- return -ENOMEM;
- plane->cache = &priv->icbs[idx];
-
- idx = find_next_zero_bit(&priv->used_icb, 32, 28);
- if (idx == 32)
- return -ENOMEM;
- plane->marker = &priv->icbs[idx];
-
- mem = meram_alloc(priv, size * 1024);
- if (mem == 0)
- return -ENOMEM;
-
- __set_bit(plane->marker->index, &priv->used_icb);
- __set_bit(plane->cache->index, &priv->used_icb);
-
- plane->marker->offset = mem - priv->meram;
- plane->marker->size = size;
-
- return 0;
-}
-
-/* Free ICBs and MERAM for a plane. */
-static void meram_plane_free(struct sh_mobile_meram_priv *priv,
- struct sh_mobile_meram_fb_plane *plane)
-{
- meram_free(priv, priv->meram + plane->marker->offset,
- plane->marker->size * 1024);
-
- __clear_bit(plane->marker->index, &priv->used_icb);
- __clear_bit(plane->cache->index, &priv->used_icb);
-}
-
-/* Is this a YCbCr(NV12, NV16 or NV24) colorspace? */
-static int is_nvcolor(int cspace)
-{
- if (cspace == SH_MOBILE_MERAM_PF_NV ||
- cspace == SH_MOBILE_MERAM_PF_NV24)
- return 1;
- return 0;
-}
-
-/* Set the next address to fetch. */
-static void meram_set_next_addr(struct sh_mobile_meram_priv *priv,
- struct sh_mobile_meram_fb_cache *cache,
- unsigned long base_addr_y,
- unsigned long base_addr_c)
-{
- struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
- unsigned long target;
-
- icb->current_reg ^= 1;
- target = icb->current_reg ? MExxSARB : MExxSARA;
-
- /* set the next address to fetch */
- meram_write_icb(priv->base, cache->planes[0].cache->index, target,
- base_addr_y);
- meram_write_icb(priv->base, cache->planes[0].marker->index, target,
- base_addr_y + cache->planes[0].marker->cache_unit);
-
- if (cache->nplanes == 2) {
- meram_write_icb(priv->base, cache->planes[1].cache->index,
- target, base_addr_c);
- meram_write_icb(priv->base, cache->planes[1].marker->index,
- target, base_addr_c +
- cache->planes[1].marker->cache_unit);
- }
-}
-
-/* Get the next ICB address. */
-static void
-meram_get_next_icb_addr(struct sh_mobile_meram_info *pdata,
- struct sh_mobile_meram_fb_cache *cache,
- unsigned long *icb_addr_y, unsigned long *icb_addr_c)
-{
- struct sh_mobile_meram_icb *icb = cache->planes[0].marker;
- unsigned long icb_offset;
-
- if (pdata->addr_mode == SH_MOBILE_MERAM_MODE0)
- icb_offset = 0x80000000 | (icb->current_reg << 29);
- else
- icb_offset = 0xc0000000 | (icb->current_reg << 23);
-
- *icb_addr_y = icb_offset | (cache->planes[0].marker->index << 24);
- if (cache->nplanes == 2)
- *icb_addr_c = icb_offset
- | (cache->planes[1].marker->index << 24);
-}
-
-#define MERAM_CALC_BYTECOUNT(x, y) \
- (((x) * (y) + (MERAM_LINE_WIDTH - 1)) & ~(MERAM_LINE_WIDTH - 1))
-
-/* Initialize MERAM. */
-static int meram_plane_init(struct sh_mobile_meram_priv *priv,
- struct sh_mobile_meram_fb_plane *plane,
- unsigned int xres, unsigned int yres,
- unsigned int *out_pitch)
-{
- struct sh_mobile_meram_icb *marker = plane->marker;
- unsigned long total_byte_count = MERAM_CALC_BYTECOUNT(xres, yres);
- unsigned long bnm;
- unsigned int lcdc_pitch;
- unsigned int xpitch;
- unsigned int line_cnt;
- unsigned int save_lines;
-
- /* adjust pitch to 1024, 2048, 4096 or 8192 */
- lcdc_pitch = (xres - 1) | 1023;
- lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 1);
- lcdc_pitch = lcdc_pitch | (lcdc_pitch >> 2);
- lcdc_pitch += 1;
-
- /* derive settings */
- if (lcdc_pitch == 8192 && yres >= 1024) {
- lcdc_pitch = xpitch = MERAM_LINE_WIDTH;
- line_cnt = total_byte_count >> 11;
- *out_pitch = xres;
- save_lines = plane->marker->size / 16 / MERAM_SEC_LINE;
- save_lines *= MERAM_SEC_LINE;
- } else {
- xpitch = xres;
- line_cnt = yres;
- *out_pitch = lcdc_pitch;
- save_lines = plane->marker->size / (lcdc_pitch >> 10) / 2;
- save_lines &= 0xff;
- }
- bnm = (save_lines - 1) << 16;
-
- /* TODO: we better to check if we have enough MERAM buffer size */
-
- /* set up ICB */
- meram_write_icb(priv->base, plane->cache->index, MExxBSIZE,
- MERAM_MExxBSIZE_VAL(0x0, line_cnt - 1, xpitch - 1));
- meram_write_icb(priv->base, plane->marker->index, MExxBSIZE,
- MERAM_MExxBSIZE_VAL(0xf, line_cnt - 1, xpitch - 1));
-
- meram_write_icb(priv->base, plane->cache->index, MExxMNCF, bnm);
- meram_write_icb(priv->base, plane->marker->index, MExxMNCF, bnm);
-
- meram_write_icb(priv->base, plane->cache->index, MExxSBSIZE, xpitch);
- meram_write_icb(priv->base, plane->marker->index, MExxSBSIZE, xpitch);
-
- /* save a cache unit size */
- plane->cache->cache_unit = xres * save_lines;
- plane->marker->cache_unit = xres * save_lines;
-
- /*
- * Set MERAM for framebuffer
- *
- * we also chain the cache_icb and the marker_icb.
- * we also split the allocated MERAM buffer between two ICBs.
- */
- meram_write_icb(priv->base, plane->cache->index, MExxCTL,
- MERAM_MExxCTL_VAL(plane->marker->index, marker->offset)
- | MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
- MExxCTL_MD_FB);
- meram_write_icb(priv->base, plane->marker->index, MExxCTL,
- MERAM_MExxCTL_VAL(plane->cache->index, marker->offset +
- plane->marker->size / 2) |
- MExxCTL_WD1 | MExxCTL_WD0 | MExxCTL_WS | MExxCTL_CM |
- MExxCTL_MD_FB);
-
- return 0;
-}
-
-static void meram_plane_cleanup(struct sh_mobile_meram_priv *priv,
- struct sh_mobile_meram_fb_plane *plane)
-{
- /* disable ICB */
- meram_write_icb(priv->base, plane->cache->index, MExxCTL,
- MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
- meram_write_icb(priv->base, plane->marker->index, MExxCTL,
- MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF);
-
- plane->cache->cache_unit = 0;
- plane->marker->cache_unit = 0;
-}
-
-/* -----------------------------------------------------------------------------
- * MERAM operations
- */
-
-unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *pdata,
- size_t size)
-{
- struct sh_mobile_meram_priv *priv = pdata->priv;
-
- return meram_alloc(priv, size);
-}
-EXPORT_SYMBOL_GPL(sh_mobile_meram_alloc);
-
-void sh_mobile_meram_free(struct sh_mobile_meram_info *pdata, unsigned long mem,
- size_t size)
-{
- struct sh_mobile_meram_priv *priv = pdata->priv;
-
- meram_free(priv, mem, size);
-}
-EXPORT_SYMBOL_GPL(sh_mobile_meram_free);
-
-/* Allocate memory for the ICBs and mark them as used. */
-static struct sh_mobile_meram_fb_cache *
-meram_cache_alloc(struct sh_mobile_meram_priv *priv,
- const struct sh_mobile_meram_cfg *cfg,
- int pixelformat)
-{
- unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
- struct sh_mobile_meram_fb_cache *cache;
- int ret;
-
- cache = kzalloc(sizeof(*cache), GFP_KERNEL);
- if (cache == NULL)
- return ERR_PTR(-ENOMEM);
-
- cache->nplanes = nplanes;
-
- ret = meram_plane_alloc(priv, &cache->planes[0],
- cfg->icb[0].meram_size);
- if (ret < 0)
- goto error;
-
- cache->planes[0].marker->current_reg = 1;
- cache->planes[0].marker->pixelformat = pixelformat;
-
- if (cache->nplanes == 1)
- return cache;
-
- ret = meram_plane_alloc(priv, &cache->planes[1],
- cfg->icb[1].meram_size);
- if (ret < 0) {
- meram_plane_free(priv, &cache->planes[0]);
- goto error;
- }
-
- return cache;
-
-error:
- kfree(cache);
- return ERR_PTR(-ENOMEM);
-}
-
-void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *pdata,
- const struct sh_mobile_meram_cfg *cfg,
- unsigned int xres, unsigned int yres,
- unsigned int pixelformat, unsigned int *pitch)
-{
- struct sh_mobile_meram_fb_cache *cache;
- struct sh_mobile_meram_priv *priv = pdata->priv;
- struct platform_device *pdev = pdata->pdev;
- unsigned int nplanes = is_nvcolor(pixelformat) ? 2 : 1;
- unsigned int out_pitch;
-
- if (priv == NULL)
- return ERR_PTR(-ENODEV);
-
- if (pixelformat != SH_MOBILE_MERAM_PF_NV &&
- pixelformat != SH_MOBILE_MERAM_PF_NV24 &&
- pixelformat != SH_MOBILE_MERAM_PF_RGB)
- return ERR_PTR(-EINVAL);
-
- dev_dbg(&pdev->dev, "registering %dx%d (%s)", xres, yres,
- !pixelformat ? "yuv" : "rgb");
-
- /* we can't handle wider than 8192px */
- if (xres > 8192) {
- dev_err(&pdev->dev, "width exceeding the limit (> 8192).");
- return ERR_PTR(-EINVAL);
- }
-
- if (cfg->icb[0].meram_size == 0)
- return ERR_PTR(-EINVAL);
-
- if (nplanes == 2 && cfg->icb[1].meram_size == 0)
- return ERR_PTR(-EINVAL);
-
- mutex_lock(&priv->lock);
-
- /* We now register the ICBs and allocate the MERAM regions. */
- cache = meram_cache_alloc(priv, cfg, pixelformat);
- if (IS_ERR(cache)) {
- dev_err(&pdev->dev, "MERAM allocation failed (%ld).",
- PTR_ERR(cache));
- goto err;
- }
-
- /* initialize MERAM */
- meram_plane_init(priv, &cache->planes[0], xres, yres, &out_pitch);
- *pitch = out_pitch;
- if (pixelformat == SH_MOBILE_MERAM_PF_NV)
- meram_plane_init(priv, &cache->planes[1],
- xres, (yres + 1) / 2, &out_pitch);
- else if (pixelformat == SH_MOBILE_MERAM_PF_NV24)
- meram_plane_init(priv, &cache->planes[1],
- 2 * xres, (yres + 1) / 2, &out_pitch);
-
-err:
- mutex_unlock(&priv->lock);
- return cache;
-}
-EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_alloc);
-
-void
-sh_mobile_meram_cache_free(struct sh_mobile_meram_info *pdata, void *data)
-{
- struct sh_mobile_meram_fb_cache *cache = data;
- struct sh_mobile_meram_priv *priv = pdata->priv;
-
- mutex_lock(&priv->lock);
-
- /* Cleanup and free. */
- meram_plane_cleanup(priv, &cache->planes[0]);
- meram_plane_free(priv, &cache->planes[0]);
-
- if (cache->nplanes == 2) {
- meram_plane_cleanup(priv, &cache->planes[1]);
- meram_plane_free(priv, &cache->planes[1]);
- }
-
- kfree(cache);
-
- mutex_unlock(&priv->lock);
-}
-EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_free);
-
-void
-sh_mobile_meram_cache_update(struct sh_mobile_meram_info *pdata, void *data,
- unsigned long base_addr_y,
- unsigned long base_addr_c,
- unsigned long *icb_addr_y,
- unsigned long *icb_addr_c)
-{
- struct sh_mobile_meram_fb_cache *cache = data;
- struct sh_mobile_meram_priv *priv = pdata->priv;
-
- mutex_lock(&priv->lock);
-
- meram_set_next_addr(priv, cache, base_addr_y, base_addr_c);
- meram_get_next_icb_addr(pdata, cache, icb_addr_y, icb_addr_c);
-
- mutex_unlock(&priv->lock);
-}
-EXPORT_SYMBOL_GPL(sh_mobile_meram_cache_update);
-
-/* -----------------------------------------------------------------------------
- * Power management
- */
-
-#ifdef CONFIG_PM
-static int sh_mobile_meram_suspend(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
- unsigned int i, j;
-
- for (i = 0; i < MERAM_REGS_SIZE; i++)
- priv->regs[i] = meram_read_reg(priv->base, common_regs[i]);
-
- for (i = 0; i < 32; i++) {
- if (!test_bit(i, &priv->used_icb))
- continue;
- for (j = 0; j < ICB_REGS_SIZE; j++) {
- priv->icbs[i].regs[j] =
- meram_read_icb(priv->base, i, icb_regs[j]);
- /* Reset ICB on resume */
- if (icb_regs[j] == MExxCTL)
- priv->icbs[i].regs[j] |=
- MExxCTL_WBF | MExxCTL_WF | MExxCTL_RF;
- }
- }
- return 0;
-}
-
-static int sh_mobile_meram_resume(struct device *dev)
-{
- struct platform_device *pdev = to_platform_device(dev);
- struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
- unsigned int i, j;
-
- for (i = 0; i < 32; i++) {
- if (!test_bit(i, &priv->used_icb))
- continue;
- for (j = 0; j < ICB_REGS_SIZE; j++)
- meram_write_icb(priv->base, i, icb_regs[j],
- priv->icbs[i].regs[j]);
- }
-
- for (i = 0; i < MERAM_REGS_SIZE; i++)
- meram_write_reg(priv->base, common_regs[i], priv->regs[i]);
- return 0;
-}
-#endif /* CONFIG_PM */
-
-static UNIVERSAL_DEV_PM_OPS(sh_mobile_meram_dev_pm_ops,
- sh_mobile_meram_suspend,
- sh_mobile_meram_resume, NULL);
-
-/* -----------------------------------------------------------------------------
- * Probe/remove and driver init/exit
- */
-
-static int sh_mobile_meram_probe(struct platform_device *pdev)
-{
- struct sh_mobile_meram_priv *priv;
- struct sh_mobile_meram_info *pdata = pdev->dev.platform_data;
- struct resource *regs;
- struct resource *meram;
- unsigned int i;
- int error;
-
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data defined\n");
- return -EINVAL;
- }
-
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- meram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (regs == NULL || meram == NULL) {
- dev_err(&pdev->dev, "cannot get platform resources\n");
- return -ENOENT;
- }
-
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (!priv) {
- dev_err(&pdev->dev, "cannot allocate device data\n");
- return -ENOMEM;
- }
-
- /* Initialize private data. */
- mutex_init(&priv->lock);
- priv->used_icb = pdata->reserved_icbs;
-
- for (i = 0; i < MERAM_ICB_NUM; ++i)
- priv->icbs[i].index = i;
-
- pdata->priv = priv;
- pdata->pdev = pdev;
-
- /* Request memory regions and remap the registers. */
- if (!request_mem_region(regs->start, resource_size(regs), pdev->name)) {
- dev_err(&pdev->dev, "MERAM registers region already claimed\n");
- error = -EBUSY;
- goto err_req_regs;
- }
-
- if (!request_mem_region(meram->start, resource_size(meram),
- pdev->name)) {
- dev_err(&pdev->dev, "MERAM memory region already claimed\n");
- error = -EBUSY;
- goto err_req_meram;
- }
-
- priv->base = ioremap_nocache(regs->start, resource_size(regs));
- if (!priv->base) {
- dev_err(&pdev->dev, "ioremap failed\n");
- error = -EFAULT;
- goto err_ioremap;
- }
-
- priv->meram = meram->start;
-
- /* Create and initialize the MERAM memory pool. */
- priv->pool = gen_pool_create(ilog2(MERAM_GRANULARITY), -1);
- if (priv->pool == NULL) {
- error = -ENOMEM;
- goto err_genpool;
- }
-
- error = gen_pool_add(priv->pool, meram->start, resource_size(meram),
- -1);
- if (error < 0)
- goto err_genpool;
-
- /* initialize ICB addressing mode */
- if (pdata->addr_mode == SH_MOBILE_MERAM_MODE1)
- meram_write_reg(priv->base, MEVCR1, MEVCR1_AMD1);
-
- platform_set_drvdata(pdev, priv);
- pm_runtime_enable(&pdev->dev);
-
- dev_info(&pdev->dev, "sh_mobile_meram initialized.");
-
- return 0;
-
-err_genpool:
- if (priv->pool)
- gen_pool_destroy(priv->pool);
- iounmap(priv->base);
-err_ioremap:
- release_mem_region(meram->start, resource_size(meram));
-err_req_meram:
- release_mem_region(regs->start, resource_size(regs));
-err_req_regs:
- mutex_destroy(&priv->lock);
- kfree(priv);
-
- return error;
-}
-
-
-static int sh_mobile_meram_remove(struct platform_device *pdev)
-{
- struct sh_mobile_meram_priv *priv = platform_get_drvdata(pdev);
- struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- struct resource *meram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-
- pm_runtime_disable(&pdev->dev);
-
- gen_pool_destroy(priv->pool);
-
- iounmap(priv->base);
- release_mem_region(meram->start, resource_size(meram));
- release_mem_region(regs->start, resource_size(regs));
-
- mutex_destroy(&priv->lock);
-
- kfree(priv);
-
- return 0;
-}
-
-static struct platform_driver sh_mobile_meram_driver = {
- .driver = {
- .name = "sh_mobile_meram",
- .pm = &sh_mobile_meram_dev_pm_ops,
- },
- .probe = sh_mobile_meram_probe,
- .remove = sh_mobile_meram_remove,
-};
-
-module_platform_driver(sh_mobile_meram_driver);
-
-MODULE_DESCRIPTION("SuperH Mobile MERAM driver");
-MODULE_AUTHOR("Damian Hobson-Garcia / Takanari Hayama");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/skeletonfb.c b/drivers/video/fbdev/skeletonfb.c
index 7f4e908..812a36c 100644
--- a/drivers/video/fbdev/skeletonfb.c
+++ b/drivers/video/fbdev/skeletonfb.c
@@ -836,7 +836,7 @@ static void xxxfb_remove(struct pci_dev *dev)
* @dev: PCI device
* @msg: the suspend event code.
*
- * See Documentation/power/admin-guide/devices.rst for more information
+ * See Documentation/driver-api/pm/devices.rst for more information
*/
static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg)
{
@@ -851,7 +851,7 @@ static int xxxfb_suspend(struct pci_dev *dev, pm_message_t msg)
* xxxfb_resume - Optional but recommended function. Resume the device.
* @dev: PCI device
*
- * See Documentation/power/admin-guide/devices.rst for more information
+ * See Documentation/driver-api/pm/devices.rst for more information
*/
static int xxxfb_resume(struct pci_dev *dev)
{
@@ -915,7 +915,7 @@ static void __exit xxxfb_exit(void)
* @dev: platform device
* @msg: the suspend event code.
*
- * See Documentation/power/admin-guide/devices.rst for more information
+ * See Documentation/driver-api/pm/devices.rst for more information
*/
static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg)
{
@@ -930,7 +930,7 @@ static int xxxfb_suspend(struct platform_device *dev, pm_message_t msg)
* xxxfb_resume - Optional but recommended function. Resume the device.
* @dev: platform device
*
- * See Documentation/power/admin-guide/devices.rst for more information
+ * See Documentation/driver-api/pm/devices.rst for more information
*/
static int xxxfb_resume(struct platform_dev *dev)
{
diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c
index 6f0a195..dde52d0 100644
--- a/drivers/video/fbdev/sm501fb.c
+++ b/drivers/video/fbdev/sm501fb.c
@@ -1932,8 +1932,7 @@ static int sm501fb_probe(struct platform_device *pdev)
int ret;
/* allocate our framebuffers */
-
- info = kzalloc(sizeof(struct sm501fb_info), GFP_KERNEL);
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info) {
dev_err(dev, "failed to allocate state\n");
return -ENOMEM;
diff --git a/drivers/video/fbdev/uvesafb.c b/drivers/video/fbdev/uvesafb.c
index 73676eb..440a663 100644
--- a/drivers/video/fbdev/uvesafb.c
+++ b/drivers/video/fbdev/uvesafb.c
@@ -486,8 +486,9 @@ static int uvesafb_vbe_getmodes(struct uvesafb_ktask *task,
mode++;
}
- par->vbe_modes = kzalloc(sizeof(struct vbe_mode_ib) *
- par->vbe_modes_cnt, GFP_KERNEL);
+ par->vbe_modes = kcalloc(par->vbe_modes_cnt,
+ sizeof(struct vbe_mode_ib),
+ GFP_KERNEL);
if (!par->vbe_modes)
return -ENOMEM;
@@ -858,7 +859,7 @@ static int uvesafb_vbe_init_mode(struct fb_info *info)
* Convert the modelist into a modedb so that we can use it with
* fb_find_mode().
*/
- mode = kzalloc(i * sizeof(*mode), GFP_KERNEL);
+ mode = kcalloc(i, sizeof(*mode), GFP_KERNEL);
if (mode) {
i = 0;
list_for_each(pos, &info->modelist) {
@@ -1044,7 +1045,8 @@ static int uvesafb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
info->cmap.len || cmap->start < info->cmap.start)
return -EINVAL;
- entries = kmalloc(sizeof(*entries) * cmap->len, GFP_KERNEL);
+ entries = kmalloc_array(cmap->len, sizeof(*entries),
+ GFP_KERNEL);
if (!entries)
return -ENOMEM;
diff --git a/drivers/video/fbdev/via/global.h b/drivers/video/fbdev/via/global.h
index 275dbbb..649d2ca 100644
--- a/drivers/video/fbdev/via/global.h
+++ b/drivers/video/fbdev/via/global.h
@@ -33,6 +33,12 @@
#include <linux/console.h>
#include <linux/timer.h>
+#ifdef CONFIG_X86
+#include <asm/olpc.h>
+#else
+#define machine_is_olpc(x) 0
+#endif
+
#include "debug.h"
#include "viafbdev.h"
diff --git a/drivers/video/fbdev/via/hw.c b/drivers/video/fbdev/via/hw.c
index 22450908..48969c6 100644
--- a/drivers/video/fbdev/via/hw.c
+++ b/drivers/video/fbdev/via/hw.c
@@ -20,7 +20,6 @@
*/
#include <linux/via-core.h>
-#include <asm/olpc.h>
#include "global.h"
#include "via_clock.h"
diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c
index 77774d8..b041eb2 100644
--- a/drivers/video/fbdev/via/via-core.c
+++ b/drivers/video/fbdev/via/via-core.c
@@ -17,7 +17,6 @@
#include <linux/platform_device.h>
#include <linux/list.h>
#include <linux/pm.h>
-#include <asm/olpc.h>
/*
* The default port config.
diff --git a/drivers/video/fbdev/via/via_clock.c b/drivers/video/fbdev/via/via_clock.c
index bf269fa..3d0efdb 100644
--- a/drivers/video/fbdev/via/via_clock.c
+++ b/drivers/video/fbdev/via/via_clock.c
@@ -25,7 +25,7 @@
#include <linux/kernel.h>
#include <linux/via-core.h>
-#include <asm/olpc.h>
+
#include "via_clock.h"
#include "global.h"
#include "debug.h"
diff --git a/drivers/video/fbdev/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c
index 9b45125..d2f7850 100644
--- a/drivers/video/fbdev/via/viafbdev.c
+++ b/drivers/video/fbdev/via/viafbdev.c
@@ -25,7 +25,6 @@
#include <linux/stat.h>
#include <linux/via-core.h>
#include <linux/via_i2c.h>
-#include <asm/olpc.h>
#define _MASTER_FILE
#include "global.h"
@@ -596,7 +595,8 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg)
break;
case VIAFB_GET_GAMMA_LUT:
- viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL);
+ viafb_gamma_table = kmalloc_array(256, sizeof(u32),
+ GFP_KERNEL);
if (!viafb_gamma_table)
return -ENOMEM;
viafb_get_gamma_table(viafb_gamma_table);
diff --git a/drivers/video/fbdev/w100fb.c b/drivers/video/fbdev/w100fb.c
index 035ff6e..696106e 100644
--- a/drivers/video/fbdev/w100fb.c
+++ b/drivers/video/fbdev/w100fb.c
@@ -693,7 +693,8 @@ int w100fb_probe(struct platform_device *pdev)
goto out;
}
- info->pseudo_palette = kmalloc(sizeof (u32) * MAX_PALETTES, GFP_KERNEL);
+ info->pseudo_palette = kmalloc_array(MAX_PALETTES, sizeof(u32),
+ GFP_KERNEL);
if (!info->pseudo_palette) {
err = -ENOMEM;
goto out;
diff --git a/drivers/video/fbdev/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c
index 46f6396..6a4bbc9 100644
--- a/drivers/video/fbdev/xen-fbfront.c
+++ b/drivers/video/fbdev/xen-fbfront.c
@@ -412,7 +412,7 @@ static int xenfb_probe(struct xenbus_device *dev,
info->nr_pages = (fb_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
- info->gfns = vmalloc(sizeof(unsigned long) * info->nr_pages);
+ info->gfns = vmalloc(array_size(sizeof(unsigned long), info->nr_pages));
if (!info->gfns)
goto error_nomem;
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
index 83b8963..5244e93 100644
--- a/drivers/video/of_display_timing.c
+++ b/drivers/video/of_display_timing.c
@@ -181,8 +181,9 @@ struct display_timings *of_get_display_timings(const struct device_node *np)
goto entryfail;
}
- disp->timings = kzalloc(sizeof(struct display_timing *) *
- disp->num_timings, GFP_KERNEL);
+ disp->timings = kcalloc(disp->num_timings,
+ sizeof(struct display_timing *),
+ GFP_KERNEL);
if (!disp->timings) {
pr_err("%pOF: could not allocate timings array\n", np);
goto entryfail;
diff --git a/drivers/virt/fsl_hypervisor.c b/drivers/virt/fsl_hypervisor.c
index 4e05d7f..8ba726e 100644
--- a/drivers/virt/fsl_hypervisor.c
+++ b/drivers/virt/fsl_hypervisor.c
@@ -223,7 +223,7 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
* 'pages' is an array of struct page pointers that's initialized by
* get_user_pages().
*/
- pages = kzalloc(num_pages * sizeof(struct page *), GFP_KERNEL);
+ pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL);
if (!pages) {
pr_debug("fsl-hv: could not allocate page list\n");
return -ENOMEM;
diff --git a/drivers/virt/vboxguest/vboxguest_core.c b/drivers/virt/vboxguest/vboxguest_core.c
index 2f3856a..3093655 100644
--- a/drivers/virt/vboxguest/vboxguest_core.c
+++ b/drivers/virt/vboxguest/vboxguest_core.c
@@ -69,7 +69,7 @@ static void vbg_guest_mappings_init(struct vbg_dev *gdev)
/* Add 4M so that we can align the vmap to 4MiB as the host requires. */
size = PAGE_ALIGN(req->hypervisor_size) + SZ_4M;
- pages = kmalloc(sizeof(*pages) * (size >> PAGE_SHIFT), GFP_KERNEL);
+ pages = kmalloc_array(size >> PAGE_SHIFT, sizeof(*pages), GFP_KERNEL);
if (!pages)
goto out;
@@ -262,8 +262,9 @@ static int vbg_balloon_inflate(struct vbg_dev *gdev, u32 chunk_idx)
struct page **pages;
int i, rc, ret;
- pages = kmalloc(sizeof(*pages) * VMMDEV_MEMORY_BALLOON_CHUNK_PAGES,
- GFP_KERNEL | __GFP_NOWARN);
+ pages = kmalloc_array(VMMDEV_MEMORY_BALLOON_CHUNK_PAGES,
+ sizeof(*pages),
+ GFP_KERNEL | __GFP_NOWARN);
if (!pages)
return -ENOMEM;
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 48d4d1c..705aebd 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -113,12 +113,13 @@ static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors,
vp_dev->msix_vectors = nvectors;
- vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names,
- GFP_KERNEL);
+ vp_dev->msix_names = kmalloc_array(nvectors,
+ sizeof(*vp_dev->msix_names),
+ GFP_KERNEL);
if (!vp_dev->msix_names)
goto error;
vp_dev->msix_affinity_masks
- = kzalloc(nvectors * sizeof *vp_dev->msix_affinity_masks,
+ = kcalloc(nvectors, sizeof(*vp_dev->msix_affinity_masks),
GFP_KERNEL);
if (!vp_dev->msix_affinity_masks)
goto error;
@@ -577,6 +578,8 @@ static void virtio_pci_remove(struct pci_dev *pci_dev)
struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
struct device *dev = get_device(&vp_dev->vdev.dev);
+ pci_disable_sriov(pci_dev);
+
unregister_virtio_device(&vp_dev->vdev);
if (vp_dev->ioaddr)
@@ -588,6 +591,33 @@ static void virtio_pci_remove(struct pci_dev *pci_dev)
put_device(dev);
}
+static int virtio_pci_sriov_configure(struct pci_dev *pci_dev, int num_vfs)
+{
+ struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
+ struct virtio_device *vdev = &vp_dev->vdev;
+ int ret;
+
+ if (!(vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_DRIVER_OK))
+ return -EBUSY;
+
+ if (!__virtio_test_bit(vdev, VIRTIO_F_SR_IOV))
+ return -EINVAL;
+
+ if (pci_vfs_assigned(pci_dev))
+ return -EPERM;
+
+ if (num_vfs == 0) {
+ pci_disable_sriov(pci_dev);
+ return 0;
+ }
+
+ ret = pci_enable_sriov(pci_dev, num_vfs);
+ if (ret < 0)
+ return ret;
+
+ return num_vfs;
+}
+
static struct pci_driver virtio_pci_driver = {
.name = "virtio-pci",
.id_table = virtio_pci_id_table,
@@ -596,6 +626,7 @@ static struct pci_driver virtio_pci_driver = {
#ifdef CONFIG_PM_SLEEP
.driver.pm = &virtio_pci_pm_ops,
#endif
+ .sriov_configure = virtio_pci_sriov_configure,
};
module_pci_driver(virtio_pci_driver);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 2555d80..07571da 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -153,14 +153,28 @@ static u64 vp_get_features(struct virtio_device *vdev)
return features;
}
+static void vp_transport_features(struct virtio_device *vdev, u64 features)
+{
+ struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+ struct pci_dev *pci_dev = vp_dev->pci_dev;
+
+ if ((features & BIT_ULL(VIRTIO_F_SR_IOV)) &&
+ pci_find_ext_capability(pci_dev, PCI_EXT_CAP_ID_SRIOV))
+ __virtio_set_bit(vdev, VIRTIO_F_SR_IOV);
+}
+
/* virtio config->finalize_features() implementation */
static int vp_finalize_features(struct virtio_device *vdev)
{
struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+ u64 features = vdev->features;
/* Give virtio_ring a chance to accept features. */
vring_transport_features(vdev);
+ /* Give virtio_pci a chance to accept features. */
+ vp_transport_features(vdev, features);
+
if (!__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) {
dev_err(&vdev->dev, "virtio: device uses modern interface "
"but does not have VIRTIO_F_VERSION_1\n");
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 21d464a..814b395 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -247,7 +247,7 @@ static struct vring_desc *alloc_indirect(struct virtqueue *_vq,
*/
gfp &= ~__GFP_HIGHMEM;
- desc = kmalloc(total_sg * sizeof(struct vring_desc), gfp);
+ desc = kmalloc_array(total_sg, sizeof(struct vring_desc), gfp);
if (!desc)
return NULL;
diff --git a/drivers/watchdog/cadence_wdt.c b/drivers/watchdog/cadence_wdt.c
index 3ec1f41..c392435 100644
--- a/drivers/watchdog/cadence_wdt.c
+++ b/drivers/watchdog/cadence_wdt.c
@@ -418,8 +418,7 @@ static void cdns_wdt_shutdown(struct platform_device *pdev)
*/
static int __maybe_unused cdns_wdt_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct cdns_wdt *wdt = platform_get_drvdata(pdev);
+ struct cdns_wdt *wdt = dev_get_drvdata(dev);
if (watchdog_active(&wdt->cdns_wdt_device)) {
cdns_wdt_stop(&wdt->cdns_wdt_device);
@@ -438,8 +437,7 @@ static int __maybe_unused cdns_wdt_suspend(struct device *dev)
static int __maybe_unused cdns_wdt_resume(struct device *dev)
{
int ret;
- struct platform_device *pdev = to_platform_device(dev);
- struct cdns_wdt *wdt = platform_get_drvdata(pdev);
+ struct cdns_wdt *wdt = dev_get_drvdata(dev);
if (watchdog_active(&wdt->cdns_wdt_device)) {
ret = clk_prepare_enable(wdt->clk);
diff --git a/drivers/watchdog/da9062_wdt.c b/drivers/watchdog/da9062_wdt.c
index a001782..fe169d8 100644
--- a/drivers/watchdog/da9062_wdt.c
+++ b/drivers/watchdog/da9062_wdt.c
@@ -30,14 +30,8 @@ static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
struct da9062_watchdog {
struct da9062 *hw;
struct watchdog_device wdtdev;
- unsigned long j_time_stamp;
};
-static void da9062_set_window_start(struct da9062_watchdog *wdt)
-{
- wdt->j_time_stamp = jiffies;
-}
-
static unsigned int da9062_wdt_timeout_to_sel(unsigned int secs)
{
unsigned int i;
@@ -59,8 +53,6 @@ static int da9062_reset_watchdog_timer(struct da9062_watchdog *wdt)
DA9062AA_WATCHDOG_MASK,
DA9062AA_WATCHDOG_MASK);
- da9062_set_window_start(wdt);
-
return ret;
}
@@ -232,8 +224,6 @@ static int da9062_wdt_probe(struct platform_device *pdev)
return ret;
}
- da9062_set_window_start(wdt);
-
return da9062_wdt_ping(&wdt->wdtdev);
}
diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c
index b17ac1b..384dca1 100644
--- a/drivers/watchdog/da9063_wdt.c
+++ b/drivers/watchdog/da9063_wdt.c
@@ -45,20 +45,56 @@ static unsigned int da9063_wdt_timeout_to_sel(unsigned int secs)
return DA9063_TWDSCALE_MAX;
}
-static int _da9063_wdt_set_timeout(struct da9063 *da9063, unsigned int regval)
+/*
+ * Return 0 if watchdog is disabled, else non zero.
+ */
+static unsigned int da9063_wdt_is_running(struct da9063 *da9063)
+{
+ unsigned int val;
+
+ regmap_read(da9063->regmap, DA9063_REG_CONTROL_D, &val);
+
+ return val & DA9063_TWDSCALE_MASK;
+}
+
+static int da9063_wdt_disable_timer(struct da9063 *da9063)
{
return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
+ DA9063_TWDSCALE_MASK,
+ DA9063_TWDSCALE_DISABLE);
+}
+
+static int
+da9063_wdt_update_timeout(struct da9063 *da9063, unsigned int timeout)
+{
+ unsigned int regval;
+ int ret;
+
+ /*
+ * The watchdog triggers a reboot if a timeout value is already
+ * programmed because the timeout value combines two functions
+ * in one: indicating the counter limit and starting the watchdog.
+ * The watchdog must be disabled to be able to change the timeout
+ * value if the watchdog is already running. Then we can set the
+ * new timeout value which enables the watchdog again.
+ */
+ ret = da9063_wdt_disable_timer(da9063);
+ if (ret)
+ return ret;
+
+ usleep_range(150, 300);
+ regval = da9063_wdt_timeout_to_sel(timeout);
+
+ return regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
DA9063_TWDSCALE_MASK, regval);
}
static int da9063_wdt_start(struct watchdog_device *wdd)
{
struct da9063 *da9063 = watchdog_get_drvdata(wdd);
- unsigned int selector;
int ret;
- selector = da9063_wdt_timeout_to_sel(wdd->timeout);
- ret = _da9063_wdt_set_timeout(da9063, selector);
+ ret = da9063_wdt_update_timeout(da9063, wdd->timeout);
if (ret)
dev_err(da9063->dev, "Watchdog failed to start (err = %d)\n",
ret);
@@ -71,8 +107,7 @@ static int da9063_wdt_stop(struct watchdog_device *wdd)
struct da9063 *da9063 = watchdog_get_drvdata(wdd);
int ret;
- ret = regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_D,
- DA9063_TWDSCALE_MASK, DA9063_TWDSCALE_DISABLE);
+ ret = da9063_wdt_disable_timer(da9063);
if (ret)
dev_alert(da9063->dev, "Watchdog failed to stop (err = %d)\n",
ret);
@@ -98,16 +133,26 @@ static int da9063_wdt_set_timeout(struct watchdog_device *wdd,
unsigned int timeout)
{
struct da9063 *da9063 = watchdog_get_drvdata(wdd);
- unsigned int selector;
- int ret;
+ int ret = 0;
+
+ /*
+ * There are two cases when a set_timeout() will be called:
+ * 1. The watchdog is off and someone wants to set the timeout for the
+ * further use.
+ * 2. The watchdog is already running and a new timeout value should be
+ * set.
+ *
+ * The watchdog can't store a timeout value not equal zero without
+ * enabling the watchdog, so the timeout must be buffered by the driver.
+ */
+ if (watchdog_active(wdd))
+ ret = da9063_wdt_update_timeout(da9063, timeout);
- selector = da9063_wdt_timeout_to_sel(timeout);
- ret = _da9063_wdt_set_timeout(da9063, selector);
if (ret)
dev_err(da9063->dev, "Failed to set watchdog timeout (err = %d)\n",
ret);
else
- wdd->timeout = wdt_timeout[selector];
+ wdd->timeout = wdt_timeout[da9063_wdt_timeout_to_sel(timeout)];
return ret;
}
@@ -171,6 +216,12 @@ static int da9063_wdt_probe(struct platform_device *pdev)
watchdog_set_drvdata(wdd, da9063);
+ /* Change the timeout to the default value if the watchdog is running */
+ if (da9063_wdt_is_running(da9063)) {
+ da9063_wdt_update_timeout(da9063, DA9063_WDG_TIMEOUT);
+ set_bit(WDOG_HW_RUNNING, &wdd->status);
+ }
+
return devm_watchdog_register_device(&pdev->dev, wdd);
}
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c
index a43ab2c..9dc62a4 100644
--- a/drivers/watchdog/hpwdt.c
+++ b/drivers/watchdog/hpwdt.c
@@ -159,7 +159,7 @@ static int hpwdt_pretimeout(unsigned int ulReason, struct pt_regs *regs)
"3. OA Forward Progress Log\n"
"4. iLO Event Log";
- if (ilo5 && ulReason == NMI_UNKNOWN && mynmi)
+ if (ilo5 && ulReason == NMI_UNKNOWN && !mynmi)
return NMI_DONE;
if (ilo5 && !pretimeout)
diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c
index aafbeb9..ec4d99a 100644
--- a/drivers/watchdog/jz4740_wdt.c
+++ b/drivers/watchdog/jz4740_wdt.c
@@ -124,12 +124,20 @@ static int jz4740_wdt_stop(struct watchdog_device *wdt_dev)
{
struct jz4740_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
- jz4740_timer_disable_watchdog();
writeb(0x0, drvdata->base + JZ_REG_WDT_COUNTER_ENABLE);
+ jz4740_timer_disable_watchdog();
return 0;
}
+static int jz4740_wdt_restart(struct watchdog_device *wdt_dev,
+ unsigned long action, void *data)
+{
+ wdt_dev->timeout = 0;
+ jz4740_wdt_start(wdt_dev);
+ return 0;
+}
+
static const struct watchdog_info jz4740_wdt_info = {
.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
.identity = "jz4740 Watchdog",
@@ -141,6 +149,7 @@ static const struct watchdog_ops jz4740_wdt_ops = {
.stop = jz4740_wdt_stop,
.ping = jz4740_wdt_ping,
.set_timeout = jz4740_wdt_set_timeout,
+ .restart = jz4740_wdt_restart,
};
#ifdef CONFIG_OF
@@ -179,45 +188,26 @@ static int jz4740_wdt_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
drvdata->base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(drvdata->base)) {
- ret = PTR_ERR(drvdata->base);
- goto err_out;
- }
+ if (IS_ERR(drvdata->base))
+ return PTR_ERR(drvdata->base);
- drvdata->rtc_clk = clk_get(&pdev->dev, "rtc");
+ drvdata->rtc_clk = devm_clk_get(&pdev->dev, "rtc");
if (IS_ERR(drvdata->rtc_clk)) {
dev_err(&pdev->dev, "cannot find RTC clock\n");
- ret = PTR_ERR(drvdata->rtc_clk);
- goto err_out;
+ return PTR_ERR(drvdata->rtc_clk);
}
- ret = watchdog_register_device(&drvdata->wdt);
+ ret = devm_watchdog_register_device(&pdev->dev, &drvdata->wdt);
if (ret < 0)
- goto err_disable_clk;
+ return ret;
platform_set_drvdata(pdev, drvdata);
- return 0;
-
-err_disable_clk:
- clk_put(drvdata->rtc_clk);
-err_out:
- return ret;
-}
-
-static int jz4740_wdt_remove(struct platform_device *pdev)
-{
- struct jz4740_wdt_drvdata *drvdata = platform_get_drvdata(pdev);
-
- jz4740_wdt_stop(&drvdata->wdt);
- watchdog_unregister_device(&drvdata->wdt);
- clk_put(drvdata->rtc_clk);
return 0;
}
static struct platform_driver jz4740_wdt_driver = {
.probe = jz4740_wdt_probe,
- .remove = jz4740_wdt_remove,
.driver = {
.name = "jz4740-wdt",
.of_match_table = of_match_ptr(jz4740_wdt_of_matches),
diff --git a/drivers/watchdog/mena21_wdt.c b/drivers/watchdog/mena21_wdt.c
index 25d5d2b..0be7f50 100644
--- a/drivers/watchdog/mena21_wdt.c
+++ b/drivers/watchdog/mena21_wdt.c
@@ -31,7 +31,6 @@ enum a21_wdt_gpios {
struct a21_wdt_drv {
struct watchdog_device wdt;
- struct mutex lock;
unsigned gpios[NUM_GPIOS];
};
@@ -55,12 +54,8 @@ static int a21_wdt_start(struct watchdog_device *wdt)
{
struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt);
- mutex_lock(&drv->lock);
-
gpio_set_value(drv->gpios[GPIO_WD_ENAB], 1);
- mutex_unlock(&drv->lock);
-
return 0;
}
@@ -68,12 +63,8 @@ static int a21_wdt_stop(struct watchdog_device *wdt)
{
struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt);
- mutex_lock(&drv->lock);
-
gpio_set_value(drv->gpios[GPIO_WD_ENAB], 0);
- mutex_unlock(&drv->lock);
-
return 0;
}
@@ -81,14 +72,10 @@ static int a21_wdt_ping(struct watchdog_device *wdt)
{
struct a21_wdt_drv *drv = watchdog_get_drvdata(wdt);
- mutex_lock(&drv->lock);
-
gpio_set_value(drv->gpios[GPIO_WD_TRIG], 0);
ndelay(10);
gpio_set_value(drv->gpios[GPIO_WD_TRIG], 1);
- mutex_unlock(&drv->lock);
-
return 0;
}
@@ -108,8 +95,6 @@ static int a21_wdt_set_timeout(struct watchdog_device *wdt,
return -EINVAL;
}
- mutex_lock(&drv->lock);
-
if (timeout == 1)
gpio_set_value(drv->gpios[GPIO_WD_FAST], 1);
else
@@ -117,8 +102,6 @@ static int a21_wdt_set_timeout(struct watchdog_device *wdt,
wdt->timeout = timeout;
- mutex_unlock(&drv->lock);
-
return 0;
}
@@ -191,7 +174,6 @@ static int a21_wdt_probe(struct platform_device *pdev)
return ret;
}
- mutex_init(&drv->lock);
watchdog_init_timeout(&a21_wdt, 30, &pdev->dev);
watchdog_set_nowayout(&a21_wdt, nowayout);
watchdog_set_drvdata(&a21_wdt, drv);
diff --git a/drivers/watchdog/of_xilinx_wdt.c b/drivers/watchdog/of_xilinx_wdt.c
index 4acbe05..d3f7eb0 100644
--- a/drivers/watchdog/of_xilinx_wdt.c
+++ b/drivers/watchdog/of_xilinx_wdt.c
@@ -268,8 +268,7 @@ static int xwdt_remove(struct platform_device *pdev)
*/
static int __maybe_unused xwdt_suspend(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct xwdt_device *xdev = platform_get_drvdata(pdev);
+ struct xwdt_device *xdev = dev_get_drvdata(dev);
if (watchdog_active(&xdev->xilinx_wdt_wdd))
xilinx_wdt_stop(&xdev->xilinx_wdt_wdd);
@@ -285,8 +284,7 @@ static int __maybe_unused xwdt_suspend(struct device *dev)
*/
static int __maybe_unused xwdt_resume(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct xwdt_device *xdev = platform_get_drvdata(pdev);
+ struct xwdt_device *xdev = dev_get_drvdata(dev);
int ret = 0;
if (watchdog_active(&xdev->xilinx_wdt_wdd))
diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c
index 514db5c..88d81fe 100644
--- a/drivers/watchdog/renesas_wdt.c
+++ b/drivers/watchdog/renesas_wdt.c
@@ -146,7 +146,7 @@ static const struct soc_device_attribute rwdt_quirks_match[] = {
.data = (void *)1, /* needs single CPU */
}, {
.soc_id = "r8a7791",
- .revision = "ES[12].*",
+ .revision = "ES1.*",
.data = (void *)1, /* needs single CPU */
}, {
.soc_id = "r8a7792",
diff --git a/drivers/watchdog/sp805_wdt.c b/drivers/watchdog/sp805_wdt.c
index 03805bc..9849db0 100644
--- a/drivers/watchdog/sp805_wdt.c
+++ b/drivers/watchdog/sp805_wdt.c
@@ -121,6 +121,18 @@ static unsigned int wdt_timeleft(struct watchdog_device *wdd)
return div_u64(load, rate);
}
+static int
+wdt_restart(struct watchdog_device *wdd, unsigned long mode, void *cmd)
+{
+ struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
+
+ writel_relaxed(0, wdt->base + WDTCONTROL);
+ writel_relaxed(0, wdt->base + WDTLOAD);
+ writel_relaxed(INT_ENABLE | RESET_ENABLE, wdt->base + WDTCONTROL);
+
+ return 0;
+}
+
static int wdt_config(struct watchdog_device *wdd, bool ping)
{
struct sp805_wdt *wdt = watchdog_get_drvdata(wdd);
@@ -197,6 +209,7 @@ static const struct watchdog_ops wdt_ops = {
.ping = wdt_ping,
.set_timeout = wdt_setload,
.get_timeleft = wdt_timeleft,
+ .restart = wdt_restart,
};
static int
@@ -230,6 +243,7 @@ sp805_wdt_probe(struct amba_device *adev, const struct amba_id *id)
spin_lock_init(&wdt->lock);
watchdog_set_nowayout(&wdt->wdd, nowayout);
watchdog_set_drvdata(&wdt->wdd, wdt);
+ watchdog_set_restart_priority(&wdt->wdd, 128);
wdt_setload(&wdt->wdd, DEFAULT_TIMEOUT);
ret = watchdog_register_device(&wdt->wdd);
diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c
index 0da9943..56ad196 100644
--- a/drivers/watchdog/wdat_wdt.c
+++ b/drivers/watchdog/wdat_wdt.c
@@ -447,8 +447,7 @@ static int wdat_wdt_probe(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int wdat_wdt_suspend_noirq(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct wdat_wdt *wdat = platform_get_drvdata(pdev);
+ struct wdat_wdt *wdat = dev_get_drvdata(dev);
int ret;
if (!watchdog_active(&wdat->wdd))
@@ -475,8 +474,7 @@ static int wdat_wdt_suspend_noirq(struct device *dev)
static int wdat_wdt_resume_noirq(struct device *dev)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct wdat_wdt *wdat = platform_get_drvdata(pdev);
+ struct wdat_wdt *wdat = dev_get_drvdata(dev);
int ret;
if (!watchdog_active(&wdat->wdd))
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile
index 451e833..48b1542 100644
--- a/drivers/xen/Makefile
+++ b/drivers/xen/Makefile
@@ -41,4 +41,4 @@ obj-$(CONFIG_XEN_PVCALLS_FRONTEND) += pvcalls-front.o
xen-evtchn-y := evtchn.o
xen-gntdev-y := gntdev.o
xen-gntalloc-y := gntalloc.o
-xen-privcmd-y := privcmd.o
+xen-privcmd-y := privcmd.o privcmd-buf.o
diff --git a/drivers/xen/arm-device.c b/drivers/xen/arm-device.c
index 85dd20e..3e789c7 100644
--- a/drivers/xen/arm-device.c
+++ b/drivers/xen/arm-device.c
@@ -70,9 +70,9 @@ static int xen_map_device_mmio(const struct resource *resources,
if ((resource_type(r) != IORESOURCE_MEM) || (nr == 0))
continue;
- gpfns = kzalloc(sizeof(xen_pfn_t) * nr, GFP_KERNEL);
- idxs = kzalloc(sizeof(xen_ulong_t) * nr, GFP_KERNEL);
- errs = kzalloc(sizeof(int) * nr, GFP_KERNEL);
+ gpfns = kcalloc(nr, sizeof(xen_pfn_t), GFP_KERNEL);
+ idxs = kcalloc(nr, sizeof(xen_ulong_t), GFP_KERNEL);
+ errs = kcalloc(nr, sizeof(int), GFP_KERNEL);
if (!gpfns || !idxs || !errs) {
kfree(gpfns);
kfree(idxs);
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 762378f..08e4af0 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -628,8 +628,6 @@ static void __unbind_from_irq(unsigned int irq)
xen_irq_info_cleanup(info);
}
- BUG_ON(info_for_irq(irq)->type == IRQT_UNBOUND);
-
xen_free_irq(irq);
}
diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
index 8cac07a..6d1a5e5 100644
--- a/drivers/xen/evtchn.c
+++ b/drivers/xen/evtchn.c
@@ -322,7 +322,7 @@ static int evtchn_resize_ring(struct per_user_data *u)
else
new_size = 2 * u->ring_size;
- new_ring = kvmalloc(new_size * sizeof(*new_ring), GFP_KERNEL);
+ new_ring = kvmalloc_array(new_size, sizeof(*new_ring), GFP_KERNEL);
if (!new_ring)
return -ENOMEM;
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 27be107..ba9f3ee 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -799,7 +799,7 @@ int gnttab_alloc_pages(int nr_pages, struct page **pages)
return 0;
}
-EXPORT_SYMBOL(gnttab_alloc_pages);
+EXPORT_SYMBOL_GPL(gnttab_alloc_pages);
/**
* gnttab_free_pages - free pages allocated by gnttab_alloc_pages()
@@ -820,7 +820,7 @@ void gnttab_free_pages(int nr_pages, struct page **pages)
}
free_xenballooned_pages(nr_pages, pages);
}
-EXPORT_SYMBOL(gnttab_free_pages);
+EXPORT_SYMBOL_GPL(gnttab_free_pages);
/* Handling of paged out grant targets (GNTST_eagain) */
#define MAX_DELAY 256
@@ -1137,7 +1137,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
/* No need for kzalloc as it is initialized in following hypercall
* GNTTABOP_setup_table.
*/
- frames = kmalloc(nr_gframes * sizeof(unsigned long), GFP_ATOMIC);
+ frames = kmalloc_array(nr_gframes, sizeof(unsigned long), GFP_ATOMIC);
if (!frames)
return -ENOMEM;
@@ -1300,8 +1300,9 @@ int gnttab_init(void)
max_nr_glist_frames = (max_nr_grant_frames *
gnttab_interface->grefs_per_grant_frame / RPP);
- gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
- GFP_KERNEL);
+ gnttab_list = kmalloc_array(max_nr_glist_frames,
+ sizeof(grant_ref_t *),
+ GFP_KERNEL);
if (gnttab_list == NULL)
return -ENOMEM;
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index 8835065..c93d8ef 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -289,8 +289,15 @@ static void sysrq_handler(struct xenbus_watch *watch, const char *path,
return;
}
- if (sysrq_key != '\0')
- xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
+ if (sysrq_key != '\0') {
+ err = xenbus_printf(xbt, "control", "sysrq", "%c", '\0');
+ if (err) {
+ pr_err("%s: Error %d writing sysrq in control/sysrq\n",
+ __func__, err);
+ xenbus_transaction_end(xbt, 1);
+ return;
+ }
+ }
err = xenbus_transaction_end(xbt, 0);
if (err == -EAGAIN)
@@ -342,7 +349,12 @@ static int setup_shutdown_watcher(void)
continue;
snprintf(node, FEATURE_PATH_SIZE, "feature-%s",
shutdown_handlers[idx].command);
- xenbus_printf(XBT_NIL, "control", node, "%u", 1);
+ err = xenbus_printf(XBT_NIL, "control", node, "%u", 1);
+ if (err) {
+ pr_err("%s: Error %d writing %s\n", __func__,
+ err, node);
+ return err;
+ }
}
return 0;
diff --git a/drivers/xen/privcmd-buf.c b/drivers/xen/privcmd-buf.c
new file mode 100644
index 0000000..df1ed37
--- /dev/null
+++ b/drivers/xen/privcmd-buf.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+
+/******************************************************************************
+ * privcmd-buf.c
+ *
+ * Mmap of hypercall buffers.
+ *
+ * Copyright (c) 2018 Juergen Gross
+ */
+
+#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/miscdevice.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include "privcmd.h"
+
+MODULE_LICENSE("GPL");
+
+static unsigned int limit = 64;
+module_param(limit, uint, 0644);
+MODULE_PARM_DESC(limit, "Maximum number of pages that may be allocated by "
+ "the privcmd-buf device per open file");
+
+struct privcmd_buf_private {
+ struct mutex lock;
+ struct list_head list;
+ unsigned int allocated;
+};
+
+struct privcmd_buf_vma_private {
+ struct privcmd_buf_private *file_priv;
+ struct list_head list;
+ unsigned int users;
+ unsigned int n_pages;
+ struct page *pages[];
+};
+
+static int privcmd_buf_open(struct inode *ino, struct file *file)
+{
+ struct privcmd_buf_private *file_priv;
+
+ file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
+ if (!file_priv)
+ return -ENOMEM;
+
+ mutex_init(&file_priv->lock);
+ INIT_LIST_HEAD(&file_priv->list);
+
+ file->private_data = file_priv;
+
+ return 0;
+}
+
+static void privcmd_buf_vmapriv_free(struct privcmd_buf_vma_private *vma_priv)
+{
+ unsigned int i;
+
+ vma_priv->file_priv->allocated -= vma_priv->n_pages;
+
+ list_del(&vma_priv->list);
+
+ for (i = 0; i < vma_priv->n_pages; i++)
+ if (vma_priv->pages[i])
+ __free_page(vma_priv->pages[i]);
+
+ kfree(vma_priv);
+}
+
+static int privcmd_buf_release(struct inode *ino, struct file *file)
+{
+ struct privcmd_buf_private *file_priv = file->private_data;
+ struct privcmd_buf_vma_private *vma_priv;
+
+ mutex_lock(&file_priv->lock);
+
+ while (!list_empty(&file_priv->list)) {
+ vma_priv = list_first_entry(&file_priv->list,
+ struct privcmd_buf_vma_private,
+ list);
+ privcmd_buf_vmapriv_free(vma_priv);
+ }
+
+ mutex_unlock(&file_priv->lock);
+
+ kfree(file_priv);
+
+ return 0;
+}
+
+static void privcmd_buf_vma_open(struct vm_area_struct *vma)
+{
+ struct privcmd_buf_vma_private *vma_priv = vma->vm_private_data;
+
+ if (!vma_priv)
+ return;
+
+ mutex_lock(&vma_priv->file_priv->lock);
+ vma_priv->users++;
+ mutex_unlock(&vma_priv->file_priv->lock);
+}
+
+static void privcmd_buf_vma_close(struct vm_area_struct *vma)
+{
+ struct privcmd_buf_vma_private *vma_priv = vma->vm_private_data;
+ struct privcmd_buf_private *file_priv;
+
+ if (!vma_priv)
+ return;
+
+ file_priv = vma_priv->file_priv;
+
+ mutex_lock(&file_priv->lock);
+
+ vma_priv->users--;
+ if (!vma_priv->users)
+ privcmd_buf_vmapriv_free(vma_priv);
+
+ mutex_unlock(&file_priv->lock);
+}
+
+static vm_fault_t privcmd_buf_vma_fault(struct vm_fault *vmf)
+{
+ pr_debug("fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n",
+ vmf->vma, vmf->vma->vm_start, vmf->vma->vm_end,
+ vmf->pgoff, (void *)vmf->address);
+
+ return VM_FAULT_SIGBUS;
+}
+
+static const struct vm_operations_struct privcmd_buf_vm_ops = {
+ .open = privcmd_buf_vma_open,
+ .close = privcmd_buf_vma_close,
+ .fault = privcmd_buf_vma_fault,
+};
+
+static int privcmd_buf_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct privcmd_buf_private *file_priv = file->private_data;
+ struct privcmd_buf_vma_private *vma_priv;
+ unsigned long count = vma_pages(vma);
+ unsigned int i;
+ int ret = 0;
+
+ if (!(vma->vm_flags & VM_SHARED) || count > limit ||
+ file_priv->allocated + count > limit)
+ return -EINVAL;
+
+ vma_priv = kzalloc(sizeof(*vma_priv) + count * sizeof(void *),
+ GFP_KERNEL);
+ if (!vma_priv)
+ return -ENOMEM;
+
+ vma_priv->n_pages = count;
+ count = 0;
+ for (i = 0; i < vma_priv->n_pages; i++) {
+ vma_priv->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!vma_priv->pages[i])
+ break;
+ count++;
+ }
+
+ mutex_lock(&file_priv->lock);
+
+ file_priv->allocated += count;
+
+ vma_priv->file_priv = file_priv;
+ vma_priv->users = 1;
+
+ vma->vm_flags |= VM_IO | VM_DONTEXPAND;
+ vma->vm_ops = &privcmd_buf_vm_ops;
+ vma->vm_private_data = vma_priv;
+
+ list_add(&vma_priv->list, &file_priv->list);
+
+ if (vma_priv->n_pages != count)
+ ret = -ENOMEM;
+ else
+ for (i = 0; i < vma_priv->n_pages; i++) {
+ ret = vm_insert_page(vma, vma->vm_start + i * PAGE_SIZE,
+ vma_priv->pages[i]);
+ if (ret)
+ break;
+ }
+
+ if (ret)
+ privcmd_buf_vmapriv_free(vma_priv);
+
+ mutex_unlock(&file_priv->lock);
+
+ return ret;
+}
+
+const struct file_operations xen_privcmdbuf_fops = {
+ .owner = THIS_MODULE,
+ .open = privcmd_buf_open,
+ .release = privcmd_buf_release,
+ .mmap = privcmd_buf_mmap,
+};
+EXPORT_SYMBOL_GPL(xen_privcmdbuf_fops);
+
+struct miscdevice xen_privcmdbuf_dev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "xen/hypercall",
+ .fops = &xen_privcmdbuf_fops,
+};
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 8ae0349..7e6e6821 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -1007,12 +1007,21 @@ static int __init privcmd_init(void)
pr_err("Could not register Xen privcmd device\n");
return err;
}
+
+ err = misc_register(&xen_privcmdbuf_dev);
+ if (err != 0) {
+ pr_err("Could not register Xen hypercall-buf device\n");
+ misc_deregister(&privcmd_dev);
+ return err;
+ }
+
return 0;
}
static void __exit privcmd_exit(void)
{
misc_deregister(&privcmd_dev);
+ misc_deregister(&xen_privcmdbuf_dev);
}
module_init(privcmd_init);
diff --git a/drivers/xen/privcmd.h b/drivers/xen/privcmd.h
index 14facae..0dd9f8f 100644
--- a/drivers/xen/privcmd.h
+++ b/drivers/xen/privcmd.h
@@ -1,3 +1,6 @@
#include <linux/fs.h>
extern const struct file_operations xen_privcmd_fops;
+extern const struct file_operations xen_privcmdbuf_fops;
+
+extern struct miscdevice xen_privcmdbuf_dev;
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c
index ee2c891..ea4a08b 100644
--- a/drivers/xen/xen-pciback/pciback_ops.c
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -234,7 +234,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev,
if (dev->msi_enabled || !(cmd & PCI_COMMAND_MEMORY))
return -ENXIO;
- entries = kmalloc(op->value * sizeof(*entries), GFP_KERNEL);
+ entries = kmalloc_array(op->value, sizeof(*entries), GFP_KERNEL);
if (entries == NULL)
return -ENOMEM;
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index 7bc88fd..e2f3e8b 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -1012,6 +1012,7 @@ static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state,
{
struct v2p_entry *entry;
unsigned long flags;
+ int err;
if (try) {
spin_lock_irqsave(&info->v2p_lock, flags);
@@ -1027,8 +1028,11 @@ static void scsiback_do_add_lun(struct vscsibk_info *info, const char *state,
scsiback_del_translation_entry(info, vir);
}
} else if (!try) {
- xenbus_printf(XBT_NIL, info->dev->nodename, state,
+ err = xenbus_printf(XBT_NIL, info->dev->nodename, state,
"%d", XenbusStateClosed);
+ if (err)
+ xenbus_dev_error(info->dev, err,
+ "%s: writing %s", __func__, state);
}
}
@@ -1067,8 +1071,11 @@ static void scsiback_do_1lun_hotplug(struct vscsibk_info *info, int op,
snprintf(str, sizeof(str), "vscsi-devs/%s/p-dev", ent);
val = xenbus_read(XBT_NIL, dev->nodename, str, NULL);
if (IS_ERR(val)) {
- xenbus_printf(XBT_NIL, dev->nodename, state,
+ err = xenbus_printf(XBT_NIL, dev->nodename, state,
"%d", XenbusStateClosed);
+ if (err)
+ xenbus_dev_error(info->dev, err,
+ "%s: writing %s", __func__, state);
return;
}
strlcpy(phy, val, VSCSI_NAMELEN);
@@ -1079,8 +1086,11 @@ static void scsiback_do_1lun_hotplug(struct vscsibk_info *info, int op,
err = xenbus_scanf(XBT_NIL, dev->nodename, str, "%u:%u:%u:%u",
&vir.hst, &vir.chn, &vir.tgt, &vir.lun);
if (XENBUS_EXIST_ERR(err)) {
- xenbus_printf(XBT_NIL, dev->nodename, state,
+ err = xenbus_printf(XBT_NIL, dev->nodename, state,
"%d", XenbusStateClosed);
+ if (err)
+ xenbus_dev_error(info->dev, err,
+ "%s: writing %s", __func__, state);
return;
}
diff --git a/fs/9p/fid.c b/fs/9p/fid.c
index ed4f851..a9ef46f 100644
--- a/fs/9p/fid.c
+++ b/fs/9p/fid.c
@@ -100,7 +100,7 @@ static int build_path_from_dentry(struct v9fs_session_info *v9ses,
for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent)
n++;
- wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL);
+ wnames = kmalloc_array(n, sizeof(char *), GFP_KERNEL);
if (!wnames)
goto err_out;
diff --git a/fs/Kconfig b/fs/Kconfig
index ab2d96d..ac474a6 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -110,7 +110,6 @@ source "fs/notify/Kconfig"
source "fs/quota/Kconfig"
source "fs/autofs/Kconfig"
-source "fs/autofs4/Kconfig"
source "fs/fuse/Kconfig"
source "fs/overlayfs/Kconfig"
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 57a27c4..56df483 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -168,7 +168,7 @@ config BINFMT_MISC
will automatically feed it to the correct interpreter.
You can do other nice things, too. Read the file
- <file:Documentation/binfmt_misc.txt> to learn how to use this
+ <file:Documentation/admin-guide/binfmt-misc.rst> to learn how to use this
feature, <file:Documentation/admin-guide/java.rst> for information about how
to include Java support. and <file:Documentation/admin-guide/mono.rst> for
information about how to include Mono-based .NET support.
diff --git a/fs/Makefile b/fs/Makefile
index 2e00552..293733f 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -103,7 +103,6 @@ obj-$(CONFIG_ROMFS_FS) += romfs/
obj-$(CONFIG_QNX4FS_FS) += qnx4/
obj-$(CONFIG_QNX6FS_FS) += qnx6/
obj-$(CONFIG_AUTOFS_FS) += autofs/
-obj-$(CONFIG_AUTOFS4_FS) += autofs4/
obj-$(CONFIG_ADFS_FS) += adfs/
obj-$(CONFIG_FUSE_FS) += fuse/
obj-$(CONFIG_OVERLAY_FS) += overlayfs/
diff --git a/fs/adfs/inode.c b/fs/adfs/inode.c
index 8dbd36f..c836c42 100644
--- a/fs/adfs/inode.c
+++ b/fs/adfs/inode.c
@@ -199,7 +199,7 @@ adfs_adfs2unix_time(struct timespec *tv, struct inode *inode)
return;
cur_time:
- *tv = current_time(inode);
+ *tv = timespec64_to_timespec(current_time(inode));
return;
too_early:
@@ -242,6 +242,7 @@ adfs_unix2adfs_time(struct inode *inode, unsigned int secs)
struct inode *
adfs_iget(struct super_block *sb, struct object_info *obj)
{
+ struct timespec ts;
struct inode *inode;
inode = new_inode(sb);
@@ -270,7 +271,9 @@ adfs_iget(struct super_block *sb, struct object_info *obj)
ADFS_I(inode)->stamped = ((obj->loadaddr & 0xfff00000) == 0xfff00000);
inode->i_mode = adfs_atts2mode(sb, inode);
- adfs_adfs2unix_time(&inode->i_mtime, inode);
+ ts = timespec64_to_timespec(inode->i_mtime);
+ adfs_adfs2unix_time(&ts, inode);
+ inode->i_mtime = timespec_to_timespec64(ts);
inode->i_atime = inode->i_mtime;
inode->i_ctime = inode->i_mtime;
diff --git a/fs/adfs/super.c b/fs/adfs/super.c
index cfda2c7..71fa525 100644
--- a/fs/adfs/super.c
+++ b/fs/adfs/super.c
@@ -313,7 +313,7 @@ static struct adfs_discmap *adfs_read_map(struct super_block *sb, struct adfs_di
asb->s_ids_per_zone = zone_size / (asb->s_idlen + 1);
- dm = kmalloc(nzones * sizeof(*dm), GFP_KERNEL);
+ dm = kmalloc_array(nzones, sizeof(*dm), GFP_KERNEL);
if (dm == NULL) {
adfs_error(sb, "not enough memory");
return ERR_PTR(-ENOMEM);
diff --git a/fs/afs/Makefile b/fs/afs/Makefile
index 532acae..5468740 100644
--- a/fs/afs/Makefile
+++ b/fs/afs/Makefile
@@ -5,7 +5,7 @@
afs-cache-$(CONFIG_AFS_FSCACHE) := cache.o
-kafs-objs := \
+kafs-y := \
$(afs-cache-y) \
addr_list.o \
callback.o \
@@ -21,7 +21,6 @@ kafs-objs := \
main.o \
misc.o \
mntpt.o \
- proc.o \
rotate.o \
rxrpc.o \
security.o \
@@ -34,4 +33,5 @@ kafs-objs := \
write.o \
xattr.o
+kafs-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_AFS_FS) := kafs.o
diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c
index 2c46c46..025a9a5 100644
--- a/fs/afs/addr_list.c
+++ b/fs/afs/addr_list.c
@@ -215,7 +215,7 @@ struct afs_addr_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry)
_enter("%s", cell->name);
ret = dns_query("afsdb", cell->name, cell->name_len,
- "ipv4", &vllist, _expiry);
+ "", &vllist, _expiry);
if (ret < 0)
return ERR_PTR(ret);
diff --git a/fs/afs/callback.c b/fs/afs/callback.c
index 571437d..5f261fb 100644
--- a/fs/afs/callback.c
+++ b/fs/afs/callback.c
@@ -21,6 +21,66 @@
#include "internal.h"
/*
+ * Create volume and callback interests on a server.
+ */
+static struct afs_cb_interest *afs_create_interest(struct afs_server *server,
+ struct afs_vnode *vnode)
+{
+ struct afs_vol_interest *new_vi, *vi;
+ struct afs_cb_interest *new;
+ struct hlist_node **pp;
+
+ new_vi = kzalloc(sizeof(struct afs_vol_interest), GFP_KERNEL);
+ if (!new_vi)
+ return NULL;
+
+ new = kzalloc(sizeof(struct afs_cb_interest), GFP_KERNEL);
+ if (!new) {
+ kfree(new_vi);
+ return NULL;
+ }
+
+ new_vi->usage = 1;
+ new_vi->vid = vnode->volume->vid;
+ INIT_HLIST_NODE(&new_vi->srv_link);
+ INIT_HLIST_HEAD(&new_vi->cb_interests);
+
+ refcount_set(&new->usage, 1);
+ new->sb = vnode->vfs_inode.i_sb;
+ new->vid = vnode->volume->vid;
+ new->server = afs_get_server(server);
+ INIT_HLIST_NODE(&new->cb_vlink);
+
+ write_lock(&server->cb_break_lock);
+
+ for (pp = &server->cb_volumes.first; *pp; pp = &(*pp)->next) {
+ vi = hlist_entry(*pp, struct afs_vol_interest, srv_link);
+ if (vi->vid < new_vi->vid)
+ continue;
+ if (vi->vid > new_vi->vid)
+ break;
+ vi->usage++;
+ goto found_vi;
+ }
+
+ new_vi->srv_link.pprev = pp;
+ new_vi->srv_link.next = *pp;
+ if (*pp)
+ (*pp)->pprev = &new_vi->srv_link.next;
+ *pp = &new_vi->srv_link;
+ vi = new_vi;
+ new_vi = NULL;
+found_vi:
+
+ new->vol_interest = vi;
+ hlist_add_head(&new->cb_vlink, &vi->cb_interests);
+
+ write_unlock(&server->cb_break_lock);
+ kfree(new_vi);
+ return new;
+}
+
+/*
* Set up an interest-in-callbacks record for a volume on a server and
* register it with the server.
* - Called with vnode->io_lock held.
@@ -77,20 +137,10 @@ again:
}
if (!cbi) {
- new = kzalloc(sizeof(struct afs_cb_interest), GFP_KERNEL);
+ new = afs_create_interest(server, vnode);
if (!new)
return -ENOMEM;
- refcount_set(&new->usage, 1);
- new->sb = vnode->vfs_inode.i_sb;
- new->vid = vnode->volume->vid;
- new->server = afs_get_server(server);
- INIT_LIST_HEAD(&new->cb_link);
-
- write_lock(&server->cb_break_lock);
- list_add_tail(&new->cb_link, &server->cb_interests);
- write_unlock(&server->cb_break_lock);
-
write_lock(&slist->lock);
if (!entry->cb_interest) {
entry->cb_interest = afs_get_cb_interest(new);
@@ -126,11 +176,22 @@ again:
*/
void afs_put_cb_interest(struct afs_net *net, struct afs_cb_interest *cbi)
{
+ struct afs_vol_interest *vi;
+
if (cbi && refcount_dec_and_test(&cbi->usage)) {
- if (!list_empty(&cbi->cb_link)) {
+ if (!hlist_unhashed(&cbi->cb_vlink)) {
write_lock(&cbi->server->cb_break_lock);
- list_del_init(&cbi->cb_link);
+
+ hlist_del_init(&cbi->cb_vlink);
+ vi = cbi->vol_interest;
+ cbi->vol_interest = NULL;
+ if (--vi->usage == 0)
+ hlist_del(&vi->srv_link);
+ else
+ vi = NULL;
+
write_unlock(&cbi->server->cb_break_lock);
+ kfree(vi);
afs_put_server(net, cbi->server);
}
kfree(cbi);
@@ -182,20 +243,34 @@ void afs_break_callback(struct afs_vnode *vnode)
static void afs_break_one_callback(struct afs_server *server,
struct afs_fid *fid)
{
+ struct afs_vol_interest *vi;
struct afs_cb_interest *cbi;
struct afs_iget_data data;
struct afs_vnode *vnode;
struct inode *inode;
read_lock(&server->cb_break_lock);
+ hlist_for_each_entry(vi, &server->cb_volumes, srv_link) {
+ if (vi->vid < fid->vid)
+ continue;
+ if (vi->vid > fid->vid) {
+ vi = NULL;
+ break;
+ }
+ //atomic_inc(&vi->usage);
+ break;
+ }
+
+ /* TODO: Find all matching volumes if we couldn't match the server and
+ * break them anyway.
+ */
+ if (!vi)
+ goto out;
/* Step through all interested superblocks. There may be more than one
* because of cell aliasing.
*/
- list_for_each_entry(cbi, &server->cb_interests, cb_link) {
- if (cbi->vid != fid->vid)
- continue;
-
+ hlist_for_each_entry(cbi, &vi->cb_interests, cb_vlink) {
if (fid->vnode == 0 && fid->unique == 0) {
/* The callback break applies to an entire volume. */
struct afs_super_info *as = AFS_FS_S(cbi->sb);
@@ -217,6 +292,7 @@ static void afs_break_one_callback(struct afs_server *server,
}
}
+out:
read_unlock(&server->cb_break_lock);
}
diff --git a/fs/afs/cell.c b/fs/afs/cell.c
index fdf4c36..f3d0bef 100644
--- a/fs/afs/cell.c
+++ b/fs/afs/cell.c
@@ -15,6 +15,7 @@
#include <linux/dns_resolver.h>
#include <linux/sched.h>
#include <linux/inet.h>
+#include <linux/namei.h>
#include <keys/rxrpc-type.h>
#include "internal.h"
@@ -341,8 +342,8 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
/* install the new cell */
write_seqlock(&net->cells_lock);
- old_root = net->ws_cell;
- net->ws_cell = new_root;
+ old_root = rcu_access_pointer(net->ws_cell);
+ rcu_assign_pointer(net->ws_cell, new_root);
write_sequnlock(&net->cells_lock);
afs_put_cell(net, old_root);
@@ -528,12 +529,14 @@ static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell)
NULL, 0,
cell, 0, true);
#endif
- ret = afs_proc_cell_setup(net, cell);
+ ret = afs_proc_cell_setup(cell);
if (ret < 0)
return ret;
- spin_lock(&net->proc_cells_lock);
+
+ mutex_lock(&net->proc_cells_lock);
list_add_tail(&cell->proc_link, &net->proc_cells);
- spin_unlock(&net->proc_cells_lock);
+ afs_dynroot_mkdir(net, cell);
+ mutex_unlock(&net->proc_cells_lock);
return 0;
}
@@ -544,11 +547,12 @@ static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell)
{
_enter("%s", cell->name);
- afs_proc_cell_remove(net, cell);
+ afs_proc_cell_remove(cell);
- spin_lock(&net->proc_cells_lock);
+ mutex_lock(&net->proc_cells_lock);
list_del_init(&cell->proc_link);
- spin_unlock(&net->proc_cells_lock);
+ afs_dynroot_rmdir(net, cell);
+ mutex_unlock(&net->proc_cells_lock);
#ifdef CONFIG_AFS_FSCACHE
fscache_relinquish_cookie(cell->cache, NULL, false);
@@ -755,8 +759,8 @@ void afs_cell_purge(struct afs_net *net)
_enter("");
write_seqlock(&net->cells_lock);
- ws = net->ws_cell;
- net->ws_cell = NULL;
+ ws = rcu_access_pointer(net->ws_cell);
+ RCU_INIT_POINTER(net->ws_cell, NULL);
write_sequnlock(&net->cells_lock);
afs_put_cell(net, ws);
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index c332c95..9e51d6f 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -191,7 +191,8 @@ static int afs_deliver_cb_callback(struct afs_call *call)
if (call->count > AFSCBMAX)
return afs_protocol_error(call, -EBADMSG);
- call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL);
+ call->buffer = kmalloc(array3_size(call->count, 3, 4),
+ GFP_KERNEL);
if (!call->buffer)
return -ENOMEM;
call->offset = 0;
@@ -330,7 +331,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
switch (call->unmarshall) {
case 0:
call->offset = 0;
- call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
+ call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
if (!call->buffer)
return -ENOMEM;
call->unmarshall++;
@@ -453,7 +454,7 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
switch (call->unmarshall) {
case 0:
call->offset = 0;
- call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
+ call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
if (!call->buffer)
return -ENOMEM;
call->unmarshall++;
@@ -525,7 +526,7 @@ static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
nifs = 0;
ifs = kcalloc(32, sizeof(*ifs), GFP_KERNEL);
if (ifs) {
- nifs = afs_get_ipv4_interfaces(ifs, 32, false);
+ nifs = afs_get_ipv4_interfaces(call->net, ifs, 32, false);
if (nifs < 0) {
kfree(ifs);
ifs = NULL;
diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c
index 983f394..174e843 100644
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -1,4 +1,4 @@
-/* dir.c: AFS dynamic root handling
+/* AFS dynamic root handling
*
* Copyright (C) 2018 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
@@ -46,7 +46,7 @@ static int afs_probe_cell_name(struct dentry *dentry)
return 0;
}
- ret = dns_query("afsdb", name, len, "ipv4", NULL, NULL);
+ ret = dns_query("afsdb", name, len, "", NULL, NULL);
if (ret == -ENODATA)
ret = -EDESTADDRREQ;
return ret;
@@ -207,3 +207,125 @@ const struct dentry_operations afs_dynroot_dentry_operations = {
.d_release = afs_d_release,
.d_automount = afs_d_automount,
};
+
+/*
+ * Create a manually added cell mount directory.
+ * - The caller must hold net->proc_cells_lock
+ */
+int afs_dynroot_mkdir(struct afs_net *net, struct afs_cell *cell)
+{
+ struct super_block *sb = net->dynroot_sb;
+ struct dentry *root, *subdir;
+ int ret;
+
+ if (!sb || atomic_read(&sb->s_active) == 0)
+ return 0;
+
+ /* Let the ->lookup op do the creation */
+ root = sb->s_root;
+ inode_lock(root->d_inode);
+ subdir = lookup_one_len(cell->name, root, cell->name_len);
+ if (IS_ERR(subdir)) {
+ ret = PTR_ERR(subdir);
+ goto unlock;
+ }
+
+ /* Note that we're retaining an extra ref on the dentry */
+ subdir->d_fsdata = (void *)1UL;
+ ret = 0;
+unlock:
+ inode_unlock(root->d_inode);
+ return ret;
+}
+
+/*
+ * Remove a manually added cell mount directory.
+ * - The caller must hold net->proc_cells_lock
+ */
+void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
+{
+ struct super_block *sb = net->dynroot_sb;
+ struct dentry *root, *subdir;
+
+ if (!sb || atomic_read(&sb->s_active) == 0)
+ return;
+
+ root = sb->s_root;
+ inode_lock(root->d_inode);
+
+ /* Don't want to trigger a lookup call, which will re-add the cell */
+ subdir = try_lookup_one_len(cell->name, root, cell->name_len);
+ if (IS_ERR_OR_NULL(subdir)) {
+ _debug("lookup %ld", PTR_ERR(subdir));
+ goto no_dentry;
+ }
+
+ _debug("rmdir %pd %u", subdir, d_count(subdir));
+
+ if (subdir->d_fsdata) {
+ _debug("unpin %u", d_count(subdir));
+ subdir->d_fsdata = NULL;
+ dput(subdir);
+ }
+ dput(subdir);
+no_dentry:
+ inode_unlock(root->d_inode);
+ _leave("");
+}
+
+/*
+ * Populate a newly created dynamic root with cell names.
+ */
+int afs_dynroot_populate(struct super_block *sb)
+{
+ struct afs_cell *cell;
+ struct afs_net *net = afs_sb2net(sb);
+ int ret;
+
+ if (mutex_lock_interruptible(&net->proc_cells_lock) < 0)
+ return -ERESTARTSYS;
+
+ net->dynroot_sb = sb;
+ list_for_each_entry(cell, &net->proc_cells, proc_link) {
+ ret = afs_dynroot_mkdir(net, cell);
+ if (ret < 0)
+ goto error;
+ }
+
+ ret = 0;
+out:
+ mutex_unlock(&net->proc_cells_lock);
+ return ret;
+
+error:
+ net->dynroot_sb = NULL;
+ goto out;
+}
+
+/*
+ * When a dynamic root that's in the process of being destroyed, depopulate it
+ * of pinned directories.
+ */
+void afs_dynroot_depopulate(struct super_block *sb)
+{
+ struct afs_net *net = afs_sb2net(sb);
+ struct dentry *root = sb->s_root, *subdir, *tmp;
+
+ /* Prevent more subdirs from being created */
+ mutex_lock(&net->proc_cells_lock);
+ if (net->dynroot_sb == sb)
+ net->dynroot_sb = NULL;
+ mutex_unlock(&net->proc_cells_lock);
+
+ inode_lock(root->d_inode);
+
+ /* Remove all the pins for dirs created for manually added cells */
+ list_for_each_entry_safe(subdir, tmp, &root->d_subdirs, d_child) {
+ if (subdir->d_fsdata) {
+ subdir->d_fsdata = NULL;
+ dput(subdir);
+ }
+ }
+
+ inode_unlock(root->d_inode);
+}
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c
index b273e1d..50929cb 100644
--- a/fs/afs/fsclient.c
+++ b/fs/afs/fsclient.c
@@ -72,7 +72,7 @@ void afs_update_inode_from_status(struct afs_vnode *vnode,
const afs_dataversion_t *expected_version,
u8 flags)
{
- struct timespec t;
+ struct timespec64 t;
umode_t mode;
t.tv_sec = status->mtime_client;
@@ -138,10 +138,6 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
u64 data_version, size;
u32 type, abort_code;
u8 flags = 0;
- int ret;
-
- if (vnode)
- write_seqlock(&vnode->cb_lock);
abort_code = ntohl(xdr->abort_code);
@@ -154,8 +150,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
* case.
*/
status->abort_code = abort_code;
- ret = 0;
- goto out;
+ return 0;
}
pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
@@ -164,8 +159,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
if (abort_code != 0 && inline_error) {
status->abort_code = abort_code;
- ret = 0;
- goto out;
+ return 0;
}
type = ntohl(xdr->type);
@@ -235,17 +229,35 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
flags);
}
- ret = 0;
-
-out:
- if (vnode)
- write_sequnlock(&vnode->cb_lock);
- return ret;
+ return 0;
bad:
xdr_dump_bad(*_bp);
- ret = afs_protocol_error(call, -EBADMSG);
- goto out;
+ return afs_protocol_error(call, -EBADMSG);
+}
+
+/*
+ * Decode the file status. We need to lock the target vnode if we're going to
+ * update its status so that stat() sees the attributes update atomically.
+ */
+static int afs_decode_status(struct afs_call *call,
+ const __be32 **_bp,
+ struct afs_file_status *status,
+ struct afs_vnode *vnode,
+ const afs_dataversion_t *expected_version,
+ struct afs_read *read_req)
+{
+ int ret;
+
+ if (!vnode)
+ return xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
+ expected_version, read_req);
+
+ write_seqlock(&vnode->cb_lock);
+ ret = xdr_decode_AFSFetchStatus(call, _bp, status, vnode,
+ expected_version, read_req);
+ write_sequnlock(&vnode->cb_lock);
+ return ret;
}
/*
@@ -387,8 +399,8 @@ static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
xdr_decode_AFSCallBack(call, vnode, &bp);
if (call->reply[1])
@@ -568,8 +580,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
return ret;
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &vnode->status.data_version, req) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode,
+ &vnode->status.data_version, req) < 0)
return afs_protocol_error(call, -EBADMSG);
xdr_decode_AFSCallBack(call, vnode, &bp);
if (call->reply[1])
@@ -721,9 +733,9 @@ static int afs_deliver_fs_create_vnode(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
xdr_decode_AFSFid(&bp, call->reply[1]);
- if (xdr_decode_AFSFetchStatus(call, &bp, call->reply[2], NULL, NULL, NULL) < 0 ||
- xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL) < 0 ||
+ afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -827,8 +839,8 @@ static int afs_deliver_fs_remove(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -917,9 +929,9 @@ static int afs_deliver_fs_link(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, NULL, NULL) < 0 ||
- xdr_decode_AFSFetchStatus(call, &bp, &dvnode->status, dvnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL) < 0 ||
+ afs_decode_status(call, &bp, &dvnode->status, dvnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -1004,9 +1016,9 @@ static int afs_deliver_fs_symlink(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
xdr_decode_AFSFid(&bp, call->reply[1]);
- if (xdr_decode_AFSFetchStatus(call, &bp, call->reply[2], NULL, NULL, NULL) ||
- xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL) ||
+ afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -1110,12 +1122,12 @@ static int afs_deliver_fs_rename(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &orig_dvnode->status, orig_dvnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
if (new_dvnode != orig_dvnode &&
- xdr_decode_AFSFetchStatus(call, &bp, &new_dvnode->status, new_dvnode,
- &call->expected_version_2, NULL) < 0)
+ afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode,
+ &call->expected_version_2, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -1219,8 +1231,8 @@ static int afs_deliver_fs_store_data(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -1395,8 +1407,8 @@ static int afs_deliver_fs_store_status(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
- &call->expected_version, NULL) < 0)
+ if (afs_decode_status(call, &bp, &vnode->status, vnode,
+ &call->expected_version, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -2097,8 +2109,8 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call)
/* unmarshall the reply once we've received all of it */
bp = call->buffer;
- xdr_decode_AFSFetchStatus(call, &bp, status, vnode,
- &call->expected_version, NULL);
+ afs_decode_status(call, &bp, status, vnode,
+ &call->expected_version, NULL);
callback[call->count].version = ntohl(bp[0]);
callback[call->count].expiry = ntohl(bp[1]);
callback[call->count].type = ntohl(bp[2]);
@@ -2209,9 +2221,9 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
bp = call->buffer;
statuses = call->reply[1];
- if (xdr_decode_AFSFetchStatus(call, &bp, &statuses[call->count],
- call->count == 0 ? vnode : NULL,
- NULL, NULL) < 0)
+ if (afs_decode_status(call, &bp, &statuses[call->count],
+ call->count == 0 ? vnode : NULL,
+ NULL, NULL) < 0)
return afs_protocol_error(call, -EBADMSG);
call->count++;
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index e3f8a46..9778df1 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -22,6 +22,8 @@
#include <linux/backing-dev.h>
#include <linux/uuid.h>
#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+#include <net/sock.h>
#include <net/af_rxrpc.h>
#include "afs.h"
@@ -40,7 +42,8 @@ struct afs_mount_params {
afs_voltype_t type; /* type of volume requested */
int volnamesz; /* size of volume name */
const char *volname; /* name of volume to mount */
- struct afs_net *net; /* Network namespace in effect */
+ struct net *net_ns; /* Network namespace in effect */
+ struct afs_net *net; /* the AFS net namespace stuff */
struct afs_cell *cell; /* cell in which to find volume */
struct afs_volume *volume; /* volume record */
struct key *key; /* key to use for secure mounting */
@@ -189,7 +192,7 @@ struct afs_read {
* - there's one superblock per volume
*/
struct afs_super_info {
- struct afs_net *net; /* Network namespace */
+ struct net *net_ns; /* Network namespace */
struct afs_cell *cell; /* The cell in which the volume resides */
struct afs_volume *volume; /* volume record */
bool dyn_root; /* True if dynamic root */
@@ -210,7 +213,6 @@ struct afs_sysnames {
char *subs[AFS_NR_SYSNAME];
refcount_t usage;
unsigned short nr;
- short error;
char blank[1];
};
@@ -218,6 +220,7 @@ struct afs_sysnames {
* AFS network namespace record.
*/
struct afs_net {
+ struct net *net; /* Backpointer to the owning net namespace */
struct afs_uuid uuid;
bool live; /* F if this namespace is being removed */
@@ -231,13 +234,13 @@ struct afs_net {
/* Cell database */
struct rb_root cells;
- struct afs_cell *ws_cell;
+ struct afs_cell __rcu *ws_cell;
struct work_struct cells_manager;
struct timer_list cells_timer;
atomic_t cells_outstanding;
seqlock_t cells_lock;
- spinlock_t proc_cells_lock;
+ struct mutex proc_cells_lock;
struct list_head proc_cells;
/* Known servers. Theoretically each fileserver can only be in one
@@ -261,6 +264,7 @@ struct afs_net {
struct mutex lock_manager_mutex;
/* Misc */
+ struct super_block *dynroot_sb; /* Dynamic root mount superblock */
struct proc_dir_entry *proc_afs; /* /proc/net/afs directory */
struct afs_sysnames *sysnames;
rwlock_t sysnames_lock;
@@ -280,7 +284,6 @@ struct afs_net {
};
extern const char afs_init_sysname[];
-extern struct afs_net __afs_net;// Dummy AFS network namespace; TODO: replace with real netns
enum afs_cell_state {
AFS_CELL_UNSET,
@@ -404,16 +407,27 @@ struct afs_server {
rwlock_t fs_lock; /* access lock */
/* callback promise management */
- struct list_head cb_interests; /* List of superblocks using this server */
+ struct hlist_head cb_volumes; /* List of volume interests on this server */
unsigned cb_s_break; /* Break-everything counter. */
rwlock_t cb_break_lock; /* Volume finding lock */
};
/*
+ * Volume collation in the server's callback interest list.
+ */
+struct afs_vol_interest {
+ struct hlist_node srv_link; /* Link in server->cb_volumes */
+ struct hlist_head cb_interests; /* List of callback interests on the server */
+ afs_volid_t vid; /* Volume ID to match */
+ unsigned int usage;
+};
+
+/*
* Interest by a superblock on a server.
*/
struct afs_cb_interest {
- struct list_head cb_link; /* Link in server->cb_interests */
+ struct hlist_node cb_vlink; /* Link in vol_interest->cb_interests */
+ struct afs_vol_interest *vol_interest;
struct afs_server *server; /* Server on which this interest resides */
struct super_block *sb; /* Superblock on which inodes reside */
afs_volid_t vid; /* Volume ID to match */
@@ -720,6 +734,10 @@ extern const struct inode_operations afs_dynroot_inode_operations;
extern const struct dentry_operations afs_dynroot_dentry_operations;
extern struct inode *afs_try_auto_mntpt(struct dentry *, struct inode *);
+extern int afs_dynroot_mkdir(struct afs_net *, struct afs_cell *);
+extern void afs_dynroot_rmdir(struct afs_net *, struct afs_cell *);
+extern int afs_dynroot_populate(struct super_block *);
+extern void afs_dynroot_depopulate(struct super_block *);
/*
* file.c
@@ -806,34 +824,36 @@ extern int afs_drop_inode(struct inode *);
* main.c
*/
extern struct workqueue_struct *afs_wq;
+extern int afs_net_id;
-static inline struct afs_net *afs_d2net(struct dentry *dentry)
+static inline struct afs_net *afs_net(struct net *net)
{
- return &__afs_net;
+ return net_generic(net, afs_net_id);
}
-static inline struct afs_net *afs_i2net(struct inode *inode)
+static inline struct afs_net *afs_sb2net(struct super_block *sb)
{
- return &__afs_net;
+ return afs_net(AFS_FS_S(sb)->net_ns);
}
-static inline struct afs_net *afs_v2net(struct afs_vnode *vnode)
+static inline struct afs_net *afs_d2net(struct dentry *dentry)
{
- return &__afs_net;
+ return afs_sb2net(dentry->d_sb);
}
-static inline struct afs_net *afs_sock2net(struct sock *sk)
+static inline struct afs_net *afs_i2net(struct inode *inode)
{
- return &__afs_net;
+ return afs_sb2net(inode->i_sb);
}
-static inline struct afs_net *afs_get_net(struct afs_net *net)
+static inline struct afs_net *afs_v2net(struct afs_vnode *vnode)
{
- return net;
+ return afs_i2net(&vnode->vfs_inode);
}
-static inline void afs_put_net(struct afs_net *net)
+static inline struct afs_net *afs_sock2net(struct sock *sk)
{
+ return net_generic(sock_net(sk), afs_net_id);
}
static inline void __afs_stat(atomic_t *s)
@@ -861,16 +881,25 @@ extern void afs_mntpt_kill_timer(void);
/*
* netdevices.c
*/
-extern int afs_get_ipv4_interfaces(struct afs_interface *, size_t, bool);
+extern int afs_get_ipv4_interfaces(struct afs_net *, struct afs_interface *,
+ size_t, bool);
/*
* proc.c
*/
+#ifdef CONFIG_PROC_FS
extern int __net_init afs_proc_init(struct afs_net *);
extern void __net_exit afs_proc_cleanup(struct afs_net *);
-extern int afs_proc_cell_setup(struct afs_net *, struct afs_cell *);
-extern void afs_proc_cell_remove(struct afs_net *, struct afs_cell *);
+extern int afs_proc_cell_setup(struct afs_cell *);
+extern void afs_proc_cell_remove(struct afs_cell *);
extern void afs_put_sysnames(struct afs_sysnames *);
+#else
+static inline int afs_proc_init(struct afs_net *net) { return 0; }
+static inline void afs_proc_cleanup(struct afs_net *net) {}
+static inline int afs_proc_cell_setup(struct afs_cell *cell) { return 0; }
+static inline void afs_proc_cell_remove(struct afs_cell *cell) {}
+static inline void afs_put_sysnames(struct afs_sysnames *sysnames) {}
+#endif
/*
* rotate.c
@@ -1002,7 +1031,7 @@ extern bool afs_annotate_server_list(struct afs_server_list *, struct afs_server
* super.c
*/
extern int __init afs_fs_init(void);
-extern void __exit afs_fs_exit(void);
+extern void afs_fs_exit(void);
/*
* vlclient.c
diff --git a/fs/afs/main.c b/fs/afs/main.c
index d756016..e84fe82 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -15,6 +15,7 @@
#include <linux/completion.h>
#include <linux/sched.h>
#include <linux/random.h>
+#include <linux/proc_fs.h>
#define CREATE_TRACE_POINTS
#include "internal.h"
@@ -32,7 +33,7 @@ module_param(rootcell, charp, 0);
MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list");
struct workqueue_struct *afs_wq;
-struct afs_net __afs_net;
+static struct proc_dir_entry *afs_proc_symlink;
#if defined(CONFIG_ALPHA)
const char afs_init_sysname[] = "alpha_linux26";
@@ -67,11 +68,13 @@ const char afs_init_sysname[] = "unknown_linux26";
/*
* Initialise an AFS network namespace record.
*/
-static int __net_init afs_net_init(struct afs_net *net)
+static int __net_init afs_net_init(struct net *net_ns)
{
struct afs_sysnames *sysnames;
+ struct afs_net *net = afs_net(net_ns);
int ret;
+ net->net = net_ns;
net->live = true;
generate_random_uuid((unsigned char *)&net->uuid);
@@ -83,7 +86,7 @@ static int __net_init afs_net_init(struct afs_net *net)
INIT_WORK(&net->cells_manager, afs_manage_cells);
timer_setup(&net->cells_timer, afs_cells_timer, 0);
- spin_lock_init(&net->proc_cells_lock);
+ mutex_init(&net->proc_cells_lock);
INIT_LIST_HEAD(&net->proc_cells);
seqlock_init(&net->fs_lock);
@@ -142,8 +145,10 @@ error_sysnames:
/*
* Clean up and destroy an AFS network namespace record.
*/
-static void __net_exit afs_net_exit(struct afs_net *net)
+static void __net_exit afs_net_exit(struct net *net_ns)
{
+ struct afs_net *net = afs_net(net_ns);
+
net->live = false;
afs_cell_purge(net);
afs_purge_servers(net);
@@ -152,6 +157,13 @@ static void __net_exit afs_net_exit(struct afs_net *net)
afs_put_sysnames(net->sysnames);
}
+static struct pernet_operations afs_net_ops = {
+ .init = afs_net_init,
+ .exit = afs_net_exit,
+ .id = &afs_net_id,
+ .size = sizeof(struct afs_net),
+};
+
/*
* initialise the AFS client FS module
*/
@@ -178,7 +190,7 @@ static int __init afs_init(void)
goto error_cache;
#endif
- ret = afs_net_init(&__afs_net);
+ ret = register_pernet_subsys(&afs_net_ops);
if (ret < 0)
goto error_net;
@@ -187,10 +199,18 @@ static int __init afs_init(void)
if (ret < 0)
goto error_fs;
+ afs_proc_symlink = proc_symlink("fs/afs", NULL, "../self/net/afs");
+ if (IS_ERR(afs_proc_symlink)) {
+ ret = PTR_ERR(afs_proc_symlink);
+ goto error_proc;
+ }
+
return ret;
+error_proc:
+ afs_fs_exit();
error_fs:
- afs_net_exit(&__afs_net);
+ unregister_pernet_subsys(&afs_net_ops);
error_net:
#ifdef CONFIG_AFS_FSCACHE
fscache_unregister_netfs(&afs_cache_netfs);
@@ -219,8 +239,9 @@ static void __exit afs_exit(void)
{
printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
+ proc_remove(afs_proc_symlink);
afs_fs_exit();
- afs_net_exit(&__afs_net);
+ unregister_pernet_subsys(&afs_net_ops);
#ifdef CONFIG_AFS_FSCACHE
fscache_unregister_netfs(&afs_cache_netfs);
#endif
diff --git a/fs/afs/netdevices.c b/fs/afs/netdevices.c
index 50bd5bb..2a009d1 100644
--- a/fs/afs/netdevices.c
+++ b/fs/afs/netdevices.c
@@ -17,8 +17,8 @@
* - maxbufs must be at least 1
* - returns the number of interface records in the buffer
*/
-int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
- bool wantloopback)
+int afs_get_ipv4_interfaces(struct afs_net *net, struct afs_interface *bufs,
+ size_t maxbufs, bool wantloopback)
{
struct net_device *dev;
struct in_device *idev;
@@ -27,7 +27,7 @@ int afs_get_ipv4_interfaces(struct afs_interface *bufs, size_t maxbufs,
ASSERT(maxbufs > 0);
rtnl_lock();
- for_each_netdev(&init_net, dev) {
+ for_each_netdev(net->net, dev) {
if (dev->type == ARPHRD_LOOPBACK && !wantloopback)
continue;
idev = __in_dev_get_rtnl(dev);
diff --git a/fs/afs/proc.c b/fs/afs/proc.c
index 3aad327..0c3285c 100644
--- a/fs/afs/proc.c
+++ b/fs/afs/proc.c
@@ -17,240 +17,78 @@
#include <linux/uaccess.h>
#include "internal.h"
-static inline struct afs_net *afs_proc2net(struct file *f)
+static inline struct afs_net *afs_seq2net(struct seq_file *m)
{
- return &__afs_net;
+ return afs_net(seq_file_net(m));
}
-static inline struct afs_net *afs_seq2net(struct seq_file *m)
+static inline struct afs_net *afs_seq2net_single(struct seq_file *m)
{
- return &__afs_net; // TODO: use seq_file_net(m)
+ return afs_net(seq_file_single_net(m));
}
-static int afs_proc_cells_open(struct inode *inode, struct file *file);
-static void *afs_proc_cells_start(struct seq_file *p, loff_t *pos);
-static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos);
-static void afs_proc_cells_stop(struct seq_file *p, void *v);
-static int afs_proc_cells_show(struct seq_file *m, void *v);
-static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
- size_t size, loff_t *_pos);
-
-static const struct seq_operations afs_proc_cells_ops = {
- .start = afs_proc_cells_start,
- .next = afs_proc_cells_next,
- .stop = afs_proc_cells_stop,
- .show = afs_proc_cells_show,
-};
-
-static const struct file_operations afs_proc_cells_fops = {
- .open = afs_proc_cells_open,
- .read = seq_read,
- .write = afs_proc_cells_write,
- .llseek = seq_lseek,
- .release = seq_release,
-};
-
-static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
- size_t size, loff_t *_pos);
-static ssize_t afs_proc_rootcell_write(struct file *file,
- const char __user *buf,
- size_t size, loff_t *_pos);
-
-static const struct file_operations afs_proc_rootcell_fops = {
- .read = afs_proc_rootcell_read,
- .write = afs_proc_rootcell_write,
- .llseek = no_llseek,
-};
-
-static void *afs_proc_cell_volumes_start(struct seq_file *p, loff_t *pos);
-static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
- loff_t *pos);
-static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v);
-static int afs_proc_cell_volumes_show(struct seq_file *m, void *v);
-
-static const struct seq_operations afs_proc_cell_volumes_ops = {
- .start = afs_proc_cell_volumes_start,
- .next = afs_proc_cell_volumes_next,
- .stop = afs_proc_cell_volumes_stop,
- .show = afs_proc_cell_volumes_show,
-};
-
-static void *afs_proc_cell_vlservers_start(struct seq_file *p, loff_t *pos);
-static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
- loff_t *pos);
-static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v);
-static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v);
-
-static const struct seq_operations afs_proc_cell_vlservers_ops = {
- .start = afs_proc_cell_vlservers_start,
- .next = afs_proc_cell_vlservers_next,
- .stop = afs_proc_cell_vlservers_stop,
- .show = afs_proc_cell_vlservers_show,
-};
-
-static void *afs_proc_servers_start(struct seq_file *p, loff_t *pos);
-static void *afs_proc_servers_next(struct seq_file *p, void *v,
- loff_t *pos);
-static void afs_proc_servers_stop(struct seq_file *p, void *v);
-static int afs_proc_servers_show(struct seq_file *m, void *v);
-
-static const struct seq_operations afs_proc_servers_ops = {
- .start = afs_proc_servers_start,
- .next = afs_proc_servers_next,
- .stop = afs_proc_servers_stop,
- .show = afs_proc_servers_show,
-};
-
-static int afs_proc_sysname_open(struct inode *inode, struct file *file);
-static int afs_proc_sysname_release(struct inode *inode, struct file *file);
-static void *afs_proc_sysname_start(struct seq_file *p, loff_t *pos);
-static void *afs_proc_sysname_next(struct seq_file *p, void *v,
- loff_t *pos);
-static void afs_proc_sysname_stop(struct seq_file *p, void *v);
-static int afs_proc_sysname_show(struct seq_file *m, void *v);
-static ssize_t afs_proc_sysname_write(struct file *file,
- const char __user *buf,
- size_t size, loff_t *_pos);
-
-static const struct seq_operations afs_proc_sysname_ops = {
- .start = afs_proc_sysname_start,
- .next = afs_proc_sysname_next,
- .stop = afs_proc_sysname_stop,
- .show = afs_proc_sysname_show,
-};
-
-static const struct file_operations afs_proc_sysname_fops = {
- .open = afs_proc_sysname_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = afs_proc_sysname_release,
- .write = afs_proc_sysname_write,
-};
-
-static int afs_proc_stats_show(struct seq_file *m, void *v);
-
/*
- * initialise the /proc/fs/afs/ directory
+ * Display the list of cells known to the namespace.
*/
-int afs_proc_init(struct afs_net *net)
+static int afs_proc_cells_show(struct seq_file *m, void *v)
{
- _enter("");
-
- net->proc_afs = proc_mkdir("fs/afs", NULL);
- if (!net->proc_afs)
- goto error_dir;
+ struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
+ struct afs_net *net = afs_seq2net(m);
- if (!proc_create("cells", 0644, net->proc_afs, &afs_proc_cells_fops) ||
- !proc_create("rootcell", 0644, net->proc_afs, &afs_proc_rootcell_fops) ||
- !proc_create_seq("servers", 0644, net->proc_afs, &afs_proc_servers_ops) ||
- !proc_create_single("stats", 0644, net->proc_afs, afs_proc_stats_show) ||
- !proc_create("sysname", 0644, net->proc_afs, &afs_proc_sysname_fops))
- goto error_tree;
+ if (v == &net->proc_cells) {
+ /* display header on line 1 */
+ seq_puts(m, "USE NAME\n");
+ return 0;
+ }
- _leave(" = 0");
+ /* display one cell per line on subsequent lines */
+ seq_printf(m, "%3u %s\n", atomic_read(&cell->usage), cell->name);
return 0;
-
-error_tree:
- proc_remove(net->proc_afs);
-error_dir:
- _leave(" = -ENOMEM");
- return -ENOMEM;
-}
-
-/*
- * clean up the /proc/fs/afs/ directory
- */
-void afs_proc_cleanup(struct afs_net *net)
-{
- proc_remove(net->proc_afs);
- net->proc_afs = NULL;
-}
-
-/*
- * open "/proc/fs/afs/cells" which provides a summary of extant cells
- */
-static int afs_proc_cells_open(struct inode *inode, struct file *file)
-{
- return seq_open(file, &afs_proc_cells_ops);
}
-/*
- * set up the iterator to start reading from the cells list and return the
- * first item
- */
static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos)
__acquires(rcu)
{
- struct afs_net *net = afs_seq2net(m);
-
rcu_read_lock();
- return seq_list_start_head(&net->proc_cells, *_pos);
+ return seq_list_start_head(&afs_seq2net(m)->proc_cells, *_pos);
}
-/*
- * move to next cell in cells list
- */
static void *afs_proc_cells_next(struct seq_file *m, void *v, loff_t *pos)
{
- struct afs_net *net = afs_seq2net(m);
-
- return seq_list_next(v, &net->proc_cells, pos);
+ return seq_list_next(v, &afs_seq2net(m)->proc_cells, pos);
}
-/*
- * clean up after reading from the cells list
- */
static void afs_proc_cells_stop(struct seq_file *m, void *v)
__releases(rcu)
{
rcu_read_unlock();
}
-/*
- * display a header line followed by a load of cell lines
- */
-static int afs_proc_cells_show(struct seq_file *m, void *v)
-{
- struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link);
- struct afs_net *net = afs_seq2net(m);
-
- if (v == &net->proc_cells) {
- /* display header on line 1 */
- seq_puts(m, "USE NAME\n");
- return 0;
- }
-
- /* display one cell per line on subsequent lines */
- seq_printf(m, "%3u %s\n", atomic_read(&cell->usage), cell->name);
- return 0;
-}
+static const struct seq_operations afs_proc_cells_ops = {
+ .start = afs_proc_cells_start,
+ .next = afs_proc_cells_next,
+ .stop = afs_proc_cells_stop,
+ .show = afs_proc_cells_show,
+};
/*
* handle writes to /proc/fs/afs/cells
* - to add cells: echo "add <cellname> <IP>[:<IP>][:<IP>]"
*/
-static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
- size_t size, loff_t *_pos)
+static int afs_proc_cells_write(struct file *file, char *buf, size_t size)
{
- struct afs_net *net = afs_proc2net(file);
- char *kbuf, *name, *args;
+ struct seq_file *m = file->private_data;
+ struct afs_net *net = afs_seq2net(m);
+ char *name, *args;
int ret;
- /* start by dragging the command into memory */
- if (size <= 1 || size >= PAGE_SIZE)
- return -EINVAL;
-
- kbuf = memdup_user_nul(buf, size);
- if (IS_ERR(kbuf))
- return PTR_ERR(kbuf);
-
/* trim to first NL */
- name = memchr(kbuf, '\n', size);
+ name = memchr(buf, '\n', size);
if (name)
*name = 0;
/* split into command, name and argslist */
- name = strchr(kbuf, ' ');
+ name = strchr(buf, ' ');
if (!name)
goto inval;
do {
@@ -269,9 +107,9 @@ static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
goto inval;
/* determine command to perform */
- _debug("cmd=%s name=%s args=%s", kbuf, name, args);
+ _debug("cmd=%s name=%s args=%s", buf, name, args);
- if (strcmp(kbuf, "add") == 0) {
+ if (strcmp(buf, "add") == 0) {
struct afs_cell *cell;
cell = afs_lookup_cell(net, name, strlen(name), args, true);
@@ -287,10 +125,9 @@ static ssize_t afs_proc_cells_write(struct file *file, const char __user *buf,
goto inval;
}
- ret = size;
+ ret = 0;
done:
- kfree(kbuf);
_leave(" = %d", ret);
return ret;
@@ -300,200 +137,136 @@ inval:
goto done;
}
-static ssize_t afs_proc_rootcell_read(struct file *file, char __user *buf,
- size_t size, loff_t *_pos)
+/*
+ * Display the name of the current workstation cell.
+ */
+static int afs_proc_rootcell_show(struct seq_file *m, void *v)
{
struct afs_cell *cell;
- struct afs_net *net = afs_proc2net(file);
- unsigned int seq = 0;
- char name[AFS_MAXCELLNAME + 1];
- int len;
-
- if (*_pos > 0)
- return 0;
- if (!net->ws_cell)
- return 0;
-
- rcu_read_lock();
- do {
- read_seqbegin_or_lock(&net->cells_lock, &seq);
- len = 0;
- cell = rcu_dereference_raw(net->ws_cell);
- if (cell) {
- len = cell->name_len;
- memcpy(name, cell->name, len);
- }
- } while (need_seqretry(&net->cells_lock, seq));
- done_seqretry(&net->cells_lock, seq);
- rcu_read_unlock();
-
- if (!len)
- return 0;
-
- name[len++] = '\n';
- if (len > size)
- len = size;
- if (copy_to_user(buf, name, len) != 0)
- return -EFAULT;
- *_pos = 1;
- return len;
+ struct afs_net *net;
+
+ net = afs_seq2net_single(m);
+ if (rcu_access_pointer(net->ws_cell)) {
+ rcu_read_lock();
+ cell = rcu_dereference(net->ws_cell);
+ if (cell)
+ seq_printf(m, "%s\n", cell->name);
+ rcu_read_unlock();
+ }
+ return 0;
}
/*
- * handle writes to /proc/fs/afs/rootcell
- * - to initialize rootcell: echo "cell.name:192.168.231.14"
+ * Set the current workstation cell and optionally supply its list of volume
+ * location servers.
+ *
+ * echo "cell.name:192.168.231.14" >/proc/fs/afs/rootcell
*/
-static ssize_t afs_proc_rootcell_write(struct file *file,
- const char __user *buf,
- size_t size, loff_t *_pos)
+static int afs_proc_rootcell_write(struct file *file, char *buf, size_t size)
{
- struct afs_net *net = afs_proc2net(file);
- char *kbuf, *s;
+ struct seq_file *m = file->private_data;
+ struct afs_net *net = afs_seq2net_single(m);
+ char *s;
int ret;
- /* start by dragging the command into memory */
- if (size <= 1 || size >= PAGE_SIZE)
- return -EINVAL;
-
- kbuf = memdup_user_nul(buf, size);
- if (IS_ERR(kbuf))
- return PTR_ERR(kbuf);
-
ret = -EINVAL;
- if (kbuf[0] == '.')
+ if (buf[0] == '.')
goto out;
- if (memchr(kbuf, '/', size))
+ if (memchr(buf, '/', size))
goto out;
/* trim to first NL */
- s = memchr(kbuf, '\n', size);
+ s = memchr(buf, '\n', size);
if (s)
*s = 0;
/* determine command to perform */
- _debug("rootcell=%s", kbuf);
+ _debug("rootcell=%s", buf);
- ret = afs_cell_init(net, kbuf);
- if (ret >= 0)
- ret = size; /* consume everything, always */
+ ret = afs_cell_init(net, buf);
out:
- kfree(kbuf);
_leave(" = %d", ret);
return ret;
}
+static const char afs_vol_types[3][3] = {
+ [AFSVL_RWVOL] = "RW",
+ [AFSVL_ROVOL] = "RO",
+ [AFSVL_BACKVOL] = "BK",
+};
+
/*
- * initialise /proc/fs/afs/<cell>/
+ * Display the list of volumes known to a cell.
*/
-int afs_proc_cell_setup(struct afs_net *net, struct afs_cell *cell)
+static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
{
- struct proc_dir_entry *dir;
-
- _enter("%p{%s},%p", cell, cell->name, net->proc_afs);
+ struct afs_cell *cell = PDE_DATA(file_inode(m->file));
+ struct afs_volume *vol = list_entry(v, struct afs_volume, proc_link);
- dir = proc_mkdir(cell->name, net->proc_afs);
- if (!dir)
- goto error_dir;
+ /* Display header on line 1 */
+ if (v == &cell->proc_volumes) {
+ seq_puts(m, "USE VID TY\n");
+ return 0;
+ }
- if (!proc_create_seq_data("vlservers", 0, dir,
- &afs_proc_cell_vlservers_ops, cell))
- goto error_tree;
- if (!proc_create_seq_data("volumes", 0, dir, &afs_proc_cell_volumes_ops,
- cell))
- goto error_tree;
+ seq_printf(m, "%3d %08x %s\n",
+ atomic_read(&vol->usage), vol->vid,
+ afs_vol_types[vol->type]);
- _leave(" = 0");
return 0;
-
-error_tree:
- remove_proc_subtree(cell->name, net->proc_afs);
-error_dir:
- _leave(" = -ENOMEM");
- return -ENOMEM;
}
-/*
- * remove /proc/fs/afs/<cell>/
- */
-void afs_proc_cell_remove(struct afs_net *net, struct afs_cell *cell)
-{
- _enter("");
-
- remove_proc_subtree(cell->name, net->proc_afs);
-
- _leave("");
-}
-
-/*
- * set up the iterator to start reading from the cells list and return the
- * first item
- */
static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos)
__acquires(cell->proc_lock)
{
struct afs_cell *cell = PDE_DATA(file_inode(m->file));
- _enter("cell=%p pos=%Ld", cell, *_pos);
-
read_lock(&cell->proc_lock);
return seq_list_start_head(&cell->proc_volumes, *_pos);
}
-/*
- * move to next cell in cells list
- */
-static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v,
+static void *afs_proc_cell_volumes_next(struct seq_file *m, void *v,
loff_t *_pos)
{
- struct afs_cell *cell = PDE_DATA(file_inode(p->file));
+ struct afs_cell *cell = PDE_DATA(file_inode(m->file));
- _enter("cell=%p pos=%Ld", cell, *_pos);
return seq_list_next(v, &cell->proc_volumes, _pos);
}
-/*
- * clean up after reading from the cells list
- */
-static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v)
+static void afs_proc_cell_volumes_stop(struct seq_file *m, void *v)
__releases(cell->proc_lock)
{
- struct afs_cell *cell = PDE_DATA(file_inode(p->file));
+ struct afs_cell *cell = PDE_DATA(file_inode(m->file));
read_unlock(&cell->proc_lock);
}
-static const char afs_vol_types[3][3] = {
- [AFSVL_RWVOL] = "RW",
- [AFSVL_ROVOL] = "RO",
- [AFSVL_BACKVOL] = "BK",
+static const struct seq_operations afs_proc_cell_volumes_ops = {
+ .start = afs_proc_cell_volumes_start,
+ .next = afs_proc_cell_volumes_next,
+ .stop = afs_proc_cell_volumes_stop,
+ .show = afs_proc_cell_volumes_show,
};
/*
- * display a header line followed by a load of volume lines
+ * Display the list of Volume Location servers we're using for a cell.
*/
-static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
+static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
{
- struct afs_cell *cell = PDE_DATA(file_inode(m->file));
- struct afs_volume *vol = list_entry(v, struct afs_volume, proc_link);
+ struct sockaddr_rxrpc *addr = v;
- /* Display header on line 1 */
- if (v == &cell->proc_volumes) {
- seq_puts(m, "USE VID TY\n");
+ /* display header on line 1 */
+ if (v == (void *)1) {
+ seq_puts(m, "ADDRESS\n");
return 0;
}
- seq_printf(m, "%3d %08x %s\n",
- atomic_read(&vol->usage), vol->vid,
- afs_vol_types[vol->type]);
-
+ /* display one cell per line on subsequent lines */
+ seq_printf(m, "%pISp\n", &addr->transport);
return 0;
}
-/*
- * set up the iterator to start reading from the cells list and return the
- * first item
- */
static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
__acquires(rcu)
{
@@ -516,14 +289,11 @@ static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
return alist->addrs + pos;
}
-/*
- * move to next cell in cells list
- */
-static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
+static void *afs_proc_cell_vlservers_next(struct seq_file *m, void *v,
loff_t *_pos)
{
struct afs_addr_list *alist;
- struct afs_cell *cell = PDE_DATA(file_inode(p->file));
+ struct afs_cell *cell = PDE_DATA(file_inode(m->file));
loff_t pos;
alist = rcu_dereference(cell->vl_addrs);
@@ -536,161 +306,145 @@ static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v,
return alist->addrs + pos;
}
-/*
- * clean up after reading from the cells list
- */
-static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v)
+static void afs_proc_cell_vlservers_stop(struct seq_file *m, void *v)
__releases(rcu)
{
rcu_read_unlock();
}
+static const struct seq_operations afs_proc_cell_vlservers_ops = {
+ .start = afs_proc_cell_vlservers_start,
+ .next = afs_proc_cell_vlservers_next,
+ .stop = afs_proc_cell_vlservers_stop,
+ .show = afs_proc_cell_vlservers_show,
+};
+
/*
- * display a header line followed by a load of volume lines
+ * Display the list of fileservers we're using within a namespace.
*/
-static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
+static int afs_proc_servers_show(struct seq_file *m, void *v)
{
- struct sockaddr_rxrpc *addr = v;
+ struct afs_server *server;
+ struct afs_addr_list *alist;
+ int i;
- /* display header on line 1 */
- if (v == (void *)1) {
- seq_puts(m, "ADDRESS\n");
+ if (v == SEQ_START_TOKEN) {
+ seq_puts(m, "UUID USE ADDR\n");
return 0;
}
- /* display one cell per line on subsequent lines */
- seq_printf(m, "%pISp\n", &addr->transport);
+ server = list_entry(v, struct afs_server, proc_link);
+ alist = rcu_dereference(server->addresses);
+ seq_printf(m, "%pU %3d %pISpc%s\n",
+ &server->uuid,
+ atomic_read(&server->usage),
+ &alist->addrs[0].transport,
+ alist->index == 0 ? "*" : "");
+ for (i = 1; i < alist->nr_addrs; i++)
+ seq_printf(m, " %pISpc%s\n",
+ &alist->addrs[i].transport,
+ alist->index == i ? "*" : "");
return 0;
}
-/*
- * Set up the iterator to start reading from the server list and return the
- * first item.
- */
static void *afs_proc_servers_start(struct seq_file *m, loff_t *_pos)
__acquires(rcu)
{
- struct afs_net *net = afs_seq2net(m);
-
rcu_read_lock();
- return seq_hlist_start_head_rcu(&net->fs_proc, *_pos);
+ return seq_hlist_start_head_rcu(&afs_seq2net(m)->fs_proc, *_pos);
}
-/*
- * move to next cell in cells list
- */
static void *afs_proc_servers_next(struct seq_file *m, void *v, loff_t *_pos)
{
- struct afs_net *net = afs_seq2net(m);
-
- return seq_hlist_next_rcu(v, &net->fs_proc, _pos);
+ return seq_hlist_next_rcu(v, &afs_seq2net(m)->fs_proc, _pos);
}
-/*
- * clean up after reading from the cells list
- */
-static void afs_proc_servers_stop(struct seq_file *p, void *v)
+static void afs_proc_servers_stop(struct seq_file *m, void *v)
__releases(rcu)
{
rcu_read_unlock();
}
+static const struct seq_operations afs_proc_servers_ops = {
+ .start = afs_proc_servers_start,
+ .next = afs_proc_servers_next,
+ .stop = afs_proc_servers_stop,
+ .show = afs_proc_servers_show,
+};
+
/*
- * display a header line followed by a load of volume lines
+ * Display the list of strings that may be substituted for the @sys pathname
+ * macro.
*/
-static int afs_proc_servers_show(struct seq_file *m, void *v)
+static int afs_proc_sysname_show(struct seq_file *m, void *v)
{
- struct afs_server *server;
- struct afs_addr_list *alist;
-
- if (v == SEQ_START_TOKEN) {
- seq_puts(m, "UUID USE ADDR\n");
- return 0;
- }
+ struct afs_net *net = afs_seq2net(m);
+ struct afs_sysnames *sysnames = net->sysnames;
+ unsigned int i = (unsigned long)v - 1;
- server = list_entry(v, struct afs_server, proc_link);
- alist = rcu_dereference(server->addresses);
- seq_printf(m, "%pU %3d %pISp\n",
- &server->uuid,
- atomic_read(&server->usage),
- &alist->addrs[alist->index].transport);
+ if (i < sysnames->nr)
+ seq_printf(m, "%s\n", sysnames->subs[i]);
return 0;
}
-void afs_put_sysnames(struct afs_sysnames *sysnames)
+static void *afs_proc_sysname_start(struct seq_file *m, loff_t *pos)
+ __acquires(&net->sysnames_lock)
{
- int i;
+ struct afs_net *net = afs_seq2net(m);
+ struct afs_sysnames *names;
- if (sysnames && refcount_dec_and_test(&sysnames->usage)) {
- for (i = 0; i < sysnames->nr; i++)
- if (sysnames->subs[i] != afs_init_sysname &&
- sysnames->subs[i] != sysnames->blank)
- kfree(sysnames->subs[i]);
- }
+ read_lock(&net->sysnames_lock);
+
+ names = net->sysnames;
+ if (*pos >= names->nr)
+ return NULL;
+ return (void *)(unsigned long)(*pos + 1);
}
-/*
- * Handle opening of /proc/fs/afs/sysname. If it is opened for writing, we
- * assume the caller wants to change the substitution list and we allocate a
- * buffer to hold the list.
- */
-static int afs_proc_sysname_open(struct inode *inode, struct file *file)
+static void *afs_proc_sysname_next(struct seq_file *m, void *v, loff_t *pos)
{
- struct afs_sysnames *sysnames;
- struct seq_file *m;
- int ret;
-
- ret = seq_open(file, &afs_proc_sysname_ops);
- if (ret < 0)
- return ret;
+ struct afs_net *net = afs_seq2net(m);
+ struct afs_sysnames *names = net->sysnames;
- if (file->f_mode & FMODE_WRITE) {
- sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL);
- if (!sysnames) {
- seq_release(inode, file);
- return -ENOMEM;
- }
+ *pos += 1;
+ if (*pos >= names->nr)
+ return NULL;
+ return (void *)(unsigned long)(*pos + 1);
+}
- refcount_set(&sysnames->usage, 1);
- m = file->private_data;
- m->private = sysnames;
- }
+static void afs_proc_sysname_stop(struct seq_file *m, void *v)
+ __releases(&net->sysnames_lock)
+{
+ struct afs_net *net = afs_seq2net(m);
- return 0;
+ read_unlock(&net->sysnames_lock);
}
+static const struct seq_operations afs_proc_sysname_ops = {
+ .start = afs_proc_sysname_start,
+ .next = afs_proc_sysname_next,
+ .stop = afs_proc_sysname_stop,
+ .show = afs_proc_sysname_show,
+};
+
/*
- * Handle writes to /proc/fs/afs/sysname to set the @sys substitution.
+ * Allow the @sys substitution to be configured.
*/
-static ssize_t afs_proc_sysname_write(struct file *file,
- const char __user *buf,
- size_t size, loff_t *_pos)
+static int afs_proc_sysname_write(struct file *file, char *buf, size_t size)
{
- struct afs_sysnames *sysnames;
+ struct afs_sysnames *sysnames, *kill;
struct seq_file *m = file->private_data;
- char *kbuf = NULL, *s, *p, *sub;
+ struct afs_net *net = afs_seq2net(m);
+ char *s, *p, *sub;
int ret, len;
- sysnames = m->private;
+ sysnames = kzalloc(sizeof(*sysnames), GFP_KERNEL);
if (!sysnames)
- return -EINVAL;
- if (sysnames->error)
- return sysnames->error;
-
- if (size >= PAGE_SIZE - 1) {
- sysnames->error = -EINVAL;
- return -EINVAL;
- }
- if (size == 0)
- return 0;
-
- kbuf = memdup_user_nul(buf, size);
- if (IS_ERR(kbuf))
- return PTR_ERR(kbuf);
-
- inode_lock(file_inode(file));
+ return -ENOMEM;
+ refcount_set(&sysnames->usage, 1);
+ kill = sysnames;
- p = kbuf;
+ p = buf;
while ((s = strsep(&p, " \t\n"))) {
len = strlen(s);
if (len == 0)
@@ -731,85 +485,36 @@ static ssize_t afs_proc_sysname_write(struct file *file,
sysnames->nr++;
}
- ret = size; /* consume everything, always */
+ if (sysnames->nr == 0) {
+ sysnames->subs[0] = sysnames->blank;
+ sysnames->nr++;
+ }
+
+ write_lock(&net->sysnames_lock);
+ kill = net->sysnames;
+ net->sysnames = sysnames;
+ write_unlock(&net->sysnames_lock);
+ ret = 0;
out:
- inode_unlock(file_inode(file));
- kfree(kbuf);
+ afs_put_sysnames(kill);
return ret;
invalid:
ret = -EINVAL;
error:
- sysnames->error = ret;
goto out;
}
-static int afs_proc_sysname_release(struct inode *inode, struct file *file)
+void afs_put_sysnames(struct afs_sysnames *sysnames)
{
- struct afs_sysnames *sysnames, *kill = NULL;
- struct seq_file *m = file->private_data;
- struct afs_net *net = afs_seq2net(m);
+ int i;
- sysnames = m->private;
- if (sysnames) {
- if (!sysnames->error) {
- kill = sysnames;
- if (sysnames->nr == 0) {
- sysnames->subs[0] = sysnames->blank;
- sysnames->nr++;
- }
- write_lock(&net->sysnames_lock);
- kill = net->sysnames;
- net->sysnames = sysnames;
- write_unlock(&net->sysnames_lock);
- }
- afs_put_sysnames(kill);
+ if (sysnames && refcount_dec_and_test(&sysnames->usage)) {
+ for (i = 0; i < sysnames->nr; i++)
+ if (sysnames->subs[i] != afs_init_sysname &&
+ sysnames->subs[i] != sysnames->blank)
+ kfree(sysnames->subs[i]);
}
-
- return seq_release(inode, file);
-}
-
-static void *afs_proc_sysname_start(struct seq_file *m, loff_t *pos)
- __acquires(&net->sysnames_lock)
-{
- struct afs_net *net = afs_seq2net(m);
- struct afs_sysnames *names = net->sysnames;
-
- read_lock(&net->sysnames_lock);
-
- if (*pos >= names->nr)
- return NULL;
- return (void *)(unsigned long)(*pos + 1);
-}
-
-static void *afs_proc_sysname_next(struct seq_file *m, void *v, loff_t *pos)
-{
- struct afs_net *net = afs_seq2net(m);
- struct afs_sysnames *names = net->sysnames;
-
- *pos += 1;
- if (*pos >= names->nr)
- return NULL;
- return (void *)(unsigned long)(*pos + 1);
-}
-
-static void afs_proc_sysname_stop(struct seq_file *m, void *v)
- __releases(&net->sysnames_lock)
-{
- struct afs_net *net = afs_seq2net(m);
-
- read_unlock(&net->sysnames_lock);
-}
-
-static int afs_proc_sysname_show(struct seq_file *m, void *v)
-{
- struct afs_net *net = afs_seq2net(m);
- struct afs_sysnames *sysnames = net->sysnames;
- unsigned int i = (unsigned long)v - 1;
-
- if (i < sysnames->nr)
- seq_printf(m, "%s\n", sysnames->subs[i]);
- return 0;
}
/*
@@ -817,7 +522,7 @@ static int afs_proc_sysname_show(struct seq_file *m, void *v)
*/
static int afs_proc_stats_show(struct seq_file *m, void *v)
{
- struct afs_net *net = afs_seq2net(m);
+ struct afs_net *net = afs_seq2net_single(m);
seq_puts(m, "kAFS statistics\n");
@@ -842,3 +547,101 @@ static int afs_proc_stats_show(struct seq_file *m, void *v)
atomic_long_read(&net->n_store_bytes));
return 0;
}
+
+/*
+ * initialise /proc/fs/afs/<cell>/
+ */
+int afs_proc_cell_setup(struct afs_cell *cell)
+{
+ struct proc_dir_entry *dir;
+ struct afs_net *net = cell->net;
+
+ _enter("%p{%s},%p", cell, cell->name, net->proc_afs);
+
+ dir = proc_net_mkdir(net->net, cell->name, net->proc_afs);
+ if (!dir)
+ goto error_dir;
+
+ if (!proc_create_net_data("vlservers", 0444, dir,
+ &afs_proc_cell_vlservers_ops,
+ sizeof(struct seq_net_private),
+ cell) ||
+ !proc_create_net_data("volumes", 0444, dir,
+ &afs_proc_cell_volumes_ops,
+ sizeof(struct seq_net_private),
+ cell))
+ goto error_tree;
+
+ _leave(" = 0");
+ return 0;
+
+error_tree:
+ remove_proc_subtree(cell->name, net->proc_afs);
+error_dir:
+ _leave(" = -ENOMEM");
+ return -ENOMEM;
+}
+
+/*
+ * remove /proc/fs/afs/<cell>/
+ */
+void afs_proc_cell_remove(struct afs_cell *cell)
+{
+ struct afs_net *net = cell->net;
+
+ _enter("");
+ remove_proc_subtree(cell->name, net->proc_afs);
+ _leave("");
+}
+
+/*
+ * initialise the /proc/fs/afs/ directory
+ */
+int afs_proc_init(struct afs_net *net)
+{
+ struct proc_dir_entry *p;
+
+ _enter("");
+
+ p = proc_net_mkdir(net->net, "afs", net->net->proc_net);
+ if (!p)
+ goto error_dir;
+
+ if (!proc_create_net_data_write("cells", 0644, p,
+ &afs_proc_cells_ops,
+ afs_proc_cells_write,
+ sizeof(struct seq_net_private),
+ NULL) ||
+ !proc_create_net_single_write("rootcell", 0644, p,
+ afs_proc_rootcell_show,
+ afs_proc_rootcell_write,
+ NULL) ||
+ !proc_create_net("servers", 0444, p, &afs_proc_servers_ops,
+ sizeof(struct seq_net_private)) ||
+ !proc_create_net_single("stats", 0444, p, afs_proc_stats_show, NULL) ||
+ !proc_create_net_data_write("sysname", 0644, p,
+ &afs_proc_sysname_ops,
+ afs_proc_sysname_write,
+ sizeof(struct seq_net_private),
+ NULL))
+ goto error_tree;
+
+ net->proc_afs = p;
+ _leave(" = 0");
+ return 0;
+
+error_tree:
+ proc_remove(p);
+error_dir:
+ _leave(" = -ENOMEM");
+ return -ENOMEM;
+}
+
+/*
+ * clean up the /proc/fs/afs/ directory
+ */
+void afs_proc_cleanup(struct afs_net *net)
+{
+ proc_remove(net->proc_afs);
+ net->proc_afs = NULL;
+}
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index 0873594..a1b1808 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -46,7 +46,7 @@ int afs_open_socket(struct afs_net *net)
_enter("");
- ret = sock_create_kern(&init_net, AF_RXRPC, SOCK_DGRAM, PF_INET6, &socket);
+ ret = sock_create_kern(net->net, AF_RXRPC, SOCK_DGRAM, PF_INET6, &socket);
if (ret < 0)
goto error_1;
diff --git a/fs/afs/server.c b/fs/afs/server.c
index 3af4625..1d329e6 100644
--- a/fs/afs/server.c
+++ b/fs/afs/server.c
@@ -228,7 +228,7 @@ static struct afs_server *afs_alloc_server(struct afs_net *net,
server->flags = (1UL << AFS_SERVER_FL_NEW);
server->update_at = ktime_get_real_seconds() + afs_server_update_delay;
rwlock_init(&server->fs_lock);
- INIT_LIST_HEAD(&server->cb_interests);
+ INIT_HLIST_HEAD(&server->cb_volumes);
rwlock_init(&server->cb_break_lock);
afs_inc_servers_outstanding(net);
diff --git a/fs/afs/super.c b/fs/afs/super.c
index 9e5d796..4d3e274 100644
--- a/fs/afs/super.c
+++ b/fs/afs/super.c
@@ -48,6 +48,8 @@ struct file_system_type afs_fs_type = {
};
MODULE_ALIAS_FS("afs");
+int afs_net_id;
+
static const struct super_operations afs_super_ops = {
.statfs = afs_statfs,
.alloc_inode = afs_alloc_inode,
@@ -117,7 +119,7 @@ int __init afs_fs_init(void)
/*
* clean up the filesystem
*/
-void __exit afs_fs_exit(void)
+void afs_fs_exit(void)
{
_enter("");
@@ -351,14 +353,19 @@ static int afs_test_super(struct super_block *sb, void *data)
struct afs_super_info *as1 = data;
struct afs_super_info *as = AFS_FS_S(sb);
- return (as->net == as1->net &&
+ return (as->net_ns == as1->net_ns &&
as->volume &&
- as->volume->vid == as1->volume->vid);
+ as->volume->vid == as1->volume->vid &&
+ !as->dyn_root);
}
static int afs_dynroot_test_super(struct super_block *sb, void *data)
{
- return false;
+ struct afs_super_info *as1 = data;
+ struct afs_super_info *as = AFS_FS_S(sb);
+
+ return (as->net_ns == as1->net_ns &&
+ as->dyn_root);
}
static int afs_set_super(struct super_block *sb, void *data)
@@ -418,10 +425,14 @@ static int afs_fill_super(struct super_block *sb,
if (!sb->s_root)
goto error;
- if (params->dyn_root)
+ if (as->dyn_root) {
sb->s_d_op = &afs_dynroot_dentry_operations;
- else
+ ret = afs_dynroot_populate(sb);
+ if (ret < 0)
+ goto error;
+ } else {
sb->s_d_op = &afs_fs_dentry_operations;
+ }
_leave(" = 0");
return 0;
@@ -437,7 +448,7 @@ static struct afs_super_info *afs_alloc_sbi(struct afs_mount_params *params)
as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL);
if (as) {
- as->net = afs_get_net(params->net);
+ as->net_ns = get_net(params->net_ns);
if (params->dyn_root)
as->dyn_root = true;
else
@@ -450,12 +461,31 @@ static void afs_destroy_sbi(struct afs_super_info *as)
{
if (as) {
afs_put_volume(as->cell, as->volume);
- afs_put_cell(as->net, as->cell);
- afs_put_net(as->net);
+ afs_put_cell(afs_net(as->net_ns), as->cell);
+ put_net(as->net_ns);
kfree(as);
}
}
+static void afs_kill_super(struct super_block *sb)
+{
+ struct afs_super_info *as = AFS_FS_S(sb);
+ struct afs_net *net = afs_net(as->net_ns);
+
+ if (as->dyn_root)
+ afs_dynroot_depopulate(sb);
+
+ /* Clear the callback interests (which will do ilookup5) before
+ * deactivating the superblock.
+ */
+ if (as->volume)
+ afs_clear_callback_interests(net, as->volume->servers);
+ kill_anon_super(sb);
+ if (as->volume)
+ afs_deactivate_volume(as->volume);
+ afs_destroy_sbi(as);
+}
+
/*
* get an AFS superblock
*/
@@ -472,12 +502,13 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
_enter(",,%s,%p", dev_name, options);
memset(&params, 0, sizeof(params));
- params.net = &__afs_net;
ret = -EINVAL;
if (current->nsproxy->net_ns != &init_net)
goto error;
-
+ params.net_ns = current->nsproxy->net_ns;
+ params.net = afs_net(params.net_ns);
+
/* parse the options and device name */
if (options) {
ret = afs_parse_options(&params, options, &dev_name);
@@ -563,21 +594,6 @@ error:
return ERR_PTR(ret);
}
-static void afs_kill_super(struct super_block *sb)
-{
- struct afs_super_info *as = AFS_FS_S(sb);
-
- /* Clear the callback interests (which will do ilookup5) before
- * deactivating the superblock.
- */
- if (as->volume)
- afs_clear_callback_interests(as->net, as->volume->servers);
- kill_anon_super(sb);
- if (as->volume)
- afs_deactivate_volume(as->volume);
- afs_destroy_sbi(as);
-}
-
/*
* Initialise an inode cache slab element prior to any use. Note that
* afs_alloc_inode() *must* reset anything that could incorrectly leak from one
diff --git a/fs/aio.c b/fs/aio.c
index 134e5b6..e1d2012 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1661,7 +1661,7 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
if (mask && !(mask & req->events))
return 0;
- mask = file->f_op->poll_mask(file, req->events);
+ mask = file->f_op->poll_mask(file, req->events) & req->events;
if (!mask)
return 0;
@@ -1719,7 +1719,7 @@ static ssize_t aio_poll(struct aio_kiocb *aiocb, struct iocb *iocb)
spin_lock_irq(&ctx->ctx_lock);
spin_lock(&req->head->lock);
- mask = req->file->f_op->poll_mask(req->file, req->events);
+ mask = req->file->f_op->poll_mask(req->file, req->events) & req->events;
if (!mask) {
__add_wait_queue(req->head, &req->wait);
list_add_tail(&aiocb->ki_list, &ctx->active_reqs);
diff --git a/fs/attr.c b/fs/attr.c
index d0b4d34..e3d53bf 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -183,14 +183,14 @@ void setattr_copy(struct inode *inode, const struct iattr *attr)
if (ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (ia_valid & ATTR_ATIME)
- inode->i_atime = timespec_trunc(attr->ia_atime,
- inode->i_sb->s_time_gran);
+ inode->i_atime = timespec64_trunc(attr->ia_atime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MTIME)
- inode->i_mtime = timespec_trunc(attr->ia_mtime,
- inode->i_sb->s_time_gran);
+ inode->i_mtime = timespec64_trunc(attr->ia_mtime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_CTIME)
- inode->i_ctime = timespec_trunc(attr->ia_ctime,
- inode->i_sb->s_time_gran);
+ inode->i_ctime = timespec64_trunc(attr->ia_ctime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MODE) {
umode_t mode = attr->ia_mode;
@@ -227,7 +227,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr, struct inode **de
struct inode *inode = dentry->d_inode;
umode_t mode = inode->i_mode;
int error;
- struct timespec now;
+ struct timespec64 now;
unsigned int ia_valid = attr->ia_valid;
WARN_ON_ONCE(!inode_is_locked(inode));
diff --git a/fs/autofs/Kconfig b/fs/autofs/Kconfig
index 6a2064e..eaebcd4 100644
--- a/fs/autofs/Kconfig
+++ b/fs/autofs/Kconfig
@@ -1,3 +1,14 @@
+config AUTOFS4_FS
+ tristate "Old Kconfig name for Kernel automounter support"
+ select AUTOFS_FS
+ help
+ This name exists for people to just automatically pick up the
+ new name of the autofs Kconfig option. All it does is select
+ the new option name.
+
+ It will go away in a release or two as people have
+ transitioned to just plain AUTOFS_FS.
+
config AUTOFS_FS
tristate "Kernel automounter support (supports v3, v4 and v5)"
default n
diff --git a/fs/autofs/init.c b/fs/autofs/init.c
index 16fb613..cc9447e 100644
--- a/fs/autofs/init.c
+++ b/fs/autofs/init.c
@@ -23,6 +23,7 @@ static struct file_system_type autofs_fs_type = {
.kill_sb = autofs_kill_sb,
};
MODULE_ALIAS_FS("autofs");
+MODULE_ALIAS("autofs4");
static int __init init_autofs_fs(void)
{
diff --git a/fs/autofs4/Kconfig b/fs/autofs4/Kconfig
deleted file mode 100644
index 99fda4d..0000000
--- a/fs/autofs4/Kconfig
+++ /dev/null
@@ -1,46 +0,0 @@
-config AUTOFS4_FS
- tristate "Kernel automounter version 4 support (also supports v3 and v5)"
- default n
- depends on AUTOFS_FS = n
- help
- The automounter is a tool to automatically mount remote file systems
- on demand. This implementation is partially kernel-based to reduce
- overhead in the already-mounted case; this is unlike the BSD
- automounter (amd), which is a pure user space daemon.
-
- To use the automounter you need the user-space tools from
- <https://www.kernel.org/pub/linux/daemons/autofs/>; you also want
- to answer Y to "NFS file system support", below.
-
- This module is in the process of being renamed from autofs4 to
- autofs. Since autofs is now the only module that provides the
- autofs file system the module is not version 4 specific.
-
- The autofs4 module is now built from the source located in
- fs/autofs. The autofs4 directory and its configuration entry
- will be removed two kernel versions from the inclusion of this
- change.
-
- Changes that will need to be made should be limited to:
- - source include statments should be changed from autofs_fs4.h to
- autofs_fs.h since these two header files have been merged.
- - user space scripts that manually load autofs4.ko should be
- changed to load autofs.ko. But since the module directory name
- and the module name are the same as the file system name there
- is no need to manually load module.
- - any "alias autofs autofs4" will need to be removed.
- - due to the autofs4 module directory name not being the same as
- its file system name autoloading didn't work properly. Because
- of this kernel configurations would often build the module into
- the kernel. This may have resulted in selinux policies that will
- prevent the autofs module from autoloading and will need to be
- updated.
-
- Please configure AUTOFS_FS instead of AUTOFS4_FS from now on.
-
- NOTE: Since the modules autofs and autofs4 use the same file system
- type name of "autofs" only one can be built. The "depends"
- above will result in AUTOFS4_FS not appearing in .config for
- any setting of AUTOFS_FS other than n and AUTOFS4_FS will
- appear under the AUTOFS_FS entry otherwise which is intended
- to draw attention to the module rename change.
diff --git a/fs/autofs4/Makefile b/fs/autofs4/Makefile
deleted file mode 100644
index 417dd72..0000000
--- a/fs/autofs4/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the linux autofs-filesystem routines.
-#
-
-obj-$(CONFIG_AUTOFS4_FS) += autofs4.o
-
-autofs4-objs := ../autofs/init.o ../autofs/inode.o ../autofs/root.o \
- ../autofs/symlink.o ../autofs/waitq.o ../autofs/expire.o \
- ../autofs/dev-ioctl.o
diff --git a/fs/bad_inode.c b/fs/bad_inode.c
index 213b51d..125e8bb 100644
--- a/fs/bad_inode.c
+++ b/fs/bad_inode.c
@@ -126,7 +126,7 @@ static int bad_inode_fiemap(struct inode *inode,
return -EIO;
}
-static int bad_inode_update_time(struct inode *inode, struct timespec *time,
+static int bad_inode_update_time(struct inode *inode, struct timespec64 *time,
int flags)
{
return -EIO;
diff --git a/fs/befs/ChangeLog b/fs/befs/ChangeLog
index 16f2dfe..aff7eec 100644
--- a/fs/befs/ChangeLog
+++ b/fs/befs/ChangeLog
@@ -389,7 +389,7 @@ Version 0.4 (2001-10-28)
(fs/nls/Config.in)
* Added Configure.help entries for CONFIG_BEFS_FS and CONFIG_DEBUG_BEFS
- (Documentation/Configure.help)
+ (currently at fs/befs/Kconfig)
2001-08-??
==========
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 4ad6f66..0ac456b 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1621,8 +1621,8 @@ static int fill_files_note(struct memelfnote *note)
if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */
return -EINVAL;
size = round_up(size, PAGE_SIZE);
- data = vmalloc(size);
- if (!data)
+ data = kvmalloc(size, GFP_KERNEL);
+ if (ZERO_OR_NULL_PTR(data))
return -ENOMEM;
start_end_ofs = data + 2;
@@ -1639,7 +1639,7 @@ static int fill_files_note(struct memelfnote *note)
filename = file_path(file, name_curpos, remaining);
if (IS_ERR(filename)) {
if (PTR_ERR(filename) == -ENAMETOOLONG) {
- vfree(data);
+ kvfree(data);
size = size * 5 / 4;
goto alloc;
}
@@ -1932,7 +1932,7 @@ static void free_note_info(struct elf_note_info *info)
kfree(t);
}
kfree(info->psinfo.data);
- vfree(info->files.data);
+ kvfree(info->files.data);
}
#else
@@ -2010,7 +2010,7 @@ static int elf_note_info_init(struct elf_note_info *info)
INIT_LIST_HEAD(&info->thread_list);
/* Allocate space for ELF notes */
- info->notes = kmalloc(8 * sizeof(struct memelfnote), GFP_KERNEL);
+ info->notes = kmalloc_array(8, sizeof(struct memelfnote), GFP_KERNEL);
if (!info->notes)
return 0;
info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL);
@@ -2148,7 +2148,7 @@ static void free_note_info(struct elf_note_info *info)
/* Free data possibly allocated by fill_files_note(): */
if (info->notes_files)
- vfree(info->notes_files->data);
+ kvfree(info->notes_files->data);
kfree(info->prstatus);
kfree(info->psinfo);
@@ -2294,8 +2294,9 @@ static int elf_core_dump(struct coredump_params *cprm)
if (segs - 1 > ULONG_MAX / sizeof(*vma_filesz))
goto end_coredump;
- vma_filesz = vmalloc((segs - 1) * sizeof(*vma_filesz));
- if (!vma_filesz)
+ vma_filesz = kvmalloc(array_size(sizeof(*vma_filesz), (segs - 1)),
+ GFP_KERNEL);
+ if (ZERO_OR_NULL_PTR(vma_filesz))
goto end_coredump;
for (i = 0, vma = first_vma(current, gate_vma); vma != NULL;
@@ -2402,7 +2403,7 @@ end_coredump:
cleanup:
free_note_info(&info);
kfree(shdr4extnum);
- vfree(vma_filesz);
+ kvfree(vma_filesz);
kfree(phdr4note);
kfree(elf);
out:
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index d90993a..b53bb37 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -1600,7 +1600,8 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
if (!psinfo)
goto cleanup;
- notes = kmalloc(NUM_NOTES * sizeof(struct memelfnote), GFP_KERNEL);
+ notes = kmalloc_array(NUM_NOTES, sizeof(struct memelfnote),
+ GFP_KERNEL);
if (!notes)
goto cleanup;
fpu = kmalloc(sizeof(*fpu), GFP_KERNEL);
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 4de1915..4b5fff3 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -4,7 +4,7 @@
* Copyright (C) 1997 Richard Günther
*
* binfmt_misc detects binaries via a magic or filename extension and invokes
- * a specified wrapper. See Documentation/binfmt_misc.txt for more details.
+ * a specified wrapper. See Documentation/admin-guide/binfmt-misc.rst for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/fs/block_dev.c b/fs/block_dev.c
index 05e12ae..0dd87aa 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -205,7 +205,8 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter,
if (nr_pages <= DIO_INLINE_BIO_VECS)
vecs = inline_vecs;
else {
- vecs = kmalloc(nr_pages * sizeof(struct bio_vec), GFP_KERNEL);
+ vecs = kmalloc_array(nr_pages, sizeof(struct bio_vec),
+ GFP_KERNEL);
if (!vecs)
return -ENOMEM;
}
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
index dc062b1..a3fdb4f 100644
--- a/fs/btrfs/check-integrity.c
+++ b/fs/btrfs/check-integrity.c
@@ -1603,8 +1603,8 @@ static int btrfsic_read_block(struct btrfsic_state *state,
num_pages = (block_ctx->len + (u64)PAGE_SIZE - 1) >>
PAGE_SHIFT;
- block_ctx->mem_to_free = kzalloc((sizeof(*block_ctx->datav) +
- sizeof(*block_ctx->pagev)) *
+ block_ctx->mem_to_free = kcalloc(sizeof(*block_ctx->datav) +
+ sizeof(*block_ctx->pagev),
num_pages, GFP_NOFS);
if (!block_ctx->mem_to_free)
return -ENOMEM;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index f4bf787..118346a 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3197,7 +3197,7 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
size_t size, struct bio *bio,
unsigned long bio_flags);
void btrfs_set_range_writeback(void *private_data, u64 start, u64 end);
-int btrfs_page_mkwrite(struct vm_fault *vmf);
+vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf);
int btrfs_readpage(struct file *file, struct page *page);
void btrfs_evict_inode(struct inode *inode);
int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 51fc015..cce6087 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -4542,7 +4542,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
offset_in_extent = em_start - em->start;
em_end = extent_map_end(em);
em_len = em_end - em_start;
- disko = 0;
+ disko = em->block_start + offset_in_extent;
flags = 0;
/*
@@ -4565,8 +4565,6 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 bytenr = em->block_start -
(em->start - em->orig_start);
- disko = em->block_start + offset_in_extent;
-
/*
* As btrfs supports shared space, this information
* can be exported to userspace tools via
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index f660ba1..51e77d7 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1842,16 +1842,16 @@ out:
static void update_time_for_write(struct inode *inode)
{
- struct timespec now;
+ struct timespec64 now;
if (IS_NOCMTIME(inode))
return;
now = current_time(inode);
- if (!timespec_equal(&inode->i_mtime, &now))
+ if (!timespec64_equal(&inode->i_mtime, &now))
inode->i_mtime = now;
- if (!timespec_equal(&inode->i_ctime, &now))
+ if (!timespec64_equal(&inode->i_ctime, &now))
inode->i_ctime = now;
if (IS_I_VERSION(inode))
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 89b2082..e9482f0 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5745,7 +5745,7 @@ static struct inode *new_simple_dir(struct super_block *s,
inode->i_mtime = current_time(inode);
inode->i_atime = inode->i_mtime;
inode->i_ctime = inode->i_mtime;
- BTRFS_I(inode)->i_otime = inode->i_mtime;
+ BTRFS_I(inode)->i_otime = timespec64_to_timespec(inode->i_mtime);
return inode;
}
@@ -6094,7 +6094,7 @@ static int btrfs_dirty_inode(struct inode *inode)
* This is a copy of file_update_time. We need this so we can return error on
* ENOSPC for updating the inode in the case of file write and mmap writes.
*/
-static int btrfs_update_time(struct inode *inode, struct timespec *now,
+static int btrfs_update_time(struct inode *inode, struct timespec64 *now,
int flags)
{
struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -6349,7 +6349,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
inode->i_mtime = current_time(inode);
inode->i_atime = inode->i_mtime;
inode->i_ctime = inode->i_mtime;
- BTRFS_I(inode)->i_otime = inode->i_mtime;
+ BTRFS_I(inode)->i_otime = timespec64_to_timespec(inode->i_mtime);
inode_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
struct btrfs_inode_item);
@@ -8872,7 +8872,7 @@ again:
* beyond EOF, then the page is guaranteed safe against truncation until we
* unlock the page.
*/
-int btrfs_page_mkwrite(struct vm_fault *vmf)
+vm_fault_t btrfs_page_mkwrite(struct vm_fault *vmf)
{
struct page *page = vmf->page;
struct inode *inode = file_inode(vmf->vma->vm_file);
@@ -8884,7 +8884,8 @@ int btrfs_page_mkwrite(struct vm_fault *vmf)
char *kaddr;
unsigned long zero_start;
loff_t size;
- int ret;
+ vm_fault_t ret;
+ int ret2;
int reserved = 0;
u64 reserved_space;
u64 page_start;
@@ -8906,17 +8907,14 @@ int btrfs_page_mkwrite(struct vm_fault *vmf)
* end up waiting indefinitely to get a lock on the page currently
* being processed by btrfs_page_mkwrite() function.
*/
- ret = btrfs_delalloc_reserve_space(inode, &data_reserved, page_start,
+ ret2 = btrfs_delalloc_reserve_space(inode, &data_reserved, page_start,
reserved_space);
- if (!ret) {
- ret = file_update_time(vmf->vma->vm_file);
+ if (!ret2) {
+ ret2 = file_update_time(vmf->vma->vm_file);
reserved = 1;
}
- if (ret) {
- if (ret == -ENOMEM)
- ret = VM_FAULT_OOM;
- else /* -ENOSPC, -EIO, etc */
- ret = VM_FAULT_SIGBUS;
+ if (ret2) {
+ ret = vmf_error(ret2);
if (reserved)
goto out;
goto out_noreserve;
@@ -8975,15 +8973,15 @@ again:
EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
0, 0, &cached_state);
- ret = btrfs_set_extent_delalloc(inode, page_start, end, 0,
+ ret2 = btrfs_set_extent_delalloc(inode, page_start, end, 0,
&cached_state, 0);
- if (ret) {
+ if (ret2) {
unlock_extent_cached(io_tree, page_start, page_end,
&cached_state);
ret = VM_FAULT_SIGBUS;
goto out_unlock;
}
- ret = 0;
+ ret2 = 0;
/* page is wholly or partially inside EOF */
if (page_start + PAGE_SIZE > size)
@@ -9008,7 +9006,7 @@ again:
unlock_extent_cached(io_tree, page_start, page_end, &cached_state);
out_unlock:
- if (!ret) {
+ if (!ret2) {
btrfs_delalloc_release_extents(BTRFS_I(inode), PAGE_SIZE, true);
sb_end_pagefault(inode->i_sb);
extent_changeset_free(data_reserved);
@@ -9437,7 +9435,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
struct btrfs_root *dest = BTRFS_I(new_dir)->root;
struct inode *new_inode = new_dentry->d_inode;
struct inode *old_inode = old_dentry->d_inode;
- struct timespec ctime = current_time(old_inode);
+ struct timespec64 ctime = current_time(old_inode);
struct dentry *parent;
u64 old_ino = btrfs_ino(BTRFS_I(old_inode));
u64 new_ino = btrfs_ino(BTRFS_I(new_inode));
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index d29992f..c2837a3 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -562,7 +562,7 @@ static noinline int create_subvol(struct inode *dir,
struct btrfs_root *root = BTRFS_I(dir)->root;
struct btrfs_root *new_root;
struct btrfs_block_rsv block_rsv;
- struct timespec cur_time = current_time(dir);
+ struct timespec64 cur_time = current_time(dir);
struct inode *inode;
int ret;
int err;
@@ -2438,6 +2438,10 @@ static int btrfs_search_path_in_tree_user(struct inode *inode,
}
temp_inode = btrfs_iget(sb, &key2, root, NULL);
+ if (IS_ERR(temp_inode)) {
+ ret = PTR_ERR(temp_inode);
+ goto out;
+ }
ret = inode_permission(temp_inode, MAY_READ | MAY_EXEC);
iput(temp_inode);
if (ret) {
@@ -5391,7 +5395,7 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file,
struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_root_item *root_item = &root->root_item;
struct btrfs_trans_handle *trans;
- struct timespec ct = current_time(inode);
+ struct timespec64 ct = current_time(inode);
int ret = 0;
int received_uuid_changed;
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index 6db3bda..c451285 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -485,9 +485,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;
+ struct timespec64 ct;
- ktime_get_real_ts(&ct);
+ ktime_get_real_ts64(&ct);
spin_lock(&root->root_item_lock);
btrfs_set_root_ctransid(item, trans->transid);
btrfs_set_stack_timespec_sec(&item->ctime, ct.tv_sec);
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index a590058..5723060 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -2799,7 +2799,7 @@ static int scrub_extent(struct scrub_ctx *sctx, struct map_lookup *map,
have_csum = scrub_find_csum(sctx, logical, csum);
if (have_csum == 0)
++sctx->stat.no_csum;
- if (sctx->is_dev_replace && !have_csum) {
+ if (0 && sctx->is_dev_replace && !have_csum) {
ret = copy_nocow_pages(sctx, logical, l,
mirror_num,
physical_for_dev_replace);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 4485eae..ff5f6c7 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1422,7 +1422,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
struct dentry *dentry;
struct extent_buffer *tmp;
struct extent_buffer *old;
- struct timespec cur_time;
+ struct timespec64 cur_time;
int ret = 0;
u64 to_reserve = 0;
u64 index = 0;
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 5f7ad3d..292b3d7 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -370,7 +370,7 @@ static int start_read(struct inode *inode, struct ceph_rw_context *rw_ctx,
/* build page vector */
nr_pages = calc_pages_for(0, len);
- pages = kmalloc(sizeof(*pages) * nr_pages, GFP_KERNEL);
+ pages = kmalloc_array(nr_pages, sizeof(*pages), GFP_KERNEL);
if (!pages) {
ret = -ENOMEM;
goto out_put;
@@ -574,6 +574,7 @@ static u64 get_writepages_data_length(struct inode *inode,
*/
static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
{
+ struct timespec ts;
struct inode *inode;
struct ceph_inode_info *ci;
struct ceph_fs_client *fsc;
@@ -624,11 +625,12 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc)
set_bdi_congested(inode_to_bdi(inode), BLK_RW_ASYNC);
set_page_writeback(page);
+ ts = timespec64_to_timespec(inode->i_mtime);
err = ceph_osdc_writepages(&fsc->client->osdc, ceph_vino(inode),
&ci->i_layout, snapc, page_off, len,
ceph_wbc.truncate_seq,
ceph_wbc.truncate_size,
- &inode->i_mtime, &page, 1);
+ &ts, &page, 1);
if (err < 0) {
struct writeback_control tmp_wbc;
if (!wbc)
@@ -966,8 +968,9 @@ get_more_pages:
BUG_ON(pages);
max_pages = calc_pages_for(0, (u64)len);
- pages = kmalloc(max_pages * sizeof (*pages),
- GFP_NOFS);
+ pages = kmalloc_array(max_pages,
+ sizeof(*pages),
+ GFP_NOFS);
if (!pages) {
pool = fsc->wb_pagevec_pool;
pages = mempool_alloc(pool, GFP_NOFS);
@@ -1113,8 +1116,8 @@ new_request:
/* allocate new pages array for next request */
data_pages = pages;
- pages = kmalloc(locked_pages * sizeof (*pages),
- GFP_NOFS);
+ pages = kmalloc_array(locked_pages, sizeof(*pages),
+ GFP_NOFS);
if (!pages) {
pool = fsc->wb_pagevec_pool;
pages = mempool_alloc(pool, GFP_NOFS);
@@ -1131,7 +1134,7 @@ new_request:
pages = NULL;
}
- req->r_mtime = inode->i_mtime;
+ req->r_mtime = timespec64_to_timespec(inode->i_mtime);
rc = ceph_osdc_start_request(&fsc->client->osdc, req, true);
BUG_ON(rc);
req = NULL;
@@ -1731,7 +1734,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
goto out;
}
- req->r_mtime = inode->i_mtime;
+ req->r_mtime = timespec64_to_timespec(inode->i_mtime);
err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!err)
err = ceph_osdc_wait_request(&fsc->client->osdc, req);
@@ -1773,7 +1776,7 @@ int ceph_uninline_data(struct file *filp, struct page *locked_page)
goto out_put;
}
- req->r_mtime = inode->i_mtime;
+ req->r_mtime = timespec64_to_timespec(inode->i_mtime);
err = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!err)
err = ceph_osdc_wait_request(&fsc->client->osdc, req);
@@ -1934,8 +1937,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
0, false, true);
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;
+ wr_req->r_mtime = timespec64_to_timespec(ci->vfs_inode.i_mtime);
err2 = ceph_osdc_start_request(&fsc->client->osdc, wr_req, false);
if (!err)
diff --git a/fs/ceph/cache.c b/fs/ceph/cache.c
index bb524c8..362900e 100644
--- a/fs/ceph/cache.c
+++ b/fs/ceph/cache.c
@@ -130,7 +130,7 @@ static enum fscache_checkaux ceph_fscache_inode_check_aux(
memset(&aux, 0, sizeof(aux));
aux.version = ci->i_version;
- aux.mtime = inode->i_mtime;
+ aux.mtime = timespec64_to_timespec(inode->i_mtime);
if (memcmp(data, &aux, sizeof(aux)) != 0)
return FSCACHE_CHECKAUX_OBSOLETE;
@@ -163,7 +163,7 @@ void ceph_fscache_register_inode_cookie(struct inode *inode)
if (!ci->fscache) {
memset(&aux, 0, sizeof(aux));
aux.version = ci->i_version;
- aux.mtime = inode->i_mtime;
+ aux.mtime = timespec64_to_timespec(inode->i_mtime);
ci->fscache = fscache_acquire_cookie(fsc->fscache,
&ceph_fscache_inode_object_def,
&ci->i_vino, sizeof(ci->i_vino),
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 23dbfae..990258c 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -69,6 +69,8 @@ static char *gcap_string(char *s, int c)
*s++ = 'w';
if (c & CEPH_CAP_GBUFFER)
*s++ = 'b';
+ if (c & CEPH_CAP_GWREXTEND)
+ *s++ = 'a';
if (c & CEPH_CAP_GLAZYIO)
*s++ = 'l';
return s;
@@ -1358,9 +1360,9 @@ static int __send_cap(struct ceph_mds_client *mdsc, struct ceph_cap *cap,
arg.xattr_buf = NULL;
}
- arg.mtime = inode->i_mtime;
- arg.atime = inode->i_atime;
- arg.ctime = inode->i_ctime;
+ arg.mtime = timespec64_to_timespec(inode->i_mtime);
+ arg.atime = timespec64_to_timespec(inode->i_atime);
+ arg.ctime = timespec64_to_timespec(inode->i_ctime);
arg.op = op;
arg.caps = cap->implemented;
@@ -3022,30 +3024,41 @@ static void invalidate_aliases(struct inode *inode)
dput(prev);
}
+struct cap_extra_info {
+ struct ceph_string *pool_ns;
+ /* inline data */
+ u64 inline_version;
+ void *inline_data;
+ u32 inline_len;
+ /* dirstat */
+ bool dirstat_valid;
+ u64 nfiles;
+ u64 nsubdirs;
+ /* currently issued */
+ int issued;
+};
+
/*
* Handle a cap GRANT message from the MDS. (Note that a GRANT may
* actually be a revocation if it specifies a smaller cap set.)
*
* caller holds s_mutex and i_ceph_lock, we drop both.
*/
-static void handle_cap_grant(struct ceph_mds_client *mdsc,
- struct inode *inode, struct ceph_mds_caps *grant,
- struct ceph_string **pns, u64 inline_version,
- void *inline_data, u32 inline_len,
- struct ceph_buffer *xattr_buf,
+static void handle_cap_grant(struct inode *inode,
struct ceph_mds_session *session,
- struct ceph_cap *cap, int issued)
+ struct ceph_cap *cap,
+ struct ceph_mds_caps *grant,
+ struct ceph_buffer *xattr_buf,
+ struct cap_extra_info *extra_info)
__releases(ci->i_ceph_lock)
- __releases(mdsc->snap_rwsem)
+ __releases(session->s_mdsc->snap_rwsem)
{
struct ceph_inode_info *ci = ceph_inode(inode);
- int mds = session->s_mds;
int seq = le32_to_cpu(grant->seq);
int newcaps = le32_to_cpu(grant->caps);
int used, wanted, dirty;
u64 size = le64_to_cpu(grant->size);
u64 max_size = le64_to_cpu(grant->max_size);
- struct timespec mtime, atime, ctime;
int check_caps = 0;
bool wake = false;
bool writeback = false;
@@ -3055,7 +3068,7 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
bool fill_inline = false;
dout("handle_cap_grant inode %p cap %p mds%d seq %d %s\n",
- inode, cap, mds, seq, ceph_cap_string(newcaps));
+ inode, cap, session->s_mds, seq, ceph_cap_string(newcaps));
dout(" size %llu max_size %llu, i_size %llu\n", size, max_size,
inode->i_size);
@@ -3101,7 +3114,7 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
__check_cap_issue(ci, cap, newcaps);
if ((newcaps & CEPH_CAP_AUTH_SHARED) &&
- (issued & CEPH_CAP_AUTH_EXCL) == 0) {
+ (extra_info->issued & CEPH_CAP_AUTH_EXCL) == 0) {
inode->i_mode = le32_to_cpu(grant->mode);
inode->i_uid = make_kuid(&init_user_ns, le32_to_cpu(grant->uid));
inode->i_gid = make_kgid(&init_user_ns, le32_to_cpu(grant->gid));
@@ -3110,15 +3123,16 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
from_kgid(&init_user_ns, inode->i_gid));
}
- if ((newcaps & CEPH_CAP_AUTH_SHARED) &&
- (issued & CEPH_CAP_LINK_EXCL) == 0) {
+ if ((newcaps & CEPH_CAP_LINK_SHARED) &&
+ (extra_info->issued & CEPH_CAP_LINK_EXCL) == 0) {
set_nlink(inode, le32_to_cpu(grant->nlink));
if (inode->i_nlink == 0 &&
(newcaps & (CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL)))
deleted_inode = true;
}
- if ((issued & CEPH_CAP_XATTR_EXCL) == 0 && grant->xattr_len) {
+ if ((extra_info->issued & CEPH_CAP_XATTR_EXCL) == 0 &&
+ grant->xattr_len) {
int len = le32_to_cpu(grant->xattr_len);
u64 version = le64_to_cpu(grant->xattr_version);
@@ -3134,15 +3148,21 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
}
if (newcaps & CEPH_CAP_ANY_RD) {
+ struct timespec mtime, atime, ctime;
/* ctime/mtime/atime? */
ceph_decode_timespec(&mtime, &grant->mtime);
ceph_decode_timespec(&atime, &grant->atime);
ceph_decode_timespec(&ctime, &grant->ctime);
- ceph_fill_file_time(inode, issued,
+ ceph_fill_file_time(inode, extra_info->issued,
le32_to_cpu(grant->time_warp_seq),
&ctime, &mtime, &atime);
}
+ if ((newcaps & CEPH_CAP_FILE_SHARED) && extra_info->dirstat_valid) {
+ ci->i_files = extra_info->nfiles;
+ ci->i_subdirs = extra_info->nsubdirs;
+ }
+
if (newcaps & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR)) {
/* file layout may have changed */
s64 old_pool = ci->i_layout.pool_id;
@@ -3151,15 +3171,16 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
ceph_file_layout_from_legacy(&ci->i_layout, &grant->layout);
old_ns = rcu_dereference_protected(ci->i_layout.pool_ns,
lockdep_is_held(&ci->i_ceph_lock));
- rcu_assign_pointer(ci->i_layout.pool_ns, *pns);
+ rcu_assign_pointer(ci->i_layout.pool_ns, extra_info->pool_ns);
- if (ci->i_layout.pool_id != old_pool || *pns != old_ns)
+ if (ci->i_layout.pool_id != old_pool ||
+ extra_info->pool_ns != old_ns)
ci->i_ceph_flags &= ~CEPH_I_POOL_PERM;
- *pns = old_ns;
+ extra_info->pool_ns = old_ns;
/* size/truncate_seq? */
- queue_trunc = ceph_fill_file_size(inode, issued,
+ queue_trunc = ceph_fill_file_size(inode, extra_info->issued,
le32_to_cpu(grant->truncate_seq),
le64_to_cpu(grant->truncate_size),
size);
@@ -3238,24 +3259,26 @@ static void handle_cap_grant(struct ceph_mds_client *mdsc,
}
BUG_ON(cap->issued & ~cap->implemented);
- if (inline_version > 0 && inline_version >= ci->i_inline_version) {
- ci->i_inline_version = inline_version;
+ if (extra_info->inline_version > 0 &&
+ extra_info->inline_version >= ci->i_inline_version) {
+ ci->i_inline_version = extra_info->inline_version;
if (ci->i_inline_version != CEPH_INLINE_NONE &&
(newcaps & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)))
fill_inline = true;
}
if (le32_to_cpu(grant->op) == CEPH_CAP_OP_IMPORT) {
- if (newcaps & ~issued)
+ if (newcaps & ~extra_info->issued)
wake = true;
- kick_flushing_inode_caps(mdsc, session, inode);
- up_read(&mdsc->snap_rwsem);
+ kick_flushing_inode_caps(session->s_mdsc, session, inode);
+ up_read(&session->s_mdsc->snap_rwsem);
} else {
spin_unlock(&ci->i_ceph_lock);
}
if (fill_inline)
- ceph_fill_inline_data(inode, NULL, inline_data, inline_len);
+ ceph_fill_inline_data(inode, NULL, extra_info->inline_data,
+ extra_info->inline_len);
if (queue_trunc)
ceph_queue_vmtruncate(inode);
@@ -3720,31 +3743,25 @@ void ceph_handle_caps(struct ceph_mds_session *session,
struct ceph_msg *msg)
{
struct ceph_mds_client *mdsc = session->s_mdsc;
- struct super_block *sb = mdsc->fsc->sb;
struct inode *inode;
struct ceph_inode_info *ci;
struct ceph_cap *cap;
struct ceph_mds_caps *h;
struct ceph_mds_cap_peer *peer = NULL;
struct ceph_snap_realm *realm = NULL;
- struct ceph_string *pool_ns = NULL;
- int mds = session->s_mds;
- int op, issued;
+ int op;
+ int msg_version = le16_to_cpu(msg->hdr.version);
u32 seq, mseq;
struct ceph_vino vino;
- u64 tid;
- u64 inline_version = 0;
- void *inline_data = NULL;
- u32 inline_len = 0;
void *snaptrace;
size_t snaptrace_len;
void *p, *end;
+ struct cap_extra_info extra_info = {};
- dout("handle_caps from mds%d\n", mds);
+ dout("handle_caps from mds%d\n", session->s_mds);
/* decode */
end = msg->front.iov_base + msg->front.iov_len;
- tid = le64_to_cpu(msg->hdr.tid);
if (msg->front.iov_len < sizeof(*h))
goto bad;
h = msg->front.iov_base;
@@ -3758,7 +3775,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
snaptrace_len = le32_to_cpu(h->snap_trace_len);
p = snaptrace + snaptrace_len;
- if (le16_to_cpu(msg->hdr.version) >= 2) {
+ if (msg_version >= 2) {
u32 flock_len;
ceph_decode_32_safe(&p, end, flock_len, bad);
if (p + flock_len > end)
@@ -3766,7 +3783,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
p += flock_len;
}
- if (le16_to_cpu(msg->hdr.version) >= 3) {
+ if (msg_version >= 3) {
if (op == CEPH_CAP_OP_IMPORT) {
if (p + sizeof(*peer) > end)
goto bad;
@@ -3778,16 +3795,16 @@ void ceph_handle_caps(struct ceph_mds_session *session,
}
}
- if (le16_to_cpu(msg->hdr.version) >= 4) {
- ceph_decode_64_safe(&p, end, inline_version, bad);
- ceph_decode_32_safe(&p, end, inline_len, bad);
- if (p + inline_len > end)
+ if (msg_version >= 4) {
+ ceph_decode_64_safe(&p, end, extra_info.inline_version, bad);
+ ceph_decode_32_safe(&p, end, extra_info.inline_len, bad);
+ if (p + extra_info.inline_len > end)
goto bad;
- inline_data = p;
- p += inline_len;
+ extra_info.inline_data = p;
+ p += extra_info.inline_len;
}
- if (le16_to_cpu(msg->hdr.version) >= 5) {
+ if (msg_version >= 5) {
struct ceph_osd_client *osdc = &mdsc->fsc->client->osdc;
u32 epoch_barrier;
@@ -3795,7 +3812,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
ceph_osdc_update_epoch_barrier(osdc, epoch_barrier);
}
- if (le16_to_cpu(msg->hdr.version) >= 8) {
+ if (msg_version >= 8) {
u64 flush_tid;
u32 caller_uid, caller_gid;
u32 pool_ns_len;
@@ -3809,13 +3826,33 @@ void ceph_handle_caps(struct ceph_mds_session *session,
ceph_decode_32_safe(&p, end, pool_ns_len, bad);
if (pool_ns_len > 0) {
ceph_decode_need(&p, end, pool_ns_len, bad);
- pool_ns = ceph_find_or_create_string(p, pool_ns_len);
+ extra_info.pool_ns =
+ ceph_find_or_create_string(p, pool_ns_len);
p += pool_ns_len;
}
}
+ if (msg_version >= 11) {
+ struct ceph_timespec *btime;
+ u64 change_attr;
+ u32 flags;
+
+ /* version >= 9 */
+ if (p + sizeof(*btime) > end)
+ goto bad;
+ btime = p;
+ p += sizeof(*btime);
+ ceph_decode_64_safe(&p, end, change_attr, bad);
+ /* version >= 10 */
+ ceph_decode_32_safe(&p, end, flags, bad);
+ /* version >= 11 */
+ extra_info.dirstat_valid = true;
+ ceph_decode_64_safe(&p, end, extra_info.nfiles, bad);
+ ceph_decode_64_safe(&p, end, extra_info.nsubdirs, bad);
+ }
+
/* lookup ino */
- inode = ceph_find_inode(sb, vino);
+ inode = ceph_find_inode(mdsc->fsc->sb, vino);
ci = ceph_inode(inode);
dout(" op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op), vino.ino,
vino.snap, inode);
@@ -3848,7 +3885,8 @@ void ceph_handle_caps(struct ceph_mds_session *session,
/* these will work even if we don't have a cap yet */
switch (op) {
case CEPH_CAP_OP_FLUSHSNAP_ACK:
- handle_cap_flushsnap_ack(inode, tid, h, session);
+ handle_cap_flushsnap_ack(inode, le64_to_cpu(msg->hdr.tid),
+ h, session);
goto done;
case CEPH_CAP_OP_EXPORT:
@@ -3867,10 +3905,9 @@ void ceph_handle_caps(struct ceph_mds_session *session,
down_read(&mdsc->snap_rwsem);
}
handle_cap_import(mdsc, inode, h, peer, session,
- &cap, &issued);
- handle_cap_grant(mdsc, inode, h, &pool_ns,
- inline_version, inline_data, inline_len,
- msg->middle, session, cap, issued);
+ &cap, &extra_info.issued);
+ handle_cap_grant(inode, session, cap,
+ h, msg->middle, &extra_info);
if (realm)
ceph_put_snap_realm(mdsc, realm);
goto done_unlocked;
@@ -3878,10 +3915,11 @@ void ceph_handle_caps(struct ceph_mds_session *session,
/* the rest require a cap */
spin_lock(&ci->i_ceph_lock);
- cap = __get_cap_for_mds(ceph_inode(inode), mds);
+ cap = __get_cap_for_mds(ceph_inode(inode), session->s_mds);
if (!cap) {
dout(" no cap on %p ino %llx.%llx from mds%d\n",
- inode, ceph_ino(inode), ceph_snap(inode), mds);
+ inode, ceph_ino(inode), ceph_snap(inode),
+ session->s_mds);
spin_unlock(&ci->i_ceph_lock);
goto flush_cap_releases;
}
@@ -3890,15 +3928,15 @@ void ceph_handle_caps(struct ceph_mds_session *session,
switch (op) {
case CEPH_CAP_OP_REVOKE:
case CEPH_CAP_OP_GRANT:
- __ceph_caps_issued(ci, &issued);
- issued |= __ceph_caps_dirty(ci);
- handle_cap_grant(mdsc, inode, h, &pool_ns,
- inline_version, inline_data, inline_len,
- msg->middle, session, cap, issued);
+ __ceph_caps_issued(ci, &extra_info.issued);
+ extra_info.issued |= __ceph_caps_dirty(ci);
+ handle_cap_grant(inode, session, cap,
+ h, msg->middle, &extra_info);
goto done_unlocked;
case CEPH_CAP_OP_FLUSH_ACK:
- handle_cap_flush_ack(inode, tid, h, session, cap);
+ handle_cap_flush_ack(inode, le64_to_cpu(msg->hdr.tid),
+ h, session, cap);
break;
case CEPH_CAP_OP_TRUNC:
@@ -3925,7 +3963,7 @@ done:
mutex_unlock(&session->s_mutex);
done_unlocked:
iput(inode);
- ceph_put_string(pool_ns);
+ ceph_put_string(extra_info.pool_ns);
return;
bad:
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 1a78dd6..036ac0f 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -1486,6 +1486,8 @@ const struct file_operations ceph_dir_fops = {
.release = ceph_release,
.unlocked_ioctl = ceph_ioctl,
.fsync = ceph_fsync,
+ .lock = ceph_lock,
+ .flock = ceph_flock,
};
const struct file_operations ceph_snapdir_fops = {
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index cf0e45b..ad0bed9 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -895,7 +895,6 @@ 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:
@@ -924,7 +923,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
int num_pages = 0;
int flags;
int ret;
- struct timespec mtime = current_time(inode);
+ struct timespec mtime = timespec64_to_timespec(current_time(inode));
size_t count = iov_iter_count(iter);
loff_t pos = iocb->ki_pos;
bool write = iov_iter_rw(iter) == WRITE;
@@ -1132,7 +1131,7 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
int flags;
int ret;
bool check_caps = false;
- struct timespec mtime = current_time(inode);
+ struct timespec mtime = timespec64_to_timespec(current_time(inode));
size_t count = iov_iter_count(from);
if (ceph_snap(file_inode(file)) != CEPH_NOSNAP)
@@ -1664,7 +1663,7 @@ static int ceph_zero_partial_object(struct inode *inode,
goto out;
}
- req->r_mtime = inode->i_mtime;
+ req->r_mtime = timespec64_to_timespec(inode->i_mtime);
ret = ceph_osdc_start_request(&fsc->client->osdc, req, false);
if (!ret) {
ret = ceph_osdc_wait_request(&fsc->client->osdc, req);
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index ae05692..ee764ac 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -662,6 +662,9 @@ void ceph_fill_file_time(struct inode *inode, int issued,
struct timespec *mtime, struct timespec *atime)
{
struct ceph_inode_info *ci = ceph_inode(inode);
+ struct timespec64 ctime64 = timespec_to_timespec64(*ctime);
+ struct timespec64 mtime64 = timespec_to_timespec64(*mtime);
+ struct timespec64 atime64 = timespec_to_timespec64(*atime);
int warn = 0;
if (issued & (CEPH_CAP_FILE_EXCL|
@@ -670,39 +673,39 @@ void ceph_fill_file_time(struct inode *inode, int issued,
CEPH_CAP_AUTH_EXCL|
CEPH_CAP_XATTR_EXCL)) {
if (ci->i_version == 0 ||
- timespec_compare(ctime, &inode->i_ctime) > 0) {
- dout("ctime %ld.%09ld -> %ld.%09ld inc w/ cap\n",
- inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
- ctime->tv_sec, ctime->tv_nsec);
- inode->i_ctime = *ctime;
+ timespec64_compare(&ctime64, &inode->i_ctime) > 0) {
+ dout("ctime %lld.%09ld -> %lld.%09ld inc w/ cap\n",
+ (long long)inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
+ (long long)ctime->tv_sec, ctime->tv_nsec);
+ inode->i_ctime = ctime64;
}
if (ci->i_version == 0 ||
ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) > 0) {
/* the MDS did a utimes() */
- dout("mtime %ld.%09ld -> %ld.%09ld "
+ dout("mtime %lld.%09ld -> %lld.%09ld "
"tw %d -> %d\n",
- inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
- mtime->tv_sec, mtime->tv_nsec,
+ (long long)inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+ (long long)mtime->tv_sec, mtime->tv_nsec,
ci->i_time_warp_seq, (int)time_warp_seq);
- inode->i_mtime = *mtime;
- inode->i_atime = *atime;
+ inode->i_mtime = mtime64;
+ inode->i_atime = atime64;
ci->i_time_warp_seq = time_warp_seq;
} else if (time_warp_seq == ci->i_time_warp_seq) {
/* nobody did utimes(); take the max */
- if (timespec_compare(mtime, &inode->i_mtime) > 0) {
- dout("mtime %ld.%09ld -> %ld.%09ld inc\n",
- inode->i_mtime.tv_sec,
+ if (timespec64_compare(&mtime64, &inode->i_mtime) > 0) {
+ dout("mtime %lld.%09ld -> %lld.%09ld inc\n",
+ (long long)inode->i_mtime.tv_sec,
inode->i_mtime.tv_nsec,
- mtime->tv_sec, mtime->tv_nsec);
- inode->i_mtime = *mtime;
+ (long long)mtime->tv_sec, mtime->tv_nsec);
+ inode->i_mtime = mtime64;
}
- if (timespec_compare(atime, &inode->i_atime) > 0) {
- dout("atime %ld.%09ld -> %ld.%09ld inc\n",
- inode->i_atime.tv_sec,
+ if (timespec64_compare(&atime64, &inode->i_atime) > 0) {
+ dout("atime %lld.%09ld -> %lld.%09ld inc\n",
+ (long long)inode->i_atime.tv_sec,
inode->i_atime.tv_nsec,
- atime->tv_sec, atime->tv_nsec);
- inode->i_atime = *atime;
+ (long long)atime->tv_sec, atime->tv_nsec);
+ inode->i_atime = atime64;
}
} else if (issued & CEPH_CAP_FILE_EXCL) {
/* we did a utimes(); ignore mds values */
@@ -712,9 +715,9 @@ void ceph_fill_file_time(struct inode *inode, int issued,
} else {
/* we have no write|excl caps; whatever the MDS says is true */
if (ceph_seq_cmp(time_warp_seq, ci->i_time_warp_seq) >= 0) {
- inode->i_ctime = *ctime;
- inode->i_mtime = *mtime;
- inode->i_atime = *atime;
+ inode->i_ctime = ctime64;
+ inode->i_mtime = mtime64;
+ inode->i_atime = atime64;
ci->i_time_warp_seq = time_warp_seq;
} else {
warn = 1;
@@ -739,7 +742,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc;
struct ceph_mds_reply_inode *info = iinfo->in;
struct ceph_inode_info *ci = ceph_inode(inode);
- int issued = 0, implemented, new_issued;
+ int issued, new_issued, info_caps;
struct timespec mtime, atime, ctime;
struct ceph_buffer *xattr_blob = NULL;
struct ceph_string *pool_ns = NULL;
@@ -754,8 +757,10 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
inode, ceph_vinop(inode), le64_to_cpu(info->version),
ci->i_version);
+ info_caps = le32_to_cpu(info->cap.caps);
+
/* prealloc new cap struct */
- if (info->cap.caps && ceph_snap(inode) == CEPH_NOSNAP)
+ if (info_caps && ceph_snap(inode) == CEPH_NOSNAP)
new_cap = ceph_get_cap(mdsc, caps_reservation);
/*
@@ -792,9 +797,9 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
le64_to_cpu(info->version) > (ci->i_version & ~1)))
new_version = true;
- issued = __ceph_caps_issued(ci, &implemented);
- issued |= implemented | __ceph_caps_dirty(ci);
- new_issued = ~issued & le32_to_cpu(info->cap.caps);
+ __ceph_caps_issued(ci, &issued);
+ issued |= __ceph_caps_dirty(ci);
+ new_issued = ~issued & info_caps;
/* update inode */
inode->i_rdev = le32_to_cpu(info->rdev);
@@ -826,6 +831,11 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
&ctime, &mtime, &atime);
}
+ if (new_version || (info_caps & CEPH_CAP_FILE_SHARED)) {
+ ci->i_files = le64_to_cpu(info->files);
+ ci->i_subdirs = le64_to_cpu(info->subdirs);
+ }
+
if (new_version ||
(new_issued & (CEPH_CAP_ANY_FILE_RD | CEPH_CAP_ANY_FILE_WR))) {
s64 old_pool = ci->i_layout.pool_id;
@@ -854,6 +864,18 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
}
}
+ /* layout and rstat are not tracked by capability, update them if
+ * the inode info is from auth mds */
+ if (new_version || (info->cap.flags & CEPH_CAP_FLAG_AUTH)) {
+ if (S_ISDIR(inode->i_mode)) {
+ ci->i_dir_layout = iinfo->dir_layout;
+ ci->i_rbytes = le64_to_cpu(info->rbytes);
+ ci->i_rfiles = le64_to_cpu(info->rfiles);
+ ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
+ ceph_decode_timespec(&ci->i_rctime, &info->rctime);
+ }
+ }
+
/* xattrs */
/* note that if i_xattrs.len <= 4, i_xattrs.data will still be NULL. */
if ((ci->i_xattrs.version == 0 || !(issued & CEPH_CAP_XATTR_EXCL)) &&
@@ -870,7 +892,8 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
}
/* finally update i_version */
- ci->i_version = le64_to_cpu(info->version);
+ if (le64_to_cpu(info->version) > ci->i_version)
+ ci->i_version = le64_to_cpu(info->version);
inode->i_mapping->a_ops = &ceph_aops;
@@ -918,15 +941,6 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
case S_IFDIR:
inode->i_op = &ceph_dir_iops;
inode->i_fop = &ceph_dir_fops;
-
- ci->i_dir_layout = iinfo->dir_layout;
-
- ci->i_files = le64_to_cpu(info->files);
- ci->i_subdirs = le64_to_cpu(info->subdirs);
- ci->i_rbytes = le64_to_cpu(info->rbytes);
- ci->i_rfiles = le64_to_cpu(info->rfiles);
- ci->i_rsubdirs = le64_to_cpu(info->rsubdirs);
- ceph_decode_timespec(&ci->i_rctime, &info->rctime);
break;
default:
pr_err("fill_inode %llx.%llx BAD mode 0%o\n",
@@ -934,12 +948,11 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
}
/* were we issued a capability? */
- if (info->cap.caps) {
+ if (info_caps) {
if (ceph_snap(inode) == CEPH_NOSNAP) {
- unsigned caps = le32_to_cpu(info->cap.caps);
ceph_add_cap(inode, session,
le64_to_cpu(info->cap.cap_id),
- cap_fmode, caps,
+ cap_fmode, info_caps,
le32_to_cpu(info->cap.wanted),
le32_to_cpu(info->cap.seq),
le32_to_cpu(info->cap.mseq),
@@ -949,7 +962,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
/* set dir completion flag? */
if (S_ISDIR(inode->i_mode) &&
ci->i_files == 0 && ci->i_subdirs == 0 &&
- (caps & CEPH_CAP_FILE_SHARED) &&
+ (info_caps & CEPH_CAP_FILE_SHARED) &&
(issued & CEPH_CAP_FILE_EXCL) == 0 &&
!__ceph_dir_is_complete(ci)) {
dout(" marking %p complete (empty)\n", inode);
@@ -962,8 +975,8 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
wake = true;
} else {
dout(" %p got snap_caps %s\n", inode,
- ceph_cap_string(le32_to_cpu(info->cap.caps)));
- ci->i_snap_caps |= le32_to_cpu(info->cap.caps);
+ ceph_cap_string(info_caps));
+ ci->i_snap_caps |= info_caps;
if (cap_fmode >= 0)
__ceph_get_fmode(ci, cap_fmode);
}
@@ -978,8 +991,7 @@ static int fill_inode(struct inode *inode, struct page *locked_page,
int cache_caps = CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO;
ci->i_inline_version = iinfo->inline_version;
if (ci->i_inline_version != CEPH_INLINE_NONE &&
- (locked_page ||
- (le32_to_cpu(info->cap.caps) & cache_caps)))
+ (locked_page || (info_caps & cache_caps)))
fill_inline = true;
}
@@ -1941,6 +1953,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
int err = 0;
int inode_dirty_flags = 0;
bool lock_snap_rwsem = false;
+ struct timespec ts;
prealloc_cf = ceph_alloc_cap_flush();
if (!prealloc_cf)
@@ -2015,44 +2028,44 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
}
if (ia_valid & ATTR_ATIME) {
- dout("setattr %p atime %ld.%ld -> %ld.%ld\n", inode,
- inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
- attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
+ dout("setattr %p atime %lld.%ld -> %lld.%ld\n", inode,
+ (long long)inode->i_atime.tv_sec, inode->i_atime.tv_nsec,
+ (long long)attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec);
if (issued & CEPH_CAP_FILE_EXCL) {
ci->i_time_warp_seq++;
inode->i_atime = attr->ia_atime;
dirtied |= CEPH_CAP_FILE_EXCL;
} else if ((issued & CEPH_CAP_FILE_WR) &&
- timespec_compare(&inode->i_atime,
+ timespec64_compare(&inode->i_atime,
&attr->ia_atime) < 0) {
inode->i_atime = attr->ia_atime;
dirtied |= CEPH_CAP_FILE_WR;
} else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
- !timespec_equal(&inode->i_atime, &attr->ia_atime)) {
- ceph_encode_timespec(&req->r_args.setattr.atime,
- &attr->ia_atime);
+ !timespec64_equal(&inode->i_atime, &attr->ia_atime)) {
+ ts = timespec64_to_timespec(attr->ia_atime);
+ ceph_encode_timespec(&req->r_args.setattr.atime, &ts);
mask |= CEPH_SETATTR_ATIME;
release |= CEPH_CAP_FILE_SHARED |
CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
}
}
if (ia_valid & ATTR_MTIME) {
- dout("setattr %p mtime %ld.%ld -> %ld.%ld\n", inode,
- inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
- attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec);
+ dout("setattr %p mtime %lld.%ld -> %lld.%ld\n", inode,
+ (long long)inode->i_mtime.tv_sec, inode->i_mtime.tv_nsec,
+ (long long)attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec);
if (issued & CEPH_CAP_FILE_EXCL) {
ci->i_time_warp_seq++;
inode->i_mtime = attr->ia_mtime;
dirtied |= CEPH_CAP_FILE_EXCL;
} else if ((issued & CEPH_CAP_FILE_WR) &&
- timespec_compare(&inode->i_mtime,
+ timespec64_compare(&inode->i_mtime,
&attr->ia_mtime) < 0) {
inode->i_mtime = attr->ia_mtime;
dirtied |= CEPH_CAP_FILE_WR;
} else if ((issued & CEPH_CAP_FILE_SHARED) == 0 ||
- !timespec_equal(&inode->i_mtime, &attr->ia_mtime)) {
- ceph_encode_timespec(&req->r_args.setattr.mtime,
- &attr->ia_mtime);
+ !timespec64_equal(&inode->i_mtime, &attr->ia_mtime)) {
+ ts = timespec64_to_timespec(attr->ia_mtime);
+ ceph_encode_timespec(&req->r_args.setattr.mtime, &ts);
mask |= CEPH_SETATTR_MTIME;
release |= CEPH_CAP_FILE_SHARED |
CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR;
@@ -2082,9 +2095,9 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
if (ia_valid & ATTR_CTIME) {
bool only = (ia_valid & (ATTR_SIZE|ATTR_MTIME|ATTR_ATIME|
ATTR_MODE|ATTR_UID|ATTR_GID)) == 0;
- dout("setattr %p ctime %ld.%ld -> %ld.%ld (%s)\n", inode,
- inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
- attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
+ dout("setattr %p ctime %lld.%ld -> %lld.%ld (%s)\n", inode,
+ (long long)inode->i_ctime.tv_sec, inode->i_ctime.tv_nsec,
+ (long long)attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec,
only ? "ctime only" : "ignored");
if (only) {
/*
@@ -2126,7 +2139,7 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr)
req->r_inode_drop = release;
req->r_args.setattr.mask = cpu_to_le32(mask);
req->r_num_caps = 1;
- req->r_stamp = attr->ia_ctime;
+ req->r_stamp = timespec64_to_timespec(attr->ia_ctime);
err = ceph_mdsc_do_request(mdsc, NULL, req);
}
dout("setattr %p result=%d (%s locally, %d remote)\n", inode, err,
@@ -2178,6 +2191,7 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
struct ceph_fs_client *fsc = ceph_sb_to_client(inode->i_sb);
struct ceph_mds_client *mdsc = fsc->mdsc;
struct ceph_mds_request *req;
+ int mode;
int err;
if (ceph_snap(inode) == CEPH_SNAPDIR) {
@@ -2190,7 +2204,8 @@ int __ceph_do_getattr(struct inode *inode, struct page *locked_page,
if (!force && ceph_caps_issued_mask(ceph_inode(inode), mask, 1))
return 0;
- req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, USE_ANY_MDS);
+ mode = (mask & CEPH_STAT_RSTAT) ? USE_AUTH_MDS : USE_ANY_MDS;
+ req = ceph_mdsc_create_request(mdsc, CEPH_MDS_OP_GETATTR, mode);
if (IS_ERR(req))
return PTR_ERR(req);
req->r_inode = inode;
@@ -2261,6 +2276,14 @@ int ceph_getattr(const struct path *path, struct kstat *stat,
stat->size = ci->i_files + ci->i_subdirs;
stat->blocks = 0;
stat->blksize = 65536;
+ /*
+ * Some applications rely on the number of st_nlink
+ * value on directories to be either 0 (if unlinked)
+ * or 2 + number of subdirectories.
+ */
+ if (stat->nlink == 1)
+ /* '.' + '..' + subdirs */
+ stat->nlink = 1 + 1 + ci->i_subdirs;
}
}
return err;
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index 5ece2e6..dc8bc66 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -2958,12 +2958,15 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap,
rec.v2.flock_len = (__force __le32)
((ci->i_ceph_flags & CEPH_I_ERROR_FILELOCK) ? 0 : 1);
} else {
+ struct timespec ts;
rec.v1.cap_id = cpu_to_le64(cap->cap_id);
rec.v1.wanted = cpu_to_le32(__ceph_caps_wanted(ci));
rec.v1.issued = cpu_to_le32(cap->issued);
rec.v1.size = cpu_to_le64(inode->i_size);
- ceph_encode_timespec(&rec.v1.mtime, &inode->i_mtime);
- ceph_encode_timespec(&rec.v1.atime, &inode->i_atime);
+ ts = timespec64_to_timespec(inode->i_mtime);
+ ceph_encode_timespec(&rec.v1.mtime, &ts);
+ ts = timespec64_to_timespec(inode->i_atime);
+ ceph_encode_timespec(&rec.v1.atime, &ts);
rec.v1.snaprealm = cpu_to_le64(ci->i_snap_realm->ino);
rec.v1.pathbase = cpu_to_le64(pathbase);
}
@@ -2992,8 +2995,9 @@ encode_again:
num_flock_locks = 0;
}
if (num_fcntl_locks + num_flock_locks > 0) {
- flocks = kmalloc((num_fcntl_locks + num_flock_locks) *
- sizeof(struct ceph_filelock), GFP_NOFS);
+ flocks = kmalloc_array(num_fcntl_locks + num_flock_locks,
+ sizeof(struct ceph_filelock),
+ GFP_NOFS);
if (!flocks) {
err = -ENOMEM;
goto out_free;
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index 041c27e..af81555 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -594,9 +594,9 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
BUG_ON(capsnap->writing);
capsnap->size = inode->i_size;
- capsnap->mtime = inode->i_mtime;
- capsnap->atime = inode->i_atime;
- capsnap->ctime = inode->i_ctime;
+ capsnap->mtime = timespec64_to_timespec(inode->i_mtime);
+ capsnap->atime = timespec64_to_timespec(inode->i_atime);
+ capsnap->ctime = timespec64_to_timespec(inode->i_ctime);
capsnap->time_warp_seq = ci->i_time_warp_seq;
capsnap->truncate_size = ci->i_truncate_size;
capsnap->truncate_seq = ci->i_truncate_seq;
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index b33082e..95a3b3a 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -45,7 +45,7 @@ static void ceph_put_super(struct super_block *s)
static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
{
struct ceph_fs_client *fsc = ceph_inode_to_client(d_inode(dentry));
- struct ceph_monmap *monmap = fsc->client->monc.monmap;
+ struct ceph_mon_client *monc = &fsc->client->monc;
struct ceph_statfs st;
u64 fsid;
int err;
@@ -58,7 +58,7 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
}
dout("statfs\n");
- err = ceph_monc_do_statfs(&fsc->client->monc, data_pool, &st);
+ err = ceph_monc_do_statfs(monc, data_pool, &st);
if (err < 0)
return err;
@@ -94,8 +94,11 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf)
buf->f_namelen = NAME_MAX;
/* Must convert the fsid, for consistent values across arches */
- fsid = le64_to_cpu(*(__le64 *)(&monmap->fsid)) ^
- le64_to_cpu(*((__le64 *)&monmap->fsid + 1));
+ mutex_lock(&monc->mutex);
+ fsid = le64_to_cpu(*(__le64 *)(&monc->monmap->fsid)) ^
+ le64_to_cpu(*((__le64 *)&monc->monmap->fsid + 1));
+ mutex_unlock(&monc->mutex);
+
buf->f_fsid.val[0] = fsid & 0xffffffff;
buf->f_fsid.val[1] = fsid >> 32;
@@ -256,19 +259,19 @@ static int parse_fsopt_token(char *c, void *private)
break;
/* misc */
case Opt_wsize:
- if (intval < PAGE_SIZE || intval > CEPH_MAX_WRITE_SIZE)
+ if (intval < (int)PAGE_SIZE || intval > CEPH_MAX_WRITE_SIZE)
return -EINVAL;
fsopt->wsize = ALIGN(intval, PAGE_SIZE);
break;
case Opt_rsize:
- if (intval < PAGE_SIZE || intval > CEPH_MAX_READ_SIZE)
+ if (intval < (int)PAGE_SIZE || intval > CEPH_MAX_READ_SIZE)
return -EINVAL;
fsopt->rsize = ALIGN(intval, PAGE_SIZE);
break;
case Opt_rasize:
if (intval < 0)
return -EINVAL;
- fsopt->rasize = ALIGN(intval + PAGE_SIZE - 1, PAGE_SIZE);
+ fsopt->rasize = ALIGN(intval, PAGE_SIZE);
break;
case Opt_caps_wanted_delay_min:
if (intval < 1)
@@ -286,7 +289,7 @@ static int parse_fsopt_token(char *c, void *private)
fsopt->max_readdir = intval;
break;
case Opt_readdir_max_bytes:
- if (intval < PAGE_SIZE && intval != 0)
+ if (intval < (int)PAGE_SIZE && intval != 0)
return -EINVAL;
fsopt->max_readdir_bytes = intval;
break;
@@ -534,6 +537,8 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
seq_puts(m, ",noasyncreaddir");
if ((fsopt->flags & CEPH_MOUNT_OPT_DCACHE) == 0)
seq_puts(m, ",nodcache");
+ if (fsopt->flags & CEPH_MOUNT_OPT_INO32)
+ seq_puts(m, ",ino32");
if (fsopt->flags & CEPH_MOUNT_OPT_FSCACHE) {
seq_show_option(m, "fsc", fsopt->fscache_uniq);
}
@@ -551,7 +556,7 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
if (fsopt->mds_namespace)
seq_show_option(m, "mds_namespace", fsopt->mds_namespace);
- if (fsopt->wsize)
+ if (fsopt->wsize != CEPH_MAX_WRITE_SIZE)
seq_printf(m, ",wsize=%d", fsopt->wsize);
if (fsopt->rsize != CEPH_MAX_READ_SIZE)
seq_printf(m, ",rsize=%d", fsopt->rsize);
@@ -616,7 +621,9 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
err = PTR_ERR(fsc->client);
goto fail;
}
+
fsc->client->extra_mon_dispatch = extra_mon_dispatch;
+ fsc->client->osdc.abort_on_full = true;
if (!fsopt->mds_namespace) {
ceph_monc_want_map(&fsc->client->monc, CEPH_SUB_MDSMAP,
@@ -674,6 +681,13 @@ fail:
return ERR_PTR(err);
}
+static void flush_fs_workqueues(struct ceph_fs_client *fsc)
+{
+ flush_workqueue(fsc->wb_wq);
+ flush_workqueue(fsc->pg_inv_wq);
+ flush_workqueue(fsc->trunc_wq);
+}
+
static void destroy_fs_client(struct ceph_fs_client *fsc)
{
dout("destroy_fs_client %p\n", fsc);
@@ -793,6 +807,7 @@ static void ceph_umount_begin(struct super_block *sb)
if (!fsc)
return;
fsc->mount_state = CEPH_MOUNT_SHUTDOWN;
+ ceph_osdc_abort_requests(&fsc->client->osdc, -EIO);
ceph_mdsc_force_umount(fsc->mdsc);
return;
}
@@ -1088,6 +1103,8 @@ static void ceph_kill_sb(struct super_block *s)
dout("kill_sb %p\n", s);
ceph_mdsc_pre_umount(fsc->mdsc);
+ flush_fs_workqueues(fsc);
+
generic_shutdown_super(s);
fsc->client->extra_mon_dispatch = NULL;
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 315f7e6..5bc8edb 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -50,10 +50,14 @@ struct ceph_vxattr {
size_t name_size; /* strlen(name) + 1 (for '\0') */
size_t (*getxattr_cb)(struct ceph_inode_info *ci, char *val,
size_t size);
- bool readonly, hidden;
bool (*exists_cb)(struct ceph_inode_info *ci);
+ unsigned int flags;
};
+#define VXATTR_FLAG_READONLY (1<<0)
+#define VXATTR_FLAG_HIDDEN (1<<1)
+#define VXATTR_FLAG_RSTAT (1<<2)
+
/* layouts */
static bool ceph_vxattrcb_layout_exists(struct ceph_inode_info *ci)
@@ -262,32 +266,31 @@ static size_t ceph_vxattrcb_quota_max_files(struct ceph_inode_info *ci,
#define CEPH_XATTR_NAME2(_type, _name, _name2) \
XATTR_CEPH_PREFIX #_type "." #_name "." #_name2
-#define XATTR_NAME_CEPH(_type, _name) \
+#define XATTR_NAME_CEPH(_type, _name, _flags) \
{ \
.name = CEPH_XATTR_NAME(_type, _name), \
.name_size = sizeof (CEPH_XATTR_NAME(_type, _name)), \
.getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
- .readonly = true, \
- .hidden = false, \
- .exists_cb = NULL, \
+ .exists_cb = NULL, \
+ .flags = (VXATTR_FLAG_READONLY | _flags), \
}
+#define XATTR_RSTAT_FIELD(_type, _name) \
+ XATTR_NAME_CEPH(_type, _name, VXATTR_FLAG_RSTAT)
#define XATTR_LAYOUT_FIELD(_type, _name, _field) \
{ \
.name = CEPH_XATTR_NAME2(_type, _name, _field), \
.name_size = sizeof (CEPH_XATTR_NAME2(_type, _name, _field)), \
.getxattr_cb = ceph_vxattrcb_ ## _name ## _ ## _field, \
- .readonly = false, \
- .hidden = true, \
.exists_cb = ceph_vxattrcb_layout_exists, \
+ .flags = VXATTR_FLAG_HIDDEN, \
}
#define XATTR_QUOTA_FIELD(_type, _name) \
{ \
.name = CEPH_XATTR_NAME(_type, _name), \
.name_size = sizeof(CEPH_XATTR_NAME(_type, _name)), \
.getxattr_cb = ceph_vxattrcb_ ## _type ## _ ## _name, \
- .readonly = false, \
- .hidden = true, \
.exists_cb = ceph_vxattrcb_quota_exists, \
+ .flags = VXATTR_FLAG_HIDDEN, \
}
static struct ceph_vxattr ceph_dir_vxattrs[] = {
@@ -295,30 +298,28 @@ static struct ceph_vxattr ceph_dir_vxattrs[] = {
.name = "ceph.dir.layout",
.name_size = sizeof("ceph.dir.layout"),
.getxattr_cb = ceph_vxattrcb_layout,
- .readonly = false,
- .hidden = true,
.exists_cb = ceph_vxattrcb_layout_exists,
+ .flags = VXATTR_FLAG_HIDDEN,
},
XATTR_LAYOUT_FIELD(dir, layout, stripe_unit),
XATTR_LAYOUT_FIELD(dir, layout, stripe_count),
XATTR_LAYOUT_FIELD(dir, layout, object_size),
XATTR_LAYOUT_FIELD(dir, layout, pool),
XATTR_LAYOUT_FIELD(dir, layout, pool_namespace),
- XATTR_NAME_CEPH(dir, entries),
- XATTR_NAME_CEPH(dir, files),
- XATTR_NAME_CEPH(dir, subdirs),
- XATTR_NAME_CEPH(dir, rentries),
- XATTR_NAME_CEPH(dir, rfiles),
- XATTR_NAME_CEPH(dir, rsubdirs),
- XATTR_NAME_CEPH(dir, rbytes),
- XATTR_NAME_CEPH(dir, rctime),
+ XATTR_NAME_CEPH(dir, entries, 0),
+ XATTR_NAME_CEPH(dir, files, 0),
+ XATTR_NAME_CEPH(dir, subdirs, 0),
+ XATTR_RSTAT_FIELD(dir, rentries),
+ XATTR_RSTAT_FIELD(dir, rfiles),
+ XATTR_RSTAT_FIELD(dir, rsubdirs),
+ XATTR_RSTAT_FIELD(dir, rbytes),
+ XATTR_RSTAT_FIELD(dir, rctime),
{
.name = "ceph.quota",
.name_size = sizeof("ceph.quota"),
.getxattr_cb = ceph_vxattrcb_quota,
- .readonly = false,
- .hidden = true,
.exists_cb = ceph_vxattrcb_quota_exists,
+ .flags = VXATTR_FLAG_HIDDEN,
},
XATTR_QUOTA_FIELD(quota, max_bytes),
XATTR_QUOTA_FIELD(quota, max_files),
@@ -333,9 +334,8 @@ static struct ceph_vxattr ceph_file_vxattrs[] = {
.name = "ceph.file.layout",
.name_size = sizeof("ceph.file.layout"),
.getxattr_cb = ceph_vxattrcb_layout,
- .readonly = false,
- .hidden = true,
.exists_cb = ceph_vxattrcb_layout_exists,
+ .flags = VXATTR_FLAG_HIDDEN,
},
XATTR_LAYOUT_FIELD(file, layout, stripe_unit),
XATTR_LAYOUT_FIELD(file, layout, stripe_count),
@@ -374,9 +374,10 @@ static size_t __init vxattrs_name_size(struct ceph_vxattr *vxattrs)
struct ceph_vxattr *vxattr;
size_t size = 0;
- for (vxattr = vxattrs; vxattr->name; vxattr++)
- if (!vxattr->hidden)
+ for (vxattr = vxattrs; vxattr->name; vxattr++) {
+ if (!(vxattr->flags & VXATTR_FLAG_HIDDEN))
size += vxattr->name_size;
+ }
return size;
}
@@ -809,7 +810,10 @@ ssize_t __ceph_getxattr(struct inode *inode, const char *name, void *value,
/* let's see if a virtual xattr was requested */
vxattr = ceph_match_vxattr(inode, name);
if (vxattr) {
- err = ceph_do_getattr(inode, 0, true);
+ int mask = 0;
+ if (vxattr->flags & VXATTR_FLAG_RSTAT)
+ mask |= CEPH_STAT_RSTAT;
+ err = ceph_do_getattr(inode, mask, true);
if (err)
return err;
err = -ENODATA;
@@ -919,7 +923,7 @@ ssize_t ceph_listxattr(struct dentry *dentry, char *names, size_t size)
err = namelen;
if (vxattrs) {
for (i = 0; vxattrs[i].name; i++) {
- if (!vxattrs[i].hidden &&
+ if (!(vxattrs[i].flags & VXATTR_FLAG_HIDDEN) &&
!(vxattrs[i].exists_cb &&
!vxattrs[i].exists_cb(ci))) {
len = sprintf(names, "%s", vxattrs[i].name);
@@ -1024,7 +1028,7 @@ int __ceph_setxattr(struct inode *inode, const char *name,
vxattr = ceph_match_vxattr(inode, name);
if (vxattr) {
- if (vxattr->readonly)
+ if (vxattr->flags & VXATTR_FLAG_READONLY)
return -EOPNOTSUPP;
if (value && !strncmp(vxattr->name, "ceph.quota", 10))
check_realm = true;
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c
index a3b5654..3d19595 100644
--- a/fs/cifs/asn1.c
+++ b/fs/cifs/asn1.c
@@ -428,7 +428,7 @@ asn1_oid_decode(struct asn1_ctx *ctx,
if (size < 2 || size > UINT_MAX/sizeof(unsigned long))
return 0;
- *oid = kmalloc(size * sizeof(unsigned long), GFP_ATOMIC);
+ *oid = kmalloc_array(size, sizeof(unsigned long), GFP_ATOMIC);
if (*oid == NULL)
return 0;
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c
index edf5f408..e1553d1 100644
--- a/fs/cifs/cache.c
+++ b/fs/cifs/cache.c
@@ -128,8 +128,8 @@ fscache_checkaux cifs_fscache_inode_check_aux(void *cookie_netfs_data,
memset(&auxdata, 0, sizeof(auxdata));
auxdata.eof = cifsi->server_eof;
- auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
- auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
+ auxdata.last_write_time = timespec64_to_timespec(cifsi->vfs_inode.i_mtime);
+ auxdata.last_change_time = timespec64_to_timespec(cifsi->vfs_inode.i_ctime);
if (memcmp(data, &auxdata, datalen) != 0)
return FSCACHE_CHECKAUX_OBSOLETE;
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index 1161460..bfe9995 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -126,6 +126,25 @@ static void cifs_debug_tcon(struct seq_file *m, struct cifs_tcon *tcon)
seq_putc(m, '\n');
}
+static void
+cifs_dump_iface(struct seq_file *m, struct cifs_server_iface *iface)
+{
+ struct sockaddr_in *ipv4 = (struct sockaddr_in *)&iface->sockaddr;
+ struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)&iface->sockaddr;
+
+ seq_printf(m, "\t\tSpeed: %zu bps\n", iface->speed);
+ seq_puts(m, "\t\tCapabilities: ");
+ if (iface->rdma_capable)
+ seq_puts(m, "rdma ");
+ if (iface->rss_capable)
+ seq_puts(m, "rss ");
+ seq_putc(m, '\n');
+ if (iface->sockaddr.ss_family == AF_INET)
+ seq_printf(m, "\t\tIPv4: %pI4\n", &ipv4->sin_addr);
+ else if (iface->sockaddr.ss_family == AF_INET6)
+ seq_printf(m, "\t\tIPv6: %pI6\n", &ipv6->sin6_addr);
+}
+
static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
{
struct list_head *tmp1, *tmp2, *tmp3;
@@ -312,6 +331,16 @@ skip_rdma:
mid_entry->mid);
}
spin_unlock(&GlobalMid_Lock);
+
+ spin_lock(&ses->iface_lock);
+ if (ses->iface_count)
+ seq_printf(m, "\n\tServer interfaces: %zu\n",
+ ses->iface_count);
+ for (j = 0; j < ses->iface_count; j++) {
+ seq_printf(m, "\t%d)\n", j);
+ cifs_dump_iface(m, &ses->iface_list[j]);
+ }
+ spin_unlock(&ses->iface_lock);
}
}
spin_unlock(&cifs_tcp_ses_lock);
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c
index 13a8a77..1d377b7 100644
--- a/fs/cifs/cifsacl.c
+++ b/fs/cifs/cifsacl.c
@@ -747,8 +747,8 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
return;
- ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
- GFP_KERNEL);
+ ppace = kmalloc_array(num_aces, sizeof(struct cifs_ace *),
+ GFP_KERNEL);
if (!ppace)
return;
diff --git a/fs/cifs/cifsacl.h b/fs/cifs/cifsacl.h
index 4f38848..dd95a6f 100644
--- a/fs/cifs/cifsacl.h
+++ b/fs/cifs/cifsacl.h
@@ -98,4 +98,18 @@ struct cifs_ace {
struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
} __attribute__((packed));
+/*
+ * Minimum security identifier can be one for system defined Users
+ * and Groups such as NULL SID and World or Built-in accounts such
+ * as Administrator and Guest and consists of
+ * Revision + Num (Sub)Auths + Authority + Domain (one Subauthority)
+ */
+#define MIN_SID_LEN (1 + 1 + 6 + 4) /* in bytes */
+
+/*
+ * Minimum security descriptor can be one without any SACL and DACL and can
+ * consist of revision, type, and two sids of minimum size for owner and group
+ */
+#define MIN_SEC_DESC_LEN (sizeof(struct cifs_ntsd) + (2 * MIN_SID_LEN))
+
#endif /* _CIFSACL_H */
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index a6ef088..ee2a8ec 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -44,19 +44,27 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
int rc;
struct kvec *iov = rqst->rq_iov;
int n_vec = rqst->rq_nvec;
+ int is_smb2 = server->vals->header_preamble_size == 0;
- if (n_vec < 2 || iov[0].iov_len != 4)
- return -EIO;
+ /* iov[0] is actual data and not the rfc1002 length for SMB2+ */
+ if (is_smb2) {
+ if (iov[0].iov_len <= 4)
+ return -EIO;
+ i = 0;
+ } else {
+ if (n_vec < 2 || iov[0].iov_len != 4)
+ return -EIO;
+ i = 1; /* skip rfc1002 length */
+ }
- for (i = 1; i < n_vec; i++) {
+ for (; i < n_vec; i++) {
if (iov[i].iov_len == 0)
continue;
if (iov[i].iov_base == NULL) {
cifs_dbg(VFS, "null iovec entry\n");
return -EIO;
}
- if (i == 1 && iov[1].iov_len <= 4)
- break; /* nothing to sign or corrupt header */
+
rc = crypto_shash_update(shash,
iov[i].iov_base, iov[i].iov_len);
if (rc) {
@@ -68,11 +76,12 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
/* now hash over the rq_pages array */
for (i = 0; i < rqst->rq_npages; i++) {
- void *kaddr = kmap(rqst->rq_pages[i]);
- size_t len = rqst->rq_pagesz;
+ void *kaddr;
+ unsigned int len, offset;
+
+ rqst_page_get_length(rqst, i, &len, &offset);
- if (i == rqst->rq_npages - 1)
- len = rqst->rq_tailsz;
+ kaddr = (char *) kmap(rqst->rq_pages[i]) + offset;
crypto_shash_update(shash, kaddr, len);
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index eb7b657..d5aa7ae 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -698,8 +698,8 @@ static int cifs_set_super(struct super_block *sb, void *data)
}
static struct dentry *
-cifs_do_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+cifs_smb3_do_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data, bool is_smb3)
{
int rc;
struct super_block *sb;
@@ -710,7 +710,7 @@ cifs_do_mount(struct file_system_type *fs_type,
cifs_dbg(FYI, "Devname: %s flags: %d\n", dev_name, flags);
- volume_info = cifs_get_volume_info((char *)data, dev_name);
+ volume_info = cifs_get_volume_info((char *)data, dev_name, is_smb3);
if (IS_ERR(volume_info))
return ERR_CAST(volume_info);
@@ -790,6 +790,20 @@ out_nls:
goto out;
}
+static struct dentry *
+smb3_do_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data)
+{
+ return cifs_smb3_do_mount(fs_type, flags, dev_name, data, true);
+}
+
+static struct dentry *
+cifs_do_mount(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data)
+{
+ return cifs_smb3_do_mount(fs_type, flags, dev_name, data, false);
+}
+
static ssize_t
cifs_loose_read_iter(struct kiocb *iocb, struct iov_iter *iter)
{
@@ -925,7 +939,7 @@ MODULE_ALIAS_FS("cifs");
static struct file_system_type smb3_fs_type = {
.owner = THIS_MODULE,
.name = "smb3",
- .mount = cifs_do_mount,
+ .mount = smb3_do_mount,
.kill_sb = cifs_kill_sb,
/* .fs_flags */
};
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 08d1cdd..bd78da5 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -33,6 +33,9 @@
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
+#define CIFS_PORT 445
+#define RFC1001_PORT 139
+
/*
* The sizes of various internal tables and strings
*/
@@ -312,6 +315,10 @@ struct smb_version_operations {
/* send echo request */
int (*echo)(struct TCP_Server_Info *);
/* create directory */
+ int (*posix_mkdir)(const unsigned int xid, struct inode *inode,
+ umode_t mode, struct cifs_tcon *tcon,
+ const char *full_path,
+ struct cifs_sb_info *cifs_sb);
int (*mkdir)(const unsigned int, struct cifs_tcon *, const char *,
struct cifs_sb_info *);
/* set info on created directory */
@@ -838,6 +845,13 @@ static inline void cifs_set_net_ns(struct TCP_Server_Info *srv, struct net *net)
#endif
+struct cifs_server_iface {
+ size_t speed;
+ unsigned int rdma_capable : 1;
+ unsigned int rss_capable : 1;
+ struct sockaddr_storage sockaddr;
+};
+
/*
* Session structure. One of these for each uid session with a particular host
*/
@@ -875,6 +889,20 @@ struct cifs_ses {
#ifdef CONFIG_CIFS_SMB311
__u8 preauth_sha_hash[SMB2_PREAUTH_HASH_SIZE];
#endif /* 3.1.1 */
+
+ /*
+ * Network interfaces available on the server this session is
+ * connected to.
+ *
+ * Other channels can be opened by connecting and binding this
+ * session to interfaces from this list.
+ *
+ * iface_lock should be taken when accessing any of these fields
+ */
+ spinlock_t iface_lock;
+ struct cifs_server_iface *iface_list;
+ size_t iface_count;
+ unsigned long iface_last_update; /* jiffies */
};
static inline bool
@@ -883,6 +911,14 @@ cap_unix(struct cifs_ses *ses)
return ses->server->vals->cap_unix & ses->capabilities;
}
+struct cached_fid {
+ bool is_valid:1; /* Do we have a useable root fid */
+ struct cifs_fid *fid;
+ struct mutex fid_mutex;
+ struct cifs_tcon *tcon;
+ struct work_struct lease_break;
+};
+
/*
* there is one of these for each connection to a resource on a particular
* session
@@ -987,9 +1023,7 @@ struct cifs_tcon {
struct fscache_cookie *fscache; /* cookie for share */
#endif
struct list_head pending_opens; /* list of incomplete opens */
- bool valid_root_fid:1; /* Do we have a useable root fid */
- struct mutex prfid_mutex; /* prevents reopen race after dead ses*/
- struct cifs_fid *prfid; /* handle to the directory at top of share */
+ struct cached_fid crfid; /* Cached root fid */
/* BB add field for back pointer to sb struct(s)? */
};
@@ -1019,6 +1053,12 @@ tlink_tcon(struct tcon_link *tlink)
return tlink->tl_tcon;
}
+static inline struct tcon_link *
+cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
+{
+ return cifs_sb->master_tlink;
+}
+
extern void cifs_put_tlink(struct tcon_link *tlink);
static inline struct tcon_link *
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 7933c5f..03018be 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -112,10 +112,6 @@ extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *,
struct kvec *, int /* nvec to send */,
int * /* type of buf returned */, const int flags,
struct kvec * /* resp vec */);
-extern int smb2_send_recv(const unsigned int xid, struct cifs_ses *pses,
- struct kvec *pkvec, int nvec_to_send,
- int *pbuftype, const int flags,
- struct kvec *presp);
extern int SendReceiveBlockingLock(const unsigned int xid,
struct cifs_tcon *ptcon,
struct smb_hdr *in_buf ,
@@ -211,7 +207,7 @@ extern int cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
extern int cifs_match_super(struct super_block *, void *);
extern void cifs_cleanup_volume_info(struct smb_vol *pvolume_info);
extern struct smb_vol *cifs_get_volume_info(char *mount_data,
- const char *devname);
+ const char *devname, bool is_smb3);
extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
extern void cifs_umount(struct cifs_sb_info *);
extern void cifs_mark_open_files_invalid(struct cifs_tcon *tcon);
@@ -552,9 +548,13 @@ enum securityEnum cifs_select_sectype(struct TCP_Server_Info *,
struct cifs_aio_ctx *cifs_aio_ctx_alloc(void);
void cifs_aio_ctx_release(struct kref *refcount);
int setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw);
+void smb2_cached_lease_break(struct work_struct *work);
int cifs_alloc_hash(const char *name, struct crypto_shash **shash,
struct sdesc **sdesc);
void cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc);
+extern void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
+ unsigned int *len, unsigned int *offset);
+
#endif /* _CIFSPROTO_H */
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 5aca336..d352da3 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -107,10 +107,10 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
}
spin_unlock(&tcon->open_file_lock);
- mutex_lock(&tcon->prfid_mutex);
- tcon->valid_root_fid = false;
- memset(tcon->prfid, 0, sizeof(struct cifs_fid));
- mutex_unlock(&tcon->prfid_mutex);
+ mutex_lock(&tcon->crfid.fid_mutex);
+ tcon->crfid.is_valid = false;
+ memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid));
+ mutex_unlock(&tcon->crfid.fid_mutex);
/*
* BB Add call to invalidate_inodes(sb) for all superblocks mounted
@@ -2077,7 +2077,7 @@ struct cifs_writedata *
cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete)
{
struct page **pages =
- kzalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
+ kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
if (pages)
return cifs_writedata_direct_alloc(pages, complete);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index e5a2fe7..a57da1b 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -57,9 +57,6 @@
#include "smb2proto.h"
#include "smbdirect.h"
-#define CIFS_PORT 445
-#define RFC1001_PORT 139
-
extern mempool_t *cifs_req_poolp;
extern bool disable_legacy_dialects;
@@ -320,7 +317,7 @@ static int generic_ip_connect(struct TCP_Server_Info *server);
static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink);
static void cifs_prune_tlinks(struct work_struct *work);
static int cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
- const char *devname);
+ const char *devname, bool is_smb3);
/*
* cifs tcp session reconnection
@@ -1166,7 +1163,7 @@ cifs_parse_cache_flavor(char *value, struct smb_vol *vol)
}
static int
-cifs_parse_smb_version(char *value, struct smb_vol *vol)
+cifs_parse_smb_version(char *value, struct smb_vol *vol, bool is_smb3)
{
substring_t args[MAX_OPT_ARGS];
@@ -1176,6 +1173,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
cifs_dbg(VFS, "mount with legacy dialect disabled\n");
return 1;
}
+ if (is_smb3) {
+ cifs_dbg(VFS, "vers=1.0 (cifs) not permitted when mounting with smb3\n");
+ return 1;
+ }
vol->ops = &smb1_operations;
vol->vals = &smb1_values;
break;
@@ -1184,6 +1185,10 @@ cifs_parse_smb_version(char *value, struct smb_vol *vol)
cifs_dbg(VFS, "mount with legacy dialect disabled\n");
return 1;
}
+ if (is_smb3) {
+ cifs_dbg(VFS, "vers=2.0 not permitted when mounting with smb3\n");
+ return 1;
+ }
vol->ops = &smb20_operations;
vol->vals = &smb20_values;
break;
@@ -1272,7 +1277,7 @@ cifs_parse_devname(const char *devname, struct smb_vol *vol)
static int
cifs_parse_mount_options(const char *mountdata, const char *devname,
- struct smb_vol *vol)
+ struct smb_vol *vol, bool is_smb3)
{
char *data, *end;
char *mountdata_copy = NULL, *options;
@@ -1985,7 +1990,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
if (string == NULL)
goto out_nomem;
- if (cifs_parse_smb_version(string, vol) != 0)
+ if (cifs_parse_smb_version(string, vol, is_smb3) != 0)
goto cifs_parse_mount_err;
got_version = true;
break;
@@ -3021,8 +3026,11 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
#ifdef CONFIG_CIFS_SMB311
if ((volume_info->linux_ext) && (ses->server->posix_ext_supported)) {
- if (ses->server->vals->protocol_id == SMB311_PROT_ID)
+ if (ses->server->vals->protocol_id == SMB311_PROT_ID) {
tcon->posix_extensions = true;
+ printk_once(KERN_WARNING
+ "SMB3.11 POSIX Extensions are experimental\n");
+ }
}
#endif /* 311 */
@@ -3116,12 +3124,6 @@ cifs_put_tlink(struct tcon_link *tlink)
return;
}
-static inline struct tcon_link *
-cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
-{
- return cifs_sb->master_tlink;
-}
-
static int
compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
{
@@ -3803,7 +3805,7 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
} else {
cleanup_volume_info_contents(volume_info);
rc = cifs_setup_volume_info(volume_info, mdata,
- fake_devname);
+ fake_devname, false);
}
kfree(fake_devname);
kfree(cifs_sb->mountdata);
@@ -3816,11 +3818,11 @@ expand_dfs_referral(const unsigned int xid, struct cifs_ses *ses,
static int
cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
- const char *devname)
+ const char *devname, bool is_smb3)
{
int rc = 0;
- if (cifs_parse_mount_options(mount_data, devname, volume_info))
+ if (cifs_parse_mount_options(mount_data, devname, volume_info, is_smb3))
return -EINVAL;
if (volume_info->nullauth) {
@@ -3854,7 +3856,7 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data,
}
struct smb_vol *
-cifs_get_volume_info(char *mount_data, const char *devname)
+cifs_get_volume_info(char *mount_data, const char *devname, bool is_smb3)
{
int rc;
struct smb_vol *volume_info;
@@ -3863,7 +3865,7 @@ cifs_get_volume_info(char *mount_data, const char *devname)
if (!volume_info)
return ERR_PTR(-ENOMEM);
- rc = cifs_setup_volume_info(volume_info, mount_data, devname);
+ rc = cifs_setup_volume_info(volume_info, mount_data, devname, is_smb3);
if (rc) {
cifs_cleanup_volume_info(volume_info);
volume_info = ERR_PTR(rc);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 87eece6..8d41ca7 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2900,7 +2900,7 @@ static struct cifs_readdata *
cifs_readdata_alloc(unsigned int nr_pages, work_func_t complete)
{
struct page **pages =
- kzalloc(sizeof(struct page *) * nr_pages, GFP_KERNEL);
+ kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
struct cifs_readdata *ret = NULL;
if (pages) {
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
index 25d3f66..85145a7 100644
--- a/fs/cifs/fscache.c
+++ b/fs/cifs/fscache.c
@@ -129,8 +129,8 @@ static void cifs_fscache_acquire_inode_cookie(struct cifsInodeInfo *cifsi,
memset(&auxdata, 0, sizeof(auxdata));
auxdata.eof = cifsi->server_eof;
- auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
- auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
+ auxdata.last_write_time = timespec64_to_timespec(cifsi->vfs_inode.i_mtime);
+ auxdata.last_change_time = timespec64_to_timespec(cifsi->vfs_inode.i_ctime);
cifsi->fscache =
fscache_acquire_cookie(tcon->fscache,
@@ -166,8 +166,8 @@ void cifs_fscache_release_inode_cookie(struct inode *inode)
if (cifsi->fscache) {
memset(&auxdata, 0, sizeof(auxdata));
auxdata.eof = cifsi->server_eof;
- auxdata.last_write_time = cifsi->vfs_inode.i_mtime;
- auxdata.last_change_time = cifsi->vfs_inode.i_ctime;
+ auxdata.last_write_time = timespec64_to_timespec(cifsi->vfs_inode.i_mtime);
+ auxdata.last_change_time = timespec64_to_timespec(cifsi->vfs_inode.i_ctime);
cifs_dbg(FYI, "%s: (0x%p)\n", __func__, cifsi->fscache);
fscache_relinquish_cookie(cifsi->fscache, &auxdata, false);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 745fd7f..a2cfb33 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -95,6 +95,7 @@ static void
cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
{
struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+ struct timespec ts;
cifs_dbg(FYI, "%s: revalidating inode %llu\n",
__func__, cifs_i->uniqueid);
@@ -113,7 +114,8 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr)
}
/* revalidate if mtime or size have changed */
- if (timespec_equal(&inode->i_mtime, &fattr->cf_mtime) &&
+ ts = timespec64_to_timespec(inode->i_mtime);
+ if (timespec_equal(&ts, &fattr->cf_mtime) &&
cifs_i->server_eof == fattr->cf_eof) {
cifs_dbg(FYI, "%s: inode %llu is unchanged\n",
__func__, cifs_i->uniqueid);
@@ -162,9 +164,9 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
cifs_revalidate_cache(inode, fattr);
spin_lock(&inode->i_lock);
- inode->i_atime = fattr->cf_atime;
- inode->i_mtime = fattr->cf_mtime;
- inode->i_ctime = fattr->cf_ctime;
+ inode->i_atime = timespec_to_timespec64(fattr->cf_atime);
+ inode->i_mtime = timespec_to_timespec64(fattr->cf_mtime);
+ inode->i_ctime = timespec_to_timespec64(fattr->cf_ctime);
inode->i_rdev = fattr->cf_rdev;
cifs_nlink_fattr_to_inode(inode, fattr);
inode->i_uid = fattr->cf_uid;
@@ -1123,14 +1125,14 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
if (attrs->ia_valid & ATTR_ATIME) {
set_time = true;
info_buf.LastAccessTime =
- cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_atime));
+ cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_atime)));
} else
info_buf.LastAccessTime = 0;
if (attrs->ia_valid & ATTR_MTIME) {
set_time = true;
info_buf.LastWriteTime =
- cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_mtime));
+ cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_mtime)));
} else
info_buf.LastWriteTime = 0;
@@ -1143,7 +1145,7 @@ cifs_set_file_info(struct inode *inode, struct iattr *attrs, unsigned int xid,
if (set_time && (attrs->ia_valid & ATTR_CTIME)) {
cifs_dbg(FYI, "CIFS - CTIME changed\n");
info_buf.ChangeTime =
- cpu_to_le64(cifs_UnixTimeToNT(attrs->ia_ctime));
+ cpu_to_le64(cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_ctime)));
} else
info_buf.ChangeTime = 0;
@@ -1573,6 +1575,17 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
goto mkdir_out;
}
+ server = tcon->ses->server;
+
+#ifdef CONFIG_CIFS_SMB311
+ if ((server->ops->posix_mkdir) && (tcon->posix_extensions)) {
+ rc = server->ops->posix_mkdir(xid, inode, mode, tcon, full_path,
+ cifs_sb);
+ d_drop(direntry); /* for time being always refresh inode info */
+ goto mkdir_out;
+ }
+#endif /* SMB311 */
+
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
le64_to_cpu(tcon->fsUnixInfo.Capability))) {
rc = cifs_posix_mkdir(inode, direntry, mode, full_path, cifs_sb,
@@ -1581,8 +1594,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
goto mkdir_out;
}
- server = tcon->ses->server;
-
if (!server->ops->mkdir) {
rc = -ENOSYS;
goto mkdir_out;
@@ -1792,7 +1803,7 @@ cifs_rename2(struct inode *source_dir, struct dentry *source_dentry,
* with unix extensions enabled.
*/
info_buf_source =
- kmalloc(2 * sizeof(FILE_UNIX_BASIC_INFO),
+ kmalloc_array(2, sizeof(FILE_UNIX_BASIC_INFO),
GFP_KERNEL);
if (info_buf_source == NULL) {
rc = -ENOMEM;
@@ -2060,8 +2071,8 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
/* old CIFS Unix Extensions doesn't return create time */
if (CIFS_I(inode)->createtime) {
stat->result_mask |= STATX_BTIME;
- stat->btime =
- cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime));
+ stat->btime = timespec_to_timespec64(
+ cifs_NTtimeToUnix(cpu_to_le64(CIFS_I(inode)->createtime)));
}
stat->attributes_mask |= (STATX_ATTR_COMPRESSED | STATX_ATTR_ENCRYPTED);
@@ -2267,17 +2278,17 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
args->gid = INVALID_GID; /* no change */
if (attrs->ia_valid & ATTR_ATIME)
- args->atime = cifs_UnixTimeToNT(attrs->ia_atime);
+ args->atime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_atime));
else
args->atime = NO_CHANGE_64;
if (attrs->ia_valid & ATTR_MTIME)
- args->mtime = cifs_UnixTimeToNT(attrs->ia_mtime);
+ args->mtime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_mtime));
else
args->mtime = NO_CHANGE_64;
if (attrs->ia_valid & ATTR_CTIME)
- args->ctime = cifs_UnixTimeToNT(attrs->ia_ctime);
+ args->ctime = cifs_UnixTimeToNT(timespec64_to_timespec(attrs->ia_ctime));
else
args->ctime = NO_CHANGE_64;
diff --git a/fs/cifs/link.c b/fs/cifs/link.c
index 889a840..de41f96 100644
--- a/fs/cifs/link.c
+++ b/fs/cifs/link.c
@@ -421,7 +421,8 @@ smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
return -ENOMEM;
}
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL);
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, pfile_info, NULL,
+ NULL);
if (rc)
goto qmf_out_open_fail;
@@ -478,7 +479,8 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
+ NULL);
if (rc) {
kfree(utf16_path);
return rc;
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index aba3fc3..53e8362c 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -82,6 +82,7 @@ sesInfoAlloc(void)
INIT_LIST_HEAD(&ret_buf->smb_ses_list);
INIT_LIST_HEAD(&ret_buf->tcon_list);
mutex_init(&ret_buf->session_mutex);
+ spin_lock_init(&ret_buf->iface_lock);
}
return ret_buf;
}
@@ -102,6 +103,7 @@ sesInfoFree(struct cifs_ses *buf_to_free)
kfree(buf_to_free->user_name);
kfree(buf_to_free->domainName);
kzfree(buf_to_free->auth_key.response);
+ kfree(buf_to_free->iface_list);
kzfree(buf_to_free);
}
@@ -117,8 +119,9 @@ tconInfoAlloc(void)
INIT_LIST_HEAD(&ret_buf->openFileList);
INIT_LIST_HEAD(&ret_buf->tcon_list);
spin_lock_init(&ret_buf->open_file_lock);
- mutex_init(&ret_buf->prfid_mutex);
- ret_buf->prfid = kzalloc(sizeof(struct cifs_fid), GFP_KERNEL);
+ mutex_init(&ret_buf->crfid.fid_mutex);
+ ret_buf->crfid.fid = kzalloc(sizeof(struct cifs_fid),
+ GFP_KERNEL);
#ifdef CONFIG_CIFS_STATS
spin_lock_init(&ret_buf->stat_lock);
#endif
@@ -136,7 +139,7 @@ tconInfoFree(struct cifs_tcon *buf_to_free)
atomic_dec(&tconInfoAllocCount);
kfree(buf_to_free->nativeFileSystem);
kzfree(buf_to_free->password);
- kfree(buf_to_free->prfid);
+ kfree(buf_to_free->crfid.fid);
kfree(buf_to_free);
}
@@ -789,7 +792,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
GFP_KERNEL);
if (!bv) {
- bv = vmalloc(max_pages * sizeof(struct bio_vec));
+ bv = vmalloc(array_size(max_pages, sizeof(struct bio_vec)));
if (!bv)
return -ENOMEM;
}
@@ -799,7 +802,7 @@ setup_aio_ctx_iter(struct cifs_aio_ctx *ctx, struct iov_iter *iter, int rw)
GFP_KERNEL);
if (!pages) {
- pages = vmalloc(max_pages * sizeof(struct page *));
+ pages = vmalloc(array_size(max_pages, sizeof(struct page *)));
if (!pages) {
kvfree(bv);
return -ENOMEM;
@@ -905,3 +908,20 @@ cifs_free_hash(struct crypto_shash **shash, struct sdesc **sdesc)
crypto_free_shash(*shash);
*shash = NULL;
}
+
+/**
+ * rqst_page_get_length - obtain the length and offset for a page in smb_rqst
+ * Input: rqst - a smb_rqst, page - a page index for rqst
+ * Output: *len - the length for this page, *offset - the offset for this page
+ */
+void rqst_page_get_length(struct smb_rqst *rqst, unsigned int page,
+ unsigned int *len, unsigned int *offset)
+{
+ *len = rqst->rq_pagesz;
+ *offset = (page == 0) ? rqst->rq_offset : 0;
+
+ if (rqst->rq_npages == 1 || page == rqst->rq_npages-1)
+ *len = rqst->rq_tailsz;
+ else if (page == 0)
+ *len = rqst->rq_pagesz - rqst->rq_offset;
+}
diff --git a/fs/cifs/smb2file.c b/fs/cifs/smb2file.c
index 12af5db..7884126 100644
--- a/fs/cifs/smb2file.c
+++ b/fs/cifs/smb2file.c
@@ -64,7 +64,8 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
if (oparms->tcon->ses->server->capabilities & SMB2_GLOBAL_CAP_LEASING)
memcpy(smb2_oplock + 1, fid->lease_key, SMB2_LEASE_KEY_SIZE);
- rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL);
+ rc = SMB2_open(xid, oparms, smb2_path, smb2_oplock, smb2_data, NULL,
+ NULL);
if (rc)
goto out;
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index a6e786e..d01ad70 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -71,7 +71,8 @@ smb2_open_op_close(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
+ NULL);
if (rc) {
kfree(utf16_path);
return rc;
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index cb5728e..3ff7cec 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -453,8 +453,11 @@ cifs_convert_path_to_utf16(const char *from, struct cifs_sb_info *cifs_sb)
start_of_path = from + 1;
#ifdef CONFIG_CIFS_SMB311
/* SMB311 POSIX extensions paths do not include leading slash */
- else if (cifs_sb_master_tcon(cifs_sb)->posix_extensions)
+ else if (cifs_sb_master_tlink(cifs_sb) &&
+ cifs_sb_master_tcon(cifs_sb)->posix_extensions &&
+ (from[0] == '/')) {
start_of_path = from + 1;
+ }
#endif /* 311 */
else
start_of_path = from;
@@ -490,10 +493,11 @@ cifs_ses_oplock_break(struct work_struct *work)
{
struct smb2_lease_break_work *lw = container_of(work,
struct smb2_lease_break_work, lease_break);
- int rc;
+ int rc = 0;
rc = SMB2_lease_break(0, tlink_tcon(lw->tlink), lw->lease_key,
lw->lease_state);
+
cifs_dbg(FYI, "Lease release rc %d\n", rc);
cifs_put_tlink(lw->tlink);
kfree(lw);
@@ -559,6 +563,7 @@ smb2_tcon_has_lease(struct cifs_tcon *tcon, struct smb2_lease_break *rsp,
open->oplock = lease_state;
}
+
return found;
}
@@ -601,6 +606,18 @@ smb2_is_valid_lease_break(char *buffer)
return true;
}
spin_unlock(&tcon->open_file_lock);
+
+ if (tcon->crfid.is_valid &&
+ !memcmp(rsp->LeaseKey,
+ tcon->crfid.fid->lease_key,
+ SMB2_LEASE_KEY_SIZE)) {
+ INIT_WORK(&tcon->crfid.lease_break,
+ smb2_cached_lease_break);
+ queue_work(cifsiod_wq,
+ &tcon->crfid.lease_break);
+ spin_unlock(&cifs_tcp_ses_lock);
+ return true;
+ }
}
}
}
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 950d0ab..0356b55 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -294,34 +294,191 @@ smb2_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *volume_info)
return rsize;
}
-#ifdef CONFIG_CIFS_STATS2
+
+static int
+parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf,
+ size_t buf_len,
+ struct cifs_server_iface **iface_list,
+ size_t *iface_count)
+{
+ struct network_interface_info_ioctl_rsp *p;
+ struct sockaddr_in *addr4;
+ struct sockaddr_in6 *addr6;
+ struct iface_info_ipv4 *p4;
+ struct iface_info_ipv6 *p6;
+ struct cifs_server_iface *info;
+ ssize_t bytes_left;
+ size_t next = 0;
+ int nb_iface = 0;
+ int rc = 0;
+
+ *iface_list = NULL;
+ *iface_count = 0;
+
+ /*
+ * Fist pass: count and sanity check
+ */
+
+ bytes_left = buf_len;
+ p = buf;
+ while (bytes_left >= sizeof(*p)) {
+ nb_iface++;
+ next = le32_to_cpu(p->Next);
+ if (!next) {
+ bytes_left -= sizeof(*p);
+ break;
+ }
+ p = (struct network_interface_info_ioctl_rsp *)((u8 *)p+next);
+ bytes_left -= next;
+ }
+
+ if (!nb_iface) {
+ cifs_dbg(VFS, "%s: malformed interface info\n", __func__);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (bytes_left || p->Next)
+ cifs_dbg(VFS, "%s: incomplete interface info\n", __func__);
+
+
+ /*
+ * Second pass: extract info to internal structure
+ */
+
+ *iface_list = kcalloc(nb_iface, sizeof(**iface_list), GFP_KERNEL);
+ if (!*iface_list) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ info = *iface_list;
+ bytes_left = buf_len;
+ p = buf;
+ while (bytes_left >= sizeof(*p)) {
+ info->speed = le64_to_cpu(p->LinkSpeed);
+ info->rdma_capable = le32_to_cpu(p->Capability & RDMA_CAPABLE);
+ info->rss_capable = le32_to_cpu(p->Capability & RSS_CAPABLE);
+
+ cifs_dbg(FYI, "%s: adding iface %zu\n", __func__, *iface_count);
+ cifs_dbg(FYI, "%s: speed %zu bps\n", __func__, info->speed);
+ cifs_dbg(FYI, "%s: capabilities 0x%08x\n", __func__,
+ le32_to_cpu(p->Capability));
+
+ switch (p->Family) {
+ /*
+ * The kernel and wire socket structures have the same
+ * layout and use network byte order but make the
+ * conversion explicit in case either one changes.
+ */
+ case INTERNETWORK:
+ addr4 = (struct sockaddr_in *)&info->sockaddr;
+ p4 = (struct iface_info_ipv4 *)p->Buffer;
+ addr4->sin_family = AF_INET;
+ memcpy(&addr4->sin_addr, &p4->IPv4Address, 4);
+
+ /* [MS-SMB2] 2.2.32.5.1.1 Clients MUST ignore these */
+ addr4->sin_port = cpu_to_be16(CIFS_PORT);
+
+ cifs_dbg(FYI, "%s: ipv4 %pI4\n", __func__,
+ &addr4->sin_addr);
+ break;
+ case INTERNETWORKV6:
+ addr6 = (struct sockaddr_in6 *)&info->sockaddr;
+ p6 = (struct iface_info_ipv6 *)p->Buffer;
+ addr6->sin6_family = AF_INET6;
+ memcpy(&addr6->sin6_addr, &p6->IPv6Address, 16);
+
+ /* [MS-SMB2] 2.2.32.5.1.2 Clients MUST ignore these */
+ addr6->sin6_flowinfo = 0;
+ addr6->sin6_scope_id = 0;
+ addr6->sin6_port = cpu_to_be16(CIFS_PORT);
+
+ cifs_dbg(FYI, "%s: ipv6 %pI6\n", __func__,
+ &addr6->sin6_addr);
+ break;
+ default:
+ cifs_dbg(VFS,
+ "%s: skipping unsupported socket family\n",
+ __func__);
+ goto next_iface;
+ }
+
+ (*iface_count)++;
+ info++;
+next_iface:
+ next = le32_to_cpu(p->Next);
+ if (!next)
+ break;
+ p = (struct network_interface_info_ioctl_rsp *)((u8 *)p+next);
+ bytes_left -= next;
+ }
+
+ if (!*iface_count) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+out:
+ if (rc) {
+ kfree(*iface_list);
+ *iface_count = 0;
+ *iface_list = NULL;
+ }
+ return rc;
+}
+
+
static int
SMB3_request_interfaces(const unsigned int xid, struct cifs_tcon *tcon)
{
int rc;
unsigned int ret_data_len = 0;
- struct network_interface_info_ioctl_rsp *out_buf;
+ struct network_interface_info_ioctl_rsp *out_buf = NULL;
+ struct cifs_server_iface *iface_list;
+ size_t iface_count;
+ struct cifs_ses *ses = tcon->ses;
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
FSCTL_QUERY_NETWORK_INTERFACE_INFO, true /* is_fsctl */,
NULL /* no data input */, 0 /* no data input */,
(char **)&out_buf, &ret_data_len);
- if (rc != 0)
+ if (rc != 0) {
cifs_dbg(VFS, "error %d on ioctl to get interface list\n", rc);
- else if (ret_data_len < sizeof(struct network_interface_info_ioctl_rsp)) {
- cifs_dbg(VFS, "server returned bad net interface info buf\n");
- rc = -EINVAL;
- } else {
- /* Dump info on first interface */
- cifs_dbg(FYI, "Adapter Capability 0x%x\t",
- le32_to_cpu(out_buf->Capability));
- cifs_dbg(FYI, "Link Speed %lld\n",
- le64_to_cpu(out_buf->LinkSpeed));
+ goto out;
}
+
+ rc = parse_server_interfaces(out_buf, ret_data_len,
+ &iface_list, &iface_count);
+ if (rc)
+ goto out;
+
+ spin_lock(&ses->iface_lock);
+ kfree(ses->iface_list);
+ ses->iface_list = iface_list;
+ ses->iface_count = iface_count;
+ ses->iface_last_update = jiffies;
+ spin_unlock(&ses->iface_lock);
+
+out:
kfree(out_buf);
return rc;
}
-#endif /* STATS2 */
+
+void
+smb2_cached_lease_break(struct work_struct *work)
+{
+ struct cached_fid *cfid = container_of(work,
+ struct cached_fid, lease_break);
+ mutex_lock(&cfid->fid_mutex);
+ if (cfid->is_valid) {
+ cifs_dbg(FYI, "clear cached root file handle\n");
+ SMB2_close(0, cfid->tcon, cfid->fid->persistent_fid,
+ cfid->fid->volatile_fid);
+ cfid->is_valid = false;
+ }
+ mutex_unlock(&cfid->fid_mutex);
+}
/*
* Open the directory at the root of a share
@@ -331,13 +488,13 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
struct cifs_open_parms oparams;
int rc;
__le16 srch_path = 0; /* Null - since an open of top of share */
- u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ u8 oplock = SMB2_OPLOCK_LEVEL_II;
- mutex_lock(&tcon->prfid_mutex);
- if (tcon->valid_root_fid) {
+ mutex_lock(&tcon->crfid.fid_mutex);
+ if (tcon->crfid.is_valid) {
cifs_dbg(FYI, "found a cached root file handle\n");
- memcpy(pfid, tcon->prfid, sizeof(struct cifs_fid));
- mutex_unlock(&tcon->prfid_mutex);
+ memcpy(pfid, tcon->crfid.fid, sizeof(struct cifs_fid));
+ mutex_unlock(&tcon->crfid.fid_mutex);
return 0;
}
@@ -348,12 +505,13 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
oparams.fid = pfid;
oparams.reconnect = false;
- rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparams, &srch_path, &oplock, NULL, NULL, NULL);
if (rc == 0) {
- memcpy(tcon->prfid, pfid, sizeof(struct cifs_fid));
- tcon->valid_root_fid = true;
+ memcpy(tcon->crfid.fid, pfid, sizeof(struct cifs_fid));
+ tcon->crfid.tcon = tcon;
+ tcon->crfid.is_valid = true;
}
- mutex_unlock(&tcon->prfid_mutex);
+ mutex_unlock(&tcon->crfid.fid_mutex);
return rc;
}
@@ -375,16 +533,15 @@ smb3_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
oparms.reconnect = false;
if (no_cached_open)
- rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL,
+ NULL);
else
rc = open_shroot(xid, tcon, &fid);
if (rc)
return;
-#ifdef CONFIG_CIFS_STATS2
SMB3_request_interfaces(xid, tcon);
-#endif /* STATS2 */
SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
FS_ATTRIBUTE_INFORMATION);
@@ -413,7 +570,7 @@ smb2_qfs_tcon(const unsigned int xid, struct cifs_tcon *tcon)
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
if (rc)
return;
@@ -435,7 +592,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_open_parms oparms;
struct cifs_fid fid;
- if ((*full_path == 0) && tcon->valid_root_fid)
+ if ((*full_path == 0) && tcon->crfid.is_valid)
return 0;
utf16_path = cifs_convert_path_to_utf16(full_path, cifs_sb);
@@ -449,7 +606,7 @@ smb2_is_path_accessible(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
if (rc) {
kfree(utf16_path);
return rc;
@@ -598,7 +755,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
kfree(utf16_path);
if (rc) {
cifs_dbg(FYI, "open failed rc=%d\n", rc);
@@ -677,7 +834,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
kfree(utf16_path);
if (rc) {
cifs_dbg(FYI, "open failed rc=%d\n", rc);
@@ -1261,7 +1418,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
kfree(utf16_path);
if (rc) {
cifs_dbg(FYI, "open dir failed rc=%d\n", rc);
@@ -1361,7 +1518,7 @@ smb2_queryfs(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, &srch_path, &oplock, NULL, NULL, NULL);
if (rc)
return rc;
buf->f_type = SMB2_MAGIC_NUMBER;
@@ -1515,7 +1672,8 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_open_parms oparms;
struct cifs_fid fid;
struct kvec err_iov = {NULL, 0};
- struct smb2_err_rsp *err_buf;
+ struct smb2_err_rsp *err_buf = NULL;
+ int resp_buftype;
struct smb2_symlink_err_rsp *symlink;
unsigned int sub_len;
unsigned int sub_offset;
@@ -1535,18 +1693,18 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov);
-
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, &err_iov,
+ &resp_buftype);
if (!rc || !err_iov.iov_base) {
- kfree(utf16_path);
- return -ENOENT;
+ rc = -ENOENT;
+ goto querty_exit;
}
err_buf = err_iov.iov_base;
if (le32_to_cpu(err_buf->ByteCount) < sizeof(struct smb2_symlink_err_rsp) ||
err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE) {
- kfree(utf16_path);
- return -ENOENT;
+ rc = -ENOENT;
+ goto querty_exit;
}
/* open must fail on symlink - reset rc */
@@ -1558,25 +1716,28 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon,
print_offset = le16_to_cpu(symlink->PrintNameOffset);
if (err_iov.iov_len < SMB2_SYMLINK_STRUCT_SIZE + sub_offset + sub_len) {
- kfree(utf16_path);
- return -ENOENT;
+ rc = -ENOENT;
+ goto querty_exit;
}
if (err_iov.iov_len <
SMB2_SYMLINK_STRUCT_SIZE + print_offset + print_len) {
- kfree(utf16_path);
- return -ENOENT;
+ rc = -ENOENT;
+ goto querty_exit;
}
*target_path = cifs_strndup_from_utf16(
(char *)symlink->PathBuffer + sub_offset,
sub_len, true, cifs_sb->local_nls);
if (!(*target_path)) {
- kfree(utf16_path);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto querty_exit;
}
convert_delimiter(*target_path, '/');
cifs_dbg(FYI, "%s: target path: %s\n", __func__, *target_path);
+
+ querty_exit:
+ free_rsp_buf(resp_buftype, err_buf);
kfree(utf16_path);
return rc;
}
@@ -1649,7 +1810,7 @@ get_smb2_acl_by_path(struct cifs_sb_info *cifs_sb,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
kfree(utf16_path);
if (!rc) {
rc = SMB2_query_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
@@ -1712,7 +1873,7 @@ set_smb2_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
oparms.fid = &fid;
oparms.reconnect = false;
- rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL, NULL);
kfree(utf16_path);
if (!rc) {
rc = SMB2_set_acl(xid, tlink_tcon(tlink), fid.persistent_fid,
@@ -2146,7 +2307,7 @@ fill_transform_hdr(struct smb2_transform_hdr *tr_hdr, unsigned int orig_len,
struct smb_rqst *old_rq)
{
struct smb2_sync_hdr *shdr =
- (struct smb2_sync_hdr *)old_rq->rq_iov[1].iov_base;
+ (struct smb2_sync_hdr *)old_rq->rq_iov[0].iov_base;
memset(tr_hdr, 0, sizeof(struct smb2_transform_hdr));
tr_hdr->ProtocolId = SMB2_TRANSFORM_PROTO_NUM;
@@ -2166,14 +2327,13 @@ static inline void smb2_sg_set_buf(struct scatterlist *sg, const void *buf,
}
/* Assumes:
- * rqst->rq_iov[0] is rfc1002 length
- * rqst->rq_iov[1] is tranform header
- * rqst->rq_iov[2+] data to be encrypted/decrypted
+ * rqst->rq_iov[0] is transform header
+ * rqst->rq_iov[1+] data to be encrypted/decrypted
*/
static struct scatterlist *
init_sg(struct smb_rqst *rqst, u8 *sign)
{
- unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages;
+ unsigned int sg_len = rqst->rq_nvec + rqst->rq_npages + 1;
unsigned int assoc_data_len = sizeof(struct smb2_transform_hdr) - 20;
struct scatterlist *sg;
unsigned int i;
@@ -2184,14 +2344,15 @@ init_sg(struct smb_rqst *rqst, u8 *sign)
return NULL;
sg_init_table(sg, sg_len);
- smb2_sg_set_buf(&sg[0], rqst->rq_iov[1].iov_base + 20, assoc_data_len);
- for (i = 1; i < rqst->rq_nvec - 1; i++)
- smb2_sg_set_buf(&sg[i], rqst->rq_iov[i+1].iov_base,
- rqst->rq_iov[i+1].iov_len);
+ smb2_sg_set_buf(&sg[0], rqst->rq_iov[0].iov_base + 20, assoc_data_len);
+ for (i = 1; i < rqst->rq_nvec; i++)
+ smb2_sg_set_buf(&sg[i], rqst->rq_iov[i].iov_base,
+ rqst->rq_iov[i].iov_len);
for (j = 0; i < sg_len - 1; i++, j++) {
- unsigned int len = (j < rqst->rq_npages - 1) ? rqst->rq_pagesz
- : rqst->rq_tailsz;
- sg_set_page(&sg[i], rqst->rq_pages[j], len, 0);
+ unsigned int len, offset;
+
+ rqst_page_get_length(rqst, j, &len, &offset);
+ sg_set_page(&sg[i], rqst->rq_pages[j], len, offset);
}
smb2_sg_set_buf(&sg[sg_len - 1], sign, SMB2_SIGNATURE_SIZE);
return sg;
@@ -2218,11 +2379,10 @@ smb2_get_enc_key(struct TCP_Server_Info *server, __u64 ses_id, int enc, u8 *key)
return 1;
}
/*
- * Encrypt or decrypt @rqst message. @rqst has the following format:
- * iov[0] - rfc1002 length
- * iov[1] - transform header (associate data),
- * iov[2-N] and pages - data to encrypt.
- * On success return encrypted data in iov[2-N] and pages, leave iov[0-1]
+ * Encrypt or decrypt @rqst message. @rqst[0] has the following format:
+ * iov[0] - transform header (associate data),
+ * iov[1-N] - SMB2 header and pages - data to encrypt.
+ * On success return encrypted data in iov[1-N] and pages, leave iov[0]
* untouched.
*/
static int
@@ -2317,10 +2477,6 @@ free_req:
return rc;
}
-/*
- * This is called from smb_send_rqst. At this point we have the rfc1002
- * header as the first element in the vector.
- */
static int
smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
struct smb_rqst *old_rq)
@@ -2329,7 +2485,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
struct page **pages;
struct smb2_transform_hdr *tr_hdr;
unsigned int npages = old_rq->rq_npages;
- unsigned int orig_len = get_rfc1002_length(old_rq->rq_iov[0].iov_base);
+ unsigned int orig_len;
int i;
int rc = -ENOMEM;
@@ -2338,6 +2494,7 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
return rc;
new_rq->rq_pages = pages;
+ new_rq->rq_offset = old_rq->rq_offset;
new_rq->rq_npages = old_rq->rq_npages;
new_rq->rq_pagesz = old_rq->rq_pagesz;
new_rq->rq_tailsz = old_rq->rq_tailsz;
@@ -2348,18 +2505,14 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
goto err_free_pages;
}
- /* Make space for one extra iov to hold the transform header */
iov = kmalloc_array(old_rq->rq_nvec + 1, sizeof(struct kvec),
GFP_KERNEL);
if (!iov)
goto err_free_pages;
- /* copy all iovs from the old except the 1st one (rfc1002 length) */
- memcpy(&iov[2], &old_rq->rq_iov[1],
- sizeof(struct kvec) * (old_rq->rq_nvec - 1));
- /* copy the rfc1002 iov */
- iov[0].iov_base = old_rq->rq_iov[0].iov_base;
- iov[0].iov_len = old_rq->rq_iov[0].iov_len;
+ /* copy all iovs from the old */
+ memcpy(&iov[1], &old_rq->rq_iov[0],
+ sizeof(struct kvec) * old_rq->rq_nvec);
new_rq->rq_iov = iov;
new_rq->rq_nvec = old_rq->rq_nvec + 1;
@@ -2368,21 +2521,23 @@ smb3_init_transform_rq(struct TCP_Server_Info *server, struct smb_rqst *new_rq,
if (!tr_hdr)
goto err_free_iov;
+ orig_len = smb2_rqst_len(old_rq, false);
+
/* fill the 2nd iov with a transform header */
fill_transform_hdr(tr_hdr, orig_len, old_rq);
- new_rq->rq_iov[1].iov_base = tr_hdr;
- new_rq->rq_iov[1].iov_len = sizeof(struct smb2_transform_hdr);
-
- /* Update rfc1002 header */
- inc_rfc1001_len(new_rq->rq_iov[0].iov_base,
- sizeof(struct smb2_transform_hdr));
+ new_rq->rq_iov[0].iov_base = tr_hdr;
+ new_rq->rq_iov[0].iov_len = sizeof(struct smb2_transform_hdr);
/* copy pages form the old */
for (i = 0; i < npages; i++) {
- char *dst = kmap(new_rq->rq_pages[i]);
- char *src = kmap(old_rq->rq_pages[i]);
- unsigned int len = (i < npages - 1) ? new_rq->rq_pagesz :
- new_rq->rq_tailsz;
+ char *dst, *src;
+ unsigned int offset, len;
+
+ rqst_page_get_length(new_rq, i, &len, &offset);
+
+ dst = (char *) kmap(new_rq->rq_pages[i]) + offset;
+ src = (char *) kmap(old_rq->rq_pages[i]) + offset;
+
memcpy(dst, src, len);
kunmap(new_rq->rq_pages[i]);
kunmap(old_rq->rq_pages[i]);
@@ -2415,7 +2570,7 @@ smb3_free_transform_rq(struct smb_rqst *rqst)
put_page(rqst->rq_pages[i]);
kfree(rqst->rq_pages);
/* free transform header */
- kfree(rqst->rq_iov[1].iov_base);
+ kfree(rqst->rq_iov[0].iov_base);
kfree(rqst->rq_iov);
}
@@ -2432,19 +2587,17 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
unsigned int buf_data_size, struct page **pages,
unsigned int npages, unsigned int page_data_size)
{
- struct kvec iov[3];
+ struct kvec iov[2];
struct smb_rqst rqst = {NULL};
int rc;
- iov[0].iov_base = NULL;
- iov[0].iov_len = 0;
- iov[1].iov_base = buf;
- iov[1].iov_len = sizeof(struct smb2_transform_hdr);
- iov[2].iov_base = buf + sizeof(struct smb2_transform_hdr);
- iov[2].iov_len = buf_data_size;
+ iov[0].iov_base = buf;
+ iov[0].iov_len = sizeof(struct smb2_transform_hdr);
+ iov[1].iov_base = buf + sizeof(struct smb2_transform_hdr);
+ iov[1].iov_len = buf_data_size;
rqst.rq_iov = iov;
- rqst.rq_nvec = 3;
+ rqst.rq_nvec = 2;
rqst.rq_pages = pages;
rqst.rq_npages = npages;
rqst.rq_pagesz = PAGE_SIZE;
@@ -2456,7 +2609,7 @@ decrypt_raw_data(struct TCP_Server_Info *server, char *buf,
if (rc)
return rc;
- memmove(buf, iov[2].iov_base, buf_data_size);
+ memmove(buf, iov[1].iov_base, buf_data_size);
server->total_read = buf_data_size + page_data_size;
@@ -3159,6 +3312,7 @@ struct smb_version_operations smb311_operations = {
.set_compression = smb2_set_compression,
.mkdir = smb2_mkdir,
.mkdir_setinfo = smb2_mkdir_setinfo,
+ .posix_mkdir = smb311_posix_mkdir,
.rmdir = smb2_rmdir,
.unlink = smb2_unlink,
.rename = smb2_rename_path,
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 281fbc1..810b857 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -602,6 +602,7 @@ static void assemble_neg_contexts(struct smb2_negotiate_req *req,
int
SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
{
+ struct smb_rqst rqst;
struct smb2_negotiate_req *req;
struct smb2_negotiate_rsp *rsp;
struct kvec iov[1];
@@ -673,7 +674,11 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
iov[0].iov_base = (char *)req;
iov[0].iov_len = total_len;
- rc = smb2_send_recv(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(req);
rsp = (struct smb2_negotiate_rsp *)rsp_iov.iov_base;
/*
@@ -990,8 +995,9 @@ SMB2_sess_alloc_buffer(struct SMB2_sess_data *sess_data)
req->PreviousSessionId = sess_data->previous_session;
req->Flags = 0; /* MBZ */
- /* to enable echos and oplocks */
- req->sync_hdr.CreditRequest = cpu_to_le16(3);
+
+ /* enough to enable echos and oplocks and one max size write */
+ req->sync_hdr.CreditRequest = cpu_to_le16(130);
/* only one of SMB2 signing flags may be set in SMB2 request */
if (server->sign)
@@ -1027,6 +1033,7 @@ static int
SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
{
int rc;
+ struct smb_rqst rqst;
struct smb2_sess_setup_req *req = sess_data->iov[0].iov_base;
struct kvec rsp_iov = { NULL, 0 };
@@ -1035,10 +1042,13 @@ SMB2_sess_sendreceive(struct SMB2_sess_data *sess_data)
cpu_to_le16(sizeof(struct smb2_sess_setup_req) - 1 /* pad */);
req->SecurityBufferLength = cpu_to_le16(sess_data->iov[1].iov_len);
- /* BB add code to build os and lm fields */
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = sess_data->iov;
+ rqst.rq_nvec = 2;
- rc = smb2_send_recv(sess_data->xid, sess_data->ses,
- sess_data->iov, 2,
+ /* BB add code to build os and lm fields */
+ rc = cifs_send_recv(sess_data->xid, sess_data->ses,
+ &rqst,
&sess_data->buf0_type,
CIFS_LOG_ERROR | CIFS_NEG_OP, &rsp_iov);
cifs_small_buf_release(sess_data->iov[0].iov_base);
@@ -1376,6 +1386,7 @@ out:
int
SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
{
+ struct smb_rqst rqst;
struct smb2_logoff_req *req; /* response is also trivial struct */
int rc = 0;
struct TCP_Server_Info *server;
@@ -1413,7 +1424,11 @@ SMB2_logoff(const unsigned int xid, struct cifs_ses *ses)
iov[0].iov_base = (char *)req;
iov[0].iov_len = total_len;
- rc = smb2_send_recv(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
cifs_small_buf_release(req);
/*
* No tcon so can't do
@@ -1443,6 +1458,7 @@ int
SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
struct cifs_tcon *tcon, const struct nls_table *cp)
{
+ struct smb_rqst rqst;
struct smb2_tree_connect_req *req;
struct smb2_tree_connect_rsp *rsp = NULL;
struct kvec iov[2];
@@ -1499,7 +1515,11 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
!smb3_encryption_required(tcon))
req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
- rc = smb2_send_recv(xid, ses, iov, 2, &resp_buftype, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 2;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(req);
rsp = (struct smb2_tree_connect_rsp *)rsp_iov.iov_base;
@@ -1563,6 +1583,7 @@ tcon_error_exit:
int
SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
{
+ struct smb_rqst rqst;
struct smb2_tree_disconnect_req *req; /* response is trivial */
int rc = 0;
struct cifs_ses *ses = tcon->ses;
@@ -1593,7 +1614,11 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
iov[0].iov_base = (char *)req;
iov[0].iov_len = total_len;
- rc = smb2_send_recv(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
cifs_small_buf_release(req);
if (rc)
cifs_stats_fail_inc(tcon, SMB2_TREE_DISCONNECT_HE);
@@ -1886,11 +1911,165 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
return 0;
}
+#ifdef CONFIG_CIFS_SMB311
+int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
+ umode_t mode, struct cifs_tcon *tcon,
+ const char *full_path,
+ struct cifs_sb_info *cifs_sb)
+{
+ struct smb_rqst rqst;
+ struct smb2_create_req *req;
+ struct smb2_create_rsp *rsp;
+ struct TCP_Server_Info *server;
+ struct cifs_ses *ses = tcon->ses;
+ struct kvec iov[3]; /* make sure at least one for each open context */
+ struct kvec rsp_iov = {NULL, 0};
+ int resp_buftype;
+ int uni_path_len;
+ __le16 *copy_path = NULL;
+ int copy_size;
+ int rc = 0;
+ unsigned int n_iov = 2;
+ __u32 file_attributes = 0;
+ char *pc_buf = NULL;
+ int flags = 0;
+ unsigned int total_len;
+ __le16 *path = cifs_convert_path_to_utf16(full_path, cifs_sb);
+
+ if (!path)
+ return -ENOMEM;
+
+ cifs_dbg(FYI, "mkdir\n");
+
+ if (ses && (ses->server))
+ server = ses->server;
+ else
+ return -EIO;
+
+ rc = smb2_plain_req_init(SMB2_CREATE, tcon, (void **) &req, &total_len);
+
+ if (rc)
+ return rc;
+
+ if (smb3_encryption_required(tcon))
+ flags |= CIFS_TRANSFORM_REQ;
+
+
+ req->ImpersonationLevel = IL_IMPERSONATION;
+ req->DesiredAccess = cpu_to_le32(FILE_WRITE_ATTRIBUTES);
+ /* File attributes ignored on open (used in create though) */
+ req->FileAttributes = cpu_to_le32(file_attributes);
+ req->ShareAccess = FILE_SHARE_ALL_LE;
+ req->CreateDisposition = cpu_to_le32(FILE_CREATE);
+ req->CreateOptions = cpu_to_le32(CREATE_NOT_FILE);
+
+ iov[0].iov_base = (char *)req;
+ /* -1 since last byte is buf[0] which is sent below (path) */
+ iov[0].iov_len = total_len - 1;
+
+ req->NameOffset = cpu_to_le16(sizeof(struct smb2_create_req));
+
+ /* [MS-SMB2] 2.2.13 NameOffset:
+ * If SMB2_FLAGS_DFS_OPERATIONS is set in the Flags field of
+ * the SMB2 header, the file name includes a prefix that will
+ * be processed during DFS name normalization as specified in
+ * section 3.3.5.9. Otherwise, the file name is relative to
+ * the share that is identified by the TreeId in the SMB2
+ * header.
+ */
+ if (tcon->share_flags & SHI1005_FLAGS_DFS) {
+ int name_len;
+
+ req->sync_hdr.Flags |= SMB2_FLAGS_DFS_OPERATIONS;
+ rc = alloc_path_with_tree_prefix(&copy_path, &copy_size,
+ &name_len,
+ tcon->treeName, path);
+ if (rc) {
+ cifs_small_buf_release(req);
+ return rc;
+ }
+ req->NameLength = cpu_to_le16(name_len * 2);
+ uni_path_len = copy_size;
+ path = copy_path;
+ } else {
+ uni_path_len = (2 * UniStrnlen((wchar_t *)path, PATH_MAX)) + 2;
+ /* MUST set path len (NameLength) to 0 opening root of share */
+ req->NameLength = cpu_to_le16(uni_path_len - 2);
+ if (uni_path_len % 8 != 0) {
+ copy_size = roundup(uni_path_len, 8);
+ copy_path = kzalloc(copy_size, GFP_KERNEL);
+ if (!copy_path) {
+ cifs_small_buf_release(req);
+ return -ENOMEM;
+ }
+ memcpy((char *)copy_path, (const char *)path,
+ uni_path_len);
+ uni_path_len = copy_size;
+ path = copy_path;
+ }
+ }
+
+ iov[1].iov_len = uni_path_len;
+ iov[1].iov_base = path;
+ req->RequestedOplockLevel = SMB2_OPLOCK_LEVEL_NONE;
+
+ if (tcon->posix_extensions) {
+ if (n_iov > 2) {
+ struct create_context *ccontext =
+ (struct create_context *)iov[n_iov-1].iov_base;
+ ccontext->Next =
+ cpu_to_le32(iov[n_iov-1].iov_len);
+ }
+
+ rc = add_posix_context(iov, &n_iov, mode);
+ if (rc) {
+ cifs_small_buf_release(req);
+ kfree(copy_path);
+ return rc;
+ }
+ pc_buf = iov[n_iov-1].iov_base;
+ }
+
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = n_iov;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
+ &rsp_iov);
+
+ cifs_small_buf_release(req);
+ rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
+
+ if (rc != 0) {
+ cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
+ trace_smb3_posix_mkdir_err(xid, tcon->tid, ses->Suid,
+ CREATE_NOT_FILE, FILE_WRITE_ATTRIBUTES, rc);
+ goto smb311_mkdir_exit;
+ } else
+ trace_smb3_posix_mkdir_done(xid, rsp->PersistentFileId, tcon->tid,
+ ses->Suid, CREATE_NOT_FILE,
+ FILE_WRITE_ATTRIBUTES);
+
+ SMB2_close(xid, tcon, rsp->PersistentFileId, rsp->VolatileFileId);
+
+ /* Eventually save off posix specific response info and timestaps */
+
+smb311_mkdir_exit:
+ kfree(copy_path);
+ kfree(pc_buf);
+ free_rsp_buf(resp_buftype, rsp);
+ return rc;
+
+}
+#endif /* SMB311 */
+
int
SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
__u8 *oplock, struct smb2_file_all_info *buf,
- struct kvec *err_iov)
+ struct kvec *err_iov, int *buftype)
{
+ struct smb_rqst rqst;
struct smb2_create_req *req;
struct smb2_create_rsp *rsp;
struct TCP_Server_Info *server;
@@ -2043,7 +2222,11 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
}
#endif /* SMB311 */
- rc = smb2_send_recv(xid, ses, iov, n_iov, &resp_buftype, flags,
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = n_iov;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
&rsp_iov);
cifs_small_buf_release(req);
rsp = (struct smb2_create_rsp *)rsp_iov.iov_base;
@@ -2052,6 +2235,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
cifs_stats_fail_inc(tcon, SMB2_CREATE_HE);
if (err_iov && rsp) {
*err_iov = rsp_iov;
+ *buftype = resp_buftype;
resp_buftype = CIFS_NO_BUFFER;
rsp = NULL;
}
@@ -2098,6 +2282,7 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
char *in_data, u32 indatalen,
char **out_data, u32 *plen /* returned data len */)
{
+ struct smb_rqst rqst;
struct smb2_ioctl_req *req;
struct smb2_ioctl_rsp *rsp;
struct cifs_ses *ses;
@@ -2188,7 +2373,11 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
req->sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
- rc = smb2_send_recv(xid, ses, iov, n_iov, &resp_buftype, flags,
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = n_iov;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
&rsp_iov);
cifs_small_buf_release(req);
rsp = (struct smb2_ioctl_rsp *)rsp_iov.iov_base;
@@ -2273,6 +2462,7 @@ int
SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, int flags)
{
+ struct smb_rqst rqst;
struct smb2_close_req *req;
struct smb2_close_rsp *rsp;
struct cifs_ses *ses = tcon->ses;
@@ -2300,7 +2490,11 @@ SMB2_close_flags(const unsigned int xid, struct cifs_tcon *tcon,
iov[0].iov_base = (char *)req;
iov[0].iov_len = total_len;
- rc = smb2_send_recv(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(req);
rsp = (struct smb2_close_rsp *)rsp_iov.iov_base;
@@ -2386,6 +2580,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
u32 additional_info, size_t output_len, size_t min_len, void **data,
u32 *dlen)
{
+ struct smb_rqst rqst;
struct smb2_query_info_req *req;
struct smb2_query_info_rsp *rsp = NULL;
struct kvec iov[2];
@@ -2426,7 +2621,11 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
/* 1 for Buffer */
iov[0].iov_len = total_len - 1;
- rc = smb2_send_recv(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(req);
rsp = (struct smb2_query_info_rsp *)rsp_iov.iov_base;
@@ -2492,8 +2691,7 @@ SMB2_query_acl(const unsigned int xid, struct cifs_tcon *tcon,
return query_info(xid, tcon, persistent_fid, volatile_fid,
0, SMB2_O_INFO_SECURITY, additional_info,
- SMB2_MAX_BUFFER_SIZE,
- sizeof(struct smb2_file_all_info), data, plen);
+ SMB2_MAX_BUFFER_SIZE, MIN_SEC_DESC_LEN, data, plen);
}
int
@@ -2594,11 +2792,10 @@ SMB2_echo(struct TCP_Server_Info *server)
{
struct smb2_echo_req *req;
int rc = 0;
- struct kvec iov[2];
+ struct kvec iov[1];
struct smb_rqst rqst = { .rq_iov = iov,
- .rq_nvec = 2 };
+ .rq_nvec = 1 };
unsigned int total_len;
- __be32 rfc1002_marker;
cifs_dbg(FYI, "In echo request\n");
@@ -2614,11 +2811,8 @@ SMB2_echo(struct TCP_Server_Info *server)
req->sync_hdr.CreditRequest = cpu_to_le16(1);
- iov[0].iov_len = 4;
- rfc1002_marker = cpu_to_be32(total_len);
- iov[0].iov_base = &rfc1002_marker;
- iov[1].iov_len = total_len;
- iov[1].iov_base = (char *)req;
+ iov[0].iov_len = total_len;
+ iov[0].iov_base = (char *)req;
rc = cifs_call_async(server, &rqst, NULL, smb2_echo_callback, NULL,
server, CIFS_ECHO_OP);
@@ -2633,6 +2827,7 @@ int
SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
u64 volatile_fid)
{
+ struct smb_rqst rqst;
struct smb2_flush_req *req;
struct cifs_ses *ses = tcon->ses;
struct kvec iov[1];
@@ -2660,7 +2855,11 @@ SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
iov[0].iov_base = (char *)req;
iov[0].iov_len = total_len;
- rc = smb2_send_recv(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(req);
if (rc != 0) {
@@ -2721,8 +2920,8 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
rdata->mr = smbd_register_mr(
server->smbd_conn, rdata->pages,
- rdata->nr_pages, rdata->tailsz,
- true, need_invalidate);
+ rdata->nr_pages, rdata->page_offset,
+ rdata->tailsz, true, need_invalidate);
if (!rdata->mr)
return -ENOBUFS;
@@ -2848,10 +3047,9 @@ smb2_async_readv(struct cifs_readdata *rdata)
struct smb2_sync_hdr *shdr;
struct cifs_io_parms io_parms;
struct smb_rqst rqst = { .rq_iov = rdata->iov,
- .rq_nvec = 2 };
+ .rq_nvec = 1 };
struct TCP_Server_Info *server;
unsigned int total_len;
- __be32 req_len;
cifs_dbg(FYI, "%s: offset=%llu bytes=%u\n",
__func__, rdata->offset, rdata->bytes);
@@ -2882,12 +3080,8 @@ smb2_async_readv(struct cifs_readdata *rdata)
if (smb3_encryption_required(io_parms.tcon))
flags |= CIFS_TRANSFORM_REQ;
- req_len = cpu_to_be32(total_len);
-
- rdata->iov[0].iov_base = &req_len;
- rdata->iov[0].iov_len = sizeof(__be32);
- rdata->iov[1].iov_base = buf;
- rdata->iov[1].iov_len = total_len;
+ rdata->iov[0].iov_base = buf;
+ rdata->iov[0].iov_len = total_len;
shdr = (struct smb2_sync_hdr *)buf;
@@ -2926,6 +3120,7 @@ int
SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
unsigned int *nbytes, char **buf, int *buf_type)
{
+ struct smb_rqst rqst;
int resp_buftype, rc = -EACCES;
struct smb2_read_plain_req *req = NULL;
struct smb2_read_rsp *rsp = NULL;
@@ -2946,7 +3141,11 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
iov[0].iov_base = (char *)req;
iov[0].iov_len = total_len;
- rc = smb2_send_recv(xid, ses, iov, 1, &resp_buftype, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(req);
rsp = (struct smb2_read_rsp *)rsp_iov.iov_base;
@@ -3062,10 +3261,9 @@ smb2_async_writev(struct cifs_writedata *wdata,
struct smb2_sync_hdr *shdr;
struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
struct TCP_Server_Info *server = tcon->ses->server;
- struct kvec iov[2];
+ struct kvec iov[1];
struct smb_rqst rqst = { };
unsigned int total_len;
- __be32 rfc1002_marker;
rc = smb2_plain_req_init(SMB2_WRITE, tcon, (void **) &req, &total_len);
if (rc) {
@@ -3108,16 +3306,22 @@ smb2_async_writev(struct cifs_writedata *wdata,
wdata->mr = smbd_register_mr(
server->smbd_conn, wdata->pages,
- wdata->nr_pages, wdata->tailsz,
- false, need_invalidate);
+ wdata->nr_pages, wdata->page_offset,
+ wdata->tailsz, false, need_invalidate);
if (!wdata->mr) {
rc = -ENOBUFS;
goto async_writev_out;
}
req->Length = 0;
req->DataOffset = 0;
- req->RemainingBytes =
- cpu_to_le32((wdata->nr_pages-1)*PAGE_SIZE + wdata->tailsz);
+ if (wdata->nr_pages > 1)
+ req->RemainingBytes =
+ cpu_to_le32(
+ (wdata->nr_pages - 1) * wdata->pagesz -
+ wdata->page_offset + wdata->tailsz
+ );
+ else
+ req->RemainingBytes = cpu_to_le32(wdata->tailsz);
req->Channel = SMB2_CHANNEL_RDMA_V1_INVALIDATE;
if (need_invalidate)
req->Channel = SMB2_CHANNEL_RDMA_V1;
@@ -3131,15 +3335,11 @@ smb2_async_writev(struct cifs_writedata *wdata,
v1->length = cpu_to_le32(wdata->mr->mr->length);
}
#endif
- /* 4 for rfc1002 length field and 1 for Buffer */
- iov[0].iov_len = 4;
- rfc1002_marker = cpu_to_be32(total_len - 1 + wdata->bytes);
- iov[0].iov_base = &rfc1002_marker;
- iov[1].iov_len = total_len - 1;
- iov[1].iov_base = (char *)req;
+ iov[0].iov_len = total_len - 1;
+ iov[0].iov_base = (char *)req;
rqst.rq_iov = iov;
- rqst.rq_nvec = 2;
+ rqst.rq_nvec = 1;
rqst.rq_pages = wdata->pages;
rqst.rq_offset = wdata->page_offset;
rqst.rq_npages = wdata->nr_pages;
@@ -3147,7 +3347,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
rqst.rq_tailsz = wdata->tailsz;
#ifdef CONFIG_CIFS_SMB_DIRECT
if (wdata->mr) {
- iov[1].iov_len += sizeof(struct smbd_buffer_descriptor_v1);
+ iov[0].iov_len += sizeof(struct smbd_buffer_descriptor_v1);
rqst.rq_npages = 0;
}
#endif
@@ -3204,6 +3404,7 @@ int
SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
unsigned int *nbytes, struct kvec *iov, int n_vec)
{
+ struct smb_rqst rqst;
int rc = 0;
struct smb2_write_req *req = NULL;
struct smb2_write_rsp *rsp = NULL;
@@ -3245,7 +3446,11 @@ SMB2_write(const unsigned int xid, struct cifs_io_parms *io_parms,
/* 1 for Buffer */
iov[0].iov_len = total_len - 1;
- rc = smb2_send_recv(xid, io_parms->tcon->ses, iov, n_vec + 1,
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = n_vec + 1;
+
+ rc = cifs_send_recv(xid, io_parms->tcon->ses, &rqst,
&resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(req);
rsp = (struct smb2_write_rsp *)rsp_iov.iov_base;
@@ -3317,6 +3522,7 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, int index,
struct cifs_search_info *srch_inf)
{
+ struct smb_rqst rqst;
struct smb2_query_directory_req *req;
struct smb2_query_directory_rsp *rsp = NULL;
struct kvec iov[2];
@@ -3389,7 +3595,11 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
iov[1].iov_base = (char *)(req->Buffer);
iov[1].iov_len = len;
- rc = smb2_send_recv(xid, ses, iov, 2, &resp_buftype, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 2;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(req);
rsp = (struct smb2_query_directory_rsp *)rsp_iov.iov_base;
@@ -3448,6 +3658,7 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
u8 info_type, u32 additional_info, unsigned int num,
void **data, unsigned int *size)
{
+ struct smb_rqst rqst;
struct smb2_set_info_req *req;
struct smb2_set_info_rsp *rsp = NULL;
struct kvec *iov;
@@ -3465,7 +3676,7 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
if (!num)
return -EINVAL;
- iov = kmalloc(sizeof(struct kvec) * num, GFP_KERNEL);
+ iov = kmalloc_array(num, sizeof(struct kvec), GFP_KERNEL);
if (!iov)
return -ENOMEM;
@@ -3503,7 +3714,11 @@ send_set_info(const unsigned int xid, struct cifs_tcon *tcon,
iov[i].iov_len = size[i];
}
- rc = smb2_send_recv(xid, ses, iov, num, &resp_buftype, flags,
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = num;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags,
&rsp_iov);
cifs_small_buf_release(req);
rsp = (struct smb2_set_info_rsp *)rsp_iov.iov_base;
@@ -3529,7 +3744,7 @@ SMB2_rename(const unsigned int xid, struct cifs_tcon *tcon,
int rc;
int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX));
- data = kmalloc(sizeof(void *) * 2, GFP_KERNEL);
+ data = kmalloc_array(2, sizeof(void *), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -3577,7 +3792,7 @@ SMB2_set_hardlink(const unsigned int xid, struct cifs_tcon *tcon,
int rc;
int len = (2 * UniStrnlen((wchar_t *)target_file, PATH_MAX));
- data = kmalloc(sizeof(void *) * 2, GFP_KERNEL);
+ data = kmalloc_array(2, sizeof(void *), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -3658,6 +3873,7 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
const u64 persistent_fid, const u64 volatile_fid,
__u8 oplock_level)
{
+ struct smb_rqst rqst;
int rc;
struct smb2_oplock_break *req = NULL;
struct cifs_ses *ses = tcon->ses;
@@ -3686,7 +3902,11 @@ SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
iov[0].iov_base = (char *)req;
iov[0].iov_len = total_len;
- rc = smb2_send_recv(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
cifs_small_buf_release(req);
if (rc) {
@@ -3749,6 +3969,7 @@ int
SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, struct kstatfs *fsdata)
{
+ struct smb_rqst rqst;
struct smb2_query_info_rsp *rsp = NULL;
struct kvec iov;
struct kvec rsp_iov;
@@ -3767,7 +3988,11 @@ SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
if (smb3_encryption_required(tcon))
flags |= CIFS_TRANSFORM_REQ;
- rc = smb2_send_recv(xid, ses, &iov, 1, &resp_buftype, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = &iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(iov.iov_base);
if (rc) {
cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
@@ -3792,6 +4017,7 @@ int
SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, int level)
{
+ struct smb_rqst rqst;
struct smb2_query_info_rsp *rsp = NULL;
struct kvec iov;
struct kvec rsp_iov;
@@ -3823,7 +4049,11 @@ SMB2_QFS_attr(const unsigned int xid, struct cifs_tcon *tcon,
if (smb3_encryption_required(tcon))
flags |= CIFS_TRANSFORM_REQ;
- rc = smb2_send_recv(xid, ses, &iov, 1, &resp_buftype, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = &iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buftype, flags, &rsp_iov);
cifs_small_buf_release(iov.iov_base);
if (rc) {
cifs_stats_fail_inc(tcon, SMB2_QUERY_INFO_HE);
@@ -3862,6 +4092,7 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
const __u64 persist_fid, const __u64 volatile_fid, const __u32 pid,
const __u32 num_lock, struct smb2_lock_element *buf)
{
+ struct smb_rqst rqst;
int rc = 0;
struct smb2_lock_req *req = NULL;
struct kvec iov[2];
@@ -3894,7 +4125,12 @@ smb2_lockv(const unsigned int xid, struct cifs_tcon *tcon,
iov[1].iov_len = count;
cifs_stats_inc(&tcon->stats.cifs_stats.num_locks);
- rc = smb2_send_recv(xid, tcon->ses, iov, 2, &resp_buf_type, flags,
+
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 2;
+
+ rc = cifs_send_recv(xid, tcon->ses, &rqst, &resp_buf_type, flags,
&rsp_iov);
cifs_small_buf_release(req);
if (rc) {
@@ -3928,6 +4164,7 @@ int
SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
__u8 *lease_key, const __le32 lease_state)
{
+ struct smb_rqst rqst;
int rc;
struct smb2_lease_ack *req = NULL;
struct cifs_ses *ses = tcon->ses;
@@ -3958,7 +4195,11 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
iov[0].iov_base = (char *)req;
iov[0].iov_len = total_len;
- rc = smb2_send_recv(xid, ses, iov, 1, &resp_buf_type, flags, &rsp_iov);
+ memset(&rqst, 0, sizeof(struct smb_rqst));
+ rqst.rq_iov = iov;
+ rqst.rq_nvec = 1;
+
+ rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
cifs_small_buf_release(req);
if (rc) {
diff --git a/fs/cifs/smb2pdu.h b/fs/cifs/smb2pdu.h
index a345560..824ddde 100644
--- a/fs/cifs/smb2pdu.h
+++ b/fs/cifs/smb2pdu.h
@@ -851,8 +851,11 @@ struct validate_negotiate_info_rsp {
__le16 Dialect; /* Dialect in use for the connection */
} __packed;
-#define RSS_CAPABLE 0x00000001
-#define RDMA_CAPABLE 0x00000002
+#define RSS_CAPABLE cpu_to_le32(0x00000001)
+#define RDMA_CAPABLE cpu_to_le32(0x00000002)
+
+#define INTERNETWORK cpu_to_le16(0x0002)
+#define INTERNETWORKV6 cpu_to_le16(0x0017)
struct network_interface_info_ioctl_rsp {
__le32 Next; /* next interface. zero if this is last one */
@@ -860,7 +863,21 @@ struct network_interface_info_ioctl_rsp {
__le32 Capability; /* RSS or RDMA Capable */
__le32 Reserved;
__le64 LinkSpeed;
- char SockAddr_Storage[128];
+ __le16 Family;
+ __u8 Buffer[126];
+} __packed;
+
+struct iface_info_ipv4 {
+ __be16 Port;
+ __be32 IPv4Address;
+ __be64 Reserved;
+} __packed;
+
+struct iface_info_ipv6 {
+ __be16 Port;
+ __be32 FlowInfo;
+ __u8 IPv6Address[16];
+ __be32 ScopeId;
} __packed;
#define NO_FILE_ID 0xFFFFFFFFFFFFFFFFULL /* general ioctls to srv not to file */
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 908555b..3ae208a 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -79,6 +79,10 @@ extern int smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb, bool set_alloc);
extern int smb2_set_file_info(struct inode *inode, const char *full_path,
FILE_BASIC_INFO *buf, const unsigned int xid);
+extern int smb311_posix_mkdir(const unsigned int xid, struct inode *inode,
+ umode_t mode, struct cifs_tcon *tcon,
+ const char *full_path,
+ struct cifs_sb_info *cifs_sb);
extern int smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon,
const char *name, struct cifs_sb_info *cifs_sb);
extern void smb2_mkdir_setinfo(struct inode *inode, const char *full_path,
@@ -109,6 +113,8 @@ extern int smb2_unlock_range(struct cifsFileInfo *cfile,
extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
extern void smb2_reconnect_server(struct work_struct *work);
extern int smb3_crypto_aead_allocate(struct TCP_Server_Info *server);
+extern unsigned long
+smb2_rqst_len(struct smb_rqst *rqst, bool skip_rfc1002_marker);
/*
* SMB2 Worker functions - most of protocol specific implementation details
@@ -125,7 +131,7 @@ extern int SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon);
extern int SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms,
__le16 *path, __u8 *oplock,
struct smb2_file_all_info *buf,
- struct kvec *err_iov);
+ struct kvec *err_iov, int *resp_buftype);
extern int SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_fid, u64 volatile_fid, u32 opcode,
bool is_fsctl, char *in_data, u32 indatalen,
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index 2c67112..51b9437 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -171,7 +171,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
unsigned char smb2_signature[SMB2_HMACSHA256_SIZE];
unsigned char *sigptr = smb2_signature;
struct kvec *iov = rqst->rq_iov;
- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
+ struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
struct cifs_ses *ses;
ses = smb2_find_smb_ses(server, shdr->SessionId);
@@ -412,7 +412,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
unsigned char smb3_signature[SMB2_CMACAES_SIZE];
unsigned char *sigptr = smb3_signature;
struct kvec *iov = rqst->rq_iov;
- struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[1].iov_base;
+ struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
struct cifs_ses *ses;
ses = smb2_find_smb_ses(server, shdr->SessionId);
@@ -458,7 +458,7 @@ smb2_sign_rqst(struct smb_rqst *rqst, struct TCP_Server_Info *server)
{
int rc = 0;
struct smb2_sync_hdr *shdr =
- (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
+ (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
if (!(shdr->Flags & SMB2_FLAGS_SIGNED) ||
server->tcpStatus == CifsNeedNegotiate)
@@ -631,7 +631,7 @@ smb2_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
{
int rc;
struct smb2_sync_hdr *shdr =
- (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
+ (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
struct mid_q_entry *mid;
smb2_seq_num_into_buf(ses->server, shdr);
@@ -652,7 +652,7 @@ smb2_setup_async_request(struct TCP_Server_Info *server, struct smb_rqst *rqst)
{
int rc;
struct smb2_sync_hdr *shdr =
- (struct smb2_sync_hdr *)rqst->rq_iov[1].iov_base;
+ (struct smb2_sync_hdr *)rqst->rq_iov[0].iov_base;
struct mid_q_entry *mid;
smb2_seq_num_into_buf(server, shdr);
diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c
index c62f7c9..6fd94d9 100644
--- a/fs/cifs/smbdirect.c
+++ b/fs/cifs/smbdirect.c
@@ -17,6 +17,8 @@
#include <linux/highmem.h>
#include "smbdirect.h"
#include "cifs_debug.h"
+#include "cifsproto.h"
+#include "smb2proto.h"
static struct smbd_response *get_empty_queue_buffer(
struct smbd_connection *info);
@@ -2003,10 +2005,12 @@ read_rfc1002_done:
* return value: actual data read
*/
static int smbd_recv_page(struct smbd_connection *info,
- struct page *page, unsigned int to_read)
+ struct page *page, unsigned int page_offset,
+ unsigned int to_read)
{
int ret;
char *to_address;
+ void *page_address;
/* make sure we have the page ready for read */
ret = wait_event_interruptible(
@@ -2014,16 +2018,17 @@ static int smbd_recv_page(struct smbd_connection *info,
info->reassembly_data_length >= to_read ||
info->transport_status != SMBD_CONNECTED);
if (ret)
- return 0;
+ return ret;
/* now we can read from reassembly queue and not sleep */
- to_address = kmap_atomic(page);
+ page_address = kmap_atomic(page);
+ to_address = (char *) page_address + page_offset;
log_read(INFO, "reading from page=%p address=%p to_read=%d\n",
page, to_address, to_read);
ret = smbd_recv_buf(info, to_address, to_read);
- kunmap_atomic(to_address);
+ kunmap_atomic(page_address);
return ret;
}
@@ -2037,7 +2042,7 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
{
char *buf;
struct page *page;
- unsigned int to_read;
+ unsigned int to_read, page_offset;
int rc;
info->smbd_recv_pending++;
@@ -2051,15 +2056,16 @@ int smbd_recv(struct smbd_connection *info, struct msghdr *msg)
case READ | ITER_BVEC:
page = msg->msg_iter.bvec->bv_page;
+ page_offset = msg->msg_iter.bvec->bv_offset;
to_read = msg->msg_iter.bvec->bv_len;
- rc = smbd_recv_page(info, page, to_read);
+ rc = smbd_recv_page(info, page, page_offset, to_read);
break;
default:
/* It's a bug in upper layer to get there */
cifs_dbg(VFS, "CIFS: invalid msg type %d\n",
msg->msg_iter.type);
- rc = -EIO;
+ rc = -EINVAL;
}
info->smbd_recv_pending--;
@@ -2082,7 +2088,7 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
struct kvec vec;
int nvecs;
int size;
- int buflen = 0, remaining_data_length;
+ unsigned int buflen, remaining_data_length;
int start, i, j;
int max_iov_size =
info->max_send_size - sizeof(struct smbd_data_transfer);
@@ -2106,18 +2112,13 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
log_write(ERR, "expected the pdu length in 1st iov, but got %zu\n", rqst->rq_iov[0].iov_len);
return -EINVAL;
}
- iov = &rqst->rq_iov[1];
-
- /* total up iov array first */
- for (i = 0; i < rqst->rq_nvec-1; i++) {
- buflen += iov[i].iov_len;
- }
- /* add in the page array if there is one */
- if (rqst->rq_npages) {
- buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
- buflen += rqst->rq_tailsz;
- }
+ /*
+ * Add in the page array if there is one. The caller needs to set
+ * rq_tailsz to PAGE_SIZE when the buffer has multiple pages and
+ * ends at page boundary
+ */
+ buflen = smb2_rqst_len(rqst, true);
if (buflen + sizeof(struct smbd_data_transfer) >
info->max_fragmented_send_size) {
@@ -2127,6 +2128,8 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
goto done;
}
+ iov = &rqst->rq_iov[1];
+
cifs_dbg(FYI, "Sending smb (RDMA): smb_len=%u\n", buflen);
for (i = 0; i < rqst->rq_nvec-1; i++)
dump_smb(iov[i].iov_base, iov[i].iov_len);
@@ -2213,8 +2216,9 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
/* now sending pages if there are any */
for (i = 0; i < rqst->rq_npages; i++) {
- buflen = (i == rqst->rq_npages-1) ?
- rqst->rq_tailsz : rqst->rq_pagesz;
+ unsigned int offset;
+
+ rqst_page_get_length(rqst, i, &buflen, &offset);
nvecs = (buflen + max_iov_size - 1) / max_iov_size;
log_write(INFO, "sending pages buflen=%d nvecs=%d\n",
buflen, nvecs);
@@ -2225,9 +2229,11 @@ int smbd_send(struct smbd_connection *info, struct smb_rqst *rqst)
remaining_data_length -= size;
log_write(INFO, "sending pages i=%d offset=%d size=%d"
" remaining_data_length=%d\n",
- i, j*max_iov_size, size, remaining_data_length);
+ i, j*max_iov_size+offset, size,
+ remaining_data_length);
rc = smbd_post_send_page(
- info, rqst->rq_pages[i], j*max_iov_size,
+ info, rqst->rq_pages[i],
+ j*max_iov_size + offset,
size, remaining_data_length);
if (rc)
goto done;
@@ -2284,37 +2290,37 @@ static void smbd_mr_recovery_work(struct work_struct *work)
if (smbdirect_mr->state == MR_INVALIDATED ||
smbdirect_mr->state == MR_ERROR) {
- if (smbdirect_mr->state == MR_INVALIDATED) {
+ /* recover this MR entry */
+ rc = ib_dereg_mr(smbdirect_mr->mr);
+ if (rc) {
+ log_rdma_mr(ERR,
+ "ib_dereg_mr failed rc=%x\n",
+ rc);
+ smbd_disconnect_rdma_connection(info);
+ continue;
+ }
+
+ smbdirect_mr->mr = ib_alloc_mr(
+ info->pd, info->mr_type,
+ info->max_frmr_depth);
+ if (IS_ERR(smbdirect_mr->mr)) {
+ log_rdma_mr(ERR,
+ "ib_alloc_mr failed mr_type=%x "
+ "max_frmr_depth=%x\n",
+ info->mr_type,
+ info->max_frmr_depth);
+ smbd_disconnect_rdma_connection(info);
+ continue;
+ }
+
+ if (smbdirect_mr->state == MR_INVALIDATED)
ib_dma_unmap_sg(
info->id->device, smbdirect_mr->sgl,
smbdirect_mr->sgl_count,
smbdirect_mr->dir);
- smbdirect_mr->state = MR_READY;
- } else if (smbdirect_mr->state == MR_ERROR) {
-
- /* recover this MR entry */
- rc = ib_dereg_mr(smbdirect_mr->mr);
- if (rc) {
- log_rdma_mr(ERR,
- "ib_dereg_mr failed rc=%x\n",
- rc);
- smbd_disconnect_rdma_connection(info);
- }
- smbdirect_mr->mr = ib_alloc_mr(
- info->pd, info->mr_type,
- info->max_frmr_depth);
- if (IS_ERR(smbdirect_mr->mr)) {
- log_rdma_mr(ERR,
- "ib_alloc_mr failed mr_type=%x "
- "max_frmr_depth=%x\n",
- info->mr_type,
- info->max_frmr_depth);
- smbd_disconnect_rdma_connection(info);
- }
+ smbdirect_mr->state = MR_READY;
- smbdirect_mr->state = MR_READY;
- }
/* smbdirect_mr->state is updated by this function
* and is read and updated by I/O issuing CPUs trying
* to get a MR, the call to atomic_inc_return
@@ -2460,7 +2466,7 @@ again:
*/
struct smbd_mr *smbd_register_mr(
struct smbd_connection *info, struct page *pages[], int num_pages,
- int tailsz, bool writing, bool need_invalidate)
+ int offset, int tailsz, bool writing, bool need_invalidate)
{
struct smbd_mr *smbdirect_mr;
int rc, i;
@@ -2483,17 +2489,31 @@ struct smbd_mr *smbd_register_mr(
smbdirect_mr->sgl_count = num_pages;
sg_init_table(smbdirect_mr->sgl, num_pages);
- for (i = 0; i < num_pages - 1; i++)
- sg_set_page(&smbdirect_mr->sgl[i], pages[i], PAGE_SIZE, 0);
+ log_rdma_mr(INFO, "num_pages=0x%x offset=0x%x tailsz=0x%x\n",
+ num_pages, offset, tailsz);
+ if (num_pages == 1) {
+ sg_set_page(&smbdirect_mr->sgl[0], pages[0], tailsz, offset);
+ goto skip_multiple_pages;
+ }
+
+ /* We have at least two pages to register */
+ sg_set_page(
+ &smbdirect_mr->sgl[0], pages[0], PAGE_SIZE - offset, offset);
+ i = 1;
+ while (i < num_pages - 1) {
+ sg_set_page(&smbdirect_mr->sgl[i], pages[i], PAGE_SIZE, 0);
+ i++;
+ }
sg_set_page(&smbdirect_mr->sgl[i], pages[i],
tailsz ? tailsz : PAGE_SIZE, 0);
+skip_multiple_pages:
dir = writing ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
smbdirect_mr->dir = dir;
rc = ib_dma_map_sg(info->id->device, smbdirect_mr->sgl, num_pages, dir);
if (!rc) {
- log_rdma_mr(INFO, "ib_dma_map_sg num_pages=%x dir=%x rc=%x\n",
+ log_rdma_mr(ERR, "ib_dma_map_sg num_pages=%x dir=%x rc=%x\n",
num_pages, dir, rc);
goto dma_map_error;
}
@@ -2501,8 +2521,8 @@ struct smbd_mr *smbd_register_mr(
rc = ib_map_mr_sg(smbdirect_mr->mr, smbdirect_mr->sgl, num_pages,
NULL, PAGE_SIZE);
if (rc != num_pages) {
- log_rdma_mr(INFO,
- "ib_map_mr_sg failed rc = %x num_pages = %x\n",
+ log_rdma_mr(ERR,
+ "ib_map_mr_sg failed rc = %d num_pages = %x\n",
rc, num_pages);
goto map_mr_error;
}
diff --git a/fs/cifs/smbdirect.h b/fs/cifs/smbdirect.h
index f9038da..1e419c2 100644
--- a/fs/cifs/smbdirect.h
+++ b/fs/cifs/smbdirect.h
@@ -321,7 +321,7 @@ struct smbd_mr {
/* Interfaces to register and deregister MR for RDMA read/write */
struct smbd_mr *smbd_register_mr(
struct smbd_connection *info, struct page *pages[], int num_pages,
- int tailsz, bool writing, bool need_invalidate);
+ int offset, int tailsz, bool writing, bool need_invalidate);
int smbd_deregister_mr(struct smbd_mr *mr);
#else
diff --git a/fs/cifs/trace.h b/fs/cifs/trace.h
index 61e74d4..67e413f6 100644
--- a/fs/cifs/trace.h
+++ b/fs/cifs/trace.h
@@ -378,7 +378,7 @@ DEFINE_EVENT(smb3_open_err_class, smb3_##name, \
TP_ARGS(xid, tid, sesid, create_options, desired_access, rc))
DEFINE_SMB3_OPEN_ERR_EVENT(open_err);
-
+DEFINE_SMB3_OPEN_ERR_EVENT(posix_mkdir_err);
DECLARE_EVENT_CLASS(smb3_open_done_class,
TP_PROTO(unsigned int xid,
@@ -420,6 +420,7 @@ DEFINE_EVENT(smb3_open_done_class, smb3_##name, \
TP_ARGS(xid, fid, tid, sesid, create_options, desired_access))
DEFINE_SMB3_OPEN_DONE_EVENT(open_done);
+DEFINE_SMB3_OPEN_DONE_EVENT(posix_mkdir_done);
#endif /* _CIFS_TRACE_H */
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index e7254e3..fb57dfb 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -201,39 +201,64 @@ smb_send_kvec(struct TCP_Server_Info *server, struct msghdr *smb_msg,
return 0;
}
-static unsigned long
-rqst_len(struct smb_rqst *rqst)
+unsigned long
+smb2_rqst_len(struct smb_rqst *rqst, bool skip_rfc1002_marker)
{
unsigned int i;
- struct kvec *iov = rqst->rq_iov;
+ struct kvec *iov;
+ int nvec;
unsigned long buflen = 0;
+ if (skip_rfc1002_marker && rqst->rq_iov[0].iov_len == 4) {
+ iov = &rqst->rq_iov[1];
+ nvec = rqst->rq_nvec - 1;
+ } else {
+ iov = rqst->rq_iov;
+ nvec = rqst->rq_nvec;
+ }
+
/* total up iov array first */
- for (i = 0; i < rqst->rq_nvec; i++)
+ for (i = 0; i < nvec; i++)
buflen += iov[i].iov_len;
- /* add in the page array if there is one */
+ /*
+ * Add in the page array if there is one. The caller needs to make
+ * sure rq_offset and rq_tailsz are set correctly. If a buffer of
+ * multiple pages ends at page boundary, rq_tailsz needs to be set to
+ * PAGE_SIZE.
+ */
if (rqst->rq_npages) {
- buflen += rqst->rq_pagesz * (rqst->rq_npages - 1);
- buflen += rqst->rq_tailsz;
+ if (rqst->rq_npages == 1)
+ buflen += rqst->rq_tailsz;
+ else {
+ /*
+ * If there is more than one page, calculate the
+ * buffer length based on rq_offset and rq_tailsz
+ */
+ buflen += rqst->rq_pagesz * (rqst->rq_npages - 1) -
+ rqst->rq_offset;
+ buflen += rqst->rq_tailsz;
+ }
}
return buflen;
}
static int
-__smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
+__smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
+ struct smb_rqst *rqst)
{
- int rc;
- struct kvec *iov = rqst->rq_iov;
- int n_vec = rqst->rq_nvec;
- unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base);
- unsigned long send_length;
- unsigned int i;
+ int rc = 0;
+ struct kvec *iov;
+ int n_vec;
+ unsigned int send_length = 0;
+ unsigned int i, j;
size_t total_len = 0, sent, size;
struct socket *ssocket = server->ssocket;
struct msghdr smb_msg;
int val = 1;
+ __be32 rfc1002_marker;
+
if (cifs_rdma_enabled(server) && server->smbd_conn) {
rc = smbd_send(server->smbd_conn, rqst);
goto smbd_done;
@@ -241,53 +266,67 @@ __smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst)
if (ssocket == NULL)
return -ENOTSOCK;
- /* sanity check send length */
- send_length = rqst_len(rqst);
- if (send_length != smb_buf_length + 4) {
- WARN(1, "Send length mismatch(send_length=%lu smb_buf_length=%u)\n",
- send_length, smb_buf_length);
- return -EIO;
- }
-
- if (n_vec < 2)
- return -EIO;
-
- cifs_dbg(FYI, "Sending smb: smb_len=%u\n", smb_buf_length);
- dump_smb(iov[0].iov_base, iov[0].iov_len);
- dump_smb(iov[1].iov_base, iov[1].iov_len);
-
/* cork the socket */
kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
(char *)&val, sizeof(val));
- size = 0;
- for (i = 0; i < n_vec; i++)
- size += iov[i].iov_len;
-
- iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, iov, n_vec, size);
+ for (j = 0; j < num_rqst; j++)
+ send_length += smb2_rqst_len(&rqst[j], true);
+ rfc1002_marker = cpu_to_be32(send_length);
- rc = smb_send_kvec(server, &smb_msg, &sent);
- if (rc < 0)
- goto uncork;
-
- total_len += sent;
-
- /* now walk the page array and send each page in it */
- for (i = 0; i < rqst->rq_npages; i++) {
- size_t len = i == rqst->rq_npages - 1
- ? rqst->rq_tailsz
- : rqst->rq_pagesz;
- struct bio_vec bvec = {
- .bv_page = rqst->rq_pages[i],
- .bv_len = len
+ /* Generate a rfc1002 marker for SMB2+ */
+ if (server->vals->header_preamble_size == 0) {
+ struct kvec hiov = {
+ .iov_base = &rfc1002_marker,
+ .iov_len = 4
};
- iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC,
- &bvec, 1, len);
+ iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC, &hiov,
+ 1, 4);
rc = smb_send_kvec(server, &smb_msg, &sent);
if (rc < 0)
- break;
+ goto uncork;
+
+ total_len += sent;
+ send_length += 4;
+ }
+
+ cifs_dbg(FYI, "Sending smb: smb_len=%u\n", send_length);
+
+ for (j = 0; j < num_rqst; j++) {
+ iov = rqst[j].rq_iov;
+ n_vec = rqst[j].rq_nvec;
+
+ size = 0;
+ for (i = 0; i < n_vec; i++) {
+ dump_smb(iov[i].iov_base, iov[i].iov_len);
+ size += iov[i].iov_len;
+ }
+
+ iov_iter_kvec(&smb_msg.msg_iter, WRITE | ITER_KVEC,
+ iov, n_vec, size);
+
+ rc = smb_send_kvec(server, &smb_msg, &sent);
+ if (rc < 0)
+ goto uncork;
total_len += sent;
+
+ /* now walk the page array and send each page in it */
+ for (i = 0; i < rqst[j].rq_npages; i++) {
+ struct bio_vec bvec;
+
+ bvec.bv_page = rqst[j].rq_pages[i];
+ rqst_page_get_length(&rqst[j], i, &bvec.bv_len,
+ &bvec.bv_offset);
+
+ iov_iter_bvec(&smb_msg.msg_iter, WRITE | ITER_BVEC,
+ &bvec, 1, bvec.bv_len);
+ rc = smb_send_kvec(server, &smb_msg, &sent);
+ if (rc < 0)
+ break;
+
+ total_len += sent;
+ }
}
uncork:
@@ -296,9 +335,9 @@ uncork:
kernel_setsockopt(ssocket, SOL_TCP, TCP_CORK,
(char *)&val, sizeof(val));
- if ((total_len > 0) && (total_len != smb_buf_length + 4)) {
+ if ((total_len > 0) && (total_len != send_length)) {
cifs_dbg(FYI, "partial send (wanted=%u sent=%zu): terminating session\n",
- smb_buf_length + 4, total_len);
+ send_length, total_len);
/*
* If we have only sent part of an SMB then the next SMB could
* be taken as the remainder of this one. We need to kill the
@@ -323,7 +362,7 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst, int flags)
int rc;
if (!(flags & CIFS_TRANSFORM_REQ))
- return __smb_send_rqst(server, rqst);
+ return __smb_send_rqst(server, 1, rqst);
if (!server->ops->init_transform_rq ||
!server->ops->free_transform_rq) {
@@ -335,7 +374,7 @@ smb_send_rqst(struct TCP_Server_Info *server, struct smb_rqst *rqst, int flags)
if (rc)
return rc;
- rc = __smb_send_rqst(server, &cur_rqst);
+ rc = __smb_send_rqst(server, 1, &cur_rqst);
server->ops->free_transform_rq(&cur_rqst);
return rc;
}
@@ -353,7 +392,7 @@ smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer,
iov[1].iov_base = (char *)smb_buffer + 4;
iov[1].iov_len = smb_buf_length;
- return __smb_send_rqst(server, &rqst);
+ return __smb_send_rqst(server, 1, &rqst);
}
static int
@@ -718,7 +757,6 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
* to the same server. We may make this configurable later or
* use ses->maxReq.
*/
-
rc = wait_for_free_request(ses->server, timeout, optype);
if (rc)
return rc;
@@ -754,8 +792,8 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
#ifdef CONFIG_CIFS_SMB311
if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP))
- smb311_update_preauth_hash(ses, rqst->rq_iov+1,
- rqst->rq_nvec-1);
+ smb311_update_preauth_hash(ses, rqst->rq_iov,
+ rqst->rq_nvec);
#endif
if (timeout == CIFS_ASYNC_OP)
@@ -800,8 +838,8 @@ cifs_send_recv(const unsigned int xid, struct cifs_ses *ses,
#ifdef CONFIG_CIFS_SMB311
if ((ses->status == CifsNew) || (optype & CIFS_NEG_OP)) {
struct kvec iov = {
- .iov_base = buf,
- .iov_len = midQ->resp_buf_size
+ .iov_base = resp_iov->iov_base,
+ .iov_len = resp_iov->iov_len
};
smb311_update_preauth_hash(ses, &iov, 1);
}
@@ -832,8 +870,8 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
int rc;
if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
- new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1),
- GFP_KERNEL);
+ new_iov = kmalloc_array(n_vec + 1, sizeof(struct kvec),
+ GFP_KERNEL);
if (!new_iov) {
/* otherwise cifs_send_recv below sets resp_buf_type */
*resp_buf_type = CIFS_NO_BUFFER;
@@ -860,49 +898,6 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
return rc;
}
-/* Like SendReceive2 but iov[0] does not contain an rfc1002 header */
-int
-smb2_send_recv(const unsigned int xid, struct cifs_ses *ses,
- struct kvec *iov, int n_vec, int *resp_buf_type /* ret */,
- const int flags, struct kvec *resp_iov)
-{
- struct smb_rqst rqst;
- struct kvec s_iov[CIFS_MAX_IOV_SIZE], *new_iov;
- int rc;
- int i;
- __u32 count;
- __be32 rfc1002_marker;
-
- if (n_vec + 1 > CIFS_MAX_IOV_SIZE) {
- new_iov = kmalloc(sizeof(struct kvec) * (n_vec + 1),
- GFP_KERNEL);
- if (!new_iov)
- return -ENOMEM;
- } else
- new_iov = s_iov;
-
- /* 1st iov is an RFC1002 Session Message length */
- memcpy(new_iov + 1, iov, (sizeof(struct kvec) * n_vec));
-
- count = 0;
- for (i = 1; i < n_vec + 1; i++)
- count += new_iov[i].iov_len;
-
- rfc1002_marker = cpu_to_be32(count);
-
- new_iov[0].iov_base = &rfc1002_marker;
- new_iov[0].iov_len = 4;
-
- memset(&rqst, 0, sizeof(struct smb_rqst));
- rqst.rq_iov = new_iov;
- rqst.rq_nvec = n_vec + 1;
-
- rc = cifs_send_recv(xid, ses, &rqst, resp_buf_type, flags, resp_iov);
- if (n_vec + 1 > CIFS_MAX_IOV_SIZE)
- kfree(new_iov);
- return rc;
-}
-
int
SendReceive(const unsigned int xid, struct cifs_ses *ses,
struct smb_hdr *in_buf, struct smb_hdr *out_buf,
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index ca599df..f3d543d 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -105,11 +105,11 @@ void coda_vattr_to_iattr(struct inode *inode, struct coda_vattr *attr)
if (attr->va_size != -1)
inode->i_blocks = (attr->va_size + 511) >> 9;
if (attr->va_atime.tv_sec != -1)
- inode->i_atime = attr->va_atime;
+ inode->i_atime = timespec_to_timespec64(attr->va_atime);
if (attr->va_mtime.tv_sec != -1)
- inode->i_mtime = attr->va_mtime;
+ inode->i_mtime = timespec_to_timespec64(attr->va_mtime);
if (attr->va_ctime.tv_sec != -1)
- inode->i_ctime = attr->va_ctime;
+ inode->i_ctime = timespec_to_timespec64(attr->va_ctime);
}
@@ -175,13 +175,13 @@ void coda_iattr_to_vattr(struct iattr *iattr, struct coda_vattr *vattr)
vattr->va_size = iattr->ia_size;
}
if ( valid & ATTR_ATIME ) {
- vattr->va_atime = iattr->ia_atime;
+ vattr->va_atime = timespec64_to_timespec(iattr->ia_atime);
}
if ( valid & ATTR_MTIME ) {
- vattr->va_mtime = iattr->ia_mtime;
+ vattr->va_mtime = timespec64_to_timespec(iattr->ia_mtime);
}
if ( valid & ATTR_CTIME ) {
- vattr->va_ctime = iattr->ia_ctime;
+ vattr->va_ctime = timespec64_to_timespec(iattr->ia_ctime);
}
}
diff --git a/fs/configfs/inode.c b/fs/configfs/inode.c
index ad718e5..28ef9e5 100644
--- a/fs/configfs/inode.c
+++ b/fs/configfs/inode.c
@@ -90,14 +90,14 @@ int configfs_setattr(struct dentry * dentry, struct iattr * iattr)
if (ia_valid & ATTR_GID)
sd_iattr->ia_gid = iattr->ia_gid;
if (ia_valid & ATTR_ATIME)
- sd_iattr->ia_atime = timespec_trunc(iattr->ia_atime,
- inode->i_sb->s_time_gran);
+ sd_iattr->ia_atime = timespec64_trunc(iattr->ia_atime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MTIME)
- sd_iattr->ia_mtime = timespec_trunc(iattr->ia_mtime,
- inode->i_sb->s_time_gran);
+ sd_iattr->ia_mtime = timespec64_trunc(iattr->ia_mtime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_CTIME)
- sd_iattr->ia_ctime = timespec_trunc(iattr->ia_ctime,
- inode->i_sb->s_time_gran);
+ sd_iattr->ia_ctime = timespec64_trunc(iattr->ia_ctime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MODE) {
umode_t mode = iattr->ia_mode;
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c
index c4fb9ad..f408994 100644
--- a/fs/cramfs/inode.c
+++ b/fs/cramfs/inode.c
@@ -90,7 +90,7 @@ static struct inode *get_cramfs_inode(struct super_block *sb,
const struct cramfs_inode *cramfs_inode, unsigned int offset)
{
struct inode *inode;
- static struct timespec zerotime;
+ static struct timespec64 zerotime;
inode = iget_locked(sb, cramino(cramfs_inode, offset));
if (!inode)
diff --git a/fs/crypto/bio.c b/fs/crypto/bio.c
index 0d5e6a5..0959044 100644
--- a/fs/crypto/bio.c
+++ b/fs/crypto/bio.c
@@ -26,15 +26,8 @@
#include <linux/namei.h>
#include "fscrypt_private.h"
-/*
- * Call fscrypt_decrypt_page on every single page, reusing the encryption
- * context.
- */
-static void completion_pages(struct work_struct *work)
+static void __fscrypt_decrypt_bio(struct bio *bio, bool done)
{
- struct fscrypt_ctx *ctx =
- container_of(work, struct fscrypt_ctx, r.work);
- struct bio *bio = ctx->r.bio;
struct bio_vec *bv;
int i;
@@ -46,22 +39,38 @@ static void completion_pages(struct work_struct *work)
if (ret) {
WARN_ON_ONCE(1);
SetPageError(page);
- } else {
+ } else if (done) {
SetPageUptodate(page);
}
- unlock_page(page);
+ if (done)
+ unlock_page(page);
}
+}
+
+void fscrypt_decrypt_bio(struct bio *bio)
+{
+ __fscrypt_decrypt_bio(bio, false);
+}
+EXPORT_SYMBOL(fscrypt_decrypt_bio);
+
+static void completion_pages(struct work_struct *work)
+{
+ struct fscrypt_ctx *ctx =
+ container_of(work, struct fscrypt_ctx, r.work);
+ struct bio *bio = ctx->r.bio;
+
+ __fscrypt_decrypt_bio(bio, true);
fscrypt_release_ctx(ctx);
bio_put(bio);
}
-void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *ctx, struct bio *bio)
+void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx, struct bio *bio)
{
INIT_WORK(&ctx->r.work, completion_pages);
ctx->r.bio = bio;
- queue_work(fscrypt_read_workqueue, &ctx->r.work);
+ fscrypt_enqueue_decrypt_work(&ctx->r.work);
}
-EXPORT_SYMBOL(fscrypt_decrypt_bio_pages);
+EXPORT_SYMBOL(fscrypt_enqueue_decrypt_bio);
void fscrypt_pullback_bio_page(struct page **page, bool restore)
{
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index 243a269..0f46cf5 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -45,12 +45,18 @@ static mempool_t *fscrypt_bounce_page_pool = NULL;
static LIST_HEAD(fscrypt_free_ctxs);
static DEFINE_SPINLOCK(fscrypt_ctx_lock);
-struct workqueue_struct *fscrypt_read_workqueue;
+static struct workqueue_struct *fscrypt_read_workqueue;
static DEFINE_MUTEX(fscrypt_init_mutex);
static struct kmem_cache *fscrypt_ctx_cachep;
struct kmem_cache *fscrypt_info_cachep;
+void fscrypt_enqueue_decrypt_work(struct work_struct *work)
+{
+ queue_work(fscrypt_read_workqueue, work);
+}
+EXPORT_SYMBOL(fscrypt_enqueue_decrypt_work);
+
/**
* fscrypt_release_ctx() - Releases an encryption context
* @ctx: The encryption context to release.
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 3756239..39c20ef 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -93,7 +93,6 @@ static inline bool fscrypt_valid_enc_modes(u32 contents_mode,
/* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep;
extern int fscrypt_initialize(unsigned int cop_flags);
-extern struct workqueue_struct *fscrypt_read_workqueue;
extern int fscrypt_do_page_crypto(const struct inode *inode,
fscrypt_direction_t rw, u64 lblk_num,
struct page *src_page,
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index a913b12..13b0135 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -512,9 +512,7 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
if (unlikely(!inode))
return failed_creating(dentry);
- if (!parent)
- parent = debugfs_mount->mnt_root;
- inode->i_mode = S_IFDIR | ((d_inode(parent)->i_mode & 0770));
+ inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
inode->i_op = &simple_dir_inode_operations;
inode->i_fop = &simple_dir_operations;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 78a7c85..5ba94be 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -517,7 +517,7 @@ static int new_lockspace(const char *name, const char *cluster,
size = dlm_config.ci_rsbtbl_size;
ls->ls_rsbtbl_size = size;
- ls->ls_rsbtbl = vmalloc(sizeof(struct dlm_rsbtable) * size);
+ ls->ls_rsbtbl = vmalloc(array_size(size, sizeof(struct dlm_rsbtable)));
if (!ls->ls_rsbtbl)
goto out_lsfree;
for (i = 0; i < size; i++) {
diff --git a/fs/eventfd.c b/fs/eventfd.c
index 61c9514..ceb1031 100644
--- a/fs/eventfd.c
+++ b/fs/eventfd.c
@@ -156,11 +156,11 @@ static __poll_t eventfd_poll_mask(struct file *file, __poll_t eventmask)
count = READ_ONCE(ctx->count);
if (count > 0)
- events |= EPOLLIN;
+ events |= (EPOLLIN & eventmask);
if (count == ULLONG_MAX)
events |= EPOLLERR;
if (ULLONG_MAX - 1 > count)
- events |= EPOLLOUT;
+ events |= (EPOLLOUT & eventmask);
return events;
}
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 67db22f..ea4436f 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -922,13 +922,17 @@ static __poll_t ep_read_events_proc(struct eventpoll *ep, struct list_head *head
return 0;
}
-static __poll_t ep_eventpoll_poll(struct file *file, poll_table *wait)
+static struct wait_queue_head *ep_eventpoll_get_poll_head(struct file *file,
+ __poll_t eventmask)
{
struct eventpoll *ep = file->private_data;
- int depth = 0;
+ return &ep->poll_wait;
+}
- /* Insert inside our poll wait queue */
- poll_wait(file, &ep->poll_wait, wait);
+static __poll_t ep_eventpoll_poll_mask(struct file *file, __poll_t eventmask)
+{
+ struct eventpoll *ep = file->private_data;
+ int depth = 0;
/*
* Proceed to find out if wanted events are really available inside
@@ -968,7 +972,8 @@ static const struct file_operations eventpoll_fops = {
.show_fdinfo = ep_show_fdinfo,
#endif
.release = ep_eventpoll_release,
- .poll = ep_eventpoll_poll,
+ .get_poll_head = ep_eventpoll_get_poll_head,
+ .poll_mask = ep_eventpoll_poll_mask,
.llseek = noop_llseek,
};
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c
index 0ac6281..5f81fcd 100644
--- a/fs/exofs/inode.c
+++ b/fs/exofs/inode.c
@@ -110,8 +110,8 @@ static int pcol_try_alloc(struct page_collect *pcol)
pages = exofs_max_io_pages(&pcol->sbi->layout, pcol->expected_pages);
for (; pages; pages >>= 1) {
- pcol->pages = kmalloc(pages * sizeof(struct page *),
- GFP_KERNEL);
+ pcol->pages = kmalloc_array(pages, sizeof(struct page *),
+ GFP_KERNEL);
if (likely(pcol->pages)) {
pcol->alloc_pages = pages;
return 0;
diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c
index ddbf872..1b8b446 100644
--- a/fs/exofs/ore.c
+++ b/fs/exofs/ore.c
@@ -146,68 +146,82 @@ int _ore_get_io_state(struct ore_layout *layout,
struct ore_io_state **pios)
{
struct ore_io_state *ios;
- struct page **pages;
- struct osd_sg_entry *sgilist;
+ size_t size_ios, size_extra, size_total;
+ void *ios_extra;
+
+ /*
+ * The desired layout looks like this, with the extra_allocation
+ * items pointed at from fields within ios or per_dev:
+
struct __alloc_all_io_state {
struct ore_io_state ios;
struct ore_per_dev_state per_dev[numdevs];
union {
struct osd_sg_entry sglist[sgs_per_dev * numdevs];
struct page *pages[num_par_pages];
- };
- } *_aios;
-
- if (likely(sizeof(*_aios) <= PAGE_SIZE)) {
- _aios = kzalloc(sizeof(*_aios), GFP_KERNEL);
- if (unlikely(!_aios)) {
- ORE_DBGMSG("Failed kzalloc bytes=%zd\n",
- sizeof(*_aios));
+ } extra_allocation;
+ } whole_allocation;
+
+ */
+
+ /* This should never happen, so abort early if it ever does. */
+ if (sgs_per_dev && num_par_pages) {
+ ORE_DBGMSG("Tried to use both pages and sglist\n");
+ *pios = NULL;
+ return -EINVAL;
+ }
+
+ if (numdevs > (INT_MAX - sizeof(*ios)) /
+ sizeof(struct ore_per_dev_state))
+ return -ENOMEM;
+ size_ios = sizeof(*ios) + sizeof(struct ore_per_dev_state) * numdevs;
+
+ if (sgs_per_dev * numdevs > INT_MAX / sizeof(struct osd_sg_entry))
+ return -ENOMEM;
+ if (num_par_pages > INT_MAX / sizeof(struct page *))
+ return -ENOMEM;
+ size_extra = max(sizeof(struct osd_sg_entry) * (sgs_per_dev * numdevs),
+ sizeof(struct page *) * num_par_pages);
+
+ size_total = size_ios + size_extra;
+
+ if (likely(size_total <= PAGE_SIZE)) {
+ ios = kzalloc(size_total, GFP_KERNEL);
+ if (unlikely(!ios)) {
+ ORE_DBGMSG("Failed kzalloc bytes=%zd\n", size_total);
*pios = NULL;
return -ENOMEM;
}
- pages = num_par_pages ? _aios->pages : NULL;
- sgilist = sgs_per_dev ? _aios->sglist : NULL;
- ios = &_aios->ios;
+ ios_extra = (char *)ios + size_ios;
} else {
- struct __alloc_small_io_state {
- struct ore_io_state ios;
- struct ore_per_dev_state per_dev[numdevs];
- } *_aio_small;
- union __extra_part {
- struct osd_sg_entry sglist[sgs_per_dev * numdevs];
- struct page *pages[num_par_pages];
- } *extra_part;
-
- _aio_small = kzalloc(sizeof(*_aio_small), GFP_KERNEL);
- if (unlikely(!_aio_small)) {
+ ios = kzalloc(size_ios, GFP_KERNEL);
+ if (unlikely(!ios)) {
ORE_DBGMSG("Failed alloc first part bytes=%zd\n",
- sizeof(*_aio_small));
+ size_ios);
*pios = NULL;
return -ENOMEM;
}
- extra_part = kzalloc(sizeof(*extra_part), GFP_KERNEL);
- if (unlikely(!extra_part)) {
+ ios_extra = kzalloc(size_extra, GFP_KERNEL);
+ if (unlikely(!ios_extra)) {
ORE_DBGMSG("Failed alloc second part bytes=%zd\n",
- sizeof(*extra_part));
- kfree(_aio_small);
+ size_extra);
+ kfree(ios);
*pios = NULL;
return -ENOMEM;
}
- pages = num_par_pages ? extra_part->pages : NULL;
- sgilist = sgs_per_dev ? extra_part->sglist : NULL;
/* In this case the per_dev[0].sgilist holds the pointer to
* be freed
*/
- ios = &_aio_small->ios;
ios->extra_part_alloc = true;
}
- if (pages) {
- ios->parity_pages = pages;
+ if (num_par_pages) {
+ ios->parity_pages = ios_extra;
ios->max_par_pages = num_par_pages;
}
- if (sgilist) {
+ if (sgs_per_dev) {
+ struct osd_sg_entry *sgilist = ios_extra;
unsigned d;
for (d = 0; d < numdevs; ++d) {
diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c
index 27cbdb6..199590f 100644
--- a/fs/exofs/ore_raid.c
+++ b/fs/exofs/ore_raid.c
@@ -71,6 +71,11 @@ static int _sp2d_alloc(unsigned pages_in_unit, unsigned group_width,
{
struct __stripe_pages_2d *sp2d;
unsigned data_devs = group_width - parity;
+
+ /*
+ * Desired allocation layout is, though when larger than PAGE_SIZE,
+ * each struct __alloc_1p_arrays is separately allocated:
+
struct _alloc_all_bytes {
struct __alloc_stripe_pages_2d {
struct __stripe_pages_2d sp2d;
@@ -82,55 +87,85 @@ static int _sp2d_alloc(unsigned pages_in_unit, unsigned group_width,
char page_is_read[data_devs];
} __a1pa[pages_in_unit];
} *_aab;
+
struct __alloc_1p_arrays *__a1pa;
struct __alloc_1p_arrays *__a1pa_end;
- const unsigned sizeof__a1pa = sizeof(_aab->__a1pa[0]);
+
+ */
+
+ char *__a1pa;
+ char *__a1pa_end;
+
+ const size_t sizeof_stripe_pages_2d =
+ sizeof(struct __stripe_pages_2d) +
+ sizeof(struct __1_page_stripe) * pages_in_unit;
+ const size_t sizeof__a1pa =
+ ALIGN(sizeof(struct page *) * (2 * group_width) + data_devs,
+ sizeof(void *));
+ const size_t sizeof__a1pa_arrays = sizeof__a1pa * pages_in_unit;
+ const size_t alloc_total = sizeof_stripe_pages_2d +
+ sizeof__a1pa_arrays;
+
unsigned num_a1pa, alloc_size, i;
/* FIXME: check these numbers in ore_verify_layout */
- BUG_ON(sizeof(_aab->__asp2d) > PAGE_SIZE);
+ BUG_ON(sizeof_stripe_pages_2d > PAGE_SIZE);
BUG_ON(sizeof__a1pa > PAGE_SIZE);
- if (sizeof(*_aab) > PAGE_SIZE) {
- num_a1pa = (PAGE_SIZE - sizeof(_aab->__asp2d)) / sizeof__a1pa;
- alloc_size = sizeof(_aab->__asp2d) + sizeof__a1pa * num_a1pa;
+ /*
+ * If alloc_total would be larger than PAGE_SIZE, only allocate
+ * as many a1pa items as would fill the rest of the page, instead
+ * of the full pages_in_unit count.
+ */
+ if (alloc_total > PAGE_SIZE) {
+ num_a1pa = (PAGE_SIZE - sizeof_stripe_pages_2d) / sizeof__a1pa;
+ alloc_size = sizeof_stripe_pages_2d + sizeof__a1pa * num_a1pa;
} else {
num_a1pa = pages_in_unit;
- alloc_size = sizeof(*_aab);
+ alloc_size = alloc_total;
}
- _aab = kzalloc(alloc_size, GFP_KERNEL);
- if (unlikely(!_aab)) {
+ *psp2d = sp2d = kzalloc(alloc_size, GFP_KERNEL);
+ if (unlikely(!sp2d)) {
ORE_DBGMSG("!! Failed to alloc sp2d size=%d\n", alloc_size);
return -ENOMEM;
}
+ /* From here Just call _sp2d_free */
- sp2d = &_aab->__asp2d.sp2d;
- *psp2d = sp2d; /* From here Just call _sp2d_free */
-
- __a1pa = _aab->__a1pa;
- __a1pa_end = __a1pa + num_a1pa;
+ /* Find start of a1pa area. */
+ __a1pa = (char *)sp2d + sizeof_stripe_pages_2d;
+ /* Find end of the _allocated_ a1pa area. */
+ __a1pa_end = __a1pa + alloc_size;
+ /* Allocate additionally needed a1pa items in PAGE_SIZE chunks. */
for (i = 0; i < pages_in_unit; ++i) {
+ struct __1_page_stripe *stripe = &sp2d->_1p_stripes[i];
+
if (unlikely(__a1pa >= __a1pa_end)) {
num_a1pa = min_t(unsigned, PAGE_SIZE / sizeof__a1pa,
pages_in_unit - i);
+ alloc_size = sizeof__a1pa * num_a1pa;
- __a1pa = kcalloc(num_a1pa, sizeof__a1pa, GFP_KERNEL);
+ __a1pa = kzalloc(alloc_size, GFP_KERNEL);
if (unlikely(!__a1pa)) {
ORE_DBGMSG("!! Failed to _alloc_1p_arrays=%d\n",
num_a1pa);
return -ENOMEM;
}
- __a1pa_end = __a1pa + num_a1pa;
+ __a1pa_end = __a1pa + alloc_size;
/* First *pages is marked for kfree of the buffer */
- sp2d->_1p_stripes[i].alloc = true;
+ stripe->alloc = true;
}
- sp2d->_1p_stripes[i].pages = __a1pa->pages;
- sp2d->_1p_stripes[i].scribble = __a1pa->scribble ;
- sp2d->_1p_stripes[i].page_is_read = __a1pa->page_is_read;
- ++__a1pa;
+ /*
+ * Attach all _lp_stripes pointers to the allocation for
+ * it which was either part of the original PAGE_SIZE
+ * allocation or the subsequent allocation in this loop.
+ */
+ stripe->pages = (void *)__a1pa;
+ stripe->scribble = stripe->pages + group_width;
+ stripe->page_is_read = (char *)stripe->scribble + group_width;
+ __a1pa += sizeof__a1pa;
}
sp2d->parity = parity;
diff --git a/fs/exofs/super.c b/fs/exofs/super.c
index 719a315..41cf2fb 100644
--- a/fs/exofs/super.c
+++ b/fs/exofs/super.c
@@ -549,27 +549,26 @@ static int exofs_devs_2_odi(struct exofs_dt_device_info *dt_dev,
static int __alloc_dev_table(struct exofs_sb_info *sbi, unsigned numdevs,
struct exofs_dev **peds)
{
- struct __alloc_ore_devs_and_exofs_devs {
- /* Twice bigger table: See exofs_init_comps() and comment at
- * exofs_read_lookup_dev_table()
- */
- struct ore_dev *oreds[numdevs * 2 - 1];
- struct exofs_dev eds[numdevs];
- } *aoded;
+ /* Twice bigger table: See exofs_init_comps() and comment at
+ * exofs_read_lookup_dev_table()
+ */
+ const size_t numores = numdevs * 2 - 1;
struct exofs_dev *eds;
unsigned i;
- aoded = kzalloc(sizeof(*aoded), GFP_KERNEL);
- if (unlikely(!aoded)) {
+ sbi->oc.ods = kzalloc(numores * sizeof(struct ore_dev *) +
+ numdevs * sizeof(struct exofs_dev), GFP_KERNEL);
+ if (unlikely(!sbi->oc.ods)) {
EXOFS_ERR("ERROR: failed allocating Device array[%d]\n",
numdevs);
return -ENOMEM;
}
- sbi->oc.ods = aoded->oreds;
- *peds = eds = aoded->eds;
+ /* Start of allocated struct exofs_dev entries */
+ *peds = eds = (void *)sbi->oc.ods[numores];
+ /* Initialize pointers into struct exofs_dev */
for (i = 0; i < numdevs; ++i)
- aoded->oreds[i] = &eds[i].ored;
+ sbi->oc.ods[i] = &eds[i].ored;
return 0;
}
diff --git a/fs/ext2/ext2.h b/fs/ext2/ext2.h
index cc40802..00e759f 100644
--- a/fs/ext2/ext2.h
+++ b/fs/ext2/ext2.h
@@ -748,7 +748,6 @@ extern void ext2_free_blocks (struct inode *, unsigned long,
unsigned long);
extern unsigned long ext2_count_free_blocks (struct super_block *);
extern unsigned long ext2_count_dirs (struct super_block *);
-extern void ext2_check_blocks_bitmap (struct super_block *);
extern struct ext2_group_desc * ext2_get_group_desc(struct super_block * sb,
unsigned int block_group,
struct buffer_head ** bh);
@@ -771,7 +770,6 @@ extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page
extern struct inode * ext2_new_inode (struct inode *, umode_t, const struct qstr *);
extern void ext2_free_inode (struct inode *);
extern unsigned long ext2_count_free_inodes (struct super_block *);
-extern void ext2_check_inodes_bitmap (struct super_block *);
extern unsigned long ext2_count_free (struct buffer_head *, unsigned);
/* inode.c */
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index c09289a..8ff53f8 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -557,6 +557,9 @@ static int parse_options(char *options, struct super_block *sb,
set_opt (opts->s_mount_opt, NO_UID32);
break;
case Opt_nocheck:
+ ext2_msg(sb, KERN_WARNING,
+ "Option nocheck/check=none is deprecated and"
+ " will be removed in June 2020.");
clear_opt (opts->s_mount_opt, CHECK);
break;
case Opt_debug:
@@ -1082,7 +1085,9 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
/ EXT2_BLOCKS_PER_GROUP(sb)) + 1;
db_count = (sbi->s_groups_count + EXT2_DESC_PER_BLOCK(sb) - 1) /
EXT2_DESC_PER_BLOCK(sb);
- sbi->s_group_desc = kmalloc (db_count * sizeof (struct buffer_head *), GFP_KERNEL);
+ sbi->s_group_desc = kmalloc_array (db_count,
+ sizeof(struct buffer_head *),
+ GFP_KERNEL);
if (sbi->s_group_desc == NULL) {
ext2_msg(sb, KERN_ERR, "error: not enough memory");
goto failed_mount;
@@ -1333,9 +1338,6 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data)
new_opts.s_resgid = sbi->s_resgid;
spin_unlock(&sbi->s_lock);
- /*
- * Allow the "check" option to be passed as a remount option.
- */
if (!parse_options(data, sb, &new_opts))
return -EINVAL;
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index df95412..0b12785 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -817,12 +817,14 @@ static inline void ext4_decode_extra_time(struct timespec *time, __le32 extra)
time->tv_nsec = (le32_to_cpu(extra) & EXT4_NSEC_MASK) >> EXT4_EPOCH_BITS;
}
-#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
-do { \
- (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec); \
- if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
- (raw_inode)->xtime ## _extra = \
- ext4_encode_extra_time(&(inode)->xtime); \
+#define EXT4_INODE_SET_XTIME(xtime, inode, raw_inode) \
+do { \
+ (raw_inode)->xtime = cpu_to_le32((inode)->xtime.tv_sec); \
+ if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) {\
+ struct timespec ts = timespec64_to_timespec((inode)->xtime); \
+ (raw_inode)->xtime ## _extra = \
+ ext4_encode_extra_time(&ts); \
+ } \
} while (0)
#define EXT4_EINODE_SET_XTIME(xtime, einode, raw_inode) \
@@ -834,16 +836,20 @@ do { \
ext4_encode_extra_time(&(einode)->xtime); \
} while (0)
-#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \
-do { \
- (inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime); \
- if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) \
- ext4_decode_extra_time(&(inode)->xtime, \
- raw_inode->xtime ## _extra); \
- else \
- (inode)->xtime.tv_nsec = 0; \
+#define EXT4_INODE_GET_XTIME(xtime, inode, raw_inode) \
+do { \
+ (inode)->xtime.tv_sec = (signed)le32_to_cpu((raw_inode)->xtime); \
+ if (EXT4_FITS_IN_INODE(raw_inode, EXT4_I(inode), xtime ## _extra)) { \
+ struct timespec ts = timespec64_to_timespec((inode)->xtime); \
+ ext4_decode_extra_time(&ts, \
+ raw_inode->xtime ## _extra); \
+ (inode)->xtime = timespec_to_timespec64(ts); \
+ } \
+ else \
+ (inode)->xtime.tv_nsec = 0; \
} while (0)
+
#define EXT4_EINODE_GET_XTIME(xtime, einode, raw_inode) \
do { \
if (EXT4_FITS_IN_INODE(raw_inode, einode, xtime)) \
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index c969275..0057fe3 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -577,7 +577,7 @@ int ext4_ext_precache(struct inode *inode)
down_read(&ei->i_data_sem);
depth = ext_depth(inode);
- path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1),
+ path = kcalloc(depth + 1, sizeof(struct ext4_ext_path),
GFP_NOFS);
if (path == NULL) {
up_read(&ei->i_data_sem);
@@ -879,7 +879,7 @@ ext4_find_extent(struct inode *inode, ext4_lblk_t block,
}
if (!path) {
/* account possible depth increase */
- path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 2),
+ path = kcalloc(depth + 2, sizeof(struct ext4_ext_path),
GFP_NOFS);
if (unlikely(!path))
return ERR_PTR(-ENOMEM);
@@ -1063,7 +1063,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode,
* We need this to handle errors and free blocks
* upon them.
*/
- ablocks = kzalloc(sizeof(ext4_fsblk_t) * depth, GFP_NOFS);
+ ablocks = kcalloc(depth, sizeof(ext4_fsblk_t), GFP_NOFS);
if (!ablocks)
return -ENOMEM;
@@ -2921,7 +2921,7 @@ again:
path[k].p_block =
le16_to_cpu(path[k].p_hdr->eh_entries)+1;
} else {
- path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1),
+ path = kcalloc(depth + 1, sizeof(struct ext4_ext_path),
GFP_NOFS);
if (path == NULL) {
ext4_journal_stop(handle);
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 4d6e007..f525f90 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1072,8 +1072,8 @@ got:
inode->i_ino = ino + group * EXT4_INODES_PER_GROUP(sb);
/* This is the optimal IO size (for stat), not the fs block size */
inode->i_blocks = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime = ei->i_crtime =
- current_time(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ ei->i_crtime = timespec64_to_timespec(inode->i_mtime);
memset(ei->i_data, 0, sizeof(ei->i_data));
ei->i_dir_start_lookup = 0;
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 4a09063..2a4c25c 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3673,7 +3673,7 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
};
u8 new_file_type;
int retval;
- struct timespec ctime;
+ struct timespec64 ctime;
if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT) &&
!projid_eq(EXT4_I(new_dir)->i_projid,
diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c
index 9ffa6fa..19b87a8 100644
--- a/fs/ext4/readpage.c
+++ b/fs/ext4/readpage.c
@@ -77,7 +77,7 @@ static void mpage_end_io(struct bio *bio)
if (bio->bi_status) {
fscrypt_release_ctx(bio->bi_private);
} else {
- fscrypt_decrypt_bio_pages(bio->bi_private, bio);
+ fscrypt_enqueue_decrypt_bio(bio->bi_private, bio);
return;
}
}
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index d792b76..e5fb384 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -204,12 +204,14 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size)
goto out2;
flex_gd->count = flexbg_size;
- flex_gd->groups = kmalloc(sizeof(struct ext4_new_group_data) *
- flexbg_size, GFP_NOFS);
+ flex_gd->groups = kmalloc_array(flexbg_size,
+ sizeof(struct ext4_new_group_data),
+ GFP_NOFS);
if (flex_gd->groups == NULL)
goto out2;
- flex_gd->bg_flags = kmalloc(flexbg_size * sizeof(__u16), GFP_NOFS);
+ flex_gd->bg_flags = kmalloc_array(flexbg_size, sizeof(__u16),
+ GFP_NOFS);
if (flex_gd->bg_flags == NULL)
goto out1;
@@ -969,7 +971,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode,
int res, i;
int err;
- primary = kmalloc(reserved_gdb * sizeof(*primary), GFP_NOFS);
+ primary = kmalloc_array(reserved_gdb, sizeof(*primary), GFP_NOFS);
if (!primary)
return -ENOMEM;
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 00fe75a..0c4c220 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3993,9 +3993,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
goto failed_mount;
}
}
- sbi->s_group_desc = kvmalloc(db_count *
- sizeof(struct buffer_head *),
- GFP_KERNEL);
+ sbi->s_group_desc = kvmalloc_array(db_count,
+ sizeof(struct buffer_head *),
+ GFP_KERNEL);
if (sbi->s_group_desc == NULL) {
ext4_msg(sb, KERN_ERR, "not enough memory");
ret = -ENOMEM;
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index bf77946..9f1c96c 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -24,7 +24,7 @@
#include <trace/events/f2fs.h>
static struct kmem_cache *ino_entry_slab;
-struct kmem_cache *inode_entry_slab;
+struct kmem_cache *f2fs_inode_entry_slab;
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io)
{
@@ -36,7 +36,7 @@ void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io)
/*
* We guarantee no failure on the returned page.
*/
-struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
+struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
{
struct address_space *mapping = META_MAPPING(sbi);
struct page *page = NULL;
@@ -100,24 +100,27 @@ repeat:
* readonly and make sure do not write checkpoint with non-uptodate
* meta page.
*/
- if (unlikely(!PageUptodate(page)))
+ if (unlikely(!PageUptodate(page))) {
+ memset(page_address(page), 0, PAGE_SIZE);
f2fs_stop_checkpoint(sbi, false);
+ }
out:
return page;
}
-struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
+struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
{
return __get_meta_page(sbi, index, true);
}
/* for POR only */
-struct page *get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index)
+struct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index)
{
return __get_meta_page(sbi, index, false);
}
-bool is_valid_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr, int type)
+bool f2fs_is_valid_meta_blkaddr(struct f2fs_sb_info *sbi,
+ block_t blkaddr, int type)
{
switch (type) {
case META_NAT:
@@ -151,7 +154,7 @@ bool is_valid_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr, int type)
/*
* Readahead CP/NAT/SIT/SSA pages
*/
-int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
+int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
int type, bool sync)
{
struct page *page;
@@ -173,7 +176,7 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
blk_start_plug(&plug);
for (; nrpages-- > 0; blkno++) {
- if (!is_valid_blkaddr(sbi, blkno, type))
+ if (!f2fs_is_valid_meta_blkaddr(sbi, blkno, type))
goto out;
switch (type) {
@@ -217,7 +220,7 @@ out:
return blkno - start;
}
-void ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index)
+void f2fs_ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index)
{
struct page *page;
bool readahead = false;
@@ -228,7 +231,7 @@ void ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index)
f2fs_put_page(page, 0);
if (readahead)
- ra_meta_pages(sbi, index, BIO_MAX_PAGES, META_POR, true);
+ f2fs_ra_meta_pages(sbi, index, BIO_MAX_PAGES, META_POR, true);
}
static int __f2fs_write_meta_page(struct page *page,
@@ -249,7 +252,7 @@ static int __f2fs_write_meta_page(struct page *page,
if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0))
goto redirty_out;
- write_meta_page(sbi, page, io_type);
+ f2fs_do_write_meta_page(sbi, page, io_type);
dec_page_count(sbi, F2FS_DIRTY_META);
if (wbc->for_reclaim)
@@ -294,7 +297,7 @@ static int f2fs_write_meta_pages(struct address_space *mapping,
trace_f2fs_writepages(mapping->host, wbc, META);
diff = nr_pages_to_write(sbi, META, wbc);
- written = sync_meta_pages(sbi, META, wbc->nr_to_write, FS_META_IO);
+ written = f2fs_sync_meta_pages(sbi, META, wbc->nr_to_write, FS_META_IO);
mutex_unlock(&sbi->cp_mutex);
wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff);
return 0;
@@ -305,7 +308,7 @@ skip_write:
return 0;
}
-long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
+long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
long nr_to_write, enum iostat_type io_type)
{
struct address_space *mapping = META_MAPPING(sbi);
@@ -382,7 +385,7 @@ static int f2fs_set_meta_page_dirty(struct page *page)
if (!PageUptodate(page))
SetPageUptodate(page);
if (!PageDirty(page)) {
- f2fs_set_page_dirty_nobuffers(page);
+ __set_page_dirty_nobuffers(page);
inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META);
SetPagePrivate(page);
f2fs_trace_pid(page);
@@ -455,20 +458,20 @@ static void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
spin_unlock(&im->ino_lock);
}
-void add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
+void f2fs_add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
{
/* add new dirty ino entry into list */
__add_ino_entry(sbi, ino, 0, type);
}
-void remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
+void f2fs_remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
{
/* remove dirty ino entry from list */
__remove_ino_entry(sbi, ino, type);
}
/* mode should be APPEND_INO or UPDATE_INO */
-bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)
+bool f2fs_exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)
{
struct inode_management *im = &sbi->im[mode];
struct ino_entry *e;
@@ -479,7 +482,7 @@ bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)
return e ? true : false;
}
-void release_ino_entry(struct f2fs_sb_info *sbi, bool all)
+void f2fs_release_ino_entry(struct f2fs_sb_info *sbi, bool all)
{
struct ino_entry *e, *tmp;
int i;
@@ -498,13 +501,13 @@ void release_ino_entry(struct f2fs_sb_info *sbi, bool all)
}
}
-void set_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
+void f2fs_set_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
unsigned int devidx, int type)
{
__add_ino_entry(sbi, ino, devidx, type);
}
-bool is_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
+bool f2fs_is_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
unsigned int devidx, int type)
{
struct inode_management *im = &sbi->im[type];
@@ -519,7 +522,7 @@ bool is_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
return is_dirty;
}
-int acquire_orphan_inode(struct f2fs_sb_info *sbi)
+int f2fs_acquire_orphan_inode(struct f2fs_sb_info *sbi)
{
struct inode_management *im = &sbi->im[ORPHAN_INO];
int err = 0;
@@ -542,7 +545,7 @@ int acquire_orphan_inode(struct f2fs_sb_info *sbi)
return err;
}
-void release_orphan_inode(struct f2fs_sb_info *sbi)
+void f2fs_release_orphan_inode(struct f2fs_sb_info *sbi)
{
struct inode_management *im = &sbi->im[ORPHAN_INO];
@@ -552,14 +555,14 @@ void release_orphan_inode(struct f2fs_sb_info *sbi)
spin_unlock(&im->ino_lock);
}
-void add_orphan_inode(struct inode *inode)
+void f2fs_add_orphan_inode(struct inode *inode)
{
/* add new orphan ino entry into list */
__add_ino_entry(F2FS_I_SB(inode), inode->i_ino, 0, ORPHAN_INO);
- update_inode_page(inode);
+ f2fs_update_inode_page(inode);
}
-void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
+void f2fs_remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
{
/* remove orphan entry from orphan list */
__remove_ino_entry(sbi, ino, ORPHAN_INO);
@@ -569,7 +572,7 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
{
struct inode *inode;
struct node_info ni;
- int err = acquire_orphan_inode(sbi);
+ int err = f2fs_acquire_orphan_inode(sbi);
if (err)
goto err_out;
@@ -587,16 +590,17 @@ static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
}
err = dquot_initialize(inode);
- if (err)
+ if (err) {
+ iput(inode);
goto err_out;
+ }
- dquot_initialize(inode);
clear_nlink(inode);
/* truncate all the data during iput */
iput(inode);
- get_node_info(sbi, ino, &ni);
+ f2fs_get_node_info(sbi, ino, &ni);
/* ENOMEM was fully retried in f2fs_evict_inode. */
if (ni.blk_addr != NULL_ADDR) {
@@ -614,7 +618,7 @@ err_out:
return err;
}
-int recover_orphan_inodes(struct f2fs_sb_info *sbi)
+int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi)
{
block_t start_blk, orphan_blocks, i, j;
unsigned int s_flags = sbi->sb->s_flags;
@@ -642,10 +646,10 @@ int recover_orphan_inodes(struct f2fs_sb_info *sbi)
start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi);
orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi);
- ra_meta_pages(sbi, start_blk, orphan_blocks, META_CP, true);
+ f2fs_ra_meta_pages(sbi, start_blk, orphan_blocks, META_CP, true);
for (i = 0; i < orphan_blocks; i++) {
- struct page *page = get_meta_page(sbi, start_blk + i);
+ struct page *page = f2fs_get_meta_page(sbi, start_blk + i);
struct f2fs_orphan_block *orphan_blk;
orphan_blk = (struct f2fs_orphan_block *)page_address(page);
@@ -695,7 +699,7 @@ static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
/* loop for each orphan inode entry and write them in Jornal block */
list_for_each_entry(orphan, head, list) {
if (!page) {
- page = grab_meta_page(sbi, start_blk++);
+ page = f2fs_grab_meta_page(sbi, start_blk++);
orphan_blk =
(struct f2fs_orphan_block *)page_address(page);
memset(orphan_blk, 0, sizeof(*orphan_blk));
@@ -737,7 +741,7 @@ static int get_checkpoint_version(struct f2fs_sb_info *sbi, block_t cp_addr,
size_t crc_offset = 0;
__u32 crc = 0;
- *cp_page = get_meta_page(sbi, cp_addr);
+ *cp_page = f2fs_get_meta_page(sbi, cp_addr);
*cp_block = (struct f2fs_checkpoint *)page_address(*cp_page);
crc_offset = le32_to_cpu((*cp_block)->checksum_offset);
@@ -790,7 +794,7 @@ invalid_cp1:
return NULL;
}
-int get_valid_checkpoint(struct f2fs_sb_info *sbi)
+int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi)
{
struct f2fs_checkpoint *cp_block;
struct f2fs_super_block *fsb = sbi->raw_super;
@@ -802,7 +806,8 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
block_t cp_blk_no;
int i;
- sbi->ckpt = f2fs_kzalloc(sbi, cp_blks * blk_size, GFP_KERNEL);
+ sbi->ckpt = f2fs_kzalloc(sbi, array_size(blk_size, cp_blks),
+ GFP_KERNEL);
if (!sbi->ckpt)
return -ENOMEM;
/*
@@ -834,7 +839,7 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
memcpy(sbi->ckpt, cp_block, blk_size);
/* Sanity checking of checkpoint */
- if (sanity_check_ckpt(sbi))
+ if (f2fs_sanity_check_ckpt(sbi))
goto free_fail_no_cp;
if (cur_page == cp1)
@@ -853,7 +858,7 @@ int get_valid_checkpoint(struct f2fs_sb_info *sbi)
void *sit_bitmap_ptr;
unsigned char *ckpt = (unsigned char *)sbi->ckpt;
- cur_page = get_meta_page(sbi, cp_blk_no + i);
+ cur_page = f2fs_get_meta_page(sbi, cp_blk_no + i);
sit_bitmap_ptr = page_address(cur_page);
memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
f2fs_put_page(cur_page, 1);
@@ -898,7 +903,7 @@ static void __remove_dirty_inode(struct inode *inode, enum inode_type type)
stat_dec_dirty_inode(F2FS_I_SB(inode), type);
}
-void update_dirty_page(struct inode *inode, struct page *page)
+void f2fs_update_dirty_page(struct inode *inode, struct page *page)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE;
@@ -917,7 +922,7 @@ void update_dirty_page(struct inode *inode, struct page *page)
f2fs_trace_pid(page);
}
-void remove_dirty_inode(struct inode *inode)
+void f2fs_remove_dirty_inode(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE;
@@ -934,7 +939,7 @@ void remove_dirty_inode(struct inode *inode)
spin_unlock(&sbi->inode_lock[type]);
}
-int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
+int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
{
struct list_head *head;
struct inode *inode;
@@ -1017,7 +1022,7 @@ int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi)
/* it's on eviction */
if (is_inode_flag_set(inode, FI_DIRTY_INODE))
- update_inode_page(inode);
+ f2fs_update_inode_page(inode);
iput(inode);
}
}
@@ -1057,7 +1062,7 @@ retry_flush_dents:
/* write all the dirty dentry pages */
if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
f2fs_unlock_all(sbi);
- err = sync_dirty_inodes(sbi, DIR_INODE);
+ err = f2fs_sync_dirty_inodes(sbi, DIR_INODE);
if (err)
goto out;
cond_resched();
@@ -1085,7 +1090,9 @@ retry_flush_nodes:
if (get_pages(sbi, F2FS_DIRTY_NODES)) {
up_write(&sbi->node_write);
- err = sync_node_pages(sbi, &wbc, false, FS_CP_NODE_IO);
+ atomic_inc(&sbi->wb_sync_req[NODE]);
+ err = f2fs_sync_node_pages(sbi, &wbc, false, FS_CP_NODE_IO);
+ atomic_dec(&sbi->wb_sync_req[NODE]);
if (err) {
up_write(&sbi->node_change);
f2fs_unlock_all(sbi);
@@ -1179,10 +1186,10 @@ static void commit_checkpoint(struct f2fs_sb_info *sbi,
/*
* pagevec_lookup_tag and lock_page again will take
- * some extra time. Therefore, update_meta_pages and
- * sync_meta_pages are combined in this function.
+ * some extra time. Therefore, f2fs_update_meta_pages and
+ * f2fs_sync_meta_pages are combined in this function.
*/
- struct page *page = grab_meta_page(sbi, blk_addr);
+ struct page *page = f2fs_grab_meta_page(sbi, blk_addr);
int err;
memcpy(page_address(page), src, PAGE_SIZE);
@@ -1220,7 +1227,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
/* Flush all the NAT/SIT pages */
while (get_pages(sbi, F2FS_DIRTY_META)) {
- sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
+ f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
if (unlikely(f2fs_cp_error(sbi)))
return -EIO;
}
@@ -1229,7 +1236,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
* modify checkpoint
* version number is already updated
*/
- ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi));
+ ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi, true));
ckpt->free_segment_count = cpu_to_le32(free_segments(sbi));
for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) {
ckpt->cur_node_segno[i] =
@@ -1249,7 +1256,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
}
/* 2 cp + n data seg summary + orphan inode blocks */
- data_sum_blocks = npages_for_summary_flush(sbi, false);
+ data_sum_blocks = f2fs_npages_for_summary_flush(sbi, false);
spin_lock_irqsave(&sbi->cp_lock, flags);
if (data_sum_blocks < NR_CURSEG_DATA_TYPE)
__set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
@@ -1294,22 +1301,23 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
blk = start_blk + sbi->blocks_per_seg - nm_i->nat_bits_blocks;
for (i = 0; i < nm_i->nat_bits_blocks; i++)
- update_meta_page(sbi, nm_i->nat_bits +
+ f2fs_update_meta_page(sbi, nm_i->nat_bits +
(i << F2FS_BLKSIZE_BITS), blk + i);
/* Flush all the NAT BITS pages */
while (get_pages(sbi, F2FS_DIRTY_META)) {
- sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
+ f2fs_sync_meta_pages(sbi, META, LONG_MAX,
+ FS_CP_META_IO);
if (unlikely(f2fs_cp_error(sbi)))
return -EIO;
}
}
/* write out checkpoint buffer at block 0 */
- update_meta_page(sbi, ckpt, start_blk++);
+ f2fs_update_meta_page(sbi, ckpt, start_blk++);
for (i = 1; i < 1 + cp_payload_blks; i++)
- update_meta_page(sbi, (char *)ckpt + i * F2FS_BLKSIZE,
+ f2fs_update_meta_page(sbi, (char *)ckpt + i * F2FS_BLKSIZE,
start_blk++);
if (orphan_num) {
@@ -1317,7 +1325,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
start_blk += orphan_blocks;
}
- write_data_summaries(sbi, start_blk);
+ f2fs_write_data_summaries(sbi, start_blk);
start_blk += data_sum_blocks;
/* Record write statistics in the hot node summary */
@@ -1328,7 +1336,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
seg_i->journal->info.kbytes_written = cpu_to_le64(kbytes_written);
if (__remain_node_summaries(cpc->reason)) {
- write_node_summaries(sbi, start_blk);
+ f2fs_write_node_summaries(sbi, start_blk);
start_blk += NR_CURSEG_NODE_TYPE;
}
@@ -1337,7 +1345,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
percpu_counter_set(&sbi->alloc_valid_block_count, 0);
/* Here, we have one bio having CP pack except cp pack 2 page */
- sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
+ f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_CP_META_IO);
/* wait for previous submitted meta pages writeback */
wait_on_all_pages_writeback(sbi);
@@ -1354,7 +1362,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
commit_checkpoint(sbi, ckpt, start_blk);
wait_on_all_pages_writeback(sbi);
- release_ino_entry(sbi, false);
+ f2fs_release_ino_entry(sbi, false);
if (unlikely(f2fs_cp_error(sbi)))
return -EIO;
@@ -1379,7 +1387,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
/*
* We guarantee that this checkpoint procedure will not fail.
*/
-int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
{
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
unsigned long long ckpt_ver;
@@ -1412,7 +1420,7 @@ int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
/* this is the case of multiple fstrims without any changes */
if (cpc->reason & CP_DISCARD) {
- if (!exist_trim_candidates(sbi, cpc)) {
+ if (!f2fs_exist_trim_candidates(sbi, cpc)) {
unblock_operations(sbi);
goto out;
}
@@ -1420,8 +1428,8 @@ int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
if (NM_I(sbi)->dirty_nat_cnt == 0 &&
SIT_I(sbi)->dirty_sentries == 0 &&
prefree_segments(sbi) == 0) {
- flush_sit_entries(sbi, cpc);
- clear_prefree_segments(sbi, cpc);
+ f2fs_flush_sit_entries(sbi, cpc);
+ f2fs_clear_prefree_segments(sbi, cpc);
unblock_operations(sbi);
goto out;
}
@@ -1436,15 +1444,15 @@ int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver);
/* write cached NAT/SIT entries to NAT/SIT area */
- flush_nat_entries(sbi, cpc);
- flush_sit_entries(sbi, cpc);
+ f2fs_flush_nat_entries(sbi, cpc);
+ f2fs_flush_sit_entries(sbi, cpc);
/* unlock all the fs_lock[] in do_checkpoint() */
err = do_checkpoint(sbi, cpc);
if (err)
- release_discard_addrs(sbi);
+ f2fs_release_discard_addrs(sbi);
else
- clear_prefree_segments(sbi, cpc);
+ f2fs_clear_prefree_segments(sbi, cpc);
unblock_operations(sbi);
stat_inc_cp_count(sbi->stat_info);
@@ -1461,7 +1469,7 @@ out:
return err;
}
-void init_ino_entry_info(struct f2fs_sb_info *sbi)
+void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi)
{
int i;
@@ -1479,23 +1487,23 @@ void init_ino_entry_info(struct f2fs_sb_info *sbi)
F2FS_ORPHANS_PER_BLOCK;
}
-int __init create_checkpoint_caches(void)
+int __init f2fs_create_checkpoint_caches(void)
{
ino_entry_slab = f2fs_kmem_cache_create("f2fs_ino_entry",
sizeof(struct ino_entry));
if (!ino_entry_slab)
return -ENOMEM;
- inode_entry_slab = f2fs_kmem_cache_create("f2fs_inode_entry",
+ f2fs_inode_entry_slab = f2fs_kmem_cache_create("f2fs_inode_entry",
sizeof(struct inode_entry));
- if (!inode_entry_slab) {
+ if (!f2fs_inode_entry_slab) {
kmem_cache_destroy(ino_entry_slab);
return -ENOMEM;
}
return 0;
}
-void destroy_checkpoint_caches(void)
+void f2fs_destroy_checkpoint_caches(void)
{
kmem_cache_destroy(ino_entry_slab);
- kmem_cache_destroy(inode_entry_slab);
+ kmem_cache_destroy(f2fs_inode_entry_slab);
}
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 02237d4..8f931d6 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -19,8 +19,6 @@
#include <linux/bio.h>
#include <linux/prefetch.h>
#include <linux/uio.h>
-#include <linux/mm.h>
-#include <linux/memcontrol.h>
#include <linux/cleancache.h>
#include <linux/sched/signal.h>
@@ -30,6 +28,11 @@
#include "trace.h"
#include <trace/events/f2fs.h>
+#define NUM_PREALLOC_POST_READ_CTXS 128
+
+static struct kmem_cache *bio_post_read_ctx_cache;
+static mempool_t *bio_post_read_ctx_pool;
+
static bool __is_cp_guaranteed(struct page *page)
{
struct address_space *mapping = page->mapping;
@@ -45,16 +48,84 @@ static bool __is_cp_guaranteed(struct page *page)
if (inode->i_ino == F2FS_META_INO(sbi) ||
inode->i_ino == F2FS_NODE_INO(sbi) ||
S_ISDIR(inode->i_mode) ||
+ (S_ISREG(inode->i_mode) &&
+ is_inode_flag_set(inode, FI_ATOMIC_FILE)) ||
is_cold_data(page))
return true;
return false;
}
-static void f2fs_read_end_io(struct bio *bio)
+/* postprocessing steps for read bios */
+enum bio_post_read_step {
+ STEP_INITIAL = 0,
+ STEP_DECRYPT,
+};
+
+struct bio_post_read_ctx {
+ struct bio *bio;
+ struct work_struct work;
+ unsigned int cur_step;
+ unsigned int enabled_steps;
+};
+
+static void __read_end_io(struct bio *bio)
{
- struct bio_vec *bvec;
+ struct page *page;
+ struct bio_vec *bv;
int i;
+ bio_for_each_segment_all(bv, bio, i) {
+ page = bv->bv_page;
+
+ /* PG_error was set if any post_read step failed */
+ if (bio->bi_status || PageError(page)) {
+ ClearPageUptodate(page);
+ SetPageError(page);
+ } else {
+ SetPageUptodate(page);
+ }
+ unlock_page(page);
+ }
+ if (bio->bi_private)
+ mempool_free(bio->bi_private, bio_post_read_ctx_pool);
+ bio_put(bio);
+}
+
+static void bio_post_read_processing(struct bio_post_read_ctx *ctx);
+
+static void decrypt_work(struct work_struct *work)
+{
+ struct bio_post_read_ctx *ctx =
+ container_of(work, struct bio_post_read_ctx, work);
+
+ fscrypt_decrypt_bio(ctx->bio);
+
+ bio_post_read_processing(ctx);
+}
+
+static void bio_post_read_processing(struct bio_post_read_ctx *ctx)
+{
+ switch (++ctx->cur_step) {
+ case STEP_DECRYPT:
+ if (ctx->enabled_steps & (1 << STEP_DECRYPT)) {
+ INIT_WORK(&ctx->work, decrypt_work);
+ fscrypt_enqueue_decrypt_work(&ctx->work);
+ return;
+ }
+ ctx->cur_step++;
+ /* fall-through */
+ default:
+ __read_end_io(ctx->bio);
+ }
+}
+
+static bool f2fs_bio_post_read_required(struct bio *bio)
+{
+ return bio->bi_private && !bio->bi_status;
+}
+
+static void f2fs_read_end_io(struct bio *bio)
+{
#ifdef CONFIG_F2FS_FAULT_INJECTION
if (time_to_inject(F2FS_P_SB(bio_first_page_all(bio)), FAULT_IO)) {
f2fs_show_injection_info(FAULT_IO);
@@ -62,28 +133,15 @@ static void f2fs_read_end_io(struct bio *bio)
}
#endif
- if (f2fs_bio_encrypted(bio)) {
- if (bio->bi_status) {
- fscrypt_release_ctx(bio->bi_private);
- } else {
- fscrypt_decrypt_bio_pages(bio->bi_private, bio);
- return;
- }
- }
-
- bio_for_each_segment_all(bvec, bio, i) {
- struct page *page = bvec->bv_page;
+ if (f2fs_bio_post_read_required(bio)) {
+ struct bio_post_read_ctx *ctx = bio->bi_private;
- if (!bio->bi_status) {
- if (!PageUptodate(page))
- SetPageUptodate(page);
- } else {
- ClearPageUptodate(page);
- SetPageError(page);
- }
- unlock_page(page);
+ ctx->cur_step = STEP_INITIAL;
+ bio_post_read_processing(ctx);
+ return;
}
- bio_put(bio);
+
+ __read_end_io(bio);
}
static void f2fs_write_end_io(struct bio *bio)
@@ -189,7 +247,7 @@ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr,
} else {
bio->bi_end_io = f2fs_write_end_io;
bio->bi_private = sbi;
- bio->bi_write_hint = io_type_to_rw_hint(sbi, type, temp);
+ bio->bi_write_hint = f2fs_io_type_to_rw_hint(sbi, type, temp);
}
if (wbc)
wbc_init_bio(wbc, bio);
@@ -404,13 +462,12 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
return 0;
}
-int f2fs_submit_page_write(struct f2fs_io_info *fio)
+void f2fs_submit_page_write(struct f2fs_io_info *fio)
{
struct f2fs_sb_info *sbi = fio->sbi;
enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
struct page *bio_page;
- int err = 0;
f2fs_bug_on(sbi, is_read_io(fio->op));
@@ -420,7 +477,7 @@ next:
spin_lock(&io->io_lock);
if (list_empty(&io->io_list)) {
spin_unlock(&io->io_lock);
- goto out_fail;
+ goto out;
}
fio = list_first_entry(&io->io_list,
struct f2fs_io_info, list);
@@ -428,7 +485,7 @@ next:
spin_unlock(&io->io_lock);
}
- if (fio->old_blkaddr != NEW_ADDR)
+ if (is_valid_blkaddr(fio->old_blkaddr))
verify_block_addr(fio, fio->old_blkaddr);
verify_block_addr(fio, fio->new_blkaddr);
@@ -447,9 +504,9 @@ alloc_new:
if (io->bio == NULL) {
if ((fio->type == DATA || fio->type == NODE) &&
fio->new_blkaddr & F2FS_IO_SIZE_MASK(sbi)) {
- err = -EAGAIN;
dec_page_count(sbi, WB_DATA_TYPE(bio_page));
- goto out_fail;
+ fio->retry = true;
+ goto skip;
}
io->bio = __bio_alloc(sbi, fio->new_blkaddr, fio->io_wbc,
BIO_MAX_PAGES, false,
@@ -469,41 +526,44 @@ alloc_new:
f2fs_trace_ios(fio, 0);
trace_f2fs_submit_page_write(fio->page, fio);
-
+skip:
if (fio->in_list)
goto next;
-out_fail:
+out:
up_write(&io->io_rwsem);
- return err;
}
static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr,
unsigned nr_pages)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
- struct fscrypt_ctx *ctx = NULL;
struct bio *bio;
-
- if (f2fs_encrypted_file(inode)) {
- ctx = fscrypt_get_ctx(inode, GFP_NOFS);
- if (IS_ERR(ctx))
- return ERR_CAST(ctx);
-
- /* wait the page to be moved by cleaning */
- f2fs_wait_on_block_writeback(sbi, blkaddr);
- }
+ struct bio_post_read_ctx *ctx;
+ unsigned int post_read_steps = 0;
bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), false);
- if (!bio) {
- if (ctx)
- fscrypt_release_ctx(ctx);
+ if (!bio)
return ERR_PTR(-ENOMEM);
- }
f2fs_target_device(sbi, blkaddr, bio);
bio->bi_end_io = f2fs_read_end_io;
- bio->bi_private = ctx;
bio_set_op_attrs(bio, REQ_OP_READ, 0);
+ if (f2fs_encrypted_file(inode))
+ post_read_steps |= 1 << STEP_DECRYPT;
+ if (post_read_steps) {
+ ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
+ if (!ctx) {
+ bio_put(bio);
+ return ERR_PTR(-ENOMEM);
+ }
+ ctx->bio = bio;
+ ctx->enabled_steps = post_read_steps;
+ bio->bi_private = ctx;
+
+ /* wait the page to be moved by cleaning */
+ f2fs_wait_on_block_writeback(sbi, blkaddr);
+ }
+
return bio;
}
@@ -544,7 +604,7 @@ static void __set_data_blkaddr(struct dnode_of_data *dn)
* ->node_page
* update block addresses in the node page
*/
-void set_data_blkaddr(struct dnode_of_data *dn)
+void f2fs_set_data_blkaddr(struct dnode_of_data *dn)
{
f2fs_wait_on_page_writeback(dn->node_page, NODE, true);
__set_data_blkaddr(dn);
@@ -555,12 +615,12 @@ void set_data_blkaddr(struct dnode_of_data *dn)
void f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr)
{
dn->data_blkaddr = blkaddr;
- set_data_blkaddr(dn);
+ f2fs_set_data_blkaddr(dn);
f2fs_update_extent_cache(dn);
}
/* dn->ofs_in_node will be returned with up-to-date last block pointer */
-int reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count)
+int f2fs_reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
int err;
@@ -594,12 +654,12 @@ int reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count)
}
/* Should keep dn->ofs_in_node unchanged */
-int reserve_new_block(struct dnode_of_data *dn)
+int f2fs_reserve_new_block(struct dnode_of_data *dn)
{
unsigned int ofs_in_node = dn->ofs_in_node;
int ret;
- ret = reserve_new_blocks(dn, 1);
+ ret = f2fs_reserve_new_blocks(dn, 1);
dn->ofs_in_node = ofs_in_node;
return ret;
}
@@ -609,12 +669,12 @@ int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index)
bool need_put = dn->inode_page ? false : true;
int err;
- err = get_dnode_of_data(dn, index, ALLOC_NODE);
+ err = f2fs_get_dnode_of_data(dn, index, ALLOC_NODE);
if (err)
return err;
if (dn->data_blkaddr == NULL_ADDR)
- err = reserve_new_block(dn);
+ err = f2fs_reserve_new_block(dn);
if (err || need_put)
f2fs_put_dnode(dn);
return err;
@@ -633,7 +693,7 @@ int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index)
return f2fs_reserve_block(dn, index);
}
-struct page *get_read_data_page(struct inode *inode, pgoff_t index,
+struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
int op_flags, bool for_write)
{
struct address_space *mapping = inode->i_mapping;
@@ -652,7 +712,7 @@ struct page *get_read_data_page(struct inode *inode, pgoff_t index,
}
set_new_dnode(&dn, inode, NULL, NULL, 0);
- err = get_dnode_of_data(&dn, index, LOOKUP_NODE);
+ err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE);
if (err)
goto put_err;
f2fs_put_dnode(&dn);
@@ -671,7 +731,8 @@ got_it:
* A new dentry page is allocated but not able to be written, since its
* new inode page couldn't be allocated due to -ENOSPC.
* In such the case, its blkaddr can be remained as NEW_ADDR.
- * see, f2fs_add_link -> get_new_data_page -> init_inode_metadata.
+ * see, f2fs_add_link -> f2fs_get_new_data_page ->
+ * f2fs_init_inode_metadata.
*/
if (dn.data_blkaddr == NEW_ADDR) {
zero_user_segment(page, 0, PAGE_SIZE);
@@ -691,7 +752,7 @@ put_err:
return ERR_PTR(err);
}
-struct page *find_data_page(struct inode *inode, pgoff_t index)
+struct page *f2fs_find_data_page(struct inode *inode, pgoff_t index)
{
struct address_space *mapping = inode->i_mapping;
struct page *page;
@@ -701,7 +762,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index)
return page;
f2fs_put_page(page, 0);
- page = get_read_data_page(inode, index, 0, false);
+ page = f2fs_get_read_data_page(inode, index, 0, false);
if (IS_ERR(page))
return page;
@@ -721,13 +782,13 @@ struct page *find_data_page(struct inode *inode, pgoff_t index)
* Because, the callers, functions in dir.c and GC, should be able to know
* whether this page exists or not.
*/
-struct page *get_lock_data_page(struct inode *inode, pgoff_t index,
+struct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index,
bool for_write)
{
struct address_space *mapping = inode->i_mapping;
struct page *page;
repeat:
- page = get_read_data_page(inode, index, 0, for_write);
+ page = f2fs_get_read_data_page(inode, index, 0, for_write);
if (IS_ERR(page))
return page;
@@ -753,7 +814,7 @@ repeat:
* Note that, ipage is set only by make_empty_dir, and if any error occur,
* ipage should be released by this function.
*/
-struct page *get_new_data_page(struct inode *inode,
+struct page *f2fs_get_new_data_page(struct inode *inode,
struct page *ipage, pgoff_t index, bool new_i_size)
{
struct address_space *mapping = inode->i_mapping;
@@ -792,7 +853,7 @@ struct page *get_new_data_page(struct inode *inode,
/* if ipage exists, blkaddr should be NEW_ADDR */
f2fs_bug_on(F2FS_I_SB(inode), ipage);
- page = get_lock_data_page(inode, index, true);
+ page = f2fs_get_lock_data_page(inode, index, true);
if (IS_ERR(page))
return page;
}
@@ -824,15 +885,15 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
return err;
alloc:
- get_node_info(sbi, dn->nid, &ni);
+ f2fs_get_node_info(sbi, dn->nid, &ni);
set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
- allocate_data_block(sbi, NULL, dn->data_blkaddr, &dn->data_blkaddr,
+ f2fs_allocate_data_block(sbi, NULL, dn->data_blkaddr, &dn->data_blkaddr,
&sum, seg_type, NULL, false);
- set_data_blkaddr(dn);
+ f2fs_set_data_blkaddr(dn);
/* update i_size */
- fofs = start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) +
+ fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) +
dn->ofs_in_node;
if (i_size_read(dn->inode) < ((loff_t)(fofs + 1) << PAGE_SHIFT))
f2fs_i_size_write(dn->inode,
@@ -870,7 +931,7 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from)
map.m_seg_type = NO_CHECK_TYPE;
if (direct_io) {
- map.m_seg_type = rw_hint_to_seg_type(iocb->ki_hint);
+ map.m_seg_type = f2fs_rw_hint_to_seg_type(iocb->ki_hint);
flag = f2fs_force_buffered_io(inode, WRITE) ?
F2FS_GET_BLOCK_PRE_AIO :
F2FS_GET_BLOCK_PRE_DIO;
@@ -960,7 +1021,7 @@ next_dnode:
/* When reading holes, we need its node page */
set_new_dnode(&dn, inode, NULL, NULL, 0);
- err = get_dnode_of_data(&dn, pgofs, mode);
+ err = f2fs_get_dnode_of_data(&dn, pgofs, mode);
if (err) {
if (flag == F2FS_GET_BLOCK_BMAP)
map->m_pblk = 0;
@@ -968,10 +1029,10 @@ next_dnode:
err = 0;
if (map->m_next_pgofs)
*map->m_next_pgofs =
- get_next_page_offset(&dn, pgofs);
+ f2fs_get_next_page_offset(&dn, pgofs);
if (map->m_next_extent)
*map->m_next_extent =
- get_next_page_offset(&dn, pgofs);
+ f2fs_get_next_page_offset(&dn, pgofs);
}
goto unlock_out;
}
@@ -984,7 +1045,7 @@ next_dnode:
next_block:
blkaddr = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node);
- if (blkaddr == NEW_ADDR || blkaddr == NULL_ADDR) {
+ if (!is_valid_blkaddr(blkaddr)) {
if (create) {
if (unlikely(f2fs_cp_error(sbi))) {
err = -EIO;
@@ -1057,7 +1118,7 @@ skip:
(pgofs == end || dn.ofs_in_node == end_offset)) {
dn.ofs_in_node = ofs_in_node;
- err = reserve_new_blocks(&dn, prealloc);
+ err = f2fs_reserve_new_blocks(&dn, prealloc);
if (err)
goto sync_out;
@@ -1176,7 +1237,7 @@ static int get_data_block_dio(struct inode *inode, sector_t iblock,
{
return __get_data_block(inode, iblock, bh_result, create,
F2FS_GET_BLOCK_DEFAULT, NULL,
- rw_hint_to_seg_type(
+ f2fs_rw_hint_to_seg_type(
inode->i_write_hint));
}
@@ -1221,7 +1282,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
if (!page)
return -ENOMEM;
- get_node_info(sbi, inode->i_ino, &ni);
+ f2fs_get_node_info(sbi, inode->i_ino, &ni);
phys = (__u64)blk_to_logical(inode, ni.blk_addr);
offset = offsetof(struct f2fs_inode, i_addr) +
@@ -1248,7 +1309,7 @@ static int f2fs_xattr_fiemap(struct inode *inode,
if (!page)
return -ENOMEM;
- get_node_info(sbi, xnid, &ni);
+ f2fs_get_node_info(sbi, xnid, &ni);
phys = (__u64)blk_to_logical(inode, ni.blk_addr);
len = inode->i_sb->s_blocksize;
@@ -1525,7 +1586,7 @@ static int encrypt_one_page(struct f2fs_io_info *fio)
if (!f2fs_encrypted_file(inode))
return 0;
- /* wait for GCed encrypted page writeback */
+ /* wait for GCed page writeback via META_MAPPING */
f2fs_wait_on_block_writeback(fio->sbi, fio->old_blkaddr);
retry_encrypt:
@@ -1552,12 +1613,12 @@ static inline bool check_inplace_update_policy(struct inode *inode,
if (policy & (0x1 << F2FS_IPU_FORCE))
return true;
- if (policy & (0x1 << F2FS_IPU_SSR) && need_SSR(sbi))
+ if (policy & (0x1 << F2FS_IPU_SSR) && f2fs_need_SSR(sbi))
return true;
if (policy & (0x1 << F2FS_IPU_UTIL) &&
utilization(sbi) > SM_I(sbi)->min_ipu_util)
return true;
- if (policy & (0x1 << F2FS_IPU_SSR_UTIL) && need_SSR(sbi) &&
+ if (policy & (0x1 << F2FS_IPU_SSR_UTIL) && f2fs_need_SSR(sbi) &&
utilization(sbi) > SM_I(sbi)->min_ipu_util)
return true;
@@ -1578,7 +1639,7 @@ static inline bool check_inplace_update_policy(struct inode *inode,
return false;
}
-bool should_update_inplace(struct inode *inode, struct f2fs_io_info *fio)
+bool f2fs_should_update_inplace(struct inode *inode, struct f2fs_io_info *fio)
{
if (f2fs_is_pinned_file(inode))
return true;
@@ -1590,7 +1651,7 @@ bool should_update_inplace(struct inode *inode, struct f2fs_io_info *fio)
return check_inplace_update_policy(inode, fio);
}
-bool should_update_outplace(struct inode *inode, struct f2fs_io_info *fio)
+bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
@@ -1613,22 +1674,13 @@ static inline bool need_inplace_update(struct f2fs_io_info *fio)
{
struct inode *inode = fio->page->mapping->host;
- if (should_update_outplace(inode, fio))
+ if (f2fs_should_update_outplace(inode, fio))
return false;
- return should_update_inplace(inode, fio);
+ return f2fs_should_update_inplace(inode, fio);
}
-static inline bool valid_ipu_blkaddr(struct f2fs_io_info *fio)
-{
- if (fio->old_blkaddr == NEW_ADDR)
- return false;
- if (fio->old_blkaddr == NULL_ADDR)
- return false;
- return true;
-}
-
-int do_write_data_page(struct f2fs_io_info *fio)
+int f2fs_do_write_data_page(struct f2fs_io_info *fio)
{
struct page *page = fio->page;
struct inode *inode = page->mapping->host;
@@ -1642,7 +1694,7 @@ int do_write_data_page(struct f2fs_io_info *fio)
f2fs_lookup_extent_cache(inode, page->index, &ei)) {
fio->old_blkaddr = ei.blk + page->index - ei.fofs;
- if (valid_ipu_blkaddr(fio)) {
+ if (is_valid_blkaddr(fio->old_blkaddr)) {
ipu_force = true;
fio->need_lock = LOCK_DONE;
goto got_it;
@@ -1653,7 +1705,7 @@ int do_write_data_page(struct f2fs_io_info *fio)
if (fio->need_lock == LOCK_REQ && !f2fs_trylock_op(fio->sbi))
return -EAGAIN;
- err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE);
+ err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE);
if (err)
goto out;
@@ -1669,16 +1721,18 @@ got_it:
* If current allocation needs SSR,
* it had better in-place writes for updated data.
*/
- if (ipu_force || (valid_ipu_blkaddr(fio) && need_inplace_update(fio))) {
+ if (ipu_force || (is_valid_blkaddr(fio->old_blkaddr) &&
+ need_inplace_update(fio))) {
err = encrypt_one_page(fio);
if (err)
goto out_writepage;
set_page_writeback(page);
+ ClearPageError(page);
f2fs_put_dnode(&dn);
if (fio->need_lock == LOCK_REQ)
f2fs_unlock_op(fio->sbi);
- err = rewrite_data_page(fio);
+ err = f2fs_inplace_write_data(fio);
trace_f2fs_do_write_data_page(fio->page, IPU);
set_inode_flag(inode, FI_UPDATE_WRITE);
return err;
@@ -1697,9 +1751,10 @@ got_it:
goto out_writepage;
set_page_writeback(page);
+ ClearPageError(page);
/* LFS mode write path */
- write_data_page(&dn, fio);
+ f2fs_outplace_write_data(&dn, fio);
trace_f2fs_do_write_data_page(page, OPU);
set_inode_flag(inode, FI_APPEND_WRITE);
if (page->index == 0)
@@ -1745,6 +1800,12 @@ static int __write_data_page(struct page *page, bool *submitted,
/* we should bypass data pages to proceed the kworkder jobs */
if (unlikely(f2fs_cp_error(sbi))) {
mapping_set_error(page->mapping, -EIO);
+ /*
+ * don't drop any dirty dentry pages for keeping lastest
+ * directory structure.
+ */
+ if (S_ISDIR(inode->i_mode))
+ goto redirty_out;
goto out;
}
@@ -1769,13 +1830,13 @@ write:
/* we should not write 0'th page having journal header */
if (f2fs_is_volatile_file(inode) && (!page->index ||
(!wbc->for_reclaim &&
- available_free_memory(sbi, BASE_CHECK))))
+ f2fs_available_free_memory(sbi, BASE_CHECK))))
goto redirty_out;
/* Dentry blocks are controlled by checkpoint */
if (S_ISDIR(inode->i_mode)) {
fio.need_lock = LOCK_DONE;
- err = do_write_data_page(&fio);
+ err = f2fs_do_write_data_page(&fio);
goto done;
}
@@ -1794,10 +1855,10 @@ write:
}
if (err == -EAGAIN) {
- err = do_write_data_page(&fio);
+ err = f2fs_do_write_data_page(&fio);
if (err == -EAGAIN) {
fio.need_lock = LOCK_REQ;
- err = do_write_data_page(&fio);
+ err = f2fs_do_write_data_page(&fio);
}
}
@@ -1822,7 +1883,7 @@ out:
if (wbc->for_reclaim) {
f2fs_submit_merged_write_cond(sbi, inode, 0, page->index, DATA);
clear_inode_flag(inode, FI_HOT_DATA);
- remove_dirty_inode(inode);
+ f2fs_remove_dirty_inode(inode);
submitted = NULL;
}
@@ -1842,7 +1903,13 @@ out:
redirty_out:
redirty_page_for_writepage(wbc, page);
- if (!err)
+ /*
+ * pageout() in MM traslates EAGAIN, so calls handle_write_error()
+ * -> mapping_set_error() -> set_bit(AS_EIO, ...).
+ * file_write_and_wait_range() will see EIO error, which is critical
+ * to return value of fsync() followed by atomic_write failure to user.
+ */
+ if (!err || wbc->for_reclaim)
return AOP_WRITEPAGE_ACTIVATE;
unlock_page(page);
return err;
@@ -1866,6 +1933,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
int ret = 0;
int done = 0;
struct pagevec pvec;
+ struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
int nr_pages;
pgoff_t uninitialized_var(writeback_index);
pgoff_t index;
@@ -1919,6 +1987,13 @@ retry:
struct page *page = pvec.pages[i];
bool submitted = false;
+ /* give a priority to WB_SYNC threads */
+ if (atomic_read(&sbi->wb_sync_req[DATA]) &&
+ wbc->sync_mode == WB_SYNC_NONE) {
+ done = 1;
+ break;
+ }
+
done_index = page->index;
retry_write:
lock_page(page);
@@ -1973,9 +2048,7 @@ continue_unlock:
last_idx = page->index;
}
- /* give a priority to WB_SYNC threads */
- if ((atomic_read(&F2FS_M_SB(mapping)->wb_sync_req) ||
- --wbc->nr_to_write <= 0) &&
+ if (--wbc->nr_to_write <= 0 &&
wbc->sync_mode == WB_SYNC_NONE) {
done = 1;
break;
@@ -2001,7 +2074,7 @@ continue_unlock:
return ret;
}
-int __f2fs_write_data_pages(struct address_space *mapping,
+static int __f2fs_write_data_pages(struct address_space *mapping,
struct writeback_control *wbc,
enum iostat_type io_type)
{
@@ -2024,7 +2097,7 @@ int __f2fs_write_data_pages(struct address_space *mapping,
if (S_ISDIR(inode->i_mode) && wbc->sync_mode == WB_SYNC_NONE &&
get_dirty_pages(inode) < nr_pages_to_skip(sbi, DATA) &&
- available_free_memory(sbi, DIRTY_DENTS))
+ f2fs_available_free_memory(sbi, DIRTY_DENTS))
goto skip_write;
/* skip writing during file defragment */
@@ -2035,8 +2108,8 @@ int __f2fs_write_data_pages(struct address_space *mapping,
/* to avoid spliting IOs due to mixed WB_SYNC_ALL and WB_SYNC_NONE */
if (wbc->sync_mode == WB_SYNC_ALL)
- atomic_inc(&sbi->wb_sync_req);
- else if (atomic_read(&sbi->wb_sync_req))
+ atomic_inc(&sbi->wb_sync_req[DATA]);
+ else if (atomic_read(&sbi->wb_sync_req[DATA]))
goto skip_write;
blk_start_plug(&plug);
@@ -2044,13 +2117,13 @@ int __f2fs_write_data_pages(struct address_space *mapping,
blk_finish_plug(&plug);
if (wbc->sync_mode == WB_SYNC_ALL)
- atomic_dec(&sbi->wb_sync_req);
+ atomic_dec(&sbi->wb_sync_req[DATA]);
/*
* if some pages were truncated, we cannot guarantee its mapping->host
* to detect pending bios.
*/
- remove_dirty_inode(inode);
+ f2fs_remove_dirty_inode(inode);
return ret;
skip_write:
@@ -2077,7 +2150,7 @@ static void f2fs_write_failed(struct address_space *mapping, loff_t to)
if (to > i_size) {
down_write(&F2FS_I(inode)->i_mmap_sem);
truncate_pagecache(inode, i_size);
- truncate_blocks(inode, i_size, true);
+ f2fs_truncate_blocks(inode, i_size, true);
up_write(&F2FS_I(inode)->i_mmap_sem);
}
}
@@ -2109,7 +2182,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
}
restart:
/* check inline_data */
- ipage = get_node_page(sbi, inode->i_ino);
+ ipage = f2fs_get_node_page(sbi, inode->i_ino);
if (IS_ERR(ipage)) {
err = PTR_ERR(ipage);
goto unlock_out;
@@ -2119,7 +2192,7 @@ restart:
if (f2fs_has_inline_data(inode)) {
if (pos + len <= MAX_INLINE_DATA(inode)) {
- read_inline_data(page, ipage);
+ f2fs_do_read_inline_data(page, ipage);
set_inode_flag(inode, FI_DATA_EXIST);
if (inode->i_nlink)
set_inline_node(ipage);
@@ -2137,7 +2210,7 @@ restart:
dn.data_blkaddr = ei.blk + index - ei.fofs;
} else {
/* hole case */
- err = get_dnode_of_data(&dn, index, LOOKUP_NODE);
+ err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE);
if (err || dn.data_blkaddr == NULL_ADDR) {
f2fs_put_dnode(&dn);
__do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO,
@@ -2174,7 +2247,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
trace_f2fs_write_begin(inode, pos, len, flags);
if (f2fs_is_atomic_file(inode) &&
- !available_free_memory(sbi, INMEM_PAGES)) {
+ !f2fs_available_free_memory(sbi, INMEM_PAGES)) {
err = -ENOMEM;
drop_atomic = true;
goto fail;
@@ -2222,8 +2295,8 @@ repeat:
f2fs_wait_on_page_writeback(page, DATA, false);
- /* wait for GCed encrypted page writeback */
- if (f2fs_encrypted_file(inode))
+ /* wait for GCed page writeback via META_MAPPING */
+ if (f2fs_post_read_required(inode))
f2fs_wait_on_block_writeback(sbi, blkaddr);
if (len == PAGE_SIZE || PageUptodate(page))
@@ -2258,7 +2331,7 @@ fail:
f2fs_put_page(page, 1);
f2fs_write_failed(mapping, pos + len);
if (drop_atomic)
- drop_inmem_pages_all(sbi);
+ f2fs_drop_inmem_pages_all(sbi, false);
return err;
}
@@ -2333,17 +2406,17 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
if (rw == WRITE && whint_mode == WHINT_MODE_OFF)
iocb->ki_hint = WRITE_LIFE_NOT_SET;
- if (!down_read_trylock(&F2FS_I(inode)->dio_rwsem[rw])) {
+ if (!down_read_trylock(&F2FS_I(inode)->i_gc_rwsem[rw])) {
if (iocb->ki_flags & IOCB_NOWAIT) {
iocb->ki_hint = hint;
err = -EAGAIN;
goto out;
}
- down_read(&F2FS_I(inode)->dio_rwsem[rw]);
+ down_read(&F2FS_I(inode)->i_gc_rwsem[rw]);
}
err = blockdev_direct_IO(iocb, inode, iter, get_data_block_dio);
- up_read(&F2FS_I(inode)->dio_rwsem[rw]);
+ up_read(&F2FS_I(inode)->i_gc_rwsem[rw]);
if (rw == WRITE) {
if (whint_mode == WHINT_MODE_OFF)
@@ -2380,13 +2453,13 @@ void f2fs_invalidate_page(struct page *page, unsigned int offset,
dec_page_count(sbi, F2FS_DIRTY_NODES);
} else {
inode_dec_dirty_pages(inode);
- remove_dirty_inode(inode);
+ f2fs_remove_dirty_inode(inode);
}
}
/* This is atomic written page, keep Private */
if (IS_ATOMIC_WRITTEN_PAGE(page))
- return drop_inmem_page(inode, page);
+ return f2fs_drop_inmem_page(inode, page);
set_page_private(page, 0);
ClearPagePrivate(page);
@@ -2407,35 +2480,6 @@ int f2fs_release_page(struct page *page, gfp_t wait)
return 1;
}
-/*
- * This was copied from __set_page_dirty_buffers which gives higher performance
- * in very high speed storages. (e.g., pmem)
- */
-void f2fs_set_page_dirty_nobuffers(struct page *page)
-{
- struct address_space *mapping = page->mapping;
- unsigned long flags;
-
- if (unlikely(!mapping))
- return;
-
- spin_lock(&mapping->private_lock);
- lock_page_memcg(page);
- SetPageDirty(page);
- spin_unlock(&mapping->private_lock);
-
- xa_lock_irqsave(&mapping->i_pages, flags);
- WARN_ON_ONCE(!PageUptodate(page));
- account_page_dirtied(page, mapping);
- radix_tree_tag_set(&mapping->i_pages,
- page_index(page), PAGECACHE_TAG_DIRTY);
- xa_unlock_irqrestore(&mapping->i_pages, flags);
- unlock_page_memcg(page);
-
- __mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
- return;
-}
-
static int f2fs_set_data_page_dirty(struct page *page)
{
struct address_space *mapping = page->mapping;
@@ -2448,7 +2492,7 @@ static int f2fs_set_data_page_dirty(struct page *page)
if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) {
if (!IS_ATOMIC_WRITTEN_PAGE(page)) {
- register_inmem_page(inode, page);
+ f2fs_register_inmem_page(inode, page);
return 1;
}
/*
@@ -2459,8 +2503,8 @@ static int f2fs_set_data_page_dirty(struct page *page)
}
if (!PageDirty(page)) {
- f2fs_set_page_dirty_nobuffers(page);
- update_dirty_page(inode, page);
+ __set_page_dirty_nobuffers(page);
+ f2fs_update_dirty_page(inode, page);
return 1;
}
return 0;
@@ -2555,3 +2599,38 @@ const struct address_space_operations f2fs_dblock_aops = {
.migratepage = f2fs_migrate_page,
#endif
};
+
+void f2fs_clear_radix_tree_dirty_tag(struct page *page)
+{
+ struct address_space *mapping = page_mapping(page);
+ unsigned long flags;
+
+ xa_lock_irqsave(&mapping->i_pages, flags);
+ radix_tree_tag_clear(&mapping->i_pages, page_index(page),
+ PAGECACHE_TAG_DIRTY);
+ xa_unlock_irqrestore(&mapping->i_pages, flags);
+}
+
+int __init f2fs_init_post_read_processing(void)
+{
+ bio_post_read_ctx_cache = KMEM_CACHE(bio_post_read_ctx, 0);
+ if (!bio_post_read_ctx_cache)
+ goto fail;
+ bio_post_read_ctx_pool =
+ mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS,
+ bio_post_read_ctx_cache);
+ if (!bio_post_read_ctx_pool)
+ goto fail_free_cache;
+ return 0;
+
+fail_free_cache:
+ kmem_cache_destroy(bio_post_read_ctx_cache);
+fail:
+ return -ENOMEM;
+}
+
+void __exit f2fs_destroy_post_read_processing(void)
+{
+ mempool_destroy(bio_post_read_ctx_pool);
+ kmem_cache_destroy(bio_post_read_ctx_cache);
+}
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index a66107b..2d65e77 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -104,6 +104,8 @@ static void update_general_status(struct f2fs_sb_info *sbi)
si->avail_nids = NM_I(sbi)->available_nids;
si->alloc_nids = NM_I(sbi)->nid_cnt[PREALLOC_NID];
si->bg_gc = sbi->bg_gc;
+ si->skipped_atomic_files[BG_GC] = sbi->skipped_atomic_files[BG_GC];
+ si->skipped_atomic_files[FG_GC] = sbi->skipped_atomic_files[FG_GC];
si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg)
* 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg)
/ 2;
@@ -342,6 +344,10 @@ static int stat_show(struct seq_file *s, void *v)
si->bg_data_blks);
seq_printf(s, " - node blocks : %d (%d)\n", si->node_blks,
si->bg_node_blks);
+ seq_printf(s, "Skipped : atomic write %llu (%llu)\n",
+ si->skipped_atomic_files[BG_GC] +
+ si->skipped_atomic_files[FG_GC],
+ si->skipped_atomic_files[BG_GC]);
seq_puts(s, "\nExtent Cache:\n");
seq_printf(s, " - Hit Count: L1-1:%llu L1-2:%llu L2:%llu\n",
si->hit_largest, si->hit_cached,
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 8c9c2f3..7f955c4 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -60,12 +60,12 @@ static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = {
[S_IFLNK >> S_SHIFT] = F2FS_FT_SYMLINK,
};
-void set_de_type(struct f2fs_dir_entry *de, umode_t mode)
+static void set_de_type(struct f2fs_dir_entry *de, umode_t mode)
{
de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT];
}
-unsigned char get_de_type(struct f2fs_dir_entry *de)
+unsigned char f2fs_get_de_type(struct f2fs_dir_entry *de)
{
if (de->file_type < F2FS_FT_MAX)
return f2fs_filetype_table[de->file_type];
@@ -97,14 +97,14 @@ static struct f2fs_dir_entry *find_in_block(struct page *dentry_page,
dentry_blk = (struct f2fs_dentry_block *)page_address(dentry_page);
make_dentry_ptr_block(NULL, &d, dentry_blk);
- de = find_target_dentry(fname, namehash, max_slots, &d);
+ de = f2fs_find_target_dentry(fname, namehash, max_slots, &d);
if (de)
*res_page = dentry_page;
return de;
}
-struct f2fs_dir_entry *find_target_dentry(struct fscrypt_name *fname,
+struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
f2fs_hash_t namehash, int *max_slots,
struct f2fs_dentry_ptr *d)
{
@@ -171,7 +171,7 @@ static struct f2fs_dir_entry *find_in_level(struct inode *dir,
for (; bidx < end_block; bidx++) {
/* no need to allocate new dentry pages to all the indices */
- dentry_page = find_data_page(dir, bidx);
+ dentry_page = f2fs_find_data_page(dir, bidx);
if (IS_ERR(dentry_page)) {
if (PTR_ERR(dentry_page) == -ENOENT) {
room = true;
@@ -210,7 +210,7 @@ struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
if (f2fs_has_inline_dentry(dir)) {
*res_page = NULL;
- de = find_in_inline_dir(dir, fname, res_page);
+ de = f2fs_find_in_inline_dir(dir, fname, res_page);
goto out;
}
@@ -319,7 +319,7 @@ static void init_dent_inode(const struct qstr *name, struct page *ipage)
set_page_dirty(ipage);
}
-void do_make_empty_dir(struct inode *inode, struct inode *parent,
+void f2fs_do_make_empty_dir(struct inode *inode, struct inode *parent,
struct f2fs_dentry_ptr *d)
{
struct qstr dot = QSTR_INIT(".", 1);
@@ -340,23 +340,23 @@ static int make_empty_dir(struct inode *inode,
struct f2fs_dentry_ptr d;
if (f2fs_has_inline_dentry(inode))
- return make_empty_inline_dir(inode, parent, page);
+ return f2fs_make_empty_inline_dir(inode, parent, page);
- dentry_page = get_new_data_page(inode, page, 0, true);
+ dentry_page = f2fs_get_new_data_page(inode, page, 0, true);
if (IS_ERR(dentry_page))
return PTR_ERR(dentry_page);
dentry_blk = page_address(dentry_page);
make_dentry_ptr_block(NULL, &d, dentry_blk);
- do_make_empty_dir(inode, parent, &d);
+ f2fs_do_make_empty_dir(inode, parent, &d);
set_page_dirty(dentry_page);
f2fs_put_page(dentry_page, 1);
return 0;
}
-struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
+struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,
const struct qstr *new_name, const struct qstr *orig_name,
struct page *dpage)
{
@@ -365,7 +365,7 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
int err;
if (is_inode_flag_set(inode, FI_NEW_INODE)) {
- page = new_inode_page(inode);
+ page = f2fs_new_inode_page(inode);
if (IS_ERR(page))
return page;
@@ -395,7 +395,7 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
goto put_error;
}
} else {
- page = get_node_page(F2FS_I_SB(dir), inode->i_ino);
+ page = f2fs_get_node_page(F2FS_I_SB(dir), inode->i_ino);
if (IS_ERR(page))
return page;
}
@@ -418,19 +418,19 @@ struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
* we should remove this inode from orphan list.
*/
if (inode->i_nlink == 0)
- remove_orphan_inode(F2FS_I_SB(dir), inode->i_ino);
+ f2fs_remove_orphan_inode(F2FS_I_SB(dir), inode->i_ino);
f2fs_i_links_write(inode, true);
}
return page;
put_error:
clear_nlink(inode);
- update_inode(inode, page);
+ f2fs_update_inode(inode, page);
f2fs_put_page(page, 1);
return ERR_PTR(err);
}
-void update_parent_metadata(struct inode *dir, struct inode *inode,
+void f2fs_update_parent_metadata(struct inode *dir, struct inode *inode,
unsigned int current_depth)
{
if (inode && is_inode_flag_set(inode, FI_NEW_INODE)) {
@@ -448,7 +448,7 @@ void update_parent_metadata(struct inode *dir, struct inode *inode,
clear_inode_flag(inode, FI_INC_LINK);
}
-int room_for_filename(const void *bitmap, int slots, int max_slots)
+int f2fs_room_for_filename(const void *bitmap, int slots, int max_slots)
{
int bit_start = 0;
int zero_start, zero_end;
@@ -537,12 +537,12 @@ start:
(le32_to_cpu(dentry_hash) % nbucket));
for (block = bidx; block <= (bidx + nblock - 1); block++) {
- dentry_page = get_new_data_page(dir, NULL, block, true);
+ dentry_page = f2fs_get_new_data_page(dir, NULL, block, true);
if (IS_ERR(dentry_page))
return PTR_ERR(dentry_page);
dentry_blk = page_address(dentry_page);
- bit_pos = room_for_filename(&dentry_blk->dentry_bitmap,
+ bit_pos = f2fs_room_for_filename(&dentry_blk->dentry_bitmap,
slots, NR_DENTRY_IN_BLOCK);
if (bit_pos < NR_DENTRY_IN_BLOCK)
goto add_dentry;
@@ -558,7 +558,7 @@ add_dentry:
if (inode) {
down_write(&F2FS_I(inode)->i_sem);
- page = init_inode_metadata(inode, dir, new_name,
+ page = f2fs_init_inode_metadata(inode, dir, new_name,
orig_name, NULL);
if (IS_ERR(page)) {
err = PTR_ERR(page);
@@ -576,7 +576,7 @@ add_dentry:
f2fs_put_page(page, 1);
}
- update_parent_metadata(dir, inode, current_depth);
+ f2fs_update_parent_metadata(dir, inode, current_depth);
fail:
if (inode)
up_write(&F2FS_I(inode)->i_sem);
@@ -586,7 +586,7 @@ fail:
return err;
}
-int __f2fs_do_add_link(struct inode *dir, struct fscrypt_name *fname,
+int f2fs_add_dentry(struct inode *dir, struct fscrypt_name *fname,
struct inode *inode, nid_t ino, umode_t mode)
{
struct qstr new_name;
@@ -610,7 +610,7 @@ int __f2fs_do_add_link(struct inode *dir, struct fscrypt_name *fname,
* Caller should grab and release a rwsem by calling f2fs_lock_op() and
* f2fs_unlock_op().
*/
-int __f2fs_add_link(struct inode *dir, const struct qstr *name,
+int f2fs_do_add_link(struct inode *dir, const struct qstr *name,
struct inode *inode, nid_t ino, umode_t mode)
{
struct fscrypt_name fname;
@@ -639,7 +639,7 @@ int __f2fs_add_link(struct inode *dir, const struct qstr *name,
} else if (IS_ERR(page)) {
err = PTR_ERR(page);
} else {
- err = __f2fs_do_add_link(dir, &fname, inode, ino, mode);
+ err = f2fs_add_dentry(dir, &fname, inode, ino, mode);
}
fscrypt_free_filename(&fname);
return err;
@@ -651,7 +651,7 @@ int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
int err = 0;
down_write(&F2FS_I(inode)->i_sem);
- page = init_inode_metadata(inode, dir, NULL, NULL, NULL);
+ page = f2fs_init_inode_metadata(inode, dir, NULL, NULL, NULL);
if (IS_ERR(page)) {
err = PTR_ERR(page);
goto fail;
@@ -683,9 +683,9 @@ void f2fs_drop_nlink(struct inode *dir, struct inode *inode)
up_write(&F2FS_I(inode)->i_sem);
if (inode->i_nlink == 0)
- add_orphan_inode(inode);
+ f2fs_add_orphan_inode(inode);
else
- release_orphan_inode(sbi);
+ f2fs_release_orphan_inode(sbi);
}
/*
@@ -698,14 +698,12 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
struct f2fs_dentry_block *dentry_blk;
unsigned int bit_pos;
int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len));
- struct address_space *mapping = page_mapping(page);
- unsigned long flags;
int i;
f2fs_update_time(F2FS_I_SB(dir), REQ_TIME);
if (F2FS_OPTION(F2FS_I_SB(dir)).fsync_mode == FSYNC_MODE_STRICT)
- add_ino_entry(F2FS_I_SB(dir), dir->i_ino, TRANS_DIR_INO);
+ f2fs_add_ino_entry(F2FS_I_SB(dir), dir->i_ino, TRANS_DIR_INO);
if (f2fs_has_inline_dentry(dir))
return f2fs_delete_inline_entry(dentry, page, dir, inode);
@@ -731,17 +729,13 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
f2fs_drop_nlink(dir, inode);
if (bit_pos == NR_DENTRY_IN_BLOCK &&
- !truncate_hole(dir, page->index, page->index + 1)) {
- xa_lock_irqsave(&mapping->i_pages, flags);
- radix_tree_tag_clear(&mapping->i_pages, page_index(page),
- PAGECACHE_TAG_DIRTY);
- xa_unlock_irqrestore(&mapping->i_pages, flags);
-
+ !f2fs_truncate_hole(dir, page->index, page->index + 1)) {
+ f2fs_clear_radix_tree_dirty_tag(page);
clear_page_dirty_for_io(page);
ClearPagePrivate(page);
ClearPageUptodate(page);
inode_dec_dirty_pages(dir);
- remove_dirty_inode(dir);
+ f2fs_remove_dirty_inode(dir);
}
f2fs_put_page(page, 1);
}
@@ -758,7 +752,7 @@ bool f2fs_empty_dir(struct inode *dir)
return f2fs_empty_inline_dir(dir);
for (bidx = 0; bidx < nblock; bidx++) {
- dentry_page = get_lock_data_page(dir, bidx, false);
+ dentry_page = f2fs_get_lock_data_page(dir, bidx, false);
if (IS_ERR(dentry_page)) {
if (PTR_ERR(dentry_page) == -ENOENT)
continue;
@@ -806,7 +800,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
continue;
}
- d_type = get_de_type(de);
+ d_type = f2fs_get_de_type(de);
de_name.name = d->filename[bit_pos];
de_name.len = le16_to_cpu(de->name_len);
@@ -830,7 +824,7 @@ int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
return 1;
if (sbi->readdir_ra == 1)
- ra_node_page(sbi, le32_to_cpu(de->ino));
+ f2fs_ra_node_page(sbi, le32_to_cpu(de->ino));
bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len));
ctx->pos = start_pos + bit_pos;
@@ -880,7 +874,7 @@ static int f2fs_readdir(struct file *file, struct dir_context *ctx)
page_cache_sync_readahead(inode->i_mapping, ra, file, n,
min(npages - n, (pgoff_t)MAX_DIR_RA_PAGES));
- dentry_page = get_lock_data_page(inode, n, false);
+ dentry_page = f2fs_get_lock_data_page(inode, n, false);
if (IS_ERR(dentry_page)) {
err = PTR_ERR(dentry_page);
if (err == -ENOENT) {
diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c
index d5a861b..231b77e 100644
--- a/fs/f2fs/extent_cache.c
+++ b/fs/f2fs/extent_cache.c
@@ -49,7 +49,7 @@ static struct rb_entry *__lookup_rb_tree_slow(struct rb_root *root,
return NULL;
}
-struct rb_entry *__lookup_rb_tree(struct rb_root *root,
+struct rb_entry *f2fs_lookup_rb_tree(struct rb_root *root,
struct rb_entry *cached_re, unsigned int ofs)
{
struct rb_entry *re;
@@ -61,7 +61,7 @@ struct rb_entry *__lookup_rb_tree(struct rb_root *root,
return re;
}
-struct rb_node **__lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi,
+struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi,
struct rb_root *root, struct rb_node **parent,
unsigned int ofs)
{
@@ -92,7 +92,7 @@ struct rb_node **__lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi,
* in order to simpfy the insertion after.
* tree must stay unchanged between lookup and insertion.
*/
-struct rb_entry *__lookup_rb_tree_ret(struct rb_root *root,
+struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root *root,
struct rb_entry *cached_re,
unsigned int ofs,
struct rb_entry **prev_entry,
@@ -159,7 +159,7 @@ lookup_neighbors:
return re;
}
-bool __check_rb_tree_consistence(struct f2fs_sb_info *sbi,
+bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi,
struct rb_root *root)
{
#ifdef CONFIG_F2FS_CHECK_FS
@@ -390,7 +390,7 @@ static bool f2fs_lookup_extent_tree(struct inode *inode, pgoff_t pgofs,
goto out;
}
- en = (struct extent_node *)__lookup_rb_tree(&et->root,
+ en = (struct extent_node *)f2fs_lookup_rb_tree(&et->root,
(struct rb_entry *)et->cached_en, pgofs);
if (!en)
goto out;
@@ -470,7 +470,7 @@ static struct extent_node *__insert_extent_tree(struct inode *inode,
goto do_insert;
}
- p = __lookup_rb_tree_for_insert(sbi, &et->root, &parent, ei->fofs);
+ p = f2fs_lookup_rb_tree_for_insert(sbi, &et->root, &parent, ei->fofs);
do_insert:
en = __attach_extent_node(sbi, et, ei, parent, p);
if (!en)
@@ -520,7 +520,7 @@ static void f2fs_update_extent_tree_range(struct inode *inode,
__drop_largest_extent(inode, fofs, len);
/* 1. lookup first extent node in range [fofs, fofs + len - 1] */
- en = (struct extent_node *)__lookup_rb_tree_ret(&et->root,
+ en = (struct extent_node *)f2fs_lookup_rb_tree_ret(&et->root,
(struct rb_entry *)et->cached_en, fofs,
(struct rb_entry **)&prev_en,
(struct rb_entry **)&next_en,
@@ -773,7 +773,7 @@ void f2fs_update_extent_cache(struct dnode_of_data *dn)
else
blkaddr = dn->data_blkaddr;
- fofs = start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) +
+ fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page), dn->inode) +
dn->ofs_in_node;
f2fs_update_extent_tree_range(dn->inode, fofs, blkaddr, 1);
}
@@ -788,7 +788,7 @@ void f2fs_update_extent_cache_range(struct dnode_of_data *dn,
f2fs_update_extent_tree_range(dn->inode, fofs, blkaddr, len);
}
-void init_extent_cache_info(struct f2fs_sb_info *sbi)
+void f2fs_init_extent_cache_info(struct f2fs_sb_info *sbi)
{
INIT_RADIX_TREE(&sbi->extent_tree_root, GFP_NOIO);
mutex_init(&sbi->extent_tree_lock);
@@ -800,7 +800,7 @@ void init_extent_cache_info(struct f2fs_sb_info *sbi)
atomic_set(&sbi->total_ext_node, 0);
}
-int __init create_extent_cache(void)
+int __init f2fs_create_extent_cache(void)
{
extent_tree_slab = f2fs_kmem_cache_create("f2fs_extent_tree",
sizeof(struct extent_tree));
@@ -815,7 +815,7 @@ int __init create_extent_cache(void)
return 0;
}
-void destroy_extent_cache(void)
+void f2fs_destroy_extent_cache(void)
{
kmem_cache_destroy(extent_node_slab);
kmem_cache_destroy(extent_tree_slab);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 1df7f10..4d8b1de 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -176,15 +176,13 @@ enum {
#define CP_DISCARD 0x00000010
#define CP_TRIMMED 0x00000020
-#define DEF_BATCHED_TRIM_SECTIONS 2048
-#define BATCHED_TRIM_SEGMENTS(sbi) \
- (GET_SEG_FROM_SEC(sbi, SM_I(sbi)->trim_sections))
-#define BATCHED_TRIM_BLOCKS(sbi) \
- (BATCHED_TRIM_SEGMENTS(sbi) << (sbi)->log_blocks_per_seg)
#define MAX_DISCARD_BLOCKS(sbi) BLKS_PER_SEC(sbi)
#define DEF_MAX_DISCARD_REQUEST 8 /* issue 8 discards per round */
+#define DEF_MAX_DISCARD_LEN 512 /* Max. 2MB per discard */
#define DEF_MIN_DISCARD_ISSUE_TIME 50 /* 50 ms, if exists */
+#define DEF_MID_DISCARD_ISSUE_TIME 500 /* 500 ms, if device busy */
#define DEF_MAX_DISCARD_ISSUE_TIME 60000 /* 60 s, if no candidates */
+#define DEF_DISCARD_URGENT_UTIL 80 /* do more discard over 80% */
#define DEF_CP_INTERVAL 60 /* 60 secs */
#define DEF_IDLE_INTERVAL 5 /* 5 secs */
@@ -285,6 +283,7 @@ enum {
struct discard_policy {
int type; /* type of discard */
unsigned int min_interval; /* used for candidates exist */
+ unsigned int mid_interval; /* used for device busy */
unsigned int max_interval; /* used for candidates not exist */
unsigned int max_requests; /* # of discards issued per round */
unsigned int io_aware_gran; /* minimum granularity discard not be aware of I/O */
@@ -620,15 +619,20 @@ enum {
#define DEF_DIR_LEVEL 0
+enum {
+ GC_FAILURE_PIN,
+ GC_FAILURE_ATOMIC,
+ MAX_GC_FAILURE
+};
+
struct f2fs_inode_info {
struct inode vfs_inode; /* serve a vfs inode */
unsigned long i_flags; /* keep an inode flags for ioctl */
unsigned char i_advise; /* use to give file attribute hints */
unsigned char i_dir_level; /* use for dentry level for large dir */
- union {
- unsigned int i_current_depth; /* only for directory depth */
- unsigned short i_gc_failures; /* only for regular file */
- };
+ unsigned int i_current_depth; /* only for directory depth */
+ /* for gc failure statistic */
+ unsigned int i_gc_failures[MAX_GC_FAILURE];
unsigned int i_pino; /* parent inode number */
umode_t i_acl_mode; /* keep file acl mode temporarily */
@@ -656,7 +660,9 @@ struct f2fs_inode_info {
struct task_struct *inmem_task; /* store inmemory task */
struct mutex inmem_lock; /* lock for inmemory pages */
struct extent_tree *extent_tree; /* cached extent_tree entry */
- struct rw_semaphore dio_rwsem[2];/* avoid racing between dio and gc */
+
+ /* avoid racing between foreground op and gc */
+ struct rw_semaphore i_gc_rwsem[2];
struct rw_semaphore i_mmap_sem;
struct rw_semaphore i_xattr_sem; /* avoid racing between reading and changing EAs */
@@ -694,7 +700,8 @@ static inline void set_extent_info(struct extent_info *ei, unsigned int fofs,
static inline bool __is_discard_mergeable(struct discard_info *back,
struct discard_info *front)
{
- return back->lstart + back->len == front->lstart;
+ return (back->lstart + back->len == front->lstart) &&
+ (back->len + front->len < DEF_MAX_DISCARD_LEN);
}
static inline bool __is_discard_back_mergeable(struct discard_info *cur,
@@ -1005,6 +1012,7 @@ struct f2fs_io_info {
int need_lock; /* indicate we need to lock cp_rwsem */
bool in_list; /* indicate fio is in io_list */
bool is_meta; /* indicate borrow meta inode mapping or not */
+ bool retry; /* need to reallocate block address */
enum iostat_type io_type; /* io type */
struct writeback_control *io_wbc; /* writeback control */
};
@@ -1067,6 +1075,13 @@ enum {
};
enum {
+ GC_NORMAL,
+ GC_IDLE_CB,
+ GC_IDLE_GREEDY,
+ GC_URGENT,
+};
+
+enum {
WHINT_MODE_OFF, /* not pass down write hints */
WHINT_MODE_USER, /* try to pass down hints given by users */
WHINT_MODE_FS, /* pass down hints with F2FS policy */
@@ -1080,6 +1095,7 @@ enum {
enum fsync_mode {
FSYNC_MODE_POSIX, /* fsync follows posix semantics */
FSYNC_MODE_STRICT, /* fsync behaves in line with ext4 */
+ FSYNC_MODE_NOBARRIER, /* fsync behaves nobarrier based on posix */
};
#ifdef CONFIG_F2FS_FS_ENCRYPTION
@@ -1113,6 +1129,8 @@ struct f2fs_sb_info {
struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
struct mutex wio_mutex[NR_PAGE_TYPE - 1][NR_TEMP_TYPE];
/* bio ordering for NODE/DATA */
+ /* keep migration IO order for LFS mode */
+ struct rw_semaphore io_order_lock;
mempool_t *write_io_dummy; /* Dummy pages */
/* for checkpoint */
@@ -1183,7 +1201,7 @@ struct f2fs_sb_info {
struct percpu_counter alloc_valid_block_count;
/* writeback control */
- atomic_t wb_sync_req; /* count # of WB_SYNC threads */
+ atomic_t wb_sync_req[META]; /* count # of WB_SYNC threads */
/* valid inode count */
struct percpu_counter total_valid_inode_count;
@@ -1194,9 +1212,9 @@ struct f2fs_sb_info {
struct mutex gc_mutex; /* mutex for GC */
struct f2fs_gc_kthread *gc_thread; /* GC thread */
unsigned int cur_victim_sec; /* current victim section num */
-
- /* threshold for converting bg victims for fg */
- u64 fggc_threshold;
+ unsigned int gc_mode; /* current GC state */
+ /* for skip statistic */
+ unsigned long long skipped_atomic_files[2]; /* FG_GC and BG_GC */
/* threshold for gc trials on pinned files */
u64 gc_pin_file_threshold;
@@ -1587,18 +1605,6 @@ static inline bool __exist_node_summaries(struct f2fs_sb_info *sbi)
}
/*
- * Check whether the given nid is within node id range.
- */
-static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
-{
- if (unlikely(nid < F2FS_ROOT_INO(sbi)))
- return -EINVAL;
- if (unlikely(nid >= NM_I(sbi)->max_nid))
- return -EINVAL;
- return 0;
-}
-
-/*
* Check whether the inode has blocks or not
*/
static inline int F2FS_HAS_BLOCKS(struct inode *inode)
@@ -1614,7 +1620,7 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)
}
static inline bool __allow_reserved_blocks(struct f2fs_sb_info *sbi,
- struct inode *inode)
+ struct inode *inode, bool cap)
{
if (!inode)
return true;
@@ -1627,7 +1633,7 @@ static inline bool __allow_reserved_blocks(struct f2fs_sb_info *sbi,
if (!gid_eq(F2FS_OPTION(sbi).s_resgid, GLOBAL_ROOT_GID) &&
in_group_p(F2FS_OPTION(sbi).s_resgid))
return true;
- if (capable(CAP_SYS_RESOURCE))
+ if (cap && capable(CAP_SYS_RESOURCE))
return true;
return false;
}
@@ -1662,7 +1668,7 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
avail_user_block_count = sbi->user_block_count -
sbi->current_reserved_blocks;
- if (!__allow_reserved_blocks(sbi, inode))
+ if (!__allow_reserved_blocks(sbi, inode, true))
avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks;
if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) {
@@ -1869,7 +1875,7 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
valid_block_count = sbi->total_valid_block_count +
sbi->current_reserved_blocks + 1;
- if (!__allow_reserved_blocks(sbi, inode))
+ if (!__allow_reserved_blocks(sbi, inode, false))
valid_block_count += F2FS_OPTION(sbi).root_reserved_blocks;
if (unlikely(valid_block_count > sbi->user_block_count)) {
@@ -2156,9 +2162,60 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr)
*addr ^= mask;
}
-#define F2FS_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
-#define F2FS_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL)
-#define F2FS_FL_INHERITED (FS_PROJINHERIT_FL)
+/*
+ * Inode flags
+ */
+#define F2FS_SECRM_FL 0x00000001 /* Secure deletion */
+#define F2FS_UNRM_FL 0x00000002 /* Undelete */
+#define F2FS_COMPR_FL 0x00000004 /* Compress file */
+#define F2FS_SYNC_FL 0x00000008 /* Synchronous updates */
+#define F2FS_IMMUTABLE_FL 0x00000010 /* Immutable file */
+#define F2FS_APPEND_FL 0x00000020 /* writes to file may only append */
+#define F2FS_NODUMP_FL 0x00000040 /* do not dump file */
+#define F2FS_NOATIME_FL 0x00000080 /* do not update atime */
+/* Reserved for compression usage... */
+#define F2FS_DIRTY_FL 0x00000100
+#define F2FS_COMPRBLK_FL 0x00000200 /* One or more compressed clusters */
+#define F2FS_NOCOMPR_FL 0x00000400 /* Don't compress */
+#define F2FS_ENCRYPT_FL 0x00000800 /* encrypted file */
+/* End compression flags --- maybe not all used */
+#define F2FS_INDEX_FL 0x00001000 /* hash-indexed directory */
+#define F2FS_IMAGIC_FL 0x00002000 /* AFS directory */
+#define F2FS_JOURNAL_DATA_FL 0x00004000 /* file data should be journaled */
+#define F2FS_NOTAIL_FL 0x00008000 /* file tail should not be merged */
+#define F2FS_DIRSYNC_FL 0x00010000 /* dirsync behaviour (directories only) */
+#define F2FS_TOPDIR_FL 0x00020000 /* Top of directory hierarchies*/
+#define F2FS_HUGE_FILE_FL 0x00040000 /* Set to each huge file */
+#define F2FS_EXTENTS_FL 0x00080000 /* Inode uses extents */
+#define F2FS_EA_INODE_FL 0x00200000 /* Inode used for large EA */
+#define F2FS_EOFBLOCKS_FL 0x00400000 /* Blocks allocated beyond EOF */
+#define F2FS_INLINE_DATA_FL 0x10000000 /* Inode has inline data. */
+#define F2FS_PROJINHERIT_FL 0x20000000 /* Create with parents projid */
+#define F2FS_RESERVED_FL 0x80000000 /* reserved for ext4 lib */
+
+#define F2FS_FL_USER_VISIBLE 0x304BDFFF /* User visible flags */
+#define F2FS_FL_USER_MODIFIABLE 0x204BC0FF /* User modifiable flags */
+
+/* Flags we can manipulate with through F2FS_IOC_FSSETXATTR */
+#define F2FS_FL_XFLAG_VISIBLE (F2FS_SYNC_FL | \
+ F2FS_IMMUTABLE_FL | \
+ F2FS_APPEND_FL | \
+ F2FS_NODUMP_FL | \
+ F2FS_NOATIME_FL | \
+ F2FS_PROJINHERIT_FL)
+
+/* Flags that should be inherited by new inodes from their parent. */
+#define F2FS_FL_INHERITED (F2FS_SECRM_FL | F2FS_UNRM_FL | F2FS_COMPR_FL |\
+ F2FS_SYNC_FL | F2FS_NODUMP_FL | F2FS_NOATIME_FL |\
+ F2FS_NOCOMPR_FL | F2FS_JOURNAL_DATA_FL |\
+ F2FS_NOTAIL_FL | F2FS_DIRSYNC_FL |\
+ F2FS_PROJINHERIT_FL)
+
+/* Flags that are appropriate for regular files (all but dir-specific ones). */
+#define F2FS_REG_FLMASK (~(F2FS_DIRSYNC_FL | F2FS_TOPDIR_FL))
+
+/* Flags that are appropriate for non-directories/regular files. */
+#define F2FS_OTHER_FLMASK (F2FS_NODUMP_FL | F2FS_NOATIME_FL)
static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags)
{
@@ -2201,6 +2258,7 @@ enum {
FI_EXTRA_ATTR, /* indicate file has extra attribute */
FI_PROJ_INHERIT, /* indicate file inherits projectid */
FI_PIN_FILE, /* indicate file should not be gced */
+ FI_ATOMIC_REVOKE_REQUEST, /* request to drop atomic data */
};
static inline void __mark_inode_dirty_flag(struct inode *inode,
@@ -2299,7 +2357,7 @@ static inline void f2fs_i_depth_write(struct inode *inode, unsigned int depth)
static inline void f2fs_i_gc_failures_write(struct inode *inode,
unsigned int count)
{
- F2FS_I(inode)->i_gc_failures = count;
+ F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN] = count;
f2fs_mark_inode_dirty_sync(inode, true);
}
@@ -2460,6 +2518,7 @@ static inline void clear_file(struct inode *inode, int type)
static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
{
+ struct timespec ts;
bool ret;
if (dsync) {
@@ -2475,11 +2534,14 @@ static inline bool f2fs_skip_inode_update(struct inode *inode, int dsync)
i_size_read(inode) & ~PAGE_MASK)
return false;
- if (!timespec_equal(F2FS_I(inode)->i_disk_time, &inode->i_atime))
+ ts = timespec64_to_timespec(inode->i_atime);
+ if (!timespec_equal(F2FS_I(inode)->i_disk_time, &ts))
return false;
- if (!timespec_equal(F2FS_I(inode)->i_disk_time + 1, &inode->i_ctime))
+ ts = timespec64_to_timespec(inode->i_ctime);
+ if (!timespec_equal(F2FS_I(inode)->i_disk_time + 1, &ts))
return false;
- if (!timespec_equal(F2FS_I(inode)->i_disk_time + 2, &inode->i_mtime))
+ ts = timespec64_to_timespec(inode->i_mtime);
+ if (!timespec_equal(F2FS_I(inode)->i_disk_time + 2, &ts))
return false;
if (!timespec_equal(F2FS_I(inode)->i_disk_time + 3,
&F2FS_I(inode)->i_crtime))
@@ -2568,7 +2630,7 @@ static inline int get_inline_xattr_addrs(struct inode *inode)
return F2FS_I(inode)->i_inline_xattr_size;
}
-#define get_inode_mode(i) \
+#define f2fs_get_inode_mode(i) \
((is_inode_flag_set(i, FI_ACL_MODE)) ? \
(F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
@@ -2607,18 +2669,25 @@ static inline void f2fs_update_iostat(struct f2fs_sb_info *sbi,
spin_unlock(&sbi->iostat_lock);
}
+static inline bool is_valid_blkaddr(block_t blkaddr)
+{
+ if (blkaddr == NEW_ADDR || blkaddr == NULL_ADDR)
+ return false;
+ return true;
+}
+
/*
* file.c
*/
int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync);
-void truncate_data_blocks(struct dnode_of_data *dn);
-int truncate_blocks(struct inode *inode, u64 from, bool lock);
+void f2fs_truncate_data_blocks(struct dnode_of_data *dn);
+int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock);
int f2fs_truncate(struct inode *inode);
int f2fs_getattr(const struct path *path, struct kstat *stat,
u32 request_mask, unsigned int flags);
int f2fs_setattr(struct dentry *dentry, struct iattr *attr);
-int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end);
-void truncate_data_blocks_range(struct dnode_of_data *dn, int count);
+int f2fs_truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end);
+void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count);
int f2fs_precache_extents(struct inode *inode);
long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
@@ -2632,38 +2701,37 @@ bool f2fs_inode_chksum_verify(struct f2fs_sb_info *sbi, struct page *page);
void f2fs_inode_chksum_set(struct f2fs_sb_info *sbi, struct page *page);
struct inode *f2fs_iget(struct super_block *sb, unsigned long ino);
struct inode *f2fs_iget_retry(struct super_block *sb, unsigned long ino);
-int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink);
-void update_inode(struct inode *inode, struct page *node_page);
-void update_inode_page(struct inode *inode);
+int f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink);
+void f2fs_update_inode(struct inode *inode, struct page *node_page);
+void f2fs_update_inode_page(struct inode *inode);
int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc);
void f2fs_evict_inode(struct inode *inode);
-void handle_failed_inode(struct inode *inode);
+void f2fs_handle_failed_inode(struct inode *inode);
/*
* namei.c
*/
-int update_extension_list(struct f2fs_sb_info *sbi, const char *name,
+int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name,
bool hot, bool set);
struct dentry *f2fs_get_parent(struct dentry *child);
/*
* dir.c
*/
-void set_de_type(struct f2fs_dir_entry *de, umode_t mode);
-unsigned char get_de_type(struct f2fs_dir_entry *de);
-struct f2fs_dir_entry *find_target_dentry(struct fscrypt_name *fname,
+unsigned char f2fs_get_de_type(struct f2fs_dir_entry *de);
+struct f2fs_dir_entry *f2fs_find_target_dentry(struct fscrypt_name *fname,
f2fs_hash_t namehash, int *max_slots,
struct f2fs_dentry_ptr *d);
int f2fs_fill_dentries(struct dir_context *ctx, struct f2fs_dentry_ptr *d,
unsigned int start_pos, struct fscrypt_str *fstr);
-void do_make_empty_dir(struct inode *inode, struct inode *parent,
+void f2fs_do_make_empty_dir(struct inode *inode, struct inode *parent,
struct f2fs_dentry_ptr *d);
-struct page *init_inode_metadata(struct inode *inode, struct inode *dir,
+struct page *f2fs_init_inode_metadata(struct inode *inode, struct inode *dir,
const struct qstr *new_name,
const struct qstr *orig_name, struct page *dpage);
-void update_parent_metadata(struct inode *dir, struct inode *inode,
+void f2fs_update_parent_metadata(struct inode *dir, struct inode *inode,
unsigned int current_depth);
-int room_for_filename(const void *bitmap, int slots, int max_slots);
+int f2fs_room_for_filename(const void *bitmap, int slots, int max_slots);
void f2fs_drop_nlink(struct inode *dir, struct inode *inode);
struct f2fs_dir_entry *__f2fs_find_entry(struct inode *dir,
struct fscrypt_name *fname, struct page **res_page);
@@ -2680,9 +2748,9 @@ void f2fs_update_dentry(nid_t ino, umode_t mode, struct f2fs_dentry_ptr *d,
int f2fs_add_regular_entry(struct inode *dir, const struct qstr *new_name,
const struct qstr *orig_name,
struct inode *inode, nid_t ino, umode_t mode);
-int __f2fs_do_add_link(struct inode *dir, struct fscrypt_name *fname,
+int f2fs_add_dentry(struct inode *dir, struct fscrypt_name *fname,
struct inode *inode, nid_t ino, umode_t mode);
-int __f2fs_add_link(struct inode *dir, const struct qstr *name,
+int f2fs_do_add_link(struct inode *dir, const struct qstr *name,
struct inode *inode, nid_t ino, umode_t mode);
void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
struct inode *dir, struct inode *inode);
@@ -2691,7 +2759,7 @@ bool f2fs_empty_dir(struct inode *dir);
static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
{
- return __f2fs_add_link(d_inode(dentry->d_parent), &dentry->d_name,
+ return f2fs_do_add_link(d_inode(dentry->d_parent), &dentry->d_name,
inode, inode->i_ino, inode->i_mode);
}
@@ -2706,7 +2774,7 @@ int f2fs_commit_super(struct f2fs_sb_info *sbi, bool recover);
int f2fs_sync_fs(struct super_block *sb, int sync);
extern __printf(3, 4)
void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...);
-int sanity_check_ckpt(struct f2fs_sb_info *sbi);
+int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi);
/*
* hash.c
@@ -2720,179 +2788,183 @@ f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info,
struct dnode_of_data;
struct node_info;
-bool available_free_memory(struct f2fs_sb_info *sbi, int type);
-int need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid);
-bool is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid);
-bool need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino);
-void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni);
-pgoff_t get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs);
-int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode);
-int truncate_inode_blocks(struct inode *inode, pgoff_t from);
-int truncate_xattr_node(struct inode *inode);
-int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino);
-int remove_inode_page(struct inode *inode);
-struct page *new_inode_page(struct inode *inode);
-struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs);
-void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid);
-struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid);
-struct page *get_node_page_ra(struct page *parent, int start);
-void move_node_page(struct page *node_page, int gc_type);
-int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
+int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid);
+bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type);
+int f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid);
+bool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid);
+bool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino);
+void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
+ struct node_info *ni);
+pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs);
+int f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode);
+int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from);
+int f2fs_truncate_xattr_node(struct inode *inode);
+int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino);
+int f2fs_remove_inode_page(struct inode *inode);
+struct page *f2fs_new_inode_page(struct inode *inode);
+struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs);
+void f2fs_ra_node_page(struct f2fs_sb_info *sbi, nid_t nid);
+struct page *f2fs_get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid);
+struct page *f2fs_get_node_page_ra(struct page *parent, int start);
+void f2fs_move_node_page(struct page *node_page, int gc_type);
+int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
struct writeback_control *wbc, bool atomic);
-int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc,
+int f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
+ struct writeback_control *wbc,
bool do_balance, enum iostat_type io_type);
-void build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount);
-bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid);
-void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid);
-void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid);
-int try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink);
-void recover_inline_xattr(struct inode *inode, struct page *page);
-int recover_xattr_data(struct inode *inode, struct page *page);
-int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page);
-void restore_node_summary(struct f2fs_sb_info *sbi,
+void f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount);
+bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid);
+void f2fs_alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid);
+void f2fs_alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid);
+int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink);
+void f2fs_recover_inline_xattr(struct inode *inode, struct page *page);
+int f2fs_recover_xattr_data(struct inode *inode, struct page *page);
+int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page);
+void f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
unsigned int segno, struct f2fs_summary_block *sum);
-void flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
-int build_node_manager(struct f2fs_sb_info *sbi);
-void destroy_node_manager(struct f2fs_sb_info *sbi);
-int __init create_node_manager_caches(void);
-void destroy_node_manager_caches(void);
+void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
+int f2fs_build_node_manager(struct f2fs_sb_info *sbi);
+void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi);
+int __init f2fs_create_node_manager_caches(void);
+void f2fs_destroy_node_manager_caches(void);
/*
* segment.c
*/
-bool need_SSR(struct f2fs_sb_info *sbi);
-void register_inmem_page(struct inode *inode, struct page *page);
-void drop_inmem_pages_all(struct f2fs_sb_info *sbi);
-void drop_inmem_pages(struct inode *inode);
-void drop_inmem_page(struct inode *inode, struct page *page);
-int commit_inmem_pages(struct inode *inode);
+bool f2fs_need_SSR(struct f2fs_sb_info *sbi);
+void f2fs_register_inmem_page(struct inode *inode, struct page *page);
+void f2fs_drop_inmem_pages_all(struct f2fs_sb_info *sbi, bool gc_failure);
+void f2fs_drop_inmem_pages(struct inode *inode);
+void f2fs_drop_inmem_page(struct inode *inode, struct page *page);
+int f2fs_commit_inmem_pages(struct inode *inode);
void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need);
void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi);
int f2fs_issue_flush(struct f2fs_sb_info *sbi, nid_t ino);
-int create_flush_cmd_control(struct f2fs_sb_info *sbi);
+int f2fs_create_flush_cmd_control(struct f2fs_sb_info *sbi);
int f2fs_flush_device_cache(struct f2fs_sb_info *sbi);
-void destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free);
-void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr);
-bool is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr);
-void init_discard_policy(struct discard_policy *dpolicy, int discard_type,
- unsigned int granularity);
-void drop_discard_cmd(struct f2fs_sb_info *sbi);
-void stop_discard_thread(struct f2fs_sb_info *sbi);
+void f2fs_destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free);
+void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr);
+bool f2fs_is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr);
+void f2fs_drop_discard_cmd(struct f2fs_sb_info *sbi);
+void f2fs_stop_discard_thread(struct f2fs_sb_info *sbi);
bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi);
-void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc);
-void release_discard_addrs(struct f2fs_sb_info *sbi);
-int npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
-void allocate_new_segments(struct f2fs_sb_info *sbi);
+void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
+ struct cp_control *cpc);
+void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi);
+int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra);
+void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi);
int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range);
-bool exist_trim_candidates(struct f2fs_sb_info *sbi, struct cp_control *cpc);
-struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno);
-void update_meta_page(struct f2fs_sb_info *sbi, void *src, block_t blk_addr);
-void write_meta_page(struct f2fs_sb_info *sbi, struct page *page,
+bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi,
+ struct cp_control *cpc);
+struct page *f2fs_get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno);
+void f2fs_update_meta_page(struct f2fs_sb_info *sbi, void *src,
+ block_t blk_addr);
+void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct page *page,
enum iostat_type io_type);
-void write_node_page(unsigned int nid, struct f2fs_io_info *fio);
-void write_data_page(struct dnode_of_data *dn, struct f2fs_io_info *fio);
-int rewrite_data_page(struct f2fs_io_info *fio);
-void __f2fs_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+void f2fs_do_write_node_page(unsigned int nid, struct f2fs_io_info *fio);
+void f2fs_outplace_write_data(struct dnode_of_data *dn,
+ struct f2fs_io_info *fio);
+int f2fs_inplace_write_data(struct f2fs_io_info *fio);
+void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
block_t old_blkaddr, block_t new_blkaddr,
bool recover_curseg, bool recover_newaddr);
void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
block_t old_addr, block_t new_addr,
unsigned char version, bool recover_curseg,
bool recover_newaddr);
-void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
+void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
block_t old_blkaddr, block_t *new_blkaddr,
struct f2fs_summary *sum, int type,
struct f2fs_io_info *fio, bool add_list);
void f2fs_wait_on_page_writeback(struct page *page,
enum page_type type, bool ordered);
void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr);
-void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
-void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
-int lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
+void f2fs_write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
+void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk);
+int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
unsigned int val, int alloc);
-void flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
-int build_segment_manager(struct f2fs_sb_info *sbi);
-void destroy_segment_manager(struct f2fs_sb_info *sbi);
-int __init create_segment_manager_caches(void);
-void destroy_segment_manager_caches(void);
-int rw_hint_to_seg_type(enum rw_hint hint);
-enum rw_hint io_type_to_rw_hint(struct f2fs_sb_info *sbi, enum page_type type,
- enum temp_type temp);
+void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc);
+int f2fs_build_segment_manager(struct f2fs_sb_info *sbi);
+void f2fs_destroy_segment_manager(struct f2fs_sb_info *sbi);
+int __init f2fs_create_segment_manager_caches(void);
+void f2fs_destroy_segment_manager_caches(void);
+int f2fs_rw_hint_to_seg_type(enum rw_hint hint);
+enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi,
+ enum page_type type, enum temp_type temp);
/*
* checkpoint.c
*/
void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi, bool end_io);
-struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
-struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
-struct page *get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index);
-bool is_valid_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr, int type);
-int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
+struct page *f2fs_grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
+struct page *f2fs_get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index);
+struct page *f2fs_get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index);
+bool f2fs_is_valid_meta_blkaddr(struct f2fs_sb_info *sbi,
+ block_t blkaddr, int type);
+int f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
int type, bool sync);
-void ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index);
-long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
+void f2fs_ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index);
+long f2fs_sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
long nr_to_write, enum iostat_type io_type);
-void add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type);
-void remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type);
-void release_ino_entry(struct f2fs_sb_info *sbi, bool all);
-bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode);
-void set_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
+void f2fs_add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type);
+void f2fs_remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type);
+void f2fs_release_ino_entry(struct f2fs_sb_info *sbi, bool all);
+bool f2fs_exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode);
+void f2fs_set_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
unsigned int devidx, int type);
-bool is_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
+bool f2fs_is_dirty_device(struct f2fs_sb_info *sbi, nid_t ino,
unsigned int devidx, int type);
int f2fs_sync_inode_meta(struct f2fs_sb_info *sbi);
-int acquire_orphan_inode(struct f2fs_sb_info *sbi);
-void release_orphan_inode(struct f2fs_sb_info *sbi);
-void add_orphan_inode(struct inode *inode);
-void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino);
-int recover_orphan_inodes(struct f2fs_sb_info *sbi);
-int get_valid_checkpoint(struct f2fs_sb_info *sbi);
-void update_dirty_page(struct inode *inode, struct page *page);
-void remove_dirty_inode(struct inode *inode);
-int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type);
-int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc);
-void init_ino_entry_info(struct f2fs_sb_info *sbi);
-int __init create_checkpoint_caches(void);
-void destroy_checkpoint_caches(void);
+int f2fs_acquire_orphan_inode(struct f2fs_sb_info *sbi);
+void f2fs_release_orphan_inode(struct f2fs_sb_info *sbi);
+void f2fs_add_orphan_inode(struct inode *inode);
+void f2fs_remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino);
+int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi);
+int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi);
+void f2fs_update_dirty_page(struct inode *inode, struct page *page);
+void f2fs_remove_dirty_inode(struct inode *inode);
+int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type);
+int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc);
+void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi);
+int __init f2fs_create_checkpoint_caches(void);
+void f2fs_destroy_checkpoint_caches(void);
/*
* data.c
*/
+int f2fs_init_post_read_processing(void);
+void f2fs_destroy_post_read_processing(void);
void f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type);
void f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi,
struct inode *inode, nid_t ino, pgoff_t idx,
enum page_type type);
void f2fs_flush_merged_writes(struct f2fs_sb_info *sbi);
int f2fs_submit_page_bio(struct f2fs_io_info *fio);
-int f2fs_submit_page_write(struct f2fs_io_info *fio);
+void f2fs_submit_page_write(struct f2fs_io_info *fio);
struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi,
block_t blk_addr, struct bio *bio);
int f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr);
-void set_data_blkaddr(struct dnode_of_data *dn);
+void f2fs_set_data_blkaddr(struct dnode_of_data *dn);
void f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr);
-int reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count);
-int reserve_new_block(struct dnode_of_data *dn);
+int f2fs_reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count);
+int f2fs_reserve_new_block(struct dnode_of_data *dn);
int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index);
int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from);
int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index);
-struct page *get_read_data_page(struct inode *inode, pgoff_t index,
+struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index,
int op_flags, bool for_write);
-struct page *find_data_page(struct inode *inode, pgoff_t index);
-struct page *get_lock_data_page(struct inode *inode, pgoff_t index,
+struct page *f2fs_find_data_page(struct inode *inode, pgoff_t index);
+struct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index,
bool for_write);
-struct page *get_new_data_page(struct inode *inode,
+struct page *f2fs_get_new_data_page(struct inode *inode,
struct page *ipage, pgoff_t index, bool new_i_size);
-int do_write_data_page(struct f2fs_io_info *fio);
+int f2fs_do_write_data_page(struct f2fs_io_info *fio);
int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
int create, int flag);
int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
u64 start, u64 len);
-bool should_update_inplace(struct inode *inode, struct f2fs_io_info *fio);
-bool should_update_outplace(struct inode *inode, struct f2fs_io_info *fio);
-void f2fs_set_page_dirty_nobuffers(struct page *page);
-int __f2fs_write_data_pages(struct address_space *mapping,
- struct writeback_control *wbc,
- enum iostat_type io_type);
+bool f2fs_should_update_inplace(struct inode *inode, struct f2fs_io_info *fio);
+bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio);
void f2fs_invalidate_page(struct page *page, unsigned int offset,
unsigned int length);
int f2fs_release_page(struct page *page, gfp_t wait);
@@ -2901,22 +2973,23 @@ int f2fs_migrate_page(struct address_space *mapping, struct page *newpage,
struct page *page, enum migrate_mode mode);
#endif
bool f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len);
+void f2fs_clear_radix_tree_dirty_tag(struct page *page);
/*
* gc.c
*/
-int start_gc_thread(struct f2fs_sb_info *sbi);
-void stop_gc_thread(struct f2fs_sb_info *sbi);
-block_t start_bidx_of_node(unsigned int node_ofs, struct inode *inode);
+int f2fs_start_gc_thread(struct f2fs_sb_info *sbi);
+void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi);
+block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode);
int f2fs_gc(struct f2fs_sb_info *sbi, bool sync, bool background,
unsigned int segno);
-void build_gc_manager(struct f2fs_sb_info *sbi);
+void f2fs_build_gc_manager(struct f2fs_sb_info *sbi);
/*
* recovery.c
*/
-int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only);
-bool space_for_roll_forward(struct f2fs_sb_info *sbi);
+int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only);
+bool f2fs_space_for_roll_forward(struct f2fs_sb_info *sbi);
/*
* debug.c
@@ -2954,6 +3027,7 @@ struct f2fs_stat_info {
int bg_node_segs, bg_data_segs;
int tot_blks, data_blks, node_blks;
int bg_data_blks, bg_node_blks;
+ unsigned long long skipped_atomic_files[2];
int curseg[NR_CURSEG_TYPE];
int cursec[NR_CURSEG_TYPE];
int curzone[NR_CURSEG_TYPE];
@@ -3120,29 +3194,31 @@ extern const struct inode_operations f2fs_dir_inode_operations;
extern const struct inode_operations f2fs_symlink_inode_operations;
extern const struct inode_operations f2fs_encrypted_symlink_inode_operations;
extern const struct inode_operations f2fs_special_inode_operations;
-extern struct kmem_cache *inode_entry_slab;
+extern struct kmem_cache *f2fs_inode_entry_slab;
/*
* inline.c
*/
bool f2fs_may_inline_data(struct inode *inode);
bool f2fs_may_inline_dentry(struct inode *inode);
-void read_inline_data(struct page *page, struct page *ipage);
-void truncate_inline_inode(struct inode *inode, struct page *ipage, u64 from);
+void f2fs_do_read_inline_data(struct page *page, struct page *ipage);
+void f2fs_truncate_inline_inode(struct inode *inode,
+ struct page *ipage, u64 from);
int f2fs_read_inline_data(struct inode *inode, struct page *page);
int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page);
int f2fs_convert_inline_inode(struct inode *inode);
int f2fs_write_inline_data(struct inode *inode, struct page *page);
-bool recover_inline_data(struct inode *inode, struct page *npage);
-struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
+bool f2fs_recover_inline_data(struct inode *inode, struct page *npage);
+struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir,
struct fscrypt_name *fname, struct page **res_page);
-int make_empty_inline_dir(struct inode *inode, struct inode *parent,
+int f2fs_make_empty_inline_dir(struct inode *inode, struct inode *parent,
struct page *ipage);
int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,
const struct qstr *orig_name,
struct inode *inode, nid_t ino, umode_t mode);
-void f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry, struct page *page,
- struct inode *dir, struct inode *inode);
+void f2fs_delete_inline_entry(struct f2fs_dir_entry *dentry,
+ struct page *page, struct inode *dir,
+ struct inode *inode);
bool f2fs_empty_inline_dir(struct inode *dir);
int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx,
struct fscrypt_str *fstr);
@@ -3163,17 +3239,17 @@ void f2fs_leave_shrinker(struct f2fs_sb_info *sbi);
/*
* extent_cache.c
*/
-struct rb_entry *__lookup_rb_tree(struct rb_root *root,
+struct rb_entry *f2fs_lookup_rb_tree(struct rb_root *root,
struct rb_entry *cached_re, unsigned int ofs);
-struct rb_node **__lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi,
+struct rb_node **f2fs_lookup_rb_tree_for_insert(struct f2fs_sb_info *sbi,
struct rb_root *root, struct rb_node **parent,
unsigned int ofs);
-struct rb_entry *__lookup_rb_tree_ret(struct rb_root *root,
+struct rb_entry *f2fs_lookup_rb_tree_ret(struct rb_root *root,
struct rb_entry *cached_re, unsigned int ofs,
struct rb_entry **prev_entry, struct rb_entry **next_entry,
struct rb_node ***insert_p, struct rb_node **insert_parent,
bool force);
-bool __check_rb_tree_consistence(struct f2fs_sb_info *sbi,
+bool f2fs_check_rb_tree_consistence(struct f2fs_sb_info *sbi,
struct rb_root *root);
unsigned int f2fs_shrink_extent_tree(struct f2fs_sb_info *sbi, int nr_shrink);
bool f2fs_init_extent_tree(struct inode *inode, struct f2fs_extent *i_ext);
@@ -3185,9 +3261,9 @@ bool f2fs_lookup_extent_cache(struct inode *inode, pgoff_t pgofs,
void f2fs_update_extent_cache(struct dnode_of_data *dn);
void f2fs_update_extent_cache_range(struct dnode_of_data *dn,
pgoff_t fofs, block_t blkaddr, unsigned int len);
-void init_extent_cache_info(struct f2fs_sb_info *sbi);
-int __init create_extent_cache(void);
-void destroy_extent_cache(void);
+void f2fs_init_extent_cache_info(struct f2fs_sb_info *sbi);
+int __init f2fs_create_extent_cache(void);
+void f2fs_destroy_extent_cache(void);
/*
* sysfs.c
@@ -3218,9 +3294,13 @@ static inline void f2fs_set_encrypted_inode(struct inode *inode)
#endif
}
-static inline bool f2fs_bio_encrypted(struct bio *bio)
+/*
+ * Returns true if the reads of the inode's data need to undergo some
+ * postprocessing step, like decryption or authenticity verification.
+ */
+static inline bool f2fs_post_read_required(struct inode *inode)
{
- return bio->bi_private != NULL;
+ return f2fs_encrypted_file(inode);
}
#define F2FS_FEATURE_FUNCS(name, flagname) \
@@ -3288,7 +3368,7 @@ static inline bool f2fs_may_encrypt(struct inode *inode)
static inline bool f2fs_force_buffered_io(struct inode *inode, int rw)
{
- return (f2fs_encrypted_file(inode) ||
+ return (f2fs_post_read_required(inode) ||
(rw == WRITE && test_opt(F2FS_I_SB(inode), LFS)) ||
F2FS_I_SB(inode)->s_ndevs);
}
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 6b94f19..6880c6f 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -33,19 +33,19 @@
#include "trace.h"
#include <trace/events/f2fs.h>
-static int f2fs_filemap_fault(struct vm_fault *vmf)
+static vm_fault_t f2fs_filemap_fault(struct vm_fault *vmf)
{
struct inode *inode = file_inode(vmf->vma->vm_file);
- int err;
+ vm_fault_t ret;
down_read(&F2FS_I(inode)->i_mmap_sem);
- err = filemap_fault(vmf);
+ ret = filemap_fault(vmf);
up_read(&F2FS_I(inode)->i_mmap_sem);
- return err;
+ return ret;
}
-static int f2fs_vm_page_mkwrite(struct vm_fault *vmf)
+static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
{
struct page *page = vmf->page;
struct inode *inode = file_inode(vmf->vma->vm_file);
@@ -95,7 +95,8 @@ static int f2fs_vm_page_mkwrite(struct vm_fault *vmf)
/* page is wholly or partially inside EOF */
if (((loff_t)(page->index + 1) << PAGE_SHIFT) >
i_size_read(inode)) {
- unsigned offset;
+ loff_t offset;
+
offset = i_size_read(inode) & ~PAGE_MASK;
zero_user_segment(page, offset, PAGE_SIZE);
}
@@ -110,8 +111,8 @@ mapped:
/* fill the page */
f2fs_wait_on_page_writeback(page, DATA, false);
- /* wait for GCed encrypted page writeback */
- if (f2fs_encrypted_file(inode))
+ /* wait for GCed page writeback via META_MAPPING */
+ if (f2fs_post_read_required(inode))
f2fs_wait_on_block_writeback(sbi, dn.data_blkaddr);
out_sem:
@@ -157,17 +158,18 @@ static inline enum cp_reason_type need_do_checkpoint(struct inode *inode)
cp_reason = CP_SB_NEED_CP;
else if (file_wrong_pino(inode))
cp_reason = CP_WRONG_PINO;
- else if (!space_for_roll_forward(sbi))
+ else if (!f2fs_space_for_roll_forward(sbi))
cp_reason = CP_NO_SPC_ROLL;
- else if (!is_checkpointed_node(sbi, F2FS_I(inode)->i_pino))
+ else if (!f2fs_is_checkpointed_node(sbi, F2FS_I(inode)->i_pino))
cp_reason = CP_NODE_NEED_CP;
else if (test_opt(sbi, FASTBOOT))
cp_reason = CP_FASTBOOT_MODE;
else if (F2FS_OPTION(sbi).active_logs == 2)
cp_reason = CP_SPEC_LOG_NUM;
else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT &&
- need_dentry_mark(sbi, inode->i_ino) &&
- exist_written_data(sbi, F2FS_I(inode)->i_pino, TRANS_DIR_INO))
+ f2fs_need_dentry_mark(sbi, inode->i_ino) &&
+ f2fs_exist_written_data(sbi, F2FS_I(inode)->i_pino,
+ TRANS_DIR_INO))
cp_reason = CP_RECOVER_DIR;
return cp_reason;
@@ -178,7 +180,7 @@ static bool need_inode_page_update(struct f2fs_sb_info *sbi, nid_t ino)
struct page *i = find_get_page(NODE_MAPPING(sbi), ino);
bool ret = false;
/* But we need to avoid that there are some inode updates */
- if ((i && PageDirty(i)) || need_inode_block_update(sbi, ino))
+ if ((i && PageDirty(i)) || f2fs_need_inode_block_update(sbi, ino))
ret = true;
f2fs_put_page(i, 0);
return ret;
@@ -238,14 +240,14 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end,
* if there is no written data, don't waste time to write recovery info.
*/
if (!is_inode_flag_set(inode, FI_APPEND_WRITE) &&
- !exist_written_data(sbi, ino, APPEND_INO)) {
+ !f2fs_exist_written_data(sbi, ino, APPEND_INO)) {
/* it may call write_inode just prior to fsync */
if (need_inode_page_update(sbi, ino))
goto go_write;
if (is_inode_flag_set(inode, FI_UPDATE_WRITE) ||
- exist_written_data(sbi, ino, UPDATE_INO))
+ f2fs_exist_written_data(sbi, ino, UPDATE_INO))
goto flush_out;
goto out;
}
@@ -272,7 +274,9 @@ go_write:
goto out;
}
sync_nodes:
- ret = fsync_node_pages(sbi, inode, &wbc, atomic);
+ atomic_inc(&sbi->wb_sync_req[NODE]);
+ ret = f2fs_fsync_node_pages(sbi, inode, &wbc, atomic);
+ atomic_dec(&sbi->wb_sync_req[NODE]);
if (ret)
goto out;
@@ -282,7 +286,7 @@ sync_nodes:
goto out;
}
- if (need_inode_block_update(sbi, ino)) {
+ if (f2fs_need_inode_block_update(sbi, ino)) {
f2fs_mark_inode_dirty_sync(inode, true);
f2fs_write_inode(inode, NULL);
goto sync_nodes;
@@ -297,21 +301,21 @@ sync_nodes:
* given fsync mark.
*/
if (!atomic) {
- ret = wait_on_node_pages_writeback(sbi, ino);
+ ret = f2fs_wait_on_node_pages_writeback(sbi, ino);
if (ret)
goto out;
}
/* once recovery info is written, don't need to tack this */
- remove_ino_entry(sbi, ino, APPEND_INO);
+ f2fs_remove_ino_entry(sbi, ino, APPEND_INO);
clear_inode_flag(inode, FI_APPEND_WRITE);
flush_out:
- if (!atomic)
+ if (!atomic && F2FS_OPTION(sbi).fsync_mode != FSYNC_MODE_NOBARRIER)
ret = f2fs_issue_flush(sbi, inode->i_ino);
if (!ret) {
- remove_ino_entry(sbi, ino, UPDATE_INO);
+ f2fs_remove_ino_entry(sbi, ino, UPDATE_INO);
clear_inode_flag(inode, FI_UPDATE_WRITE);
- remove_ino_entry(sbi, ino, FLUSH_INO);
+ f2fs_remove_ino_entry(sbi, ino, FLUSH_INO);
}
f2fs_update_time(sbi, REQ_TIME);
out:
@@ -352,7 +356,7 @@ static bool __found_offset(block_t blkaddr, pgoff_t dirty, pgoff_t pgofs,
switch (whence) {
case SEEK_DATA:
if ((blkaddr == NEW_ADDR && dirty == pgofs) ||
- (blkaddr != NEW_ADDR && blkaddr != NULL_ADDR))
+ is_valid_blkaddr(blkaddr))
return true;
break;
case SEEK_HOLE:
@@ -392,13 +396,13 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
for (; data_ofs < isize; data_ofs = (loff_t)pgofs << PAGE_SHIFT) {
set_new_dnode(&dn, inode, NULL, NULL, 0);
- err = get_dnode_of_data(&dn, pgofs, LOOKUP_NODE);
+ err = f2fs_get_dnode_of_data(&dn, pgofs, LOOKUP_NODE);
if (err && err != -ENOENT) {
goto fail;
} else if (err == -ENOENT) {
/* direct node does not exists */
if (whence == SEEK_DATA) {
- pgofs = get_next_page_offset(&dn, pgofs);
+ pgofs = f2fs_get_next_page_offset(&dn, pgofs);
continue;
} else {
goto found;
@@ -412,6 +416,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence)
dn.ofs_in_node++, pgofs++,
data_ofs = (loff_t)pgofs << PAGE_SHIFT) {
block_t blkaddr;
+
blkaddr = datablock_addr(dn.inode,
dn.node_page, dn.ofs_in_node);
@@ -486,7 +491,7 @@ static int f2fs_file_open(struct inode *inode, struct file *filp)
return dquot_file_open(inode, filp);
}
-void truncate_data_blocks_range(struct dnode_of_data *dn, int count)
+void f2fs_truncate_data_blocks_range(struct dnode_of_data *dn, int count)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
struct f2fs_node *raw_node;
@@ -502,12 +507,13 @@ void truncate_data_blocks_range(struct dnode_of_data *dn, int count)
for (; count > 0; count--, addr++, dn->ofs_in_node++) {
block_t blkaddr = le32_to_cpu(*addr);
+
if (blkaddr == NULL_ADDR)
continue;
dn->data_blkaddr = NULL_ADDR;
- set_data_blkaddr(dn);
- invalidate_blocks(sbi, blkaddr);
+ f2fs_set_data_blkaddr(dn);
+ f2fs_invalidate_blocks(sbi, blkaddr);
if (dn->ofs_in_node == 0 && IS_INODE(dn->node_page))
clear_inode_flag(dn->inode, FI_FIRST_BLOCK_WRITTEN);
nr_free++;
@@ -519,7 +525,7 @@ void truncate_data_blocks_range(struct dnode_of_data *dn, int count)
* once we invalidate valid blkaddr in range [ofs, ofs + count],
* we will invalidate all blkaddr in the whole range.
*/
- fofs = start_bidx_of_node(ofs_of_node(dn->node_page),
+ fofs = f2fs_start_bidx_of_node(ofs_of_node(dn->node_page),
dn->inode) + ofs;
f2fs_update_extent_cache_range(dn, fofs, 0, len);
dec_valid_block_count(sbi, dn->inode, nr_free);
@@ -531,15 +537,15 @@ void truncate_data_blocks_range(struct dnode_of_data *dn, int count)
dn->ofs_in_node, nr_free);
}
-void truncate_data_blocks(struct dnode_of_data *dn)
+void f2fs_truncate_data_blocks(struct dnode_of_data *dn)
{
- truncate_data_blocks_range(dn, ADDRS_PER_BLOCK);
+ f2fs_truncate_data_blocks_range(dn, ADDRS_PER_BLOCK);
}
static int truncate_partial_data_page(struct inode *inode, u64 from,
bool cache_only)
{
- unsigned offset = from & (PAGE_SIZE - 1);
+ loff_t offset = from & (PAGE_SIZE - 1);
pgoff_t index = from >> PAGE_SHIFT;
struct address_space *mapping = inode->i_mapping;
struct page *page;
@@ -555,7 +561,7 @@ static int truncate_partial_data_page(struct inode *inode, u64 from,
return 0;
}
- page = get_lock_data_page(inode, index, true);
+ page = f2fs_get_lock_data_page(inode, index, true);
if (IS_ERR(page))
return PTR_ERR(page) == -ENOENT ? 0 : PTR_ERR(page);
truncate_out:
@@ -570,7 +576,7 @@ truncate_out:
return 0;
}
-int truncate_blocks(struct inode *inode, u64 from, bool lock)
+int f2fs_truncate_blocks(struct inode *inode, u64 from, bool lock)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct dnode_of_data dn;
@@ -589,21 +595,21 @@ int truncate_blocks(struct inode *inode, u64 from, bool lock)
if (lock)
f2fs_lock_op(sbi);
- ipage = get_node_page(sbi, inode->i_ino);
+ ipage = f2fs_get_node_page(sbi, inode->i_ino);
if (IS_ERR(ipage)) {
err = PTR_ERR(ipage);
goto out;
}
if (f2fs_has_inline_data(inode)) {
- truncate_inline_inode(inode, ipage, from);
+ f2fs_truncate_inline_inode(inode, ipage, from);
f2fs_put_page(ipage, 1);
truncate_page = true;
goto out;
}
set_new_dnode(&dn, inode, ipage, NULL, 0);
- err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE_RA);
+ err = f2fs_get_dnode_of_data(&dn, free_from, LOOKUP_NODE_RA);
if (err) {
if (err == -ENOENT)
goto free_next;
@@ -616,13 +622,13 @@ int truncate_blocks(struct inode *inode, u64 from, bool lock)
f2fs_bug_on(sbi, count < 0);
if (dn.ofs_in_node || IS_INODE(dn.node_page)) {
- truncate_data_blocks_range(&dn, count);
+ f2fs_truncate_data_blocks_range(&dn, count);
free_from += count;
}
f2fs_put_dnode(&dn);
free_next:
- err = truncate_inode_blocks(inode, free_from);
+ err = f2fs_truncate_inode_blocks(inode, free_from);
out:
if (lock)
f2fs_unlock_op(sbi);
@@ -661,7 +667,7 @@ int f2fs_truncate(struct inode *inode)
return err;
}
- err = truncate_blocks(inode, i_size_read(inode), true);
+ err = f2fs_truncate_blocks(inode, i_size_read(inode), true);
if (err)
return err;
@@ -686,16 +692,16 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
stat->btime.tv_nsec = fi->i_crtime.tv_nsec;
}
- flags = fi->i_flags & (FS_FL_USER_VISIBLE | FS_PROJINHERIT_FL);
- if (flags & FS_APPEND_FL)
+ flags = fi->i_flags & F2FS_FL_USER_VISIBLE;
+ if (flags & F2FS_APPEND_FL)
stat->attributes |= STATX_ATTR_APPEND;
- if (flags & FS_COMPR_FL)
+ if (flags & F2FS_COMPR_FL)
stat->attributes |= STATX_ATTR_COMPRESSED;
if (f2fs_encrypted_inode(inode))
stat->attributes |= STATX_ATTR_ENCRYPTED;
- if (flags & FS_IMMUTABLE_FL)
+ if (flags & F2FS_IMMUTABLE_FL)
stat->attributes |= STATX_ATTR_IMMUTABLE;
- if (flags & FS_NODUMP_FL)
+ if (flags & F2FS_NODUMP_FL)
stat->attributes |= STATX_ATTR_NODUMP;
stat->attributes_mask |= (STATX_ATTR_APPEND |
@@ -724,14 +730,14 @@ static void __setattr_copy(struct inode *inode, const struct iattr *attr)
if (ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (ia_valid & ATTR_ATIME)
- inode->i_atime = timespec_trunc(attr->ia_atime,
- inode->i_sb->s_time_gran);
+ inode->i_atime = timespec64_trunc(attr->ia_atime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MTIME)
- inode->i_mtime = timespec_trunc(attr->ia_mtime,
- inode->i_sb->s_time_gran);
+ inode->i_mtime = timespec64_trunc(attr->ia_mtime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_CTIME)
- inode->i_ctime = timespec_trunc(attr->ia_ctime,
- inode->i_sb->s_time_gran);
+ inode->i_ctime = timespec64_trunc(attr->ia_ctime,
+ inode->i_sb->s_time_gran);
if (ia_valid & ATTR_MODE) {
umode_t mode = attr->ia_mode;
@@ -811,7 +817,7 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
__setattr_copy(inode, attr);
if (attr->ia_valid & ATTR_MODE) {
- err = posix_acl_chmod(inode, get_inode_mode(inode));
+ err = posix_acl_chmod(inode, f2fs_get_inode_mode(inode));
if (err || is_inode_flag_set(inode, FI_ACL_MODE)) {
inode->i_mode = F2FS_I(inode)->i_acl_mode;
clear_inode_flag(inode, FI_ACL_MODE);
@@ -850,7 +856,7 @@ static int fill_zero(struct inode *inode, pgoff_t index,
f2fs_balance_fs(sbi, true);
f2fs_lock_op(sbi);
- page = get_new_data_page(inode, NULL, index, false);
+ page = f2fs_get_new_data_page(inode, NULL, index, false);
f2fs_unlock_op(sbi);
if (IS_ERR(page))
@@ -863,7 +869,7 @@ static int fill_zero(struct inode *inode, pgoff_t index,
return 0;
}
-int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
+int f2fs_truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
{
int err;
@@ -872,10 +878,11 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
pgoff_t end_offset, count;
set_new_dnode(&dn, inode, NULL, NULL, 0);
- err = get_dnode_of_data(&dn, pg_start, LOOKUP_NODE);
+ err = f2fs_get_dnode_of_data(&dn, pg_start, LOOKUP_NODE);
if (err) {
if (err == -ENOENT) {
- pg_start = get_next_page_offset(&dn, pg_start);
+ pg_start = f2fs_get_next_page_offset(&dn,
+ pg_start);
continue;
}
return err;
@@ -886,7 +893,7 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
f2fs_bug_on(F2FS_I_SB(inode), count == 0 || count > end_offset);
- truncate_data_blocks_range(&dn, count);
+ f2fs_truncate_data_blocks_range(&dn, count);
f2fs_put_dnode(&dn);
pg_start += count;
@@ -942,7 +949,7 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
blk_end - 1);
f2fs_lock_op(sbi);
- ret = truncate_hole(inode, pg_start, pg_end);
+ ret = f2fs_truncate_hole(inode, pg_start, pg_end);
f2fs_unlock_op(sbi);
up_write(&F2FS_I(inode)->i_mmap_sem);
}
@@ -960,7 +967,7 @@ static int __read_out_blkaddrs(struct inode *inode, block_t *blkaddr,
next_dnode:
set_new_dnode(&dn, inode, NULL, NULL, 0);
- ret = get_dnode_of_data(&dn, off, LOOKUP_NODE_RA);
+ ret = f2fs_get_dnode_of_data(&dn, off, LOOKUP_NODE_RA);
if (ret && ret != -ENOENT) {
return ret;
} else if (ret == -ENOENT) {
@@ -977,7 +984,7 @@ next_dnode:
for (i = 0; i < done; i++, blkaddr++, do_replace++, dn.ofs_in_node++) {
*blkaddr = datablock_addr(dn.inode,
dn.node_page, dn.ofs_in_node);
- if (!is_checkpointed_data(sbi, *blkaddr)) {
+ if (!f2fs_is_checkpointed_data(sbi, *blkaddr)) {
if (test_opt(sbi, LFS)) {
f2fs_put_dnode(&dn);
@@ -1010,10 +1017,10 @@ static int __roll_back_blkaddrs(struct inode *inode, block_t *blkaddr,
continue;
set_new_dnode(&dn, inode, NULL, NULL, 0);
- ret = get_dnode_of_data(&dn, off + i, LOOKUP_NODE_RA);
+ ret = f2fs_get_dnode_of_data(&dn, off + i, LOOKUP_NODE_RA);
if (ret) {
dec_valid_block_count(sbi, inode, 1);
- invalidate_blocks(sbi, *blkaddr);
+ f2fs_invalidate_blocks(sbi, *blkaddr);
} else {
f2fs_update_data_blkaddr(&dn, *blkaddr);
}
@@ -1043,18 +1050,18 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,
pgoff_t ilen;
set_new_dnode(&dn, dst_inode, NULL, NULL, 0);
- ret = get_dnode_of_data(&dn, dst + i, ALLOC_NODE);
+ ret = f2fs_get_dnode_of_data(&dn, dst + i, ALLOC_NODE);
if (ret)
return ret;
- get_node_info(sbi, dn.nid, &ni);
+ f2fs_get_node_info(sbi, dn.nid, &ni);
ilen = min((pgoff_t)
ADDRS_PER_PAGE(dn.node_page, dst_inode) -
dn.ofs_in_node, len - i);
do {
dn.data_blkaddr = datablock_addr(dn.inode,
dn.node_page, dn.ofs_in_node);
- truncate_data_blocks_range(&dn, 1);
+ f2fs_truncate_data_blocks_range(&dn, 1);
if (do_replace[i]) {
f2fs_i_blocks_write(src_inode,
@@ -1077,10 +1084,11 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,
} else {
struct page *psrc, *pdst;
- psrc = get_lock_data_page(src_inode, src + i, true);
+ psrc = f2fs_get_lock_data_page(src_inode,
+ src + i, true);
if (IS_ERR(psrc))
return PTR_ERR(psrc);
- pdst = get_new_data_page(dst_inode, NULL, dst + i,
+ pdst = f2fs_get_new_data_page(dst_inode, NULL, dst + i,
true);
if (IS_ERR(pdst)) {
f2fs_put_page(psrc, 1);
@@ -1091,7 +1099,8 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,
f2fs_put_page(pdst, 1);
f2fs_put_page(psrc, 1);
- ret = truncate_hole(src_inode, src + i, src + i + 1);
+ ret = f2fs_truncate_hole(src_inode,
+ src + i, src + i + 1);
if (ret)
return ret;
i++;
@@ -1113,12 +1122,14 @@ static int __exchange_data_block(struct inode *src_inode,
olen = min((pgoff_t)4 * ADDRS_PER_BLOCK, len);
src_blkaddr = f2fs_kvzalloc(F2FS_I_SB(src_inode),
- sizeof(block_t) * olen, GFP_KERNEL);
+ array_size(olen, sizeof(block_t)),
+ GFP_KERNEL);
if (!src_blkaddr)
return -ENOMEM;
do_replace = f2fs_kvzalloc(F2FS_I_SB(src_inode),
- sizeof(int) * olen, GFP_KERNEL);
+ array_size(olen, sizeof(int)),
+ GFP_KERNEL);
if (!do_replace) {
kvfree(src_blkaddr);
return -ENOMEM;
@@ -1144,7 +1155,7 @@ static int __exchange_data_block(struct inode *src_inode,
return 0;
roll_back:
- __roll_back_blkaddrs(src_inode, src_blkaddr, do_replace, src, len);
+ __roll_back_blkaddrs(src_inode, src_blkaddr, do_replace, src, olen);
kvfree(src_blkaddr);
kvfree(do_replace);
return ret;
@@ -1187,7 +1198,7 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
pg_end = (offset + len) >> PAGE_SHIFT;
/* avoid gc operation during block exchange */
- down_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
+ down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
down_write(&F2FS_I(inode)->i_mmap_sem);
/* write out all dirty pages from offset */
@@ -1208,12 +1219,12 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
new_size = i_size_read(inode) - len;
truncate_pagecache(inode, new_size);
- ret = truncate_blocks(inode, new_size, true);
+ ret = f2fs_truncate_blocks(inode, new_size, true);
if (!ret)
f2fs_i_size_write(inode, new_size);
out_unlock:
up_write(&F2FS_I(inode)->i_mmap_sem);
- up_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
+ up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
return ret;
}
@@ -1233,7 +1244,7 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,
}
dn->ofs_in_node = ofs_in_node;
- ret = reserve_new_blocks(dn, count);
+ ret = f2fs_reserve_new_blocks(dn, count);
if (ret)
return ret;
@@ -1242,7 +1253,7 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,
dn->data_blkaddr = datablock_addr(dn->inode,
dn->node_page, dn->ofs_in_node);
/*
- * reserve_new_blocks will not guarantee entire block
+ * f2fs_reserve_new_blocks will not guarantee entire block
* allocation.
*/
if (dn->data_blkaddr == NULL_ADDR) {
@@ -1250,9 +1261,9 @@ static int f2fs_do_zero_range(struct dnode_of_data *dn, pgoff_t start,
break;
}
if (dn->data_blkaddr != NEW_ADDR) {
- invalidate_blocks(sbi, dn->data_blkaddr);
+ f2fs_invalidate_blocks(sbi, dn->data_blkaddr);
dn->data_blkaddr = NEW_ADDR;
- set_data_blkaddr(dn);
+ f2fs_set_data_blkaddr(dn);
}
}
@@ -1318,7 +1329,7 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
f2fs_lock_op(sbi);
set_new_dnode(&dn, inode, NULL, NULL, 0);
- ret = get_dnode_of_data(&dn, index, ALLOC_NODE);
+ ret = f2fs_get_dnode_of_data(&dn, index, ALLOC_NODE);
if (ret) {
f2fs_unlock_op(sbi);
goto out;
@@ -1389,10 +1400,10 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
f2fs_balance_fs(sbi, true);
/* avoid gc operation during block exchange */
- down_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
+ down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
down_write(&F2FS_I(inode)->i_mmap_sem);
- ret = truncate_blocks(inode, i_size_read(inode), true);
+ ret = f2fs_truncate_blocks(inode, i_size_read(inode), true);
if (ret)
goto out;
@@ -1430,7 +1441,7 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
f2fs_i_size_write(inode, new_size);
out:
up_write(&F2FS_I(inode)->i_mmap_sem);
- up_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
+ up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
return ret;
}
@@ -1473,7 +1484,7 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
last_off = map.m_lblk + map.m_len - 1;
/* update new size to the failed position */
- new_size = (last_off == pg_end) ? offset + len:
+ new_size = (last_off == pg_end) ? offset + len :
(loff_t)(last_off + 1) << PAGE_SHIFT;
} else {
new_size = ((loff_t)pg_end << PAGE_SHIFT) + off_end;
@@ -1553,13 +1564,13 @@ static int f2fs_release_file(struct inode *inode, struct file *filp)
/* some remained atomic pages should discarded */
if (f2fs_is_atomic_file(inode))
- drop_inmem_pages(inode);
+ f2fs_drop_inmem_pages(inode);
if (f2fs_is_volatile_file(inode)) {
- clear_inode_flag(inode, FI_VOLATILE_FILE);
- stat_dec_volatile_write(inode);
set_inode_flag(inode, FI_DROP_CACHE);
filemap_fdatawrite(inode->i_mapping);
clear_inode_flag(inode, FI_DROP_CACHE);
+ clear_inode_flag(inode, FI_VOLATILE_FILE);
+ stat_dec_volatile_write(inode);
}
return 0;
}
@@ -1576,7 +1587,7 @@ static int f2fs_file_flush(struct file *file, fl_owner_t id)
*/
if (f2fs_is_atomic_file(inode) &&
F2FS_I(inode)->inmem_task == current)
- drop_inmem_pages(inode);
+ f2fs_drop_inmem_pages(inode);
return 0;
}
@@ -1584,8 +1595,15 @@ static int f2fs_ioc_getflags(struct file *filp, unsigned long arg)
{
struct inode *inode = file_inode(filp);
struct f2fs_inode_info *fi = F2FS_I(inode);
- unsigned int flags = fi->i_flags &
- (FS_FL_USER_VISIBLE | FS_PROJINHERIT_FL);
+ unsigned int flags = fi->i_flags;
+
+ if (file_is_encrypt(inode))
+ flags |= F2FS_ENCRYPT_FL;
+ if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode))
+ flags |= F2FS_INLINE_DATA_FL;
+
+ flags &= F2FS_FL_USER_VISIBLE;
+
return put_user(flags, (int __user *)arg);
}
@@ -1602,15 +1620,15 @@ static int __f2fs_ioc_setflags(struct inode *inode, unsigned int flags)
oldflags = fi->i_flags;
- if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL))
+ if ((flags ^ oldflags) & (F2FS_APPEND_FL | F2FS_IMMUTABLE_FL))
if (!capable(CAP_LINUX_IMMUTABLE))
return -EPERM;
- flags = flags & (FS_FL_USER_MODIFIABLE | FS_PROJINHERIT_FL);
- flags |= oldflags & ~(FS_FL_USER_MODIFIABLE | FS_PROJINHERIT_FL);
+ flags = flags & F2FS_FL_USER_MODIFIABLE;
+ flags |= oldflags & ~F2FS_FL_USER_MODIFIABLE;
fi->i_flags = flags;
- if (fi->i_flags & FS_PROJINHERIT_FL)
+ if (fi->i_flags & F2FS_PROJINHERIT_FL)
set_inode_flag(inode, FI_PROJ_INHERIT);
else
clear_inode_flag(inode, FI_PROJ_INHERIT);
@@ -1670,6 +1688,8 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
inode_lock(inode);
+ down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
+
if (f2fs_is_atomic_file(inode))
goto out;
@@ -1677,28 +1697,25 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
if (ret)
goto out;
- set_inode_flag(inode, FI_ATOMIC_FILE);
- set_inode_flag(inode, FI_HOT_DATA);
- f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
-
if (!get_dirty_pages(inode))
- goto inc_stat;
+ goto skip_flush;
f2fs_msg(F2FS_I_SB(inode)->sb, KERN_WARNING,
"Unexpected flush for atomic writes: ino=%lu, npages=%u",
inode->i_ino, get_dirty_pages(inode));
ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX);
- if (ret) {
- clear_inode_flag(inode, FI_ATOMIC_FILE);
- clear_inode_flag(inode, FI_HOT_DATA);
+ if (ret)
goto out;
- }
+skip_flush:
+ set_inode_flag(inode, FI_ATOMIC_FILE);
+ clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
+ f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
-inc_stat:
F2FS_I(inode)->inmem_task = current;
stat_inc_atomic_write(inode);
stat_update_max_atomic_write(inode);
out:
+ up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
inode_unlock(inode);
mnt_drop_write_file(filp);
return ret;
@@ -1718,27 +1735,33 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
inode_lock(inode);
- down_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
+ down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
- if (f2fs_is_volatile_file(inode))
+ if (f2fs_is_volatile_file(inode)) {
+ ret = -EINVAL;
goto err_out;
+ }
if (f2fs_is_atomic_file(inode)) {
- ret = commit_inmem_pages(inode);
+ ret = f2fs_commit_inmem_pages(inode);
if (ret)
goto err_out;
ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true);
if (!ret) {
clear_inode_flag(inode, FI_ATOMIC_FILE);
- clear_inode_flag(inode, FI_HOT_DATA);
+ F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
stat_dec_atomic_write(inode);
}
} else {
ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 1, false);
}
err_out:
- up_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
+ if (is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) {
+ clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
+ ret = -EINVAL;
+ }
+ up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
inode_unlock(inode);
mnt_drop_write_file(filp);
return ret;
@@ -1823,7 +1846,7 @@ static int f2fs_ioc_abort_volatile_write(struct file *filp)
inode_lock(inode);
if (f2fs_is_atomic_file(inode))
- drop_inmem_pages(inode);
+ f2fs_drop_inmem_pages(inode);
if (f2fs_is_volatile_file(inode)) {
clear_inode_flag(inode, FI_VOLATILE_FILE);
stat_dec_volatile_write(inode);
@@ -1851,9 +1874,11 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
if (get_user(in, (__u32 __user *)arg))
return -EFAULT;
- ret = mnt_want_write_file(filp);
- if (ret)
- return ret;
+ if (in != F2FS_GOING_DOWN_FULLSYNC) {
+ ret = mnt_want_write_file(filp);
+ if (ret)
+ return ret;
+ }
switch (in) {
case F2FS_GOING_DOWN_FULLSYNC:
@@ -1878,7 +1903,7 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
f2fs_stop_checkpoint(sbi, false);
break;
case F2FS_GOING_DOWN_METAFLUSH:
- sync_meta_pages(sbi, META, LONG_MAX, FS_META_IO);
+ f2fs_sync_meta_pages(sbi, META, LONG_MAX, FS_META_IO);
f2fs_stop_checkpoint(sbi, false);
break;
default:
@@ -1886,15 +1911,16 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
goto out;
}
- stop_gc_thread(sbi);
- stop_discard_thread(sbi);
+ f2fs_stop_gc_thread(sbi);
+ f2fs_stop_discard_thread(sbi);
- drop_discard_cmd(sbi);
+ f2fs_drop_discard_cmd(sbi);
clear_opt(sbi, DISCARD);
f2fs_update_time(sbi, REQ_TIME);
out:
- mnt_drop_write_file(filp);
+ if (in != F2FS_GOING_DOWN_FULLSYNC)
+ mnt_drop_write_file(filp);
return ret;
}
@@ -2053,15 +2079,15 @@ static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg)
if (f2fs_readonly(sbi->sb))
return -EROFS;
+ end = range.start + range.len;
+ if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
+ return -EINVAL;
+ }
+
ret = mnt_want_write_file(filp);
if (ret)
return ret;
- end = range.start + range.len;
- if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi)) {
- ret = -EINVAL;
- goto out;
- }
do_more:
if (!range.sync) {
if (!mutex_trylock(&sbi->gc_mutex)) {
@@ -2081,7 +2107,7 @@ out:
return ret;
}
-static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg)
+static int f2fs_ioc_f2fs_write_checkpoint(struct file *filp, unsigned long arg)
{
struct inode *inode = file_inode(filp);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
@@ -2110,7 +2136,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
struct inode *inode = file_inode(filp);
struct f2fs_map_blocks map = { .m_next_extent = NULL,
.m_seg_type = NO_CHECK_TYPE };
- struct extent_info ei = {0,0,0};
+ struct extent_info ei = {0, 0, 0};
pgoff_t pg_start, pg_end, next_pgofs;
unsigned int blk_per_seg = sbi->blocks_per_seg;
unsigned int total = 0, sec_num;
@@ -2119,7 +2145,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
int err;
/* if in-place-update policy is enabled, don't waste time here */
- if (should_update_inplace(inode, NULL))
+ if (f2fs_should_update_inplace(inode, NULL))
return -EINVAL;
pg_start = range->start >> PAGE_SHIFT;
@@ -2214,7 +2240,7 @@ do_map:
while (idx < map.m_lblk + map.m_len && cnt < blk_per_seg) {
struct page *page;
- page = get_lock_data_page(inode, idx, true);
+ page = f2fs_get_lock_data_page(inode, idx, true);
if (IS_ERR(page)) {
err = PTR_ERR(page);
goto clear_out;
@@ -2325,12 +2351,12 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
}
inode_lock(src);
- down_write(&F2FS_I(src)->dio_rwsem[WRITE]);
+ down_write(&F2FS_I(src)->i_gc_rwsem[WRITE]);
if (src != dst) {
ret = -EBUSY;
if (!inode_trylock(dst))
goto out;
- if (!down_write_trylock(&F2FS_I(dst)->dio_rwsem[WRITE])) {
+ if (!down_write_trylock(&F2FS_I(dst)->i_gc_rwsem[WRITE])) {
inode_unlock(dst);
goto out;
}
@@ -2392,11 +2418,11 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in,
f2fs_unlock_op(sbi);
out_unlock:
if (src != dst) {
- up_write(&F2FS_I(dst)->dio_rwsem[WRITE]);
+ up_write(&F2FS_I(dst)->i_gc_rwsem[WRITE]);
inode_unlock(dst);
}
out:
- up_write(&F2FS_I(src)->dio_rwsem[WRITE]);
+ up_write(&F2FS_I(src)->i_gc_rwsem[WRITE]);
inode_unlock(src);
return ret;
}
@@ -2554,7 +2580,7 @@ static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
if (IS_NOQUOTA(inode))
goto out_unlock;
- ipage = get_node_page(sbi, inode->i_ino);
+ ipage = f2fs_get_node_page(sbi, inode->i_ino);
if (IS_ERR(ipage)) {
err = PTR_ERR(ipage);
goto out_unlock;
@@ -2568,7 +2594,9 @@ static int f2fs_ioc_setproject(struct file *filp, __u32 projid)
}
f2fs_put_page(ipage, 1);
- dquot_initialize(inode);
+ err = dquot_initialize(inode);
+ if (err)
+ goto out_unlock;
transfer_to[PRJQUOTA] = dqget(sb, make_kqid_projid(kprojid));
if (!IS_ERR(transfer_to[PRJQUOTA])) {
@@ -2601,17 +2629,17 @@ static inline __u32 f2fs_iflags_to_xflags(unsigned long iflags)
{
__u32 xflags = 0;
- if (iflags & FS_SYNC_FL)
+ if (iflags & F2FS_SYNC_FL)
xflags |= FS_XFLAG_SYNC;
- if (iflags & FS_IMMUTABLE_FL)
+ if (iflags & F2FS_IMMUTABLE_FL)
xflags |= FS_XFLAG_IMMUTABLE;
- if (iflags & FS_APPEND_FL)
+ if (iflags & F2FS_APPEND_FL)
xflags |= FS_XFLAG_APPEND;
- if (iflags & FS_NODUMP_FL)
+ if (iflags & F2FS_NODUMP_FL)
xflags |= FS_XFLAG_NODUMP;
- if (iflags & FS_NOATIME_FL)
+ if (iflags & F2FS_NOATIME_FL)
xflags |= FS_XFLAG_NOATIME;
- if (iflags & FS_PROJINHERIT_FL)
+ if (iflags & F2FS_PROJINHERIT_FL)
xflags |= FS_XFLAG_PROJINHERIT;
return xflags;
}
@@ -2620,31 +2648,23 @@ static inline __u32 f2fs_iflags_to_xflags(unsigned long iflags)
FS_XFLAG_APPEND | FS_XFLAG_NODUMP | \
FS_XFLAG_NOATIME | FS_XFLAG_PROJINHERIT)
-/* Flags we can manipulate with through EXT4_IOC_FSSETXATTR */
-#define F2FS_FL_XFLAG_VISIBLE (FS_SYNC_FL | \
- FS_IMMUTABLE_FL | \
- FS_APPEND_FL | \
- FS_NODUMP_FL | \
- FS_NOATIME_FL | \
- FS_PROJINHERIT_FL)
-
/* Transfer xflags flags to internal */
static inline unsigned long f2fs_xflags_to_iflags(__u32 xflags)
{
unsigned long iflags = 0;
if (xflags & FS_XFLAG_SYNC)
- iflags |= FS_SYNC_FL;
+ iflags |= F2FS_SYNC_FL;
if (xflags & FS_XFLAG_IMMUTABLE)
- iflags |= FS_IMMUTABLE_FL;
+ iflags |= F2FS_IMMUTABLE_FL;
if (xflags & FS_XFLAG_APPEND)
- iflags |= FS_APPEND_FL;
+ iflags |= F2FS_APPEND_FL;
if (xflags & FS_XFLAG_NODUMP)
- iflags |= FS_NODUMP_FL;
+ iflags |= F2FS_NODUMP_FL;
if (xflags & FS_XFLAG_NOATIME)
- iflags |= FS_NOATIME_FL;
+ iflags |= F2FS_NOATIME_FL;
if (xflags & FS_XFLAG_PROJINHERIT)
- iflags |= FS_PROJINHERIT_FL;
+ iflags |= F2FS_PROJINHERIT_FL;
return iflags;
}
@@ -2657,7 +2677,7 @@ static int f2fs_ioc_fsgetxattr(struct file *filp, unsigned long arg)
memset(&fa, 0, sizeof(struct fsxattr));
fa.fsx_xflags = f2fs_iflags_to_xflags(fi->i_flags &
- (FS_FL_USER_VISIBLE | FS_PROJINHERIT_FL));
+ F2FS_FL_USER_VISIBLE);
if (f2fs_sb_has_project_quota(inode->i_sb))
fa.fsx_projid = (__u32)from_kprojid(&init_user_ns,
@@ -2717,12 +2737,14 @@ int f2fs_pin_file_control(struct inode *inode, bool inc)
/* Use i_gc_failures for normal file as a risk signal. */
if (inc)
- f2fs_i_gc_failures_write(inode, fi->i_gc_failures + 1);
+ f2fs_i_gc_failures_write(inode,
+ fi->i_gc_failures[GC_FAILURE_PIN] + 1);
- if (fi->i_gc_failures > sbi->gc_pin_file_threshold) {
+ if (fi->i_gc_failures[GC_FAILURE_PIN] > sbi->gc_pin_file_threshold) {
f2fs_msg(sbi->sb, KERN_WARNING,
"%s: Enable GC = ino %lx after %x GC trials\n",
- __func__, inode->i_ino, fi->i_gc_failures);
+ __func__, inode->i_ino,
+ fi->i_gc_failures[GC_FAILURE_PIN]);
clear_inode_flag(inode, FI_PIN_FILE);
return -EAGAIN;
}
@@ -2753,14 +2775,14 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
inode_lock(inode);
- if (should_update_outplace(inode, NULL)) {
+ if (f2fs_should_update_outplace(inode, NULL)) {
ret = -EINVAL;
goto out;
}
if (!pin) {
clear_inode_flag(inode, FI_PIN_FILE);
- F2FS_I(inode)->i_gc_failures = 1;
+ F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN] = 1;
goto done;
}
@@ -2773,7 +2795,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
goto out;
set_inode_flag(inode, FI_PIN_FILE);
- ret = F2FS_I(inode)->i_gc_failures;
+ ret = F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN];
done:
f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
out:
@@ -2788,7 +2810,7 @@ static int f2fs_ioc_get_pin_file(struct file *filp, unsigned long arg)
__u32 pin = 0;
if (is_inode_flag_set(inode, FI_PIN_FILE))
- pin = F2FS_I(inode)->i_gc_failures;
+ pin = F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN];
return put_user(pin, (u32 __user *)arg);
}
@@ -2812,9 +2834,9 @@ int f2fs_precache_extents(struct inode *inode)
while (map.m_lblk < end) {
map.m_len = end - map.m_lblk;
- down_write(&fi->dio_rwsem[WRITE]);
+ down_write(&fi->i_gc_rwsem[WRITE]);
err = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_PRECACHE);
- up_write(&fi->dio_rwsem[WRITE]);
+ up_write(&fi->i_gc_rwsem[WRITE]);
if (err)
return err;
@@ -2866,7 +2888,7 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
case F2FS_IOC_GARBAGE_COLLECT_RANGE:
return f2fs_ioc_gc_range(filp, arg);
case F2FS_IOC_WRITE_CHECKPOINT:
- return f2fs_ioc_write_checkpoint(filp, arg);
+ return f2fs_ioc_f2fs_write_checkpoint(filp, arg);
case F2FS_IOC_DEFRAGMENT:
return f2fs_ioc_defragment(filp, arg);
case F2FS_IOC_MOVE_RANGE:
@@ -2894,7 +2916,6 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
{
struct file *file = iocb->ki_filp;
struct inode *inode = file_inode(file);
- struct blk_plug plug;
ssize_t ret;
if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
@@ -2924,6 +2945,8 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
iov_iter_count(from)) ||
f2fs_has_inline_data(inode) ||
f2fs_force_buffered_io(inode, WRITE)) {
+ clear_inode_flag(inode,
+ FI_NO_PREALLOC);
inode_unlock(inode);
return -EAGAIN;
}
@@ -2939,9 +2962,7 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
return err;
}
}
- blk_start_plug(&plug);
ret = __generic_file_write_iter(iocb, from);
- blk_finish_plug(&plug);
clear_inode_flag(inode, FI_NO_PREALLOC);
/* if we couldn't write data, we should deallocate blocks. */
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 9327411..9093be6 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -76,7 +76,7 @@ static int gc_thread_func(void *data)
* invalidated soon after by user update or deletion.
* So, I'd like to wait some time to collect dirty segments.
*/
- if (gc_th->gc_urgent) {
+ if (sbi->gc_mode == GC_URGENT) {
wait_ms = gc_th->urgent_sleep_time;
mutex_lock(&sbi->gc_mutex);
goto do_gc;
@@ -114,7 +114,7 @@ next:
return 0;
}
-int start_gc_thread(struct f2fs_sb_info *sbi)
+int f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
{
struct f2fs_gc_kthread *gc_th;
dev_t dev = sbi->sb->s_bdev->bd_dev;
@@ -131,8 +131,6 @@ int start_gc_thread(struct f2fs_sb_info *sbi)
gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME;
gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME;
- gc_th->gc_idle = 0;
- gc_th->gc_urgent = 0;
gc_th->gc_wake= 0;
sbi->gc_thread = gc_th;
@@ -148,7 +146,7 @@ out:
return err;
}
-void stop_gc_thread(struct f2fs_sb_info *sbi)
+void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi)
{
struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
if (!gc_th)
@@ -158,21 +156,19 @@ void stop_gc_thread(struct f2fs_sb_info *sbi)
sbi->gc_thread = NULL;
}
-static int select_gc_type(struct f2fs_gc_kthread *gc_th, int gc_type)
+static int select_gc_type(struct f2fs_sb_info *sbi, int gc_type)
{
int gc_mode = (gc_type == BG_GC) ? GC_CB : GC_GREEDY;
- if (!gc_th)
- return gc_mode;
-
- if (gc_th->gc_idle) {
- if (gc_th->gc_idle == 1)
- gc_mode = GC_CB;
- else if (gc_th->gc_idle == 2)
- gc_mode = GC_GREEDY;
- }
- if (gc_th->gc_urgent)
+ switch (sbi->gc_mode) {
+ case GC_IDLE_CB:
+ gc_mode = GC_CB;
+ break;
+ case GC_IDLE_GREEDY:
+ case GC_URGENT:
gc_mode = GC_GREEDY;
+ break;
+ }
return gc_mode;
}
@@ -187,7 +183,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
p->max_search = dirty_i->nr_dirty[type];
p->ofs_unit = 1;
} else {
- p->gc_mode = select_gc_type(sbi->gc_thread, gc_type);
+ p->gc_mode = select_gc_type(sbi, gc_type);
p->dirty_segmap = dirty_i->dirty_segmap[DIRTY];
p->max_search = dirty_i->nr_dirty[DIRTY];
p->ofs_unit = sbi->segs_per_sec;
@@ -195,7 +191,7 @@ static void select_policy(struct f2fs_sb_info *sbi, int gc_type,
/* we need to check every dirty segments in the FG_GC case */
if (gc_type != FG_GC &&
- (sbi->gc_thread && !sbi->gc_thread->gc_urgent) &&
+ (sbi->gc_mode != GC_URGENT) &&
p->max_search > sbi->max_victim_search)
p->max_search = sbi->max_victim_search;
@@ -234,10 +230,6 @@ static unsigned int check_bg_victims(struct f2fs_sb_info *sbi)
for_each_set_bit(secno, dirty_i->victim_secmap, MAIN_SECS(sbi)) {
if (sec_usage_check(sbi, secno))
continue;
-
- if (no_fggc_candidate(sbi, secno))
- continue;
-
clear_bit(secno, dirty_i->victim_secmap);
return GET_SEG_FROM_SEC(sbi, secno);
}
@@ -377,9 +369,6 @@ static int get_victim_by_default(struct f2fs_sb_info *sbi,
goto next;
if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap))
goto next;
- if (gc_type == FG_GC && p.alloc_mode == LFS &&
- no_fggc_candidate(sbi, secno))
- goto next;
cost = get_gc_cost(sbi, segno, &p);
@@ -440,7 +429,7 @@ static void add_gc_inode(struct gc_inode_list *gc_list, struct inode *inode)
iput(inode);
return;
}
- new_ie = f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS);
+ new_ie = f2fs_kmem_cache_alloc(f2fs_inode_entry_slab, GFP_NOFS);
new_ie->inode = inode;
f2fs_radix_tree_insert(&gc_list->iroot, inode->i_ino, new_ie);
@@ -454,7 +443,7 @@ static void put_gc_inode(struct gc_inode_list *gc_list)
radix_tree_delete(&gc_list->iroot, ie->inode->i_ino);
iput(ie->inode);
list_del(&ie->list);
- kmem_cache_free(inode_entry_slab, ie);
+ kmem_cache_free(f2fs_inode_entry_slab, ie);
}
}
@@ -484,12 +473,16 @@ static void gc_node_segment(struct f2fs_sb_info *sbi,
block_t start_addr;
int off;
int phase = 0;
+ bool fggc = (gc_type == FG_GC);
start_addr = START_BLOCK(sbi, segno);
next_step:
entry = sum;
+ if (fggc && phase == 2)
+ atomic_inc(&sbi->wb_sync_req[NODE]);
+
for (off = 0; off < sbi->blocks_per_seg; off++, entry++) {
nid_t nid = le32_to_cpu(entry->nid);
struct page *node_page;
@@ -503,39 +496,42 @@ next_step:
continue;
if (phase == 0) {
- ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
+ f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
META_NAT, true);
continue;
}
if (phase == 1) {
- ra_node_page(sbi, nid);
+ f2fs_ra_node_page(sbi, nid);
continue;
}
/* phase == 2 */
- node_page = get_node_page(sbi, nid);
+ node_page = f2fs_get_node_page(sbi, nid);
if (IS_ERR(node_page))
continue;
- /* block may become invalid during get_node_page */
+ /* block may become invalid during f2fs_get_node_page */
if (check_valid_map(sbi, segno, off) == 0) {
f2fs_put_page(node_page, 1);
continue;
}
- get_node_info(sbi, nid, &ni);
+ f2fs_get_node_info(sbi, nid, &ni);
if (ni.blk_addr != start_addr + off) {
f2fs_put_page(node_page, 1);
continue;
}
- move_node_page(node_page, gc_type);
+ f2fs_move_node_page(node_page, gc_type);
stat_inc_node_blk_count(sbi, 1, gc_type);
}
if (++phase < 3)
goto next_step;
+
+ if (fggc)
+ atomic_dec(&sbi->wb_sync_req[NODE]);
}
/*
@@ -545,7 +541,7 @@ next_step:
* as indirect or double indirect node blocks, are given, it must be a caller's
* bug.
*/
-block_t start_bidx_of_node(unsigned int node_ofs, struct inode *inode)
+block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode)
{
unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4;
unsigned int bidx;
@@ -576,11 +572,11 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
nid = le32_to_cpu(sum->nid);
ofs_in_node = le16_to_cpu(sum->ofs_in_node);
- node_page = get_node_page(sbi, nid);
+ node_page = f2fs_get_node_page(sbi, nid);
if (IS_ERR(node_page))
return false;
- get_node_info(sbi, nid, dni);
+ f2fs_get_node_info(sbi, nid, dni);
if (sum->version != dni->version) {
f2fs_msg(sbi->sb, KERN_WARNING,
@@ -603,7 +599,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
* This can be used to move blocks, aka LBAs, directly on disk.
*/
static void move_data_block(struct inode *inode, block_t bidx,
- unsigned int segno, int off)
+ int gc_type, unsigned int segno, int off)
{
struct f2fs_io_info fio = {
.sbi = F2FS_I_SB(inode),
@@ -614,6 +610,7 @@ static void move_data_block(struct inode *inode, block_t bidx,
.op_flags = 0,
.encrypted_page = NULL,
.in_list = false,
+ .retry = false,
};
struct dnode_of_data dn;
struct f2fs_summary sum;
@@ -621,6 +618,7 @@ static void move_data_block(struct inode *inode, block_t bidx,
struct page *page;
block_t newaddr;
int err;
+ bool lfs_mode = test_opt(fio.sbi, LFS);
/* do not read out */
page = f2fs_grab_cache_page(inode->i_mapping, bidx, false);
@@ -630,8 +628,11 @@ static void move_data_block(struct inode *inode, block_t bidx,
if (!check_valid_map(F2FS_I_SB(inode), segno, off))
goto out;
- if (f2fs_is_atomic_file(inode))
+ if (f2fs_is_atomic_file(inode)) {
+ F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++;
+ F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++;
goto out;
+ }
if (f2fs_is_pinned_file(inode)) {
f2fs_pin_file_control(inode, true);
@@ -639,7 +640,7 @@ static void move_data_block(struct inode *inode, block_t bidx,
}
set_new_dnode(&dn, inode, NULL, NULL, 0);
- err = get_dnode_of_data(&dn, bidx, LOOKUP_NODE);
+ err = f2fs_get_dnode_of_data(&dn, bidx, LOOKUP_NODE);
if (err)
goto out;
@@ -654,14 +655,17 @@ static void move_data_block(struct inode *inode, block_t bidx,
*/
f2fs_wait_on_page_writeback(page, DATA, true);
- get_node_info(fio.sbi, dn.nid, &ni);
+ f2fs_get_node_info(fio.sbi, dn.nid, &ni);
set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
/* read page */
fio.page = page;
fio.new_blkaddr = fio.old_blkaddr = dn.data_blkaddr;
- allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
+ if (lfs_mode)
+ down_write(&fio.sbi->io_order_lock);
+
+ f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
&sum, CURSEG_COLD_DATA, NULL, false);
fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
@@ -693,6 +697,7 @@ static void move_data_block(struct inode *inode, block_t bidx,
dec_page_count(fio.sbi, F2FS_DIRTY_META);
set_page_writeback(fio.encrypted_page);
+ ClearPageError(page);
/* allocate block address */
f2fs_wait_on_page_writeback(dn.node_page, NODE, true);
@@ -700,8 +705,8 @@ static void move_data_block(struct inode *inode, block_t bidx,
fio.op = REQ_OP_WRITE;
fio.op_flags = REQ_SYNC;
fio.new_blkaddr = newaddr;
- err = f2fs_submit_page_write(&fio);
- if (err) {
+ f2fs_submit_page_write(&fio);
+ if (fio.retry) {
if (PageWriteback(fio.encrypted_page))
end_page_writeback(fio.encrypted_page);
goto put_page_out;
@@ -716,8 +721,10 @@ static void move_data_block(struct inode *inode, block_t bidx,
put_page_out:
f2fs_put_page(fio.encrypted_page, 1);
recover_block:
+ if (lfs_mode)
+ up_write(&fio.sbi->io_order_lock);
if (err)
- __f2fs_replace_block(fio.sbi, &sum, newaddr, fio.old_blkaddr,
+ f2fs_do_replace_block(fio.sbi, &sum, newaddr, fio.old_blkaddr,
true, true);
put_out:
f2fs_put_dnode(&dn);
@@ -730,15 +737,18 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type,
{
struct page *page;
- page = get_lock_data_page(inode, bidx, true);
+ page = f2fs_get_lock_data_page(inode, bidx, true);
if (IS_ERR(page))
return;
if (!check_valid_map(F2FS_I_SB(inode), segno, off))
goto out;
- if (f2fs_is_atomic_file(inode))
+ if (f2fs_is_atomic_file(inode)) {
+ F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC]++;
+ F2FS_I_SB(inode)->skipped_atomic_files[gc_type]++;
goto out;
+ }
if (f2fs_is_pinned_file(inode)) {
if (gc_type == FG_GC)
f2fs_pin_file_control(inode, true);
@@ -772,15 +782,20 @@ retry:
f2fs_wait_on_page_writeback(page, DATA, true);
if (clear_page_dirty_for_io(page)) {
inode_dec_dirty_pages(inode);
- remove_dirty_inode(inode);
+ f2fs_remove_dirty_inode(inode);
}
set_cold_data(page);
- err = do_write_data_page(&fio);
- if (err == -ENOMEM && is_dirty) {
- congestion_wait(BLK_RW_ASYNC, HZ/50);
- goto retry;
+ err = f2fs_do_write_data_page(&fio);
+ if (err) {
+ clear_cold_data(page);
+ if (err == -ENOMEM) {
+ congestion_wait(BLK_RW_ASYNC, HZ/50);
+ goto retry;
+ }
+ if (is_dirty)
+ set_page_dirty(page);
}
}
out:
@@ -824,13 +839,13 @@ next_step:
continue;
if (phase == 0) {
- ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
+ f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), 1,
META_NAT, true);
continue;
}
if (phase == 1) {
- ra_node_page(sbi, nid);
+ f2fs_ra_node_page(sbi, nid);
continue;
}
@@ -839,7 +854,7 @@ next_step:
continue;
if (phase == 2) {
- ra_node_page(sbi, dni.ino);
+ f2fs_ra_node_page(sbi, dni.ino);
continue;
}
@@ -850,23 +865,23 @@ next_step:
if (IS_ERR(inode) || is_bad_inode(inode))
continue;
- /* if encrypted inode, let's go phase 3 */
- if (f2fs_encrypted_file(inode)) {
+ /* if inode uses special I/O path, let's go phase 3 */
+ if (f2fs_post_read_required(inode)) {
add_gc_inode(gc_list, inode);
continue;
}
if (!down_write_trylock(
- &F2FS_I(inode)->dio_rwsem[WRITE])) {
+ &F2FS_I(inode)->i_gc_rwsem[WRITE])) {
iput(inode);
continue;
}
- start_bidx = start_bidx_of_node(nofs, inode);
- data_page = get_read_data_page(inode,
+ start_bidx = f2fs_start_bidx_of_node(nofs, inode);
+ data_page = f2fs_get_read_data_page(inode,
start_bidx + ofs_in_node, REQ_RAHEAD,
true);
- up_write(&F2FS_I(inode)->dio_rwsem[WRITE]);
+ up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
if (IS_ERR(data_page)) {
iput(inode);
continue;
@@ -884,11 +899,11 @@ next_step:
bool locked = false;
if (S_ISREG(inode->i_mode)) {
- if (!down_write_trylock(&fi->dio_rwsem[READ]))
+ if (!down_write_trylock(&fi->i_gc_rwsem[READ]))
continue;
if (!down_write_trylock(
- &fi->dio_rwsem[WRITE])) {
- up_write(&fi->dio_rwsem[READ]);
+ &fi->i_gc_rwsem[WRITE])) {
+ up_write(&fi->i_gc_rwsem[READ]);
continue;
}
locked = true;
@@ -897,17 +912,18 @@ next_step:
inode_dio_wait(inode);
}
- start_bidx = start_bidx_of_node(nofs, inode)
+ start_bidx = f2fs_start_bidx_of_node(nofs, inode)
+ ofs_in_node;
- if (f2fs_encrypted_file(inode))
- move_data_block(inode, start_bidx, segno, off);
+ if (f2fs_post_read_required(inode))
+ move_data_block(inode, start_bidx, gc_type,
+ segno, off);
else
move_data_page(inode, start_bidx, gc_type,
segno, off);
if (locked) {
- up_write(&fi->dio_rwsem[WRITE]);
- up_write(&fi->dio_rwsem[READ]);
+ up_write(&fi->i_gc_rwsem[WRITE]);
+ up_write(&fi->i_gc_rwsem[READ]);
}
stat_inc_data_blk_count(sbi, 1, gc_type);
@@ -946,12 +962,12 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
/* readahead multi ssa blocks those have contiguous address */
if (sbi->segs_per_sec > 1)
- ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
+ f2fs_ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno),
sbi->segs_per_sec, META_SSA, true);
/* reference all summary page */
while (segno < end_segno) {
- sum_page = get_sum_page(sbi, segno++);
+ sum_page = f2fs_get_sum_page(sbi, segno++);
unlock_page(sum_page);
}
@@ -1017,6 +1033,8 @@ int f2fs_gc(struct f2fs_sb_info *sbi, bool sync,
.ilist = LIST_HEAD_INIT(gc_list.ilist),
.iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
};
+ unsigned long long last_skipped = sbi->skipped_atomic_files[FG_GC];
+ unsigned int skipped_round = 0, round = 0;
trace_f2fs_gc_begin(sbi->sb, sync, background,
get_pages(sbi, F2FS_DIRTY_NODES),
@@ -1045,7 +1063,7 @@ gc_more:
* secure free segments which doesn't need fggc any more.
*/
if (prefree_segments(sbi)) {
- ret = write_checkpoint(sbi, &cpc);
+ ret = f2fs_write_checkpoint(sbi, &cpc);
if (ret)
goto stop;
}
@@ -1068,17 +1086,27 @@ gc_more:
sec_freed++;
total_freed += seg_freed;
+ if (gc_type == FG_GC) {
+ if (sbi->skipped_atomic_files[FG_GC] > last_skipped)
+ skipped_round++;
+ last_skipped = sbi->skipped_atomic_files[FG_GC];
+ round++;
+ }
+
if (gc_type == FG_GC)
sbi->cur_victim_sec = NULL_SEGNO;
if (!sync) {
if (has_not_enough_free_secs(sbi, sec_freed, 0)) {
+ if (skipped_round > MAX_SKIP_ATOMIC_COUNT &&
+ skipped_round * 2 >= round)
+ f2fs_drop_inmem_pages_all(sbi, true);
segno = NULL_SEGNO;
goto gc_more;
}
if (gc_type == FG_GC)
- ret = write_checkpoint(sbi, &cpc);
+ ret = f2fs_write_checkpoint(sbi, &cpc);
}
stop:
SIT_I(sbi)->last_victim[ALLOC_NEXT] = 0;
@@ -1102,19 +1130,10 @@ stop:
return ret;
}
-void build_gc_manager(struct f2fs_sb_info *sbi)
+void f2fs_build_gc_manager(struct f2fs_sb_info *sbi)
{
- u64 main_count, resv_count, ovp_count;
-
DIRTY_I(sbi)->v_ops = &default_v_ops;
- /* threshold of # of valid blocks in a section for victims of FG_GC */
- main_count = SM_I(sbi)->main_segments << sbi->log_blocks_per_seg;
- resv_count = SM_I(sbi)->reserved_segments << sbi->log_blocks_per_seg;
- ovp_count = SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg;
-
- sbi->fggc_threshold = div64_u64((main_count - ovp_count) *
- BLKS_PER_SEC(sbi), (main_count - resv_count));
sbi->gc_pin_file_threshold = DEF_GC_FAILED_PINNED_FILES;
/* give warm/cold data area from slower device */
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
index b0045d4..c8619e4 100644
--- a/fs/f2fs/gc.h
+++ b/fs/f2fs/gc.h
@@ -36,8 +36,6 @@ struct f2fs_gc_kthread {
unsigned int no_gc_sleep_time;
/* for changing gc mode */
- unsigned int gc_idle;
- unsigned int gc_urgent;
unsigned int gc_wake;
};
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 265da20..043830be 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -25,7 +25,7 @@ bool f2fs_may_inline_data(struct inode *inode)
if (i_size_read(inode) > MAX_INLINE_DATA(inode))
return false;
- if (f2fs_encrypted_file(inode))
+ if (f2fs_post_read_required(inode))
return false;
return true;
@@ -42,7 +42,7 @@ bool f2fs_may_inline_dentry(struct inode *inode)
return true;
}
-void read_inline_data(struct page *page, struct page *ipage)
+void f2fs_do_read_inline_data(struct page *page, struct page *ipage)
{
struct inode *inode = page->mapping->host;
void *src_addr, *dst_addr;
@@ -64,7 +64,8 @@ void read_inline_data(struct page *page, struct page *ipage)
SetPageUptodate(page);
}
-void truncate_inline_inode(struct inode *inode, struct page *ipage, u64 from)
+void f2fs_truncate_inline_inode(struct inode *inode,
+ struct page *ipage, u64 from)
{
void *addr;
@@ -85,7 +86,7 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)
{
struct page *ipage;
- ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino);
+ ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
if (IS_ERR(ipage)) {
unlock_page(page);
return PTR_ERR(ipage);
@@ -99,7 +100,7 @@ int f2fs_read_inline_data(struct inode *inode, struct page *page)
if (page->index)
zero_user_segment(page, 0, PAGE_SIZE);
else
- read_inline_data(page, ipage);
+ f2fs_do_read_inline_data(page, ipage);
if (!PageUptodate(page))
SetPageUptodate(page);
@@ -131,7 +132,7 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
f2fs_bug_on(F2FS_P_SB(page), PageWriteback(page));
- read_inline_data(page, dn->inode_page);
+ f2fs_do_read_inline_data(page, dn->inode_page);
set_page_dirty(page);
/* clear dirty state */
@@ -139,20 +140,21 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page)
/* write data page to try to make data consistent */
set_page_writeback(page);
+ ClearPageError(page);
fio.old_blkaddr = dn->data_blkaddr;
set_inode_flag(dn->inode, FI_HOT_DATA);
- write_data_page(dn, &fio);
+ f2fs_outplace_write_data(dn, &fio);
f2fs_wait_on_page_writeback(page, DATA, true);
if (dirty) {
inode_dec_dirty_pages(dn->inode);
- remove_dirty_inode(dn->inode);
+ f2fs_remove_dirty_inode(dn->inode);
}
/* this converted inline_data should be recovered. */
set_inode_flag(dn->inode, FI_APPEND_WRITE);
/* clear inline data and flag after data writeback */
- truncate_inline_inode(dn->inode, dn->inode_page, 0);
+ f2fs_truncate_inline_inode(dn->inode, dn->inode_page, 0);
clear_inline_node(dn->inode_page);
clear_out:
stat_dec_inline_inode(dn->inode);
@@ -177,7 +179,7 @@ int f2fs_convert_inline_inode(struct inode *inode)
f2fs_lock_op(sbi);
- ipage = get_node_page(sbi, inode->i_ino);
+ ipage = f2fs_get_node_page(sbi, inode->i_ino);
if (IS_ERR(ipage)) {
err = PTR_ERR(ipage);
goto out;
@@ -203,12 +205,10 @@ int f2fs_write_inline_data(struct inode *inode, struct page *page)
{
void *src_addr, *dst_addr;
struct dnode_of_data dn;
- struct address_space *mapping = page_mapping(page);
- unsigned long flags;
int err;
set_new_dnode(&dn, inode, NULL, NULL, 0);
- err = get_dnode_of_data(&dn, 0, LOOKUP_NODE);
+ err = f2fs_get_dnode_of_data(&dn, 0, LOOKUP_NODE);
if (err)
return err;
@@ -226,10 +226,7 @@ int f2fs_write_inline_data(struct inode *inode, struct page *page)
kunmap_atomic(src_addr);
set_page_dirty(dn.inode_page);
- xa_lock_irqsave(&mapping->i_pages, flags);
- radix_tree_tag_clear(&mapping->i_pages, page_index(page),
- PAGECACHE_TAG_DIRTY);
- xa_unlock_irqrestore(&mapping->i_pages, flags);
+ f2fs_clear_radix_tree_dirty_tag(page);
set_inode_flag(inode, FI_APPEND_WRITE);
set_inode_flag(inode, FI_DATA_EXIST);
@@ -239,7 +236,7 @@ int f2fs_write_inline_data(struct inode *inode, struct page *page)
return 0;
}
-bool recover_inline_data(struct inode *inode, struct page *npage)
+bool f2fs_recover_inline_data(struct inode *inode, struct page *npage)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_inode *ri = NULL;
@@ -260,7 +257,7 @@ bool recover_inline_data(struct inode *inode, struct page *npage)
if (f2fs_has_inline_data(inode) &&
ri && (ri->i_inline & F2FS_INLINE_DATA)) {
process_inline:
- ipage = get_node_page(sbi, inode->i_ino);
+ ipage = f2fs_get_node_page(sbi, inode->i_ino);
f2fs_bug_on(sbi, IS_ERR(ipage));
f2fs_wait_on_page_writeback(ipage, NODE, true);
@@ -278,20 +275,20 @@ process_inline:
}
if (f2fs_has_inline_data(inode)) {
- ipage = get_node_page(sbi, inode->i_ino);
+ ipage = f2fs_get_node_page(sbi, inode->i_ino);
f2fs_bug_on(sbi, IS_ERR(ipage));
- truncate_inline_inode(inode, ipage, 0);
+ f2fs_truncate_inline_inode(inode, ipage, 0);
clear_inode_flag(inode, FI_INLINE_DATA);
f2fs_put_page(ipage, 1);
} else if (ri && (ri->i_inline & F2FS_INLINE_DATA)) {
- if (truncate_blocks(inode, 0, false))
+ if (f2fs_truncate_blocks(inode, 0, false))
return false;
goto process_inline;
}
return false;
}
-struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
+struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir,
struct fscrypt_name *fname, struct page **res_page)
{
struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb);
@@ -302,7 +299,7 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
void *inline_dentry;
f2fs_hash_t namehash;
- ipage = get_node_page(sbi, dir->i_ino);
+ ipage = f2fs_get_node_page(sbi, dir->i_ino);
if (IS_ERR(ipage)) {
*res_page = ipage;
return NULL;
@@ -313,7 +310,7 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
inline_dentry = inline_data_addr(dir, ipage);
make_dentry_ptr_inline(dir, &d, inline_dentry);
- de = find_target_dentry(fname, namehash, NULL, &d);
+ de = f2fs_find_target_dentry(fname, namehash, NULL, &d);
unlock_page(ipage);
if (de)
*res_page = ipage;
@@ -323,7 +320,7 @@ struct f2fs_dir_entry *find_in_inline_dir(struct inode *dir,
return de;
}
-int make_empty_inline_dir(struct inode *inode, struct inode *parent,
+int f2fs_make_empty_inline_dir(struct inode *inode, struct inode *parent,
struct page *ipage)
{
struct f2fs_dentry_ptr d;
@@ -332,7 +329,7 @@ int make_empty_inline_dir(struct inode *inode, struct inode *parent,
inline_dentry = inline_data_addr(inode, ipage);
make_dentry_ptr_inline(inode, &d, inline_dentry);
- do_make_empty_dir(inode, parent, &d);
+ f2fs_do_make_empty_dir(inode, parent, &d);
set_page_dirty(ipage);
@@ -367,7 +364,6 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
goto out;
f2fs_wait_on_page_writeback(page, DATA, true);
- zero_user_segment(page, MAX_INLINE_DATA(dir), PAGE_SIZE);
dentry_blk = page_address(page);
@@ -391,7 +387,7 @@ static int f2fs_move_inline_dirents(struct inode *dir, struct page *ipage,
set_page_dirty(page);
/* clear inline dir and flag after data writeback */
- truncate_inline_inode(dir, ipage, 0);
+ f2fs_truncate_inline_inode(dir, ipage, 0);
stat_dec_inline_dir(dir);
clear_inode_flag(dir, FI_INLINE_DENTRY);
@@ -434,7 +430,7 @@ static int f2fs_add_inline_entries(struct inode *dir, void *inline_dentry)
new_name.len = le16_to_cpu(de->name_len);
ino = le32_to_cpu(de->ino);
- fake_mode = get_de_type(de) << S_SHIFT;
+ fake_mode = f2fs_get_de_type(de) << S_SHIFT;
err = f2fs_add_regular_entry(dir, &new_name, NULL, NULL,
ino, fake_mode);
@@ -446,8 +442,8 @@ static int f2fs_add_inline_entries(struct inode *dir, void *inline_dentry)
return 0;
punch_dentry_pages:
truncate_inode_pages(&dir->i_data, 0);
- truncate_blocks(dir, 0, false);
- remove_dirty_inode(dir);
+ f2fs_truncate_blocks(dir, 0, false);
+ f2fs_remove_dirty_inode(dir);
return err;
}
@@ -465,7 +461,7 @@ static int f2fs_move_rehashed_dirents(struct inode *dir, struct page *ipage,
}
memcpy(backup_dentry, inline_dentry, MAX_INLINE_DATA(dir));
- truncate_inline_inode(dir, ipage, 0);
+ f2fs_truncate_inline_inode(dir, ipage, 0);
unlock_page(ipage);
@@ -514,14 +510,14 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,
struct page *page = NULL;
int err = 0;
- ipage = get_node_page(sbi, dir->i_ino);
+ ipage = f2fs_get_node_page(sbi, dir->i_ino);
if (IS_ERR(ipage))
return PTR_ERR(ipage);
inline_dentry = inline_data_addr(dir, ipage);
make_dentry_ptr_inline(dir, &d, inline_dentry);
- bit_pos = room_for_filename(d.bitmap, slots, d.max);
+ bit_pos = f2fs_room_for_filename(d.bitmap, slots, d.max);
if (bit_pos >= d.max) {
err = f2fs_convert_inline_dir(dir, ipage, inline_dentry);
if (err)
@@ -532,7 +528,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,
if (inode) {
down_write(&F2FS_I(inode)->i_sem);
- page = init_inode_metadata(inode, dir, new_name,
+ page = f2fs_init_inode_metadata(inode, dir, new_name,
orig_name, ipage);
if (IS_ERR(page)) {
err = PTR_ERR(page);
@@ -553,7 +549,7 @@ int f2fs_add_inline_entry(struct inode *dir, const struct qstr *new_name,
f2fs_put_page(page, 1);
}
- update_parent_metadata(dir, inode, 0);
+ f2fs_update_parent_metadata(dir, inode, 0);
fail:
if (inode)
up_write(&F2FS_I(inode)->i_sem);
@@ -599,7 +595,7 @@ bool f2fs_empty_inline_dir(struct inode *dir)
void *inline_dentry;
struct f2fs_dentry_ptr d;
- ipage = get_node_page(sbi, dir->i_ino);
+ ipage = f2fs_get_node_page(sbi, dir->i_ino);
if (IS_ERR(ipage))
return false;
@@ -630,7 +626,7 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx,
if (ctx->pos == d.max)
return 0;
- ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino);
+ ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
if (IS_ERR(ipage))
return PTR_ERR(ipage);
@@ -656,7 +652,7 @@ int f2fs_inline_data_fiemap(struct inode *inode,
struct page *ipage;
int err = 0;
- ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino);
+ ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
if (IS_ERR(ipage))
return PTR_ERR(ipage);
@@ -672,7 +668,7 @@ int f2fs_inline_data_fiemap(struct inode *inode,
ilen = start + len;
ilen -= start;
- get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni);
+ f2fs_get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni);
byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits;
byteaddr += (char *)inline_data_addr(inode, ipage) -
(char *)F2FS_INODE(ipage);
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index e0d9e8f..f121c86 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -36,15 +36,15 @@ void f2fs_set_inode_flags(struct inode *inode)
unsigned int flags = F2FS_I(inode)->i_flags;
unsigned int new_fl = 0;
- if (flags & FS_SYNC_FL)
+ if (flags & F2FS_SYNC_FL)
new_fl |= S_SYNC;
- if (flags & FS_APPEND_FL)
+ if (flags & F2FS_APPEND_FL)
new_fl |= S_APPEND;
- if (flags & FS_IMMUTABLE_FL)
+ if (flags & F2FS_IMMUTABLE_FL)
new_fl |= S_IMMUTABLE;
- if (flags & FS_NOATIME_FL)
+ if (flags & F2FS_NOATIME_FL)
new_fl |= S_NOATIME;
- if (flags & FS_DIRSYNC_FL)
+ if (flags & F2FS_DIRSYNC_FL)
new_fl |= S_DIRSYNC;
if (f2fs_encrypted_inode(inode))
new_fl |= S_ENCRYPTED;
@@ -72,7 +72,7 @@ static bool __written_first_block(struct f2fs_inode *ri)
{
block_t addr = le32_to_cpu(ri->i_addr[offset_in_addr(ri)]);
- if (addr != NEW_ADDR && addr != NULL_ADDR)
+ if (is_valid_blkaddr(addr))
return true;
return false;
}
@@ -117,7 +117,6 @@ static void __recover_inline_status(struct inode *inode, struct page *ipage)
static bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct page *page)
{
struct f2fs_inode *ri = &F2FS_NODE(page)->i;
- int extra_isize = le32_to_cpu(ri->i_extra_isize);
if (!f2fs_sb_has_inode_chksum(sbi->sb))
return false;
@@ -125,7 +124,8 @@ static bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct page *page
if (!RAW_IS_INODE(F2FS_NODE(page)) || !(ri->i_inline & F2FS_EXTRA_ATTR))
return false;
- if (!F2FS_FITS_IN_INODE(ri, extra_isize, i_inode_checksum))
+ if (!F2FS_FITS_IN_INODE(ri, le16_to_cpu(ri->i_extra_isize),
+ i_inode_checksum))
return false;
return true;
@@ -185,6 +185,21 @@ void f2fs_inode_chksum_set(struct f2fs_sb_info *sbi, struct page *page)
ri->i_inode_checksum = cpu_to_le32(f2fs_inode_chksum(sbi, page));
}
+static bool sanity_check_inode(struct inode *inode)
+{
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+
+ if (f2fs_sb_has_flexible_inline_xattr(sbi->sb)
+ && !f2fs_has_extra_attr(inode)) {
+ set_sbi_flag(sbi, SBI_NEED_FSCK);
+ f2fs_msg(sbi->sb, KERN_WARNING,
+ "%s: corrupted inode ino=%lx, run fsck to fix.",
+ __func__, inode->i_ino);
+ return false;
+ }
+ return true;
+}
+
static int do_read_inode(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
@@ -194,14 +209,10 @@ static int do_read_inode(struct inode *inode)
projid_t i_projid;
/* Check if ino is within scope */
- if (check_nid_range(sbi, inode->i_ino)) {
- f2fs_msg(inode->i_sb, KERN_ERR, "bad inode number: %lu",
- (unsigned long) inode->i_ino);
- WARN_ON(1);
+ if (f2fs_check_nid_range(sbi, inode->i_ino))
return -EINVAL;
- }
- node_page = get_node_page(sbi, inode->i_ino);
+ node_page = f2fs_get_node_page(sbi, inode->i_ino);
if (IS_ERR(node_page))
return PTR_ERR(node_page);
@@ -221,8 +232,11 @@ static int do_read_inode(struct inode *inode)
inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec);
inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec);
inode->i_generation = le32_to_cpu(ri->i_generation);
-
- fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
+ if (S_ISDIR(inode->i_mode))
+ fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
+ else if (S_ISREG(inode->i_mode))
+ fi->i_gc_failures[GC_FAILURE_PIN] =
+ le16_to_cpu(ri->i_gc_failures);
fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
fi->i_flags = le32_to_cpu(ri->i_flags);
fi->flags = 0;
@@ -239,7 +253,6 @@ static int do_read_inode(struct inode *inode)
le16_to_cpu(ri->i_extra_isize) : 0;
if (f2fs_sb_has_flexible_inline_xattr(sbi->sb)) {
- f2fs_bug_on(sbi, !f2fs_has_extra_attr(inode));
fi->i_inline_xattr_size = le16_to_cpu(ri->i_inline_xattr_size);
} else if (f2fs_has_inline_xattr(inode) ||
f2fs_has_inline_dentry(inode)) {
@@ -265,10 +278,10 @@ static int do_read_inode(struct inode *inode)
if (__written_first_block(ri))
set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN);
- if (!need_inode_block_update(sbi, inode->i_ino))
+ if (!f2fs_need_inode_block_update(sbi, inode->i_ino))
fi->last_disk_size = inode->i_size;
- if (fi->i_flags & FS_PROJINHERIT_FL)
+ if (fi->i_flags & F2FS_PROJINHERIT_FL)
set_inode_flag(inode, FI_PROJ_INHERIT);
if (f2fs_has_extra_attr(inode) && f2fs_sb_has_project_quota(sbi->sb) &&
@@ -284,9 +297,9 @@ static int do_read_inode(struct inode *inode)
fi->i_crtime.tv_nsec = le32_to_cpu(ri->i_crtime_nsec);
}
- F2FS_I(inode)->i_disk_time[0] = inode->i_atime;
- F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
- F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
+ F2FS_I(inode)->i_disk_time[0] = timespec64_to_timespec(inode->i_atime);
+ F2FS_I(inode)->i_disk_time[1] = timespec64_to_timespec(inode->i_ctime);
+ F2FS_I(inode)->i_disk_time[2] = timespec64_to_timespec(inode->i_mtime);
F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
f2fs_put_page(node_page, 1);
@@ -317,13 +330,17 @@ struct inode *f2fs_iget(struct super_block *sb, unsigned long ino)
ret = do_read_inode(inode);
if (ret)
goto bad_inode;
+ if (!sanity_check_inode(inode)) {
+ ret = -EINVAL;
+ goto bad_inode;
+ }
make_now:
if (ino == F2FS_NODE_INO(sbi)) {
inode->i_mapping->a_ops = &f2fs_node_aops;
- mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
+ mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
} else if (ino == F2FS_META_INO(sbi)) {
inode->i_mapping->a_ops = &f2fs_meta_aops;
- mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);
+ mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
} else if (S_ISREG(inode->i_mode)) {
inode->i_op = &f2fs_file_inode_operations;
inode->i_fop = &f2fs_file_operations;
@@ -373,7 +390,7 @@ retry:
return inode;
}
-void update_inode(struct inode *inode, struct page *node_page)
+void f2fs_update_inode(struct inode *inode, struct page *node_page)
{
struct f2fs_inode *ri;
struct extent_tree *et = F2FS_I(inode)->extent_tree;
@@ -408,7 +425,12 @@ void update_inode(struct inode *inode, struct page *node_page)
ri->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec);
ri->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec);
ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec);
- ri->i_current_depth = cpu_to_le32(F2FS_I(inode)->i_current_depth);
+ if (S_ISDIR(inode->i_mode))
+ ri->i_current_depth =
+ cpu_to_le32(F2FS_I(inode)->i_current_depth);
+ else if (S_ISREG(inode->i_mode))
+ ri->i_gc_failures =
+ cpu_to_le16(F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN]);
ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
@@ -448,18 +470,18 @@ void update_inode(struct inode *inode, struct page *node_page)
if (inode->i_nlink == 0)
clear_inline_node(node_page);
- F2FS_I(inode)->i_disk_time[0] = inode->i_atime;
- F2FS_I(inode)->i_disk_time[1] = inode->i_ctime;
- F2FS_I(inode)->i_disk_time[2] = inode->i_mtime;
+ F2FS_I(inode)->i_disk_time[0] = timespec64_to_timespec(inode->i_atime);
+ F2FS_I(inode)->i_disk_time[1] = timespec64_to_timespec(inode->i_ctime);
+ F2FS_I(inode)->i_disk_time[2] = timespec64_to_timespec(inode->i_mtime);
F2FS_I(inode)->i_disk_time[3] = F2FS_I(inode)->i_crtime;
}
-void update_inode_page(struct inode *inode)
+void f2fs_update_inode_page(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct page *node_page;
retry:
- node_page = get_node_page(sbi, inode->i_ino);
+ node_page = f2fs_get_node_page(sbi, inode->i_ino);
if (IS_ERR(node_page)) {
int err = PTR_ERR(node_page);
if (err == -ENOMEM) {
@@ -470,7 +492,7 @@ retry:
}
return;
}
- update_inode(inode, node_page);
+ f2fs_update_inode(inode, node_page);
f2fs_put_page(node_page, 1);
}
@@ -489,7 +511,7 @@ int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc)
* We need to balance fs here to prevent from producing dirty node pages
* during the urgent cleaning time when runing out of free sections.
*/
- update_inode_page(inode);
+ f2fs_update_inode_page(inode);
if (wbc && wbc->nr_to_write)
f2fs_balance_fs(sbi, true);
return 0;
@@ -506,7 +528,7 @@ void f2fs_evict_inode(struct inode *inode)
/* some remained atomic pages should discarded */
if (f2fs_is_atomic_file(inode))
- drop_inmem_pages(inode);
+ f2fs_drop_inmem_pages(inode);
trace_f2fs_evict_inode(inode);
truncate_inode_pages_final(&inode->i_data);
@@ -516,7 +538,7 @@ void f2fs_evict_inode(struct inode *inode)
goto out_clear;
f2fs_bug_on(sbi, get_dirty_pages(inode));
- remove_dirty_inode(inode);
+ f2fs_remove_dirty_inode(inode);
f2fs_destroy_extent_tree(inode);
@@ -525,9 +547,9 @@ void f2fs_evict_inode(struct inode *inode)
dquot_initialize(inode);
- remove_ino_entry(sbi, inode->i_ino, APPEND_INO);
- remove_ino_entry(sbi, inode->i_ino, UPDATE_INO);
- remove_ino_entry(sbi, inode->i_ino, FLUSH_INO);
+ f2fs_remove_ino_entry(sbi, inode->i_ino, APPEND_INO);
+ f2fs_remove_ino_entry(sbi, inode->i_ino, UPDATE_INO);
+ f2fs_remove_ino_entry(sbi, inode->i_ino, FLUSH_INO);
sb_start_intwrite(inode->i_sb);
set_inode_flag(inode, FI_NO_ALLOC);
@@ -544,7 +566,7 @@ retry:
#endif
if (!err) {
f2fs_lock_op(sbi);
- err = remove_inode_page(inode);
+ err = f2fs_remove_inode_page(inode);
f2fs_unlock_op(sbi);
if (err == -ENOENT)
err = 0;
@@ -557,7 +579,7 @@ retry:
}
if (err)
- update_inode_page(inode);
+ f2fs_update_inode_page(inode);
dquot_free_inode(inode);
sb_end_intwrite(inode->i_sb);
no_delete:
@@ -580,16 +602,19 @@ no_delete:
invalidate_mapping_pages(NODE_MAPPING(sbi), xnid, xnid);
if (inode->i_nlink) {
if (is_inode_flag_set(inode, FI_APPEND_WRITE))
- add_ino_entry(sbi, inode->i_ino, APPEND_INO);
+ f2fs_add_ino_entry(sbi, inode->i_ino, APPEND_INO);
if (is_inode_flag_set(inode, FI_UPDATE_WRITE))
- add_ino_entry(sbi, inode->i_ino, UPDATE_INO);
+ f2fs_add_ino_entry(sbi, inode->i_ino, UPDATE_INO);
}
if (is_inode_flag_set(inode, FI_FREE_NID)) {
- alloc_nid_failed(sbi, inode->i_ino);
+ f2fs_alloc_nid_failed(sbi, inode->i_ino);
clear_inode_flag(inode, FI_FREE_NID);
} else {
- f2fs_bug_on(sbi, err &&
- !exist_written_data(sbi, inode->i_ino, ORPHAN_INO));
+ /*
+ * If xattr nid is corrupted, we can reach out error condition,
+ * err & !f2fs_exist_written_data(sbi, inode->i_ino, ORPHAN_INO)).
+ * In that case, f2fs_check_nid_range() is enough to give a clue.
+ */
}
out_clear:
fscrypt_put_encryption_info(inode);
@@ -597,7 +622,7 @@ out_clear:
}
/* caller should call f2fs_lock_op() */
-void handle_failed_inode(struct inode *inode)
+void f2fs_handle_failed_inode(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct node_info ni;
@@ -612,7 +637,7 @@ void handle_failed_inode(struct inode *inode)
* we must call this to avoid inode being remained as dirty, resulting
* in a panic when flushing dirty inodes in gdirty_list.
*/
- update_inode_page(inode);
+ f2fs_update_inode_page(inode);
f2fs_inode_synced(inode);
/* don't make bad inode, since it becomes a regular file. */
@@ -623,18 +648,18 @@ void handle_failed_inode(struct inode *inode)
* so we can prevent losing this orphan when encoutering checkpoint
* and following suddenly power-off.
*/
- get_node_info(sbi, inode->i_ino, &ni);
+ f2fs_get_node_info(sbi, inode->i_ino, &ni);
if (ni.blk_addr != NULL_ADDR) {
- int err = acquire_orphan_inode(sbi);
+ int err = f2fs_acquire_orphan_inode(sbi);
if (err) {
set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_msg(sbi->sb, KERN_WARNING,
"Too many orphan inodes, run fsck to fix.");
} else {
- add_orphan_inode(inode);
+ f2fs_add_orphan_inode(inode);
}
- alloc_nid_done(sbi, inode->i_ino);
+ f2fs_alloc_nid_done(sbi, inode->i_ino);
} else {
set_inode_flag(inode, FI_FREE_NID);
}
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index 75e37fd..231b7f3 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -37,7 +37,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
return ERR_PTR(-ENOMEM);
f2fs_lock_op(sbi);
- if (!alloc_nid(sbi, &ino)) {
+ if (!f2fs_alloc_nid(sbi, &ino)) {
f2fs_unlock_op(sbi);
err = -ENOSPC;
goto fail;
@@ -50,10 +50,13 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
inode->i_ino = ino;
inode->i_blocks = 0;
- inode->i_mtime = inode->i_atime = inode->i_ctime =
- F2FS_I(inode)->i_crtime = current_time(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ F2FS_I(inode)->i_crtime = timespec64_to_timespec(inode->i_mtime);
inode->i_generation = sbi->s_next_generation++;
+ if (S_ISDIR(inode->i_mode))
+ F2FS_I(inode)->i_current_depth = 1;
+
err = insert_inode_locked(inode);
if (err) {
err = -EINVAL;
@@ -61,7 +64,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
}
if (f2fs_sb_has_project_quota(sbi->sb) &&
- (F2FS_I(dir)->i_flags & FS_PROJINHERIT_FL))
+ (F2FS_I(dir)->i_flags & F2FS_PROJINHERIT_FL))
F2FS_I(inode)->i_projid = F2FS_I(dir)->i_projid;
else
F2FS_I(inode)->i_projid = make_kprojid(&init_user_ns,
@@ -116,9 +119,9 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
f2fs_mask_flags(mode, F2FS_I(dir)->i_flags & F2FS_FL_INHERITED);
if (S_ISDIR(inode->i_mode))
- F2FS_I(inode)->i_flags |= FS_INDEX_FL;
+ F2FS_I(inode)->i_flags |= F2FS_INDEX_FL;
- if (F2FS_I(inode)->i_flags & FS_PROJINHERIT_FL)
+ if (F2FS_I(inode)->i_flags & F2FS_PROJINHERIT_FL)
set_inode_flag(inode, FI_PROJ_INHERIT);
trace_f2fs_new_inode(inode, 0);
@@ -193,7 +196,7 @@ static inline void set_file_temperature(struct f2fs_sb_info *sbi, struct inode *
up_read(&sbi->sb_lock);
}
-int update_extension_list(struct f2fs_sb_info *sbi, const char *name,
+int f2fs_update_extension_list(struct f2fs_sb_info *sbi, const char *name,
bool hot, bool set)
{
__u8 (*extlist)[F2FS_EXTENSION_LEN] = sbi->raw_super->extension_list;
@@ -292,7 +295,7 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
goto out;
f2fs_unlock_op(sbi);
- alloc_nid_done(sbi, ino);
+ f2fs_alloc_nid_done(sbi, ino);
d_instantiate_new(dentry, inode);
@@ -302,7 +305,7 @@ static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
f2fs_balance_fs(sbi, true);
return 0;
out:
- handle_failed_inode(inode);
+ f2fs_handle_failed_inode(inode);
return err;
}
@@ -397,7 +400,7 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino)
err = PTR_ERR(page);
goto out;
} else {
- err = __f2fs_add_link(dir, &dot, NULL, dir->i_ino, S_IFDIR);
+ err = f2fs_do_add_link(dir, &dot, NULL, dir->i_ino, S_IFDIR);
if (err)
goto out;
}
@@ -408,7 +411,7 @@ static int __recover_dot_dentries(struct inode *dir, nid_t pino)
else if (IS_ERR(page))
err = PTR_ERR(page);
else
- err = __f2fs_add_link(dir, &dotdot, NULL, pino, S_IFDIR);
+ err = f2fs_do_add_link(dir, &dotdot, NULL, pino, S_IFDIR);
out:
if (!err)
clear_inode_flag(dir, FI_INLINE_DOTS);
@@ -520,7 +523,7 @@ static int f2fs_unlink(struct inode *dir, struct dentry *dentry)
f2fs_balance_fs(sbi, true);
f2fs_lock_op(sbi);
- err = acquire_orphan_inode(sbi);
+ err = f2fs_acquire_orphan_inode(sbi);
if (err) {
f2fs_unlock_op(sbi);
f2fs_put_page(page, 0);
@@ -585,9 +588,9 @@ static int f2fs_symlink(struct inode *dir, struct dentry *dentry,
f2fs_lock_op(sbi);
err = f2fs_add_link(dentry, inode);
if (err)
- goto out_handle_failed_inode;
+ goto out_f2fs_handle_failed_inode;
f2fs_unlock_op(sbi);
- alloc_nid_done(sbi, inode->i_ino);
+ f2fs_alloc_nid_done(sbi, inode->i_ino);
err = fscrypt_encrypt_symlink(inode, symname, len, &disk_link);
if (err)
@@ -620,8 +623,8 @@ err_out:
f2fs_balance_fs(sbi, true);
goto out_free_encrypted_link;
-out_handle_failed_inode:
- handle_failed_inode(inode);
+out_f2fs_handle_failed_inode:
+ f2fs_handle_failed_inode(inode);
out_free_encrypted_link:
if (disk_link.name != (unsigned char *)symname)
kfree(disk_link.name);
@@ -657,7 +660,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
goto out_fail;
f2fs_unlock_op(sbi);
- alloc_nid_done(sbi, inode->i_ino);
+ f2fs_alloc_nid_done(sbi, inode->i_ino);
d_instantiate_new(dentry, inode);
@@ -669,7 +672,7 @@ static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
out_fail:
clear_inode_flag(inode, FI_INC_LINK);
- handle_failed_inode(inode);
+ f2fs_handle_failed_inode(inode);
return err;
}
@@ -708,7 +711,7 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
goto out;
f2fs_unlock_op(sbi);
- alloc_nid_done(sbi, inode->i_ino);
+ f2fs_alloc_nid_done(sbi, inode->i_ino);
d_instantiate_new(dentry, inode);
@@ -718,7 +721,7 @@ static int f2fs_mknod(struct inode *dir, struct dentry *dentry,
f2fs_balance_fs(sbi, true);
return 0;
out:
- handle_failed_inode(inode);
+ f2fs_handle_failed_inode(inode);
return err;
}
@@ -747,7 +750,7 @@ static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry,
}
f2fs_lock_op(sbi);
- err = acquire_orphan_inode(sbi);
+ err = f2fs_acquire_orphan_inode(sbi);
if (err)
goto out;
@@ -759,8 +762,8 @@ static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry,
* add this non-linked tmpfile to orphan list, in this way we could
* remove all unused data of tmpfile after abnormal power-off.
*/
- add_orphan_inode(inode);
- alloc_nid_done(sbi, inode->i_ino);
+ f2fs_add_orphan_inode(inode);
+ f2fs_alloc_nid_done(sbi, inode->i_ino);
if (whiteout) {
f2fs_i_links_write(inode, false);
@@ -776,9 +779,9 @@ static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry,
return 0;
release_out:
- release_orphan_inode(sbi);
+ f2fs_release_orphan_inode(sbi);
out:
- handle_failed_inode(inode);
+ f2fs_handle_failed_inode(inode);
return err;
}
@@ -885,7 +888,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
f2fs_lock_op(sbi);
- err = acquire_orphan_inode(sbi);
+ err = f2fs_acquire_orphan_inode(sbi);
if (err)
goto put_out_dir;
@@ -899,9 +902,9 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
up_write(&F2FS_I(new_inode)->i_sem);
if (!new_inode->i_nlink)
- add_orphan_inode(new_inode);
+ f2fs_add_orphan_inode(new_inode);
else
- release_orphan_inode(sbi);
+ f2fs_release_orphan_inode(sbi);
} else {
f2fs_balance_fs(sbi, true);
@@ -969,8 +972,12 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
f2fs_put_page(old_dir_page, 0);
f2fs_i_links_write(old_dir, false);
}
- if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT)
- add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
+ if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT) {
+ f2fs_add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
+ if (S_ISDIR(old_inode->i_mode))
+ f2fs_add_ino_entry(sbi, old_inode->i_ino,
+ TRANS_DIR_INO);
+ }
f2fs_unlock_op(sbi);
@@ -1121,8 +1128,8 @@ static int f2fs_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
f2fs_mark_inode_dirty_sync(new_dir, false);
if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT) {
- add_ino_entry(sbi, old_dir->i_ino, TRANS_DIR_INO);
- add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
+ f2fs_add_ino_entry(sbi, old_dir->i_ino, TRANS_DIR_INO);
+ f2fs_add_ino_entry(sbi, new_dir->i_ino, TRANS_DIR_INO);
}
f2fs_unlock_op(sbi);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index f202398..10643b1 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -23,13 +23,28 @@
#include "trace.h"
#include <trace/events/f2fs.h>
-#define on_build_free_nids(nmi) mutex_is_locked(&(nm_i)->build_lock)
+#define on_f2fs_build_free_nids(nmi) mutex_is_locked(&(nm_i)->build_lock)
static struct kmem_cache *nat_entry_slab;
static struct kmem_cache *free_nid_slab;
static struct kmem_cache *nat_entry_set_slab;
-bool available_free_memory(struct f2fs_sb_info *sbi, int type)
+/*
+ * Check whether the given nid is within node id range.
+ */
+int f2fs_check_nid_range(struct f2fs_sb_info *sbi, nid_t nid)
+{
+ if (unlikely(nid < F2FS_ROOT_INO(sbi) || nid >= NM_I(sbi)->max_nid)) {
+ set_sbi_flag(sbi, SBI_NEED_FSCK);
+ f2fs_msg(sbi->sb, KERN_WARNING,
+ "%s: out-of-range nid=%x, run fsck to fix.",
+ __func__, nid);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+bool f2fs_available_free_memory(struct f2fs_sb_info *sbi, int type)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct sysinfo val;
@@ -87,18 +102,10 @@ bool available_free_memory(struct f2fs_sb_info *sbi, int type)
static void clear_node_page_dirty(struct page *page)
{
- struct address_space *mapping = page->mapping;
- unsigned int long flags;
-
if (PageDirty(page)) {
- xa_lock_irqsave(&mapping->i_pages, flags);
- radix_tree_tag_clear(&mapping->i_pages,
- page_index(page),
- PAGECACHE_TAG_DIRTY);
- xa_unlock_irqrestore(&mapping->i_pages, flags);
-
+ f2fs_clear_radix_tree_dirty_tag(page);
clear_page_dirty_for_io(page);
- dec_page_count(F2FS_M_SB(mapping), F2FS_DIRTY_NODES);
+ dec_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES);
}
ClearPageUptodate(page);
}
@@ -106,7 +113,7 @@ static void clear_node_page_dirty(struct page *page)
static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
{
pgoff_t index = current_nat_addr(sbi, nid);
- return get_meta_page(sbi, index);
+ return f2fs_get_meta_page(sbi, index);
}
static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
@@ -123,8 +130,8 @@ static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
dst_off = next_nat_addr(sbi, src_off);
/* get current nat block page with lock */
- src_page = get_meta_page(sbi, src_off);
- dst_page = grab_meta_page(sbi, dst_off);
+ src_page = f2fs_get_meta_page(sbi, src_off);
+ dst_page = f2fs_grab_meta_page(sbi, dst_off);
f2fs_bug_on(sbi, PageDirty(src_page));
src_addr = page_address(src_page);
@@ -260,7 +267,7 @@ static unsigned int __gang_lookup_nat_set(struct f2fs_nm_info *nm_i,
start, nr);
}
-int need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid)
+int f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct nat_entry *e;
@@ -277,7 +284,7 @@ int need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid)
return need;
}
-bool is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
+bool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct nat_entry *e;
@@ -291,7 +298,7 @@ bool is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
return is_cp;
}
-bool need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino)
+bool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct nat_entry *e;
@@ -364,8 +371,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
new_blkaddr == NULL_ADDR);
f2fs_bug_on(sbi, nat_get_blkaddr(e) == NEW_ADDR &&
new_blkaddr == NEW_ADDR);
- f2fs_bug_on(sbi, nat_get_blkaddr(e) != NEW_ADDR &&
- nat_get_blkaddr(e) != NULL_ADDR &&
+ f2fs_bug_on(sbi, is_valid_blkaddr(nat_get_blkaddr(e)) &&
new_blkaddr == NEW_ADDR);
/* increment version no as node is removed */
@@ -376,7 +382,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
/* change address */
nat_set_blkaddr(e, new_blkaddr);
- if (new_blkaddr == NEW_ADDR || new_blkaddr == NULL_ADDR)
+ if (!is_valid_blkaddr(new_blkaddr))
set_nat_flag(e, IS_CHECKPOINTED, false);
__set_nat_cache_dirty(nm_i, e);
@@ -391,7 +397,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
up_write(&nm_i->nat_tree_lock);
}
-int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
+int f2fs_try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
int nr = nr_shrink;
@@ -413,7 +419,8 @@ int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
/*
* This function always returns success
*/
-void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
+void f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
+ struct node_info *ni)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
@@ -443,7 +450,7 @@ void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
/* Check current segment summary */
down_read(&curseg->journal_rwsem);
- i = lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
+ i = f2fs_lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
if (i >= 0) {
ne = nat_in_journal(journal, i);
node_info_from_raw_nat(ni, &ne);
@@ -458,7 +465,7 @@ void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
index = current_nat_addr(sbi, nid);
up_read(&nm_i->nat_tree_lock);
- page = get_meta_page(sbi, index);
+ page = f2fs_get_meta_page(sbi, index);
nat_blk = (struct f2fs_nat_block *)page_address(page);
ne = nat_blk->entries[nid - start_nid];
node_info_from_raw_nat(ni, &ne);
@@ -471,7 +478,7 @@ cache:
/*
* readahead MAX_RA_NODE number of node pages.
*/
-static void ra_node_pages(struct page *parent, int start, int n)
+static void f2fs_ra_node_pages(struct page *parent, int start, int n)
{
struct f2fs_sb_info *sbi = F2FS_P_SB(parent);
struct blk_plug plug;
@@ -485,13 +492,13 @@ static void ra_node_pages(struct page *parent, int start, int n)
end = min(end, NIDS_PER_BLOCK);
for (i = start; i < end; i++) {
nid = get_nid(parent, i, false);
- ra_node_page(sbi, nid);
+ f2fs_ra_node_page(sbi, nid);
}
blk_finish_plug(&plug);
}
-pgoff_t get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
+pgoff_t f2fs_get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs)
{
const long direct_index = ADDRS_PER_INODE(dn->inode);
const long direct_blks = ADDRS_PER_BLOCK;
@@ -606,7 +613,7 @@ got:
* f2fs_unlock_op() only if ro is not set RDONLY_NODE.
* In the case of RDONLY_NODE, we don't need to care about mutex.
*/
-int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
+int f2fs_get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
struct page *npage[4];
@@ -625,7 +632,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
npage[0] = dn->inode_page;
if (!npage[0]) {
- npage[0] = get_node_page(sbi, nids[0]);
+ npage[0] = f2fs_get_node_page(sbi, nids[0]);
if (IS_ERR(npage[0]))
return PTR_ERR(npage[0]);
}
@@ -649,24 +656,24 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
if (!nids[i] && mode == ALLOC_NODE) {
/* alloc new node */
- if (!alloc_nid(sbi, &(nids[i]))) {
+ if (!f2fs_alloc_nid(sbi, &(nids[i]))) {
err = -ENOSPC;
goto release_pages;
}
dn->nid = nids[i];
- npage[i] = new_node_page(dn, noffset[i]);
+ npage[i] = f2fs_new_node_page(dn, noffset[i]);
if (IS_ERR(npage[i])) {
- alloc_nid_failed(sbi, nids[i]);
+ f2fs_alloc_nid_failed(sbi, nids[i]);
err = PTR_ERR(npage[i]);
goto release_pages;
}
set_nid(parent, offset[i - 1], nids[i], i == 1);
- alloc_nid_done(sbi, nids[i]);
+ f2fs_alloc_nid_done(sbi, nids[i]);
done = true;
} else if (mode == LOOKUP_NODE_RA && i == level && level > 1) {
- npage[i] = get_node_page_ra(parent, offset[i - 1]);
+ npage[i] = f2fs_get_node_page_ra(parent, offset[i - 1]);
if (IS_ERR(npage[i])) {
err = PTR_ERR(npage[i]);
goto release_pages;
@@ -681,7 +688,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
}
if (!done) {
- npage[i] = get_node_page(sbi, nids[i]);
+ npage[i] = f2fs_get_node_page(sbi, nids[i]);
if (IS_ERR(npage[i])) {
err = PTR_ERR(npage[i]);
f2fs_put_page(npage[0], 0);
@@ -720,15 +727,15 @@ static void truncate_node(struct dnode_of_data *dn)
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
struct node_info ni;
- get_node_info(sbi, dn->nid, &ni);
+ f2fs_get_node_info(sbi, dn->nid, &ni);
/* Deallocate node address */
- invalidate_blocks(sbi, ni.blk_addr);
+ f2fs_invalidate_blocks(sbi, ni.blk_addr);
dec_valid_node_count(sbi, dn->inode, dn->nid == dn->inode->i_ino);
set_node_addr(sbi, &ni, NULL_ADDR, false);
if (dn->nid == dn->inode->i_ino) {
- remove_orphan_inode(sbi, dn->nid);
+ f2fs_remove_orphan_inode(sbi, dn->nid);
dec_valid_inode_count(sbi);
f2fs_inode_synced(dn->inode);
}
@@ -753,7 +760,7 @@ static int truncate_dnode(struct dnode_of_data *dn)
return 1;
/* get direct node */
- page = get_node_page(F2FS_I_SB(dn->inode), dn->nid);
+ page = f2fs_get_node_page(F2FS_I_SB(dn->inode), dn->nid);
if (IS_ERR(page) && PTR_ERR(page) == -ENOENT)
return 1;
else if (IS_ERR(page))
@@ -762,7 +769,7 @@ static int truncate_dnode(struct dnode_of_data *dn)
/* Make dnode_of_data for parameter */
dn->node_page = page;
dn->ofs_in_node = 0;
- truncate_data_blocks(dn);
+ f2fs_truncate_data_blocks(dn);
truncate_node(dn);
return 1;
}
@@ -783,13 +790,13 @@ static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr);
- page = get_node_page(F2FS_I_SB(dn->inode), dn->nid);
+ page = f2fs_get_node_page(F2FS_I_SB(dn->inode), dn->nid);
if (IS_ERR(page)) {
trace_f2fs_truncate_nodes_exit(dn->inode, PTR_ERR(page));
return PTR_ERR(page);
}
- ra_node_pages(page, ofs, NIDS_PER_BLOCK);
+ f2fs_ra_node_pages(page, ofs, NIDS_PER_BLOCK);
rn = F2FS_NODE(page);
if (depth < 3) {
@@ -859,7 +866,7 @@ static int truncate_partial_nodes(struct dnode_of_data *dn,
/* get indirect nodes in the path */
for (i = 0; i < idx + 1; i++) {
/* reference count'll be increased */
- pages[i] = get_node_page(F2FS_I_SB(dn->inode), nid[i]);
+ pages[i] = f2fs_get_node_page(F2FS_I_SB(dn->inode), nid[i]);
if (IS_ERR(pages[i])) {
err = PTR_ERR(pages[i]);
idx = i - 1;
@@ -868,7 +875,7 @@ static int truncate_partial_nodes(struct dnode_of_data *dn,
nid[i + 1] = get_nid(pages[i], offset[i + 1], false);
}
- ra_node_pages(pages[idx], offset[idx + 1], NIDS_PER_BLOCK);
+ f2fs_ra_node_pages(pages[idx], offset[idx + 1], NIDS_PER_BLOCK);
/* free direct nodes linked to a partial indirect node */
for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) {
@@ -905,7 +912,7 @@ fail:
/*
* All the block addresses of data and nodes should be nullified.
*/
-int truncate_inode_blocks(struct inode *inode, pgoff_t from)
+int f2fs_truncate_inode_blocks(struct inode *inode, pgoff_t from)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
int err = 0, cont = 1;
@@ -921,7 +928,7 @@ int truncate_inode_blocks(struct inode *inode, pgoff_t from)
if (level < 0)
return level;
- page = get_node_page(sbi, inode->i_ino);
+ page = f2fs_get_node_page(sbi, inode->i_ino);
if (IS_ERR(page)) {
trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page));
return PTR_ERR(page);
@@ -1001,7 +1008,7 @@ fail:
}
/* caller must lock inode page */
-int truncate_xattr_node(struct inode *inode)
+int f2fs_truncate_xattr_node(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
nid_t nid = F2FS_I(inode)->i_xattr_nid;
@@ -1011,7 +1018,7 @@ int truncate_xattr_node(struct inode *inode)
if (!nid)
return 0;
- npage = get_node_page(sbi, nid);
+ npage = f2fs_get_node_page(sbi, nid);
if (IS_ERR(npage))
return PTR_ERR(npage);
@@ -1026,17 +1033,17 @@ int truncate_xattr_node(struct inode *inode)
* Caller should grab and release a rwsem by calling f2fs_lock_op() and
* f2fs_unlock_op().
*/
-int remove_inode_page(struct inode *inode)
+int f2fs_remove_inode_page(struct inode *inode)
{
struct dnode_of_data dn;
int err;
set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
- err = get_dnode_of_data(&dn, 0, LOOKUP_NODE);
+ err = f2fs_get_dnode_of_data(&dn, 0, LOOKUP_NODE);
if (err)
return err;
- err = truncate_xattr_node(inode);
+ err = f2fs_truncate_xattr_node(inode);
if (err) {
f2fs_put_dnode(&dn);
return err;
@@ -1045,7 +1052,7 @@ int remove_inode_page(struct inode *inode)
/* remove potential inline_data blocks */
if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode))
- truncate_data_blocks_range(&dn, 1);
+ f2fs_truncate_data_blocks_range(&dn, 1);
/* 0 is possible, after f2fs_new_inode() has failed */
f2fs_bug_on(F2FS_I_SB(inode),
@@ -1056,7 +1063,7 @@ int remove_inode_page(struct inode *inode)
return 0;
}
-struct page *new_inode_page(struct inode *inode)
+struct page *f2fs_new_inode_page(struct inode *inode)
{
struct dnode_of_data dn;
@@ -1064,10 +1071,10 @@ struct page *new_inode_page(struct inode *inode)
set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
/* caller should f2fs_put_page(page, 1); */
- return new_node_page(&dn, 0);
+ return f2fs_new_node_page(&dn, 0);
}
-struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
+struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
struct node_info new_ni;
@@ -1085,7 +1092,7 @@ struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
goto fail;
#ifdef CONFIG_F2FS_CHECK_FS
- get_node_info(sbi, dn->nid, &new_ni);
+ f2fs_get_node_info(sbi, dn->nid, &new_ni);
f2fs_bug_on(sbi, new_ni.blk_addr != NULL_ADDR);
#endif
new_ni.nid = dn->nid;
@@ -1137,7 +1144,7 @@ static int read_node_page(struct page *page, int op_flags)
if (PageUptodate(page))
return LOCKED_PAGE;
- get_node_info(sbi, page->index, &ni);
+ f2fs_get_node_info(sbi, page->index, &ni);
if (unlikely(ni.blk_addr == NULL_ADDR)) {
ClearPageUptodate(page);
@@ -1151,14 +1158,15 @@ static int read_node_page(struct page *page, int op_flags)
/*
* Readahead a node page
*/
-void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)
+void f2fs_ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)
{
struct page *apage;
int err;
if (!nid)
return;
- f2fs_bug_on(sbi, check_nid_range(sbi, nid));
+ if (f2fs_check_nid_range(sbi, nid))
+ return;
rcu_read_lock();
apage = radix_tree_lookup(&NODE_MAPPING(sbi)->i_pages, nid);
@@ -1182,7 +1190,8 @@ static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid,
if (!nid)
return ERR_PTR(-ENOENT);
- f2fs_bug_on(sbi, check_nid_range(sbi, nid));
+ if (f2fs_check_nid_range(sbi, nid))
+ return ERR_PTR(-EINVAL);
repeat:
page = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false);
if (!page)
@@ -1198,7 +1207,7 @@ repeat:
}
if (parent)
- ra_node_pages(parent, start + 1, MAX_RA_NODE);
+ f2fs_ra_node_pages(parent, start + 1, MAX_RA_NODE);
lock_page(page);
@@ -1232,12 +1241,12 @@ out_err:
return page;
}
-struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid)
+struct page *f2fs_get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid)
{
return __get_node_page(sbi, nid, NULL, 0);
}
-struct page *get_node_page_ra(struct page *parent, int start)
+struct page *f2fs_get_node_page_ra(struct page *parent, int start)
{
struct f2fs_sb_info *sbi = F2FS_P_SB(parent);
nid_t nid = get_nid(parent, start, false);
@@ -1272,7 +1281,7 @@ static void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino)
ret = f2fs_write_inline_data(inode, page);
inode_dec_dirty_pages(inode);
- remove_dirty_inode(inode);
+ f2fs_remove_dirty_inode(inode);
if (ret)
set_page_dirty(page);
page_out:
@@ -1359,11 +1368,8 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
trace_f2fs_writepage(page, NODE);
- if (unlikely(f2fs_cp_error(sbi))) {
- dec_page_count(sbi, F2FS_DIRTY_NODES);
- unlock_page(page);
- return 0;
- }
+ if (unlikely(f2fs_cp_error(sbi)))
+ goto redirty_out;
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
goto redirty_out;
@@ -1379,7 +1385,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
down_read(&sbi->node_write);
}
- get_node_info(sbi, nid, &ni);
+ f2fs_get_node_info(sbi, nid, &ni);
/* This page is already truncated */
if (unlikely(ni.blk_addr == NULL_ADDR)) {
@@ -1394,8 +1400,9 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted,
fio.op_flags |= REQ_PREFLUSH | REQ_FUA;
set_page_writeback(page);
+ ClearPageError(page);
fio.old_blkaddr = ni.blk_addr;
- write_node_page(nid, &fio);
+ f2fs_do_write_node_page(nid, &fio);
set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page));
dec_page_count(sbi, F2FS_DIRTY_NODES);
up_read(&sbi->node_write);
@@ -1424,7 +1431,7 @@ redirty_out:
return AOP_WRITEPAGE_ACTIVATE;
}
-void move_node_page(struct page *node_page, int gc_type)
+void f2fs_move_node_page(struct page *node_page, int gc_type)
{
if (gc_type == FG_GC) {
struct writeback_control wbc = {
@@ -1461,7 +1468,7 @@ static int f2fs_write_node_page(struct page *page,
return __write_node_page(page, false, NULL, wbc, false, FS_NODE_IO);
}
-int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
+int f2fs_fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
struct writeback_control *wbc, bool atomic)
{
pgoff_t index;
@@ -1528,9 +1535,9 @@ continue_unlock:
if (IS_INODE(page)) {
if (is_inode_flag_set(inode,
FI_DIRTY_INODE))
- update_inode(inode, page);
+ f2fs_update_inode(inode, page);
set_dentry_mark(page,
- need_dentry_mark(sbi, ino));
+ f2fs_need_dentry_mark(sbi, ino));
}
/* may be written by other thread */
if (!PageDirty(page))
@@ -1580,7 +1587,8 @@ out:
return ret ? -EIO: 0;
}
-int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc,
+int f2fs_sync_node_pages(struct f2fs_sb_info *sbi,
+ struct writeback_control *wbc,
bool do_balance, enum iostat_type io_type)
{
pgoff_t index;
@@ -1588,21 +1596,28 @@ int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc,
int step = 0;
int nwritten = 0;
int ret = 0;
- int nr_pages;
+ int nr_pages, done = 0;
pagevec_init(&pvec);
next_step:
index = 0;
- while ((nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
- PAGECACHE_TAG_DIRTY))) {
+ while (!done && (nr_pages = pagevec_lookup_tag(&pvec,
+ NODE_MAPPING(sbi), &index, PAGECACHE_TAG_DIRTY))) {
int i;
for (i = 0; i < nr_pages; i++) {
struct page *page = pvec.pages[i];
bool submitted = false;
+ /* give a priority to WB_SYNC threads */
+ if (atomic_read(&sbi->wb_sync_req[NODE]) &&
+ wbc->sync_mode == WB_SYNC_NONE) {
+ done = 1;
+ break;
+ }
+
/*
* flushing sequence with step:
* 0. indirect nodes
@@ -1681,7 +1696,7 @@ continue_unlock:
return ret;
}
-int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
+int f2fs_wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
{
pgoff_t index = 0;
struct pagevec pvec;
@@ -1730,14 +1745,21 @@ static int f2fs_write_node_pages(struct address_space *mapping,
if (get_pages(sbi, F2FS_DIRTY_NODES) < nr_pages_to_skip(sbi, NODE))
goto skip_write;
+ if (wbc->sync_mode == WB_SYNC_ALL)
+ atomic_inc(&sbi->wb_sync_req[NODE]);
+ else if (atomic_read(&sbi->wb_sync_req[NODE]))
+ goto skip_write;
+
trace_f2fs_writepages(mapping->host, wbc, NODE);
diff = nr_pages_to_write(sbi, NODE, wbc);
- wbc->sync_mode = WB_SYNC_NONE;
blk_start_plug(&plug);
- sync_node_pages(sbi, wbc, true, FS_NODE_IO);
+ f2fs_sync_node_pages(sbi, wbc, true, FS_NODE_IO);
blk_finish_plug(&plug);
wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff);
+
+ if (wbc->sync_mode == WB_SYNC_ALL)
+ atomic_dec(&sbi->wb_sync_req[NODE]);
return 0;
skip_write:
@@ -1753,7 +1775,7 @@ static int f2fs_set_node_page_dirty(struct page *page)
if (!PageUptodate(page))
SetPageUptodate(page);
if (!PageDirty(page)) {
- f2fs_set_page_dirty_nobuffers(page);
+ __set_page_dirty_nobuffers(page);
inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES);
SetPagePrivate(page);
f2fs_trace_pid(page);
@@ -1883,20 +1905,20 @@ static bool add_free_nid(struct f2fs_sb_info *sbi,
* Thread A Thread B
* - f2fs_create
* - f2fs_new_inode
- * - alloc_nid
+ * - f2fs_alloc_nid
* - __insert_nid_to_list(PREALLOC_NID)
* - f2fs_balance_fs_bg
- * - build_free_nids
- * - __build_free_nids
+ * - f2fs_build_free_nids
+ * - __f2fs_build_free_nids
* - scan_nat_page
* - add_free_nid
* - __lookup_nat_cache
* - f2fs_add_link
- * - init_inode_metadata
- * - new_inode_page
- * - new_node_page
+ * - f2fs_init_inode_metadata
+ * - f2fs_new_inode_page
+ * - f2fs_new_node_page
* - set_node_addr
- * - alloc_nid_done
+ * - f2fs_alloc_nid_done
* - __remove_nid_from_list(PREALLOC_NID)
* - __insert_nid_to_list(FREE_NID)
*/
@@ -2028,7 +2050,8 @@ out:
up_read(&nm_i->nat_tree_lock);
}
-static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
+static void __f2fs_build_free_nids(struct f2fs_sb_info *sbi,
+ bool sync, bool mount)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
int i = 0;
@@ -2041,7 +2064,7 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
if (nm_i->nid_cnt[FREE_NID] >= NAT_ENTRY_PER_BLOCK)
return;
- if (!sync && !available_free_memory(sbi, FREE_NIDS))
+ if (!sync && !f2fs_available_free_memory(sbi, FREE_NIDS))
return;
if (!mount) {
@@ -2053,7 +2076,7 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
}
/* readahead nat pages to be scanned */
- ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
+ f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
META_NAT, true);
down_read(&nm_i->nat_tree_lock);
@@ -2083,14 +2106,14 @@ static void __build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
up_read(&nm_i->nat_tree_lock);
- ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
+ f2fs_ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
nm_i->ra_nid_pages, META_NAT, false);
}
-void build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
+void f2fs_build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
{
mutex_lock(&NM_I(sbi)->build_lock);
- __build_free_nids(sbi, sync, mount);
+ __f2fs_build_free_nids(sbi, sync, mount);
mutex_unlock(&NM_I(sbi)->build_lock);
}
@@ -2099,7 +2122,7 @@ void build_free_nids(struct f2fs_sb_info *sbi, bool sync, bool mount)
* from second parameter of this function.
* The returned nid could be used ino as well as nid when inode is created.
*/
-bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
+bool f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct free_nid *i = NULL;
@@ -2117,8 +2140,8 @@ retry:
return false;
}
- /* We should not use stale free nids created by build_free_nids */
- if (nm_i->nid_cnt[FREE_NID] && !on_build_free_nids(nm_i)) {
+ /* We should not use stale free nids created by f2fs_build_free_nids */
+ if (nm_i->nid_cnt[FREE_NID] && !on_f2fs_build_free_nids(nm_i)) {
f2fs_bug_on(sbi, list_empty(&nm_i->free_nid_list));
i = list_first_entry(&nm_i->free_nid_list,
struct free_nid, list);
@@ -2135,14 +2158,14 @@ retry:
spin_unlock(&nm_i->nid_list_lock);
/* Let's scan nat pages and its caches to get free nids */
- build_free_nids(sbi, true, false);
+ f2fs_build_free_nids(sbi, true, false);
goto retry;
}
/*
- * alloc_nid() should be called prior to this function.
+ * f2fs_alloc_nid() should be called prior to this function.
*/
-void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
+void f2fs_alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct free_nid *i;
@@ -2157,9 +2180,9 @@ void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
}
/*
- * alloc_nid() should be called prior to this function.
+ * f2fs_alloc_nid() should be called prior to this function.
*/
-void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
+void f2fs_alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct free_nid *i;
@@ -2172,7 +2195,7 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
i = __lookup_free_nid_list(nm_i, nid);
f2fs_bug_on(sbi, !i);
- if (!available_free_memory(sbi, FREE_NIDS)) {
+ if (!f2fs_available_free_memory(sbi, FREE_NIDS)) {
__remove_free_nid(sbi, i, PREALLOC_NID);
need_free = true;
} else {
@@ -2189,7 +2212,7 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
kmem_cache_free(free_nid_slab, i);
}
-int try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink)
+int f2fs_try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct free_nid *i, *next;
@@ -2217,14 +2240,14 @@ int try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink)
return nr - nr_shrink;
}
-void recover_inline_xattr(struct inode *inode, struct page *page)
+void f2fs_recover_inline_xattr(struct inode *inode, struct page *page)
{
void *src_addr, *dst_addr;
size_t inline_size;
struct page *ipage;
struct f2fs_inode *ri;
- ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino);
+ ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino);
f2fs_bug_on(F2FS_I_SB(inode), IS_ERR(ipage));
ri = F2FS_INODE(page);
@@ -2242,11 +2265,11 @@ void recover_inline_xattr(struct inode *inode, struct page *page)
f2fs_wait_on_page_writeback(ipage, NODE, true);
memcpy(dst_addr, src_addr, inline_size);
update_inode:
- update_inode(inode, ipage);
+ f2fs_update_inode(inode, ipage);
f2fs_put_page(ipage, 1);
}
-int recover_xattr_data(struct inode *inode, struct page *page)
+int f2fs_recover_xattr_data(struct inode *inode, struct page *page)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid;
@@ -2259,25 +2282,25 @@ int recover_xattr_data(struct inode *inode, struct page *page)
goto recover_xnid;
/* 1: invalidate the previous xattr nid */
- get_node_info(sbi, prev_xnid, &ni);
- invalidate_blocks(sbi, ni.blk_addr);
+ f2fs_get_node_info(sbi, prev_xnid, &ni);
+ f2fs_invalidate_blocks(sbi, ni.blk_addr);
dec_valid_node_count(sbi, inode, false);
set_node_addr(sbi, &ni, NULL_ADDR, false);
recover_xnid:
/* 2: update xattr nid in inode */
- if (!alloc_nid(sbi, &new_xnid))
+ if (!f2fs_alloc_nid(sbi, &new_xnid))
return -ENOSPC;
set_new_dnode(&dn, inode, NULL, NULL, new_xnid);
- xpage = new_node_page(&dn, XATTR_NODE_OFFSET);
+ xpage = f2fs_new_node_page(&dn, XATTR_NODE_OFFSET);
if (IS_ERR(xpage)) {
- alloc_nid_failed(sbi, new_xnid);
+ f2fs_alloc_nid_failed(sbi, new_xnid);
return PTR_ERR(xpage);
}
- alloc_nid_done(sbi, new_xnid);
- update_inode_page(inode);
+ f2fs_alloc_nid_done(sbi, new_xnid);
+ f2fs_update_inode_page(inode);
/* 3: update and set xattr node page dirty */
memcpy(F2FS_NODE(xpage), F2FS_NODE(page), VALID_XATTR_BLOCK_SIZE);
@@ -2288,14 +2311,14 @@ recover_xnid:
return 0;
}
-int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
+int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
{
struct f2fs_inode *src, *dst;
nid_t ino = ino_of_node(page);
struct node_info old_ni, new_ni;
struct page *ipage;
- get_node_info(sbi, ino, &old_ni);
+ f2fs_get_node_info(sbi, ino, &old_ni);
if (unlikely(old_ni.blk_addr != NULL_ADDR))
return -EINVAL;
@@ -2349,7 +2372,7 @@ retry:
return 0;
}
-void restore_node_summary(struct f2fs_sb_info *sbi,
+void f2fs_restore_node_summary(struct f2fs_sb_info *sbi,
unsigned int segno, struct f2fs_summary_block *sum)
{
struct f2fs_node *rn;
@@ -2366,10 +2389,10 @@ void restore_node_summary(struct f2fs_sb_info *sbi,
nrpages = min(last_offset - i, BIO_MAX_PAGES);
/* readahead node pages */
- ra_meta_pages(sbi, addr, nrpages, META_POR, true);
+ f2fs_ra_meta_pages(sbi, addr, nrpages, META_POR, true);
for (idx = addr; idx < addr + nrpages; idx++) {
- struct page *page = get_tmp_page(sbi, idx);
+ struct page *page = f2fs_get_tmp_page(sbi, idx);
rn = F2FS_NODE(page);
sum_entry->nid = rn->footer.nid;
@@ -2511,7 +2534,7 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
f2fs_bug_on(sbi, nat_get_blkaddr(ne) == NEW_ADDR);
if (to_journal) {
- offset = lookup_journal_in_cursum(journal,
+ offset = f2fs_lookup_journal_in_cursum(journal,
NAT_JOURNAL, nid, 1);
f2fs_bug_on(sbi, offset < 0);
raw_ne = &nat_in_journal(journal, offset);
@@ -2548,7 +2571,7 @@ static void __flush_nat_entry_set(struct f2fs_sb_info *sbi,
/*
* This function is called during the checkpointing process.
*/
-void flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+void f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
@@ -2611,7 +2634,7 @@ static int __get_nat_bitmaps(struct f2fs_sb_info *sbi)
nat_bits_addr = __start_cp_addr(sbi) + sbi->blocks_per_seg -
nm_i->nat_bits_blocks;
for (i = 0; i < nm_i->nat_bits_blocks; i++) {
- struct page *page = get_meta_page(sbi, nat_bits_addr++);
+ struct page *page = f2fs_get_meta_page(sbi, nat_bits_addr++);
memcpy(nm_i->nat_bits + (i << F2FS_BLKSIZE_BITS),
page_address(page), F2FS_BLKSIZE);
@@ -2730,8 +2753,10 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
struct f2fs_nm_info *nm_i = NM_I(sbi);
int i;
- nm_i->free_nid_bitmap = f2fs_kzalloc(sbi, nm_i->nat_blocks *
- sizeof(unsigned char *), GFP_KERNEL);
+ nm_i->free_nid_bitmap =
+ f2fs_kzalloc(sbi, array_size(sizeof(unsigned char *),
+ nm_i->nat_blocks),
+ GFP_KERNEL);
if (!nm_i->free_nid_bitmap)
return -ENOMEM;
@@ -2747,14 +2772,16 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
if (!nm_i->nat_block_bitmap)
return -ENOMEM;
- nm_i->free_nid_count = f2fs_kvzalloc(sbi, nm_i->nat_blocks *
- sizeof(unsigned short), GFP_KERNEL);
+ nm_i->free_nid_count =
+ f2fs_kvzalloc(sbi, array_size(sizeof(unsigned short),
+ nm_i->nat_blocks),
+ GFP_KERNEL);
if (!nm_i->free_nid_count)
return -ENOMEM;
return 0;
}
-int build_node_manager(struct f2fs_sb_info *sbi)
+int f2fs_build_node_manager(struct f2fs_sb_info *sbi)
{
int err;
@@ -2774,11 +2801,11 @@ int build_node_manager(struct f2fs_sb_info *sbi)
/* load free nid status from nat_bits table */
load_free_nid_bitmap(sbi);
- build_free_nids(sbi, true, true);
+ f2fs_build_free_nids(sbi, true, true);
return 0;
}
-void destroy_node_manager(struct f2fs_sb_info *sbi)
+void f2fs_destroy_node_manager(struct f2fs_sb_info *sbi)
{
struct f2fs_nm_info *nm_i = NM_I(sbi);
struct free_nid *i, *next_i;
@@ -2850,7 +2877,7 @@ void destroy_node_manager(struct f2fs_sb_info *sbi)
kfree(nm_i);
}
-int __init create_node_manager_caches(void)
+int __init f2fs_create_node_manager_caches(void)
{
nat_entry_slab = f2fs_kmem_cache_create("nat_entry",
sizeof(struct nat_entry));
@@ -2876,7 +2903,7 @@ fail:
return -ENOMEM;
}
-void destroy_node_manager_caches(void)
+void f2fs_destroy_node_manager_caches(void)
{
kmem_cache_destroy(nat_entry_set_slab);
kmem_cache_destroy(free_nid_slab);
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index 1b23d3f..38f25f0 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -47,7 +47,7 @@
static struct kmem_cache *fsync_entry_slab;
-bool space_for_roll_forward(struct f2fs_sb_info *sbi)
+bool f2fs_space_for_roll_forward(struct f2fs_sb_info *sbi)
{
s64 nalloc = percpu_counter_sum_positive(&sbi->alloc_valid_block_count);
@@ -162,7 +162,7 @@ retry:
goto out_put;
}
- err = acquire_orphan_inode(F2FS_I_SB(inode));
+ err = f2fs_acquire_orphan_inode(F2FS_I_SB(inode));
if (err) {
iput(einode);
goto out_put;
@@ -173,7 +173,7 @@ retry:
} else if (IS_ERR(page)) {
err = PTR_ERR(page);
} else {
- err = __f2fs_do_add_link(dir, &fname, inode,
+ err = f2fs_add_dentry(dir, &fname, inode,
inode->i_ino, inode->i_mode);
}
if (err == -ENOMEM)
@@ -204,8 +204,6 @@ static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri)
set_inode_flag(inode, FI_DATA_EXIST);
else
clear_inode_flag(inode, FI_DATA_EXIST);
- if (!(ri->i_inline & F2FS_INLINE_DOTS))
- clear_inode_flag(inode, FI_INLINE_DOTS);
}
static void recover_inode(struct inode *inode, struct page *page)
@@ -254,10 +252,10 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
while (1) {
struct fsync_inode_entry *entry;
- if (!is_valid_blkaddr(sbi, blkaddr, META_POR))
+ if (!f2fs_is_valid_meta_blkaddr(sbi, blkaddr, META_POR))
return 0;
- page = get_tmp_page(sbi, blkaddr);
+ page = f2fs_get_tmp_page(sbi, blkaddr);
if (!is_recoverable_dnode(page))
break;
@@ -271,7 +269,7 @@ static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
if (!check_only &&
IS_INODE(page) && is_dent_dnode(page)) {
- err = recover_inode_page(sbi, page);
+ err = f2fs_recover_inode_page(sbi, page);
if (err)
break;
quota_inode = true;
@@ -312,7 +310,7 @@ next:
blkaddr = next_blkaddr_of_node(page);
f2fs_put_page(page, 1);
- ra_meta_pages_cond(sbi, blkaddr);
+ f2fs_ra_meta_pages_cond(sbi, blkaddr);
}
f2fs_put_page(page, 1);
return err;
@@ -355,7 +353,7 @@ static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
}
}
- sum_page = get_sum_page(sbi, segno);
+ sum_page = f2fs_get_sum_page(sbi, segno);
sum_node = (struct f2fs_summary_block *)page_address(sum_page);
sum = sum_node->entries[blkoff];
f2fs_put_page(sum_page, 1);
@@ -375,7 +373,7 @@ got_it:
}
/* Get the node page */
- node_page = get_node_page(sbi, nid);
+ node_page = f2fs_get_node_page(sbi, nid);
if (IS_ERR(node_page))
return PTR_ERR(node_page);
@@ -400,7 +398,8 @@ got_it:
inode = dn->inode;
}
- bidx = start_bidx_of_node(offset, inode) + le16_to_cpu(sum.ofs_in_node);
+ bidx = f2fs_start_bidx_of_node(offset, inode) +
+ le16_to_cpu(sum.ofs_in_node);
/*
* if inode page is locked, unlock temporarily, but its reference
@@ -410,11 +409,11 @@ got_it:
unlock_page(dn->inode_page);
set_new_dnode(&tdn, inode, NULL, NULL, 0);
- if (get_dnode_of_data(&tdn, bidx, LOOKUP_NODE))
+ if (f2fs_get_dnode_of_data(&tdn, bidx, LOOKUP_NODE))
goto out;
if (tdn.data_blkaddr == blkaddr)
- truncate_data_blocks_range(&tdn, 1);
+ f2fs_truncate_data_blocks_range(&tdn, 1);
f2fs_put_dnode(&tdn);
out:
@@ -427,7 +426,7 @@ out:
truncate_out:
if (datablock_addr(tdn.inode, tdn.node_page,
tdn.ofs_in_node) == blkaddr)
- truncate_data_blocks_range(&tdn, 1);
+ f2fs_truncate_data_blocks_range(&tdn, 1);
if (dn->inode->i_ino == nid && !dn->inode_page_locked)
unlock_page(dn->inode_page);
return 0;
@@ -443,25 +442,25 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
/* step 1: recover xattr */
if (IS_INODE(page)) {
- recover_inline_xattr(inode, page);
+ f2fs_recover_inline_xattr(inode, page);
} else if (f2fs_has_xattr_block(ofs_of_node(page))) {
- err = recover_xattr_data(inode, page);
+ err = f2fs_recover_xattr_data(inode, page);
if (!err)
recovered++;
goto out;
}
/* step 2: recover inline data */
- if (recover_inline_data(inode, page))
+ if (f2fs_recover_inline_data(inode, page))
goto out;
/* step 3: recover data indices */
- start = start_bidx_of_node(ofs_of_node(page), inode);
+ start = f2fs_start_bidx_of_node(ofs_of_node(page), inode);
end = start + ADDRS_PER_PAGE(page, inode);
set_new_dnode(&dn, inode, NULL, NULL, 0);
retry_dn:
- err = get_dnode_of_data(&dn, start, ALLOC_NODE);
+ err = f2fs_get_dnode_of_data(&dn, start, ALLOC_NODE);
if (err) {
if (err == -ENOMEM) {
congestion_wait(BLK_RW_ASYNC, HZ/50);
@@ -472,7 +471,7 @@ retry_dn:
f2fs_wait_on_page_writeback(dn.node_page, NODE, true);
- get_node_info(sbi, dn.nid, &ni);
+ f2fs_get_node_info(sbi, dn.nid, &ni);
f2fs_bug_on(sbi, ni.ino != ino_of_node(page));
f2fs_bug_on(sbi, ofs_of_node(dn.node_page) != ofs_of_node(page));
@@ -488,7 +487,7 @@ retry_dn:
/* dest is invalid, just invalidate src block */
if (dest == NULL_ADDR) {
- truncate_data_blocks_range(&dn, 1);
+ f2fs_truncate_data_blocks_range(&dn, 1);
continue;
}
@@ -502,19 +501,19 @@ retry_dn:
* and then reserve one new block in dnode page.
*/
if (dest == NEW_ADDR) {
- truncate_data_blocks_range(&dn, 1);
- reserve_new_block(&dn);
+ f2fs_truncate_data_blocks_range(&dn, 1);
+ f2fs_reserve_new_block(&dn);
continue;
}
/* dest is valid block, try to recover from src to dest */
- if (is_valid_blkaddr(sbi, dest, META_POR)) {
+ if (f2fs_is_valid_meta_blkaddr(sbi, dest, META_POR)) {
if (src == NULL_ADDR) {
- err = reserve_new_block(&dn);
+ err = f2fs_reserve_new_block(&dn);
#ifdef CONFIG_F2FS_FAULT_INJECTION
while (err)
- err = reserve_new_block(&dn);
+ err = f2fs_reserve_new_block(&dn);
#endif
/* We should not get -ENOSPC */
f2fs_bug_on(sbi, err);
@@ -569,12 +568,12 @@ static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
while (1) {
struct fsync_inode_entry *entry;
- if (!is_valid_blkaddr(sbi, blkaddr, META_POR))
+ if (!f2fs_is_valid_meta_blkaddr(sbi, blkaddr, META_POR))
break;
- ra_meta_pages_cond(sbi, blkaddr);
+ f2fs_ra_meta_pages_cond(sbi, blkaddr);
- page = get_tmp_page(sbi, blkaddr);
+ page = f2fs_get_tmp_page(sbi, blkaddr);
if (!is_recoverable_dnode(page)) {
f2fs_put_page(page, 1);
@@ -612,11 +611,11 @@ next:
f2fs_put_page(page, 1);
}
if (!err)
- allocate_new_segments(sbi);
+ f2fs_allocate_new_segments(sbi);
return err;
}
-int recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
+int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
{
struct list_head inode_list;
struct list_head dir_list;
@@ -691,7 +690,7 @@ skip:
struct cp_control cpc = {
.reason = CP_RECOVERY,
};
- err = write_checkpoint(sbi, &cpc);
+ err = f2fs_write_checkpoint(sbi, &cpc);
}
kmem_cache_destroy(fsync_entry_slab);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 5854cc4..9efce17 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -169,7 +169,7 @@ found:
return result - size + __reverse_ffz(tmp);
}
-bool need_SSR(struct f2fs_sb_info *sbi)
+bool f2fs_need_SSR(struct f2fs_sb_info *sbi)
{
int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES);
int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS);
@@ -177,14 +177,14 @@ bool need_SSR(struct f2fs_sb_info *sbi)
if (test_opt(sbi, LFS))
return false;
- if (sbi->gc_thread && sbi->gc_thread->gc_urgent)
+ if (sbi->gc_mode == GC_URGENT)
return true;
return free_sections(sbi) <= (node_secs + 2 * dent_secs + imeta_secs +
SM_I(sbi)->min_ssr_sections + reserved_sections(sbi));
}
-void register_inmem_page(struct inode *inode, struct page *page)
+void f2fs_register_inmem_page(struct inode *inode, struct page *page)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_inode_info *fi = F2FS_I(inode);
@@ -230,6 +230,8 @@ static int __revoke_inmem_pages(struct inode *inode,
lock_page(page);
+ f2fs_wait_on_page_writeback(page, DATA, true);
+
if (recover) {
struct dnode_of_data dn;
struct node_info ni;
@@ -237,7 +239,8 @@ static int __revoke_inmem_pages(struct inode *inode,
trace_f2fs_commit_inmem_page(page, INMEM_REVOKE);
retry:
set_new_dnode(&dn, inode, NULL, NULL, 0);
- err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE);
+ err = f2fs_get_dnode_of_data(&dn, page->index,
+ LOOKUP_NODE);
if (err) {
if (err == -ENOMEM) {
congestion_wait(BLK_RW_ASYNC, HZ/50);
@@ -247,9 +250,9 @@ retry:
err = -EAGAIN;
goto next;
}
- get_node_info(sbi, dn.nid, &ni);
+ f2fs_get_node_info(sbi, dn.nid, &ni);
if (cur->old_addr == NEW_ADDR) {
- invalidate_blocks(sbi, dn.data_blkaddr);
+ f2fs_invalidate_blocks(sbi, dn.data_blkaddr);
f2fs_update_data_blkaddr(&dn, NEW_ADDR);
} else
f2fs_replace_block(sbi, &dn, dn.data_blkaddr,
@@ -271,7 +274,7 @@ next:
return err;
}
-void drop_inmem_pages_all(struct f2fs_sb_info *sbi)
+void f2fs_drop_inmem_pages_all(struct f2fs_sb_info *sbi, bool gc_failure)
{
struct list_head *head = &sbi->inode_list[ATOMIC_FILE];
struct inode *inode;
@@ -287,15 +290,23 @@ next:
spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
if (inode) {
- drop_inmem_pages(inode);
+ if (gc_failure) {
+ if (fi->i_gc_failures[GC_FAILURE_ATOMIC])
+ goto drop;
+ goto skip;
+ }
+drop:
+ set_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
+ f2fs_drop_inmem_pages(inode);
iput(inode);
}
+skip:
congestion_wait(BLK_RW_ASYNC, HZ/50);
cond_resched();
goto next;
}
-void drop_inmem_pages(struct inode *inode)
+void f2fs_drop_inmem_pages(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_inode_info *fi = F2FS_I(inode);
@@ -309,11 +320,11 @@ void drop_inmem_pages(struct inode *inode)
mutex_unlock(&fi->inmem_lock);
clear_inode_flag(inode, FI_ATOMIC_FILE);
- clear_inode_flag(inode, FI_HOT_DATA);
+ fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
stat_dec_atomic_write(inode);
}
-void drop_inmem_page(struct inode *inode, struct page *page)
+void f2fs_drop_inmem_page(struct inode *inode, struct page *page)
{
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
@@ -328,7 +339,7 @@ void drop_inmem_page(struct inode *inode, struct page *page)
break;
}
- f2fs_bug_on(sbi, !cur || cur->page != page);
+ f2fs_bug_on(sbi, list_empty(head) || cur->page != page);
list_del(&cur->list);
mutex_unlock(&fi->inmem_lock);
@@ -343,8 +354,7 @@ void drop_inmem_page(struct inode *inode, struct page *page)
trace_f2fs_commit_inmem_page(page, INMEM_INVALIDATE);
}
-static int __commit_inmem_pages(struct inode *inode,
- struct list_head *revoke_list)
+static int __f2fs_commit_inmem_pages(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_inode_info *fi = F2FS_I(inode);
@@ -357,9 +367,12 @@ static int __commit_inmem_pages(struct inode *inode,
.op_flags = REQ_SYNC | REQ_PRIO,
.io_type = FS_DATA_IO,
};
+ struct list_head revoke_list;
pgoff_t last_idx = ULONG_MAX;
int err = 0;
+ INIT_LIST_HEAD(&revoke_list);
+
list_for_each_entry_safe(cur, tmp, &fi->inmem_pages, list) {
struct page *page = cur->page;
@@ -371,14 +384,14 @@ static int __commit_inmem_pages(struct inode *inode,
f2fs_wait_on_page_writeback(page, DATA, true);
if (clear_page_dirty_for_io(page)) {
inode_dec_dirty_pages(inode);
- remove_dirty_inode(inode);
+ f2fs_remove_dirty_inode(inode);
}
retry:
fio.page = page;
fio.old_blkaddr = NULL_ADDR;
fio.encrypted_page = NULL;
fio.need_lock = LOCK_DONE;
- err = do_write_data_page(&fio);
+ err = f2fs_do_write_data_page(&fio);
if (err) {
if (err == -ENOMEM) {
congestion_wait(BLK_RW_ASYNC, HZ/50);
@@ -393,50 +406,46 @@ retry:
last_idx = page->index;
}
unlock_page(page);
- list_move_tail(&cur->list, revoke_list);
+ list_move_tail(&cur->list, &revoke_list);
}
if (last_idx != ULONG_MAX)
f2fs_submit_merged_write_cond(sbi, inode, 0, last_idx, DATA);
- if (!err)
- __revoke_inmem_pages(inode, revoke_list, false, false);
+ if (err) {
+ /*
+ * try to revoke all committed pages, but still we could fail
+ * due to no memory or other reason, if that happened, EAGAIN
+ * will be returned, which means in such case, transaction is
+ * already not integrity, caller should use journal to do the
+ * recovery or rewrite & commit last transaction. For other
+ * error number, revoking was done by filesystem itself.
+ */
+ err = __revoke_inmem_pages(inode, &revoke_list, false, true);
+
+ /* drop all uncommitted pages */
+ __revoke_inmem_pages(inode, &fi->inmem_pages, true, false);
+ } else {
+ __revoke_inmem_pages(inode, &revoke_list, false, false);
+ }
return err;
}
-int commit_inmem_pages(struct inode *inode)
+int f2fs_commit_inmem_pages(struct inode *inode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct f2fs_inode_info *fi = F2FS_I(inode);
- struct list_head revoke_list;
int err;
- INIT_LIST_HEAD(&revoke_list);
f2fs_balance_fs(sbi, true);
f2fs_lock_op(sbi);
set_inode_flag(inode, FI_ATOMIC_COMMIT);
mutex_lock(&fi->inmem_lock);
- err = __commit_inmem_pages(inode, &revoke_list);
- if (err) {
- int ret;
- /*
- * try to revoke all committed pages, but still we could fail
- * due to no memory or other reason, if that happened, EAGAIN
- * will be returned, which means in such case, transaction is
- * already not integrity, caller should use journal to do the
- * recovery or rewrite & commit last transaction. For other
- * error number, revoking was done by filesystem itself.
- */
- ret = __revoke_inmem_pages(inode, &revoke_list, false, true);
- if (ret)
- err = ret;
+ err = __f2fs_commit_inmem_pages(inode);
- /* drop all uncommitted pages */
- __revoke_inmem_pages(inode, &fi->inmem_pages, true, false);
- }
spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
if (!list_empty(&fi->inmem_ilist))
list_del_init(&fi->inmem_ilist);
@@ -478,25 +487,28 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
{
+ if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
+ return;
+
/* try to shrink extent cache when there is no enough memory */
- if (!available_free_memory(sbi, EXTENT_CACHE))
+ if (!f2fs_available_free_memory(sbi, EXTENT_CACHE))
f2fs_shrink_extent_tree(sbi, EXTENT_CACHE_SHRINK_NUMBER);
/* check the # of cached NAT entries */
- if (!available_free_memory(sbi, NAT_ENTRIES))
- try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK);
+ if (!f2fs_available_free_memory(sbi, NAT_ENTRIES))
+ f2fs_try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK);
- if (!available_free_memory(sbi, FREE_NIDS))
- try_to_free_nids(sbi, MAX_FREE_NIDS);
+ if (!f2fs_available_free_memory(sbi, FREE_NIDS))
+ f2fs_try_to_free_nids(sbi, MAX_FREE_NIDS);
else
- build_free_nids(sbi, false, false);
+ f2fs_build_free_nids(sbi, false, false);
if (!is_idle(sbi) && !excess_dirty_nats(sbi))
return;
/* checkpoint is the only way to shrink partial cached entries */
- if (!available_free_memory(sbi, NAT_ENTRIES) ||
- !available_free_memory(sbi, INO_ENTRIES) ||
+ if (!f2fs_available_free_memory(sbi, NAT_ENTRIES) ||
+ !f2fs_available_free_memory(sbi, INO_ENTRIES) ||
excess_prefree_segs(sbi) ||
excess_dirty_nats(sbi) ||
f2fs_time_over(sbi, CP_TIME)) {
@@ -504,7 +516,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
struct blk_plug plug;
blk_start_plug(&plug);
- sync_dirty_inodes(sbi, FILE_INODE);
+ f2fs_sync_dirty_inodes(sbi, FILE_INODE);
blk_finish_plug(&plug);
}
f2fs_sync_fs(sbi->sb, true);
@@ -537,7 +549,7 @@ static int submit_flush_wait(struct f2fs_sb_info *sbi, nid_t ino)
return __submit_flush_wait(sbi, sbi->sb->s_bdev);
for (i = 0; i < sbi->s_ndevs; i++) {
- if (!is_dirty_device(sbi, ino, i, FLUSH_INO))
+ if (!f2fs_is_dirty_device(sbi, ino, i, FLUSH_INO))
continue;
ret = __submit_flush_wait(sbi, FDEV(i).bdev);
if (ret)
@@ -648,7 +660,7 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi, nid_t ino)
return cmd.ret;
}
-int create_flush_cmd_control(struct f2fs_sb_info *sbi)
+int f2fs_create_flush_cmd_control(struct f2fs_sb_info *sbi)
{
dev_t dev = sbi->sb->s_bdev->bd_dev;
struct flush_cmd_control *fcc;
@@ -685,7 +697,7 @@ init_thread:
return err;
}
-void destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free)
+void f2fs_destroy_flush_cmd_control(struct f2fs_sb_info *sbi, bool free)
{
struct flush_cmd_control *fcc = SM_I(sbi)->fcc_info;
@@ -915,6 +927,42 @@ static void __check_sit_bitmap(struct f2fs_sb_info *sbi,
#endif
}
+static void __init_discard_policy(struct f2fs_sb_info *sbi,
+ struct discard_policy *dpolicy,
+ int discard_type, unsigned int granularity)
+{
+ /* common policy */
+ dpolicy->type = discard_type;
+ dpolicy->sync = true;
+ dpolicy->granularity = granularity;
+
+ dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST;
+ dpolicy->io_aware_gran = MAX_PLIST_NUM;
+
+ if (discard_type == DPOLICY_BG) {
+ dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME;
+ dpolicy->mid_interval = DEF_MID_DISCARD_ISSUE_TIME;
+ dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME;
+ dpolicy->io_aware = true;
+ dpolicy->sync = false;
+ if (utilization(sbi) > DEF_DISCARD_URGENT_UTIL) {
+ dpolicy->granularity = 1;
+ dpolicy->max_interval = DEF_MIN_DISCARD_ISSUE_TIME;
+ }
+ } else if (discard_type == DPOLICY_FORCE) {
+ dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME;
+ dpolicy->mid_interval = DEF_MID_DISCARD_ISSUE_TIME;
+ dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME;
+ dpolicy->io_aware = false;
+ } else if (discard_type == DPOLICY_FSTRIM) {
+ dpolicy->io_aware = false;
+ } else if (discard_type == DPOLICY_UMOUNT) {
+ dpolicy->max_requests = UINT_MAX;
+ dpolicy->io_aware = false;
+ }
+}
+
+
/* this function is copied from blkdev_issue_discard from block/blk-lib.c */
static void __submit_discard_cmd(struct f2fs_sb_info *sbi,
struct discard_policy *dpolicy,
@@ -929,6 +977,9 @@ static void __submit_discard_cmd(struct f2fs_sb_info *sbi,
if (dc->state != D_PREP)
return;
+ if (is_sbi_flag_set(sbi, SBI_NEED_FSCK))
+ return;
+
trace_f2fs_issue_discard(dc->bdev, dc->start, dc->len);
dc->error = __blkdev_issue_discard(dc->bdev,
@@ -972,7 +1023,7 @@ static struct discard_cmd *__insert_discard_tree(struct f2fs_sb_info *sbi,
goto do_insert;
}
- p = __lookup_rb_tree_for_insert(sbi, &dcc->root, &parent, lstart);
+ p = f2fs_lookup_rb_tree_for_insert(sbi, &dcc->root, &parent, lstart);
do_insert:
dc = __attach_discard_cmd(sbi, bdev, lstart, start, len, parent, p);
if (!dc)
@@ -1037,7 +1088,7 @@ static void __update_discard_tree_range(struct f2fs_sb_info *sbi,
mutex_lock(&dcc->cmd_lock);
- dc = (struct discard_cmd *)__lookup_rb_tree_ret(&dcc->root,
+ dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root,
NULL, lstart,
(struct rb_entry **)&prev_dc,
(struct rb_entry **)&next_dc,
@@ -1130,68 +1181,6 @@ static int __queue_discard_cmd(struct f2fs_sb_info *sbi,
return 0;
}
-static void __issue_discard_cmd_range(struct f2fs_sb_info *sbi,
- struct discard_policy *dpolicy,
- unsigned int start, unsigned int end)
-{
- struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
- struct discard_cmd *prev_dc = NULL, *next_dc = NULL;
- struct rb_node **insert_p = NULL, *insert_parent = NULL;
- struct discard_cmd *dc;
- struct blk_plug plug;
- int issued;
-
-next:
- issued = 0;
-
- mutex_lock(&dcc->cmd_lock);
- f2fs_bug_on(sbi, !__check_rb_tree_consistence(sbi, &dcc->root));
-
- dc = (struct discard_cmd *)__lookup_rb_tree_ret(&dcc->root,
- NULL, start,
- (struct rb_entry **)&prev_dc,
- (struct rb_entry **)&next_dc,
- &insert_p, &insert_parent, true);
- if (!dc)
- dc = next_dc;
-
- blk_start_plug(&plug);
-
- while (dc && dc->lstart <= end) {
- struct rb_node *node;
-
- if (dc->len < dpolicy->granularity)
- goto skip;
-
- if (dc->state != D_PREP) {
- list_move_tail(&dc->list, &dcc->fstrim_list);
- goto skip;
- }
-
- __submit_discard_cmd(sbi, dpolicy, dc);
-
- if (++issued >= dpolicy->max_requests) {
- start = dc->lstart + dc->len;
-
- blk_finish_plug(&plug);
- mutex_unlock(&dcc->cmd_lock);
-
- schedule();
-
- goto next;
- }
-skip:
- node = rb_next(&dc->rb_node);
- dc = rb_entry_safe(node, struct discard_cmd, rb_node);
-
- if (fatal_signal_pending(current))
- break;
- }
-
- blk_finish_plug(&plug);
- mutex_unlock(&dcc->cmd_lock);
-}
-
static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
struct discard_policy *dpolicy)
{
@@ -1210,7 +1199,8 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
mutex_lock(&dcc->cmd_lock);
if (list_empty(pend_list))
goto next;
- f2fs_bug_on(sbi, !__check_rb_tree_consistence(sbi, &dcc->root));
+ f2fs_bug_on(sbi,
+ !f2fs_check_rb_tree_consistence(sbi, &dcc->root));
blk_start_plug(&plug);
list_for_each_entry_safe(dc, tmp, pend_list, list) {
f2fs_bug_on(sbi, dc->state != D_PREP);
@@ -1263,7 +1253,7 @@ static bool __drop_discard_cmd(struct f2fs_sb_info *sbi)
return dropped;
}
-void drop_discard_cmd(struct f2fs_sb_info *sbi)
+void f2fs_drop_discard_cmd(struct f2fs_sb_info *sbi)
{
__drop_discard_cmd(sbi);
}
@@ -1332,7 +1322,18 @@ next:
static void __wait_all_discard_cmd(struct f2fs_sb_info *sbi,
struct discard_policy *dpolicy)
{
- __wait_discard_cmd_range(sbi, dpolicy, 0, UINT_MAX);
+ struct discard_policy dp;
+
+ if (dpolicy) {
+ __wait_discard_cmd_range(sbi, dpolicy, 0, UINT_MAX);
+ return;
+ }
+
+ /* wait all */
+ __init_discard_policy(sbi, &dp, DPOLICY_FSTRIM, 1);
+ __wait_discard_cmd_range(sbi, &dp, 0, UINT_MAX);
+ __init_discard_policy(sbi, &dp, DPOLICY_UMOUNT, 1);
+ __wait_discard_cmd_range(sbi, &dp, 0, UINT_MAX);
}
/* This should be covered by global mutex, &sit_i->sentry_lock */
@@ -1343,7 +1344,8 @@ static void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
bool need_wait = false;
mutex_lock(&dcc->cmd_lock);
- dc = (struct discard_cmd *)__lookup_rb_tree(&dcc->root, NULL, blkaddr);
+ dc = (struct discard_cmd *)f2fs_lookup_rb_tree(&dcc->root,
+ NULL, blkaddr);
if (dc) {
if (dc->state == D_PREP) {
__punch_discard_cmd(sbi, dc, blkaddr);
@@ -1358,7 +1360,7 @@ static void f2fs_wait_discard_bio(struct f2fs_sb_info *sbi, block_t blkaddr)
__wait_one_discard_bio(sbi, dc);
}
-void stop_discard_thread(struct f2fs_sb_info *sbi)
+void f2fs_stop_discard_thread(struct f2fs_sb_info *sbi)
{
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
@@ -1377,11 +1379,13 @@ bool f2fs_wait_discard_bios(struct f2fs_sb_info *sbi)
struct discard_policy dpolicy;
bool dropped;
- init_discard_policy(&dpolicy, DPOLICY_UMOUNT, dcc->discard_granularity);
+ __init_discard_policy(sbi, &dpolicy, DPOLICY_UMOUNT,
+ dcc->discard_granularity);
__issue_discard_cmd(sbi, &dpolicy);
dropped = __drop_discard_cmd(sbi);
- __wait_all_discard_cmd(sbi, &dpolicy);
+ /* just to make sure there is no pending discard commands */
+ __wait_all_discard_cmd(sbi, NULL);
return dropped;
}
@@ -1397,32 +1401,39 @@ static int issue_discard_thread(void *data)
set_freezable();
do {
- init_discard_policy(&dpolicy, DPOLICY_BG,
+ __init_discard_policy(sbi, &dpolicy, DPOLICY_BG,
dcc->discard_granularity);
wait_event_interruptible_timeout(*q,
kthread_should_stop() || freezing(current) ||
dcc->discard_wake,
msecs_to_jiffies(wait_ms));
+
+ if (dcc->discard_wake)
+ dcc->discard_wake = 0;
+
if (try_to_freeze())
continue;
if (f2fs_readonly(sbi->sb))
continue;
if (kthread_should_stop())
return 0;
+ if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) {
+ wait_ms = dpolicy.max_interval;
+ continue;
+ }
- if (dcc->discard_wake)
- dcc->discard_wake = 0;
-
- if (sbi->gc_thread && sbi->gc_thread->gc_urgent)
- init_discard_policy(&dpolicy, DPOLICY_FORCE, 1);
+ if (sbi->gc_mode == GC_URGENT)
+ __init_discard_policy(sbi, &dpolicy, DPOLICY_FORCE, 1);
sb_start_intwrite(sbi->sb);
issued = __issue_discard_cmd(sbi, &dpolicy);
- if (issued) {
+ if (issued > 0) {
__wait_all_discard_cmd(sbi, &dpolicy);
wait_ms = dpolicy.min_interval;
+ } else if (issued == -1){
+ wait_ms = dpolicy.mid_interval;
} else {
wait_ms = dpolicy.max_interval;
}
@@ -1591,20 +1602,24 @@ static bool add_discard_addrs(struct f2fs_sb_info *sbi, struct cp_control *cpc,
return false;
}
-void release_discard_addrs(struct f2fs_sb_info *sbi)
+static void release_discard_addr(struct discard_entry *entry)
+{
+ list_del(&entry->list);
+ kmem_cache_free(discard_entry_slab, entry);
+}
+
+void f2fs_release_discard_addrs(struct f2fs_sb_info *sbi)
{
struct list_head *head = &(SM_I(sbi)->dcc_info->entry_list);
struct discard_entry *entry, *this;
/* drop caches */
- list_for_each_entry_safe(entry, this, head, list) {
- list_del(&entry->list);
- kmem_cache_free(discard_entry_slab, entry);
- }
+ list_for_each_entry_safe(entry, this, head, list)
+ release_discard_addr(entry);
}
/*
- * Should call clear_prefree_segments after checkpoint is done.
+ * Should call f2fs_clear_prefree_segments after checkpoint is done.
*/
static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
{
@@ -1617,7 +1632,8 @@ static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi)
mutex_unlock(&dirty_i->seglist_lock);
}
-void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+void f2fs_clear_prefree_segments(struct f2fs_sb_info *sbi,
+ struct cp_control *cpc)
{
struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
struct list_head *head = &dcc->entry_list;
@@ -1700,40 +1716,13 @@ skip:
if (cur_pos < sbi->blocks_per_seg)
goto find_next;
- list_del(&entry->list);
+ release_discard_addr(entry);
dcc->nr_discards -= total_len;
- kmem_cache_free(discard_entry_slab, entry);
}
wake_up_discard_thread(sbi, false);
}
-void init_discard_policy(struct discard_policy *dpolicy,
- int discard_type, unsigned int granularity)
-{
- /* common policy */
- dpolicy->type = discard_type;
- dpolicy->sync = true;
- dpolicy->granularity = granularity;
-
- dpolicy->max_requests = DEF_MAX_DISCARD_REQUEST;
- dpolicy->io_aware_gran = MAX_PLIST_NUM;
-
- if (discard_type == DPOLICY_BG) {
- dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME;
- dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME;
- dpolicy->io_aware = true;
- } else if (discard_type == DPOLICY_FORCE) {
- dpolicy->min_interval = DEF_MIN_DISCARD_ISSUE_TIME;
- dpolicy->max_interval = DEF_MAX_DISCARD_ISSUE_TIME;
- dpolicy->io_aware = false;
- } else if (discard_type == DPOLICY_FSTRIM) {
- dpolicy->io_aware = false;
- } else if (discard_type == DPOLICY_UMOUNT) {
- dpolicy->io_aware = false;
- }
-}
-
static int create_discard_cmd_control(struct f2fs_sb_info *sbi)
{
dev_t dev = sbi->sb->s_bdev->bd_dev;
@@ -1786,7 +1775,7 @@ static void destroy_discard_cmd_control(struct f2fs_sb_info *sbi)
if (!dcc)
return;
- stop_discard_thread(sbi);
+ f2fs_stop_discard_thread(sbi);
kfree(dcc);
SM_I(sbi)->dcc_info = NULL;
@@ -1833,8 +1822,9 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
(new_vblocks > sbi->blocks_per_seg)));
se->valid_blocks = new_vblocks;
- se->mtime = get_mtime(sbi);
- SIT_I(sbi)->max_mtime = se->mtime;
+ se->mtime = get_mtime(sbi, false);
+ if (se->mtime > SIT_I(sbi)->max_mtime)
+ SIT_I(sbi)->max_mtime = se->mtime;
/* Update valid block bitmap */
if (del > 0) {
@@ -1902,7 +1892,7 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del)
get_sec_entry(sbi, segno)->valid_blocks += del;
}
-void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
+void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
{
unsigned int segno = GET_SEGNO(sbi, addr);
struct sit_info *sit_i = SIT_I(sbi);
@@ -1922,14 +1912,14 @@ void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr)
up_write(&sit_i->sentry_lock);
}
-bool is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr)
+bool f2fs_is_checkpointed_data(struct f2fs_sb_info *sbi, block_t blkaddr)
{
struct sit_info *sit_i = SIT_I(sbi);
unsigned int segno, offset;
struct seg_entry *se;
bool is_cp = false;
- if (blkaddr == NEW_ADDR || blkaddr == NULL_ADDR)
+ if (!is_valid_blkaddr(blkaddr))
return true;
down_read(&sit_i->sentry_lock);
@@ -1961,7 +1951,7 @@ static void __add_sum_entry(struct f2fs_sb_info *sbi, int type,
/*
* Calculate the number of current summary pages for writing
*/
-int npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)
+int f2fs_npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)
{
int valid_sum_count = 0;
int i, sum_in_page;
@@ -1991,14 +1981,15 @@ int npages_for_summary_flush(struct f2fs_sb_info *sbi, bool for_ra)
/*
* Caller should put this summary page
*/
-struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno)
+struct page *f2fs_get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno)
{
- return get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno));
+ return f2fs_get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno));
}
-void update_meta_page(struct f2fs_sb_info *sbi, void *src, block_t blk_addr)
+void f2fs_update_meta_page(struct f2fs_sb_info *sbi,
+ void *src, block_t blk_addr)
{
- struct page *page = grab_meta_page(sbi, blk_addr);
+ struct page *page = f2fs_grab_meta_page(sbi, blk_addr);
memcpy(page_address(page), src, PAGE_SIZE);
set_page_dirty(page);
@@ -2008,18 +1999,19 @@ void update_meta_page(struct f2fs_sb_info *sbi, void *src, block_t blk_addr)
static void write_sum_page(struct f2fs_sb_info *sbi,
struct f2fs_summary_block *sum_blk, block_t blk_addr)
{
- update_meta_page(sbi, (void *)sum_blk, blk_addr);
+ f2fs_update_meta_page(sbi, (void *)sum_blk, blk_addr);
}
static void write_current_sum_page(struct f2fs_sb_info *sbi,
int type, block_t blk_addr)
{
struct curseg_info *curseg = CURSEG_I(sbi, type);
- struct page *page = grab_meta_page(sbi, blk_addr);
+ struct page *page = f2fs_grab_meta_page(sbi, blk_addr);
struct f2fs_summary_block *src = curseg->sum_blk;
struct f2fs_summary_block *dst;
dst = (struct f2fs_summary_block *)page_address(page);
+ memset(dst, 0, PAGE_SIZE);
mutex_lock(&curseg->curseg_mutex);
@@ -2259,7 +2251,7 @@ static void change_curseg(struct f2fs_sb_info *sbi, int type)
curseg->alloc_type = SSR;
__next_free_blkoff(sbi, curseg, 0);
- sum_page = get_sum_page(sbi, new_segno);
+ sum_page = f2fs_get_sum_page(sbi, new_segno);
sum_node = (struct f2fs_summary_block *)page_address(sum_page);
memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE);
f2fs_put_page(sum_page, 1);
@@ -2273,7 +2265,7 @@ static int get_ssr_segment(struct f2fs_sb_info *sbi, int type)
int i, cnt;
bool reversed = false;
- /* need_SSR() already forces to do this */
+ /* f2fs_need_SSR() already forces to do this */
if (v_ops->get_victim(sbi, &segno, BG_GC, type, SSR)) {
curseg->next_segno = segno;
return 1;
@@ -2325,7 +2317,7 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi,
new_curseg(sbi, type, false);
else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type))
new_curseg(sbi, type, false);
- else if (need_SSR(sbi) && get_ssr_segment(sbi, type))
+ else if (f2fs_need_SSR(sbi) && get_ssr_segment(sbi, type))
change_curseg(sbi, type);
else
new_curseg(sbi, type, false);
@@ -2333,7 +2325,7 @@ static void allocate_segment_by_default(struct f2fs_sb_info *sbi,
stat_inc_seg_type(sbi, curseg);
}
-void allocate_new_segments(struct f2fs_sb_info *sbi)
+void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi)
{
struct curseg_info *curseg;
unsigned int old_segno;
@@ -2355,7 +2347,8 @@ static const struct segment_allocation default_salloc_ops = {
.allocate_segment = allocate_segment_by_default,
};
-bool exist_trim_candidates(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi,
+ struct cp_control *cpc)
{
__u64 trim_start = cpc->trim_start;
bool has_candidate = false;
@@ -2373,11 +2366,72 @@ bool exist_trim_candidates(struct f2fs_sb_info *sbi, struct cp_control *cpc)
return has_candidate;
}
+static void __issue_discard_cmd_range(struct f2fs_sb_info *sbi,
+ struct discard_policy *dpolicy,
+ unsigned int start, unsigned int end)
+{
+ struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
+ struct discard_cmd *prev_dc = NULL, *next_dc = NULL;
+ struct rb_node **insert_p = NULL, *insert_parent = NULL;
+ struct discard_cmd *dc;
+ struct blk_plug plug;
+ int issued;
+
+next:
+ issued = 0;
+
+ mutex_lock(&dcc->cmd_lock);
+ f2fs_bug_on(sbi, !f2fs_check_rb_tree_consistence(sbi, &dcc->root));
+
+ dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root,
+ NULL, start,
+ (struct rb_entry **)&prev_dc,
+ (struct rb_entry **)&next_dc,
+ &insert_p, &insert_parent, true);
+ if (!dc)
+ dc = next_dc;
+
+ blk_start_plug(&plug);
+
+ while (dc && dc->lstart <= end) {
+ struct rb_node *node;
+
+ if (dc->len < dpolicy->granularity)
+ goto skip;
+
+ if (dc->state != D_PREP) {
+ list_move_tail(&dc->list, &dcc->fstrim_list);
+ goto skip;
+ }
+
+ __submit_discard_cmd(sbi, dpolicy, dc);
+
+ if (++issued >= dpolicy->max_requests) {
+ start = dc->lstart + dc->len;
+
+ blk_finish_plug(&plug);
+ mutex_unlock(&dcc->cmd_lock);
+ __wait_all_discard_cmd(sbi, NULL);
+ congestion_wait(BLK_RW_ASYNC, HZ/50);
+ goto next;
+ }
+skip:
+ node = rb_next(&dc->rb_node);
+ dc = rb_entry_safe(node, struct discard_cmd, rb_node);
+
+ if (fatal_signal_pending(current))
+ break;
+ }
+
+ blk_finish_plug(&plug);
+ mutex_unlock(&dcc->cmd_lock);
+}
+
int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
{
__u64 start = F2FS_BYTES_TO_BLK(range->start);
__u64 end = start + F2FS_BYTES_TO_BLK(range->len) - 1;
- unsigned int start_segno, end_segno, cur_segno;
+ unsigned int start_segno, end_segno;
block_t start_block, end_block;
struct cp_control cpc;
struct discard_policy dpolicy;
@@ -2388,12 +2442,12 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
return -EINVAL;
if (end <= MAIN_BLKADDR(sbi))
- goto out;
+ return -EINVAL;
if (is_sbi_flag_set(sbi, SBI_NEED_FSCK)) {
f2fs_msg(sbi->sb, KERN_WARNING,
"Found FS corruption, run fsck to fix.");
- goto out;
+ return -EIO;
}
/* start/end segment number in main_area */
@@ -2403,40 +2457,36 @@ int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range)
cpc.reason = CP_DISCARD;
cpc.trim_minlen = max_t(__u64, 1, F2FS_BYTES_TO_BLK(range->minlen));
+ cpc.trim_start = start_segno;
+ cpc.trim_end = end_segno;
- /* do checkpoint to issue discard commands safely */
- for (cur_segno = start_segno; cur_segno <= end_segno;
- cur_segno = cpc.trim_end + 1) {
- cpc.trim_start = cur_segno;
-
- if (sbi->discard_blks == 0)
- break;
- else if (sbi->discard_blks < BATCHED_TRIM_BLOCKS(sbi))
- cpc.trim_end = end_segno;
- else
- cpc.trim_end = min_t(unsigned int,
- rounddown(cur_segno +
- BATCHED_TRIM_SEGMENTS(sbi),
- sbi->segs_per_sec) - 1, end_segno);
-
- mutex_lock(&sbi->gc_mutex);
- err = write_checkpoint(sbi, &cpc);
- mutex_unlock(&sbi->gc_mutex);
- if (err)
- break;
+ if (sbi->discard_blks == 0)
+ goto out;
- schedule();
- }
+ mutex_lock(&sbi->gc_mutex);
+ err = f2fs_write_checkpoint(sbi, &cpc);
+ mutex_unlock(&sbi->gc_mutex);
+ if (err)
+ goto out;
start_block = START_BLOCK(sbi, start_segno);
- end_block = START_BLOCK(sbi, min(cur_segno, end_segno) + 1);
+ end_block = START_BLOCK(sbi, end_segno + 1);
- init_discard_policy(&dpolicy, DPOLICY_FSTRIM, cpc.trim_minlen);
+ __init_discard_policy(sbi, &dpolicy, DPOLICY_FSTRIM, cpc.trim_minlen);
__issue_discard_cmd_range(sbi, &dpolicy, start_block, end_block);
- trimmed = __wait_discard_cmd_range(sbi, &dpolicy,
+
+ /*
+ * We filed discard candidates, but actually we don't need to wait for
+ * all of them, since they'll be issued in idle time along with runtime
+ * discard option. User configuration looks like using runtime discard
+ * or periodic fstrim instead of it.
+ */
+ if (!test_opt(sbi, DISCARD)) {
+ trimmed = __wait_discard_cmd_range(sbi, &dpolicy,
start_block, end_block);
+ range->len = F2FS_BLK_TO_BYTES(trimmed);
+ }
out:
- range->len = F2FS_BLK_TO_BYTES(trimmed);
return err;
}
@@ -2448,7 +2498,7 @@ static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type)
return false;
}
-int rw_hint_to_seg_type(enum rw_hint hint)
+int f2fs_rw_hint_to_seg_type(enum rw_hint hint)
{
switch (hint) {
case WRITE_LIFE_SHORT:
@@ -2521,7 +2571,7 @@ int rw_hint_to_seg_type(enum rw_hint hint)
* WRITE_LIFE_LONG " WRITE_LIFE_LONG
*/
-enum rw_hint io_type_to_rw_hint(struct f2fs_sb_info *sbi,
+enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi,
enum page_type type, enum temp_type temp)
{
if (F2FS_OPTION(sbi).whint_mode == WHINT_MODE_USER) {
@@ -2588,9 +2638,11 @@ static int __get_segment_type_6(struct f2fs_io_info *fio)
if (is_cold_data(fio->page) || file_is_cold(inode))
return CURSEG_COLD_DATA;
if (file_is_hot(inode) ||
- is_inode_flag_set(inode, FI_HOT_DATA))
+ is_inode_flag_set(inode, FI_HOT_DATA) ||
+ is_inode_flag_set(inode, FI_ATOMIC_FILE) ||
+ is_inode_flag_set(inode, FI_VOLATILE_FILE))
return CURSEG_HOT_DATA;
- return rw_hint_to_seg_type(inode->i_write_hint);
+ return f2fs_rw_hint_to_seg_type(inode->i_write_hint);
} else {
if (IS_DNODE(fio->page))
return is_cold_node(fio->page) ? CURSEG_WARM_NODE :
@@ -2626,7 +2678,7 @@ static int __get_segment_type(struct f2fs_io_info *fio)
return type;
}
-void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
+void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
block_t old_blkaddr, block_t *new_blkaddr,
struct f2fs_summary *sum, int type,
struct f2fs_io_info *fio, bool add_list)
@@ -2686,6 +2738,7 @@ void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
INIT_LIST_HEAD(&fio->list);
fio->in_list = true;
+ fio->retry = false;
io = sbi->write_io[fio->type] + fio->temp;
spin_lock(&io->io_lock);
list_add_tail(&fio->list, &io->io_list);
@@ -2708,7 +2761,7 @@ static void update_device_state(struct f2fs_io_info *fio)
devidx = f2fs_target_device_index(sbi, fio->new_blkaddr);
/* update device state for fsync */
- set_dirty_device(sbi, fio->ino, devidx, FLUSH_INO);
+ f2fs_set_dirty_device(sbi, fio->ino, devidx, FLUSH_INO);
/* update device state for checkpoint */
if (!f2fs_test_bit(devidx, (char *)&sbi->dirty_device)) {
@@ -2721,23 +2774,28 @@ static void update_device_state(struct f2fs_io_info *fio)
static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
{
int type = __get_segment_type(fio);
- int err;
+ bool keep_order = (test_opt(fio->sbi, LFS) && type == CURSEG_COLD_DATA);
+ if (keep_order)
+ down_read(&fio->sbi->io_order_lock);
reallocate:
- allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
+ f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
&fio->new_blkaddr, sum, type, fio, true);
/* writeout dirty page into bdev */
- err = f2fs_submit_page_write(fio);
- if (err == -EAGAIN) {
+ f2fs_submit_page_write(fio);
+ if (fio->retry) {
fio->old_blkaddr = fio->new_blkaddr;
goto reallocate;
- } else if (!err) {
- update_device_state(fio);
}
+
+ update_device_state(fio);
+
+ if (keep_order)
+ up_read(&fio->sbi->io_order_lock);
}
-void write_meta_page(struct f2fs_sb_info *sbi, struct page *page,
+void f2fs_do_write_meta_page(struct f2fs_sb_info *sbi, struct page *page,
enum iostat_type io_type)
{
struct f2fs_io_info fio = {
@@ -2757,12 +2815,13 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page,
fio.op_flags &= ~REQ_META;
set_page_writeback(page);
+ ClearPageError(page);
f2fs_submit_page_write(&fio);
f2fs_update_iostat(sbi, io_type, F2FS_BLKSIZE);
}
-void write_node_page(unsigned int nid, struct f2fs_io_info *fio)
+void f2fs_do_write_node_page(unsigned int nid, struct f2fs_io_info *fio)
{
struct f2fs_summary sum;
@@ -2772,14 +2831,15 @@ void write_node_page(unsigned int nid, struct f2fs_io_info *fio)
f2fs_update_iostat(fio->sbi, fio->io_type, F2FS_BLKSIZE);
}
-void write_data_page(struct dnode_of_data *dn, struct f2fs_io_info *fio)
+void f2fs_outplace_write_data(struct dnode_of_data *dn,
+ struct f2fs_io_info *fio)
{
struct f2fs_sb_info *sbi = fio->sbi;
struct f2fs_summary sum;
struct node_info ni;
f2fs_bug_on(sbi, dn->data_blkaddr == NULL_ADDR);
- get_node_info(sbi, dn->nid, &ni);
+ f2fs_get_node_info(sbi, dn->nid, &ni);
set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
do_write_page(&sum, fio);
f2fs_update_data_blkaddr(dn, fio->new_blkaddr);
@@ -2787,7 +2847,7 @@ void write_data_page(struct dnode_of_data *dn, struct f2fs_io_info *fio)
f2fs_update_iostat(sbi, fio->io_type, F2FS_BLKSIZE);
}
-int rewrite_data_page(struct f2fs_io_info *fio)
+int f2fs_inplace_write_data(struct f2fs_io_info *fio)
{
int err;
struct f2fs_sb_info *sbi = fio->sbi;
@@ -2822,7 +2882,7 @@ static inline int __f2fs_get_curseg(struct f2fs_sb_info *sbi,
return i;
}
-void __f2fs_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
+void f2fs_do_replace_block(struct f2fs_sb_info *sbi, struct f2fs_summary *sum,
block_t old_blkaddr, block_t new_blkaddr,
bool recover_curseg, bool recover_newaddr)
{
@@ -2907,7 +2967,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
set_summary(&sum, dn->nid, dn->ofs_in_node, version);
- __f2fs_replace_block(sbi, &sum, old_addr, new_addr,
+ f2fs_do_replace_block(sbi, &sum, old_addr, new_addr,
recover_curseg, recover_newaddr);
f2fs_update_data_blkaddr(dn, new_addr);
@@ -2932,7 +2992,7 @@ void f2fs_wait_on_block_writeback(struct f2fs_sb_info *sbi, block_t blkaddr)
{
struct page *cpage;
- if (blkaddr == NEW_ADDR || blkaddr == NULL_ADDR)
+ if (!is_valid_blkaddr(blkaddr))
return;
cpage = find_lock_page(META_MAPPING(sbi), blkaddr);
@@ -2953,7 +3013,7 @@ static void read_compacted_summaries(struct f2fs_sb_info *sbi)
start = start_sum_block(sbi);
- page = get_meta_page(sbi, start++);
+ page = f2fs_get_meta_page(sbi, start++);
kaddr = (unsigned char *)page_address(page);
/* Step 1: restore nat cache */
@@ -2993,7 +3053,7 @@ static void read_compacted_summaries(struct f2fs_sb_info *sbi)
f2fs_put_page(page, 1);
page = NULL;
- page = get_meta_page(sbi, start++);
+ page = f2fs_get_meta_page(sbi, start++);
kaddr = (unsigned char *)page_address(page);
offset = 0;
}
@@ -3032,7 +3092,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
blk_addr = GET_SUM_BLOCK(sbi, segno);
}
- new = get_meta_page(sbi, blk_addr);
+ new = f2fs_get_meta_page(sbi, blk_addr);
sum = (struct f2fs_summary_block *)page_address(new);
if (IS_NODESEG(type)) {
@@ -3044,7 +3104,7 @@ static int read_normal_summaries(struct f2fs_sb_info *sbi, int type)
ns->ofs_in_node = 0;
}
} else {
- restore_node_summary(sbi, segno, sum);
+ f2fs_restore_node_summary(sbi, segno, sum);
}
}
@@ -3076,10 +3136,10 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
int err;
if (is_set_ckpt_flags(sbi, CP_COMPACT_SUM_FLAG)) {
- int npages = npages_for_summary_flush(sbi, true);
+ int npages = f2fs_npages_for_summary_flush(sbi, true);
if (npages >= 2)
- ra_meta_pages(sbi, start_sum_block(sbi), npages,
+ f2fs_ra_meta_pages(sbi, start_sum_block(sbi), npages,
META_CP, true);
/* restore for compacted data summary */
@@ -3088,7 +3148,7 @@ static int restore_curseg_summaries(struct f2fs_sb_info *sbi)
}
if (__exist_node_summaries(sbi))
- ra_meta_pages(sbi, sum_blk_addr(sbi, NR_CURSEG_TYPE, type),
+ f2fs_ra_meta_pages(sbi, sum_blk_addr(sbi, NR_CURSEG_TYPE, type),
NR_CURSEG_TYPE - type, META_CP, true);
for (; type <= CURSEG_COLD_NODE; type++) {
@@ -3114,8 +3174,9 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
int written_size = 0;
int i, j;
- page = grab_meta_page(sbi, blkaddr++);
+ page = f2fs_grab_meta_page(sbi, blkaddr++);
kaddr = (unsigned char *)page_address(page);
+ memset(kaddr, 0, PAGE_SIZE);
/* Step 1: write nat cache */
seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA);
@@ -3138,8 +3199,9 @@ static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr)
for (j = 0; j < blkoff; j++) {
if (!page) {
- page = grab_meta_page(sbi, blkaddr++);
+ page = f2fs_grab_meta_page(sbi, blkaddr++);
kaddr = (unsigned char *)page_address(page);
+ memset(kaddr, 0, PAGE_SIZE);
written_size = 0;
}
summary = (struct f2fs_summary *)(kaddr + written_size);
@@ -3174,7 +3236,7 @@ static void write_normal_summaries(struct f2fs_sb_info *sbi,
write_current_sum_page(sbi, i, blkaddr + (i - type));
}
-void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
+void f2fs_write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
{
if (is_set_ckpt_flags(sbi, CP_COMPACT_SUM_FLAG))
write_compacted_summaries(sbi, start_blk);
@@ -3182,12 +3244,12 @@ void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
write_normal_summaries(sbi, start_blk, CURSEG_HOT_DATA);
}
-void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
+void f2fs_write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk)
{
write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE);
}
-int lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
+int f2fs_lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
unsigned int val, int alloc)
{
int i;
@@ -3212,7 +3274,7 @@ int lookup_journal_in_cursum(struct f2fs_journal *journal, int type,
static struct page *get_current_sit_page(struct f2fs_sb_info *sbi,
unsigned int segno)
{
- return get_meta_page(sbi, current_sit_addr(sbi, segno));
+ return f2fs_get_meta_page(sbi, current_sit_addr(sbi, segno));
}
static struct page *get_next_sit_page(struct f2fs_sb_info *sbi,
@@ -3225,7 +3287,7 @@ static struct page *get_next_sit_page(struct f2fs_sb_info *sbi,
src_off = current_sit_addr(sbi, start);
dst_off = next_sit_addr(sbi, src_off);
- page = grab_meta_page(sbi, dst_off);
+ page = f2fs_grab_meta_page(sbi, dst_off);
seg_info_to_sit_page(sbi, page, start);
set_page_dirty(page);
@@ -3321,7 +3383,7 @@ static void remove_sits_in_journal(struct f2fs_sb_info *sbi)
* CP calls this function, which flushes SIT entries including sit_journal,
* and moves prefree segs to free segs.
*/
-void flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
+void f2fs_flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
{
struct sit_info *sit_i = SIT_I(sbi);
unsigned long *bitmap = sit_i->dirty_sentries_bitmap;
@@ -3380,6 +3442,11 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
int offset, sit_offset;
se = get_seg_entry(sbi, segno);
+#ifdef CONFIG_F2FS_CHECK_FS
+ if (memcmp(se->cur_valid_map, se->cur_valid_map_mir,
+ SIT_VBLOCK_MAP_SIZE))
+ f2fs_bug_on(sbi, 1);
+#endif
/* add discard candidates */
if (!(cpc->reason & CP_DISCARD)) {
@@ -3388,17 +3455,21 @@ void flush_sit_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc)
}
if (to_journal) {
- offset = lookup_journal_in_cursum(journal,
+ offset = f2fs_lookup_journal_in_cursum(journal,
SIT_JOURNAL, segno, 1);
f2fs_bug_on(sbi, offset < 0);
segno_in_journal(journal, offset) =
cpu_to_le32(segno);
seg_info_to_raw_sit(se,
&sit_in_journal(journal, offset));
+ check_block_count(sbi, segno,
+ &sit_in_journal(journal, offset));
} else {
sit_offset = SIT_ENTRY_OFFSET(sit_i, segno);
seg_info_to_raw_sit(se,
&raw_sit->entries[sit_offset]);
+ check_block_count(sbi, segno,
+ &raw_sit->entries[sit_offset]);
}
__clear_bit(segno, bitmap);
@@ -3446,8 +3517,10 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
SM_I(sbi)->sit_info = sit_i;
- sit_i->sentries = f2fs_kvzalloc(sbi, MAIN_SEGS(sbi) *
- sizeof(struct seg_entry), GFP_KERNEL);
+ sit_i->sentries =
+ f2fs_kvzalloc(sbi, array_size(sizeof(struct seg_entry),
+ MAIN_SEGS(sbi)),
+ GFP_KERNEL);
if (!sit_i->sentries)
return -ENOMEM;
@@ -3487,8 +3560,10 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
return -ENOMEM;
if (sbi->segs_per_sec > 1) {
- sit_i->sec_entries = f2fs_kvzalloc(sbi, MAIN_SECS(sbi) *
- sizeof(struct sec_entry), GFP_KERNEL);
+ sit_i->sec_entries =
+ f2fs_kvzalloc(sbi, array_size(sizeof(struct sec_entry),
+ MAIN_SECS(sbi)),
+ GFP_KERNEL);
if (!sit_i->sec_entries)
return -ENOMEM;
}
@@ -3564,7 +3639,8 @@ static int build_curseg(struct f2fs_sb_info *sbi)
struct curseg_info *array;
int i;
- array = f2fs_kzalloc(sbi, sizeof(*array) * NR_CURSEG_TYPE, GFP_KERNEL);
+ array = f2fs_kzalloc(sbi, array_size(NR_CURSEG_TYPE, sizeof(*array)),
+ GFP_KERNEL);
if (!array)
return -ENOMEM;
@@ -3597,9 +3673,10 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
unsigned int i, start, end;
unsigned int readed, start_blk = 0;
int err = 0;
+ block_t total_node_blocks = 0;
do {
- readed = ra_meta_pages(sbi, start_blk, BIO_MAX_PAGES,
+ readed = f2fs_ra_meta_pages(sbi, start_blk, BIO_MAX_PAGES,
META_SIT, true);
start = start_blk * sit_i->sents_per_block;
@@ -3619,6 +3696,8 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
if (err)
return err;
seg_info_from_raw_sit(se, &sit);
+ if (IS_NODESEG(se->type))
+ total_node_blocks += se->valid_blocks;
/* build discard map only one time */
if (f2fs_discard_en(sbi)) {
@@ -3647,15 +3726,28 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
unsigned int old_valid_blocks;
start = le32_to_cpu(segno_in_journal(journal, i));
+ if (start >= MAIN_SEGS(sbi)) {
+ f2fs_msg(sbi->sb, KERN_ERR,
+ "Wrong journal entry on segno %u",
+ start);
+ set_sbi_flag(sbi, SBI_NEED_FSCK);
+ err = -EINVAL;
+ break;
+ }
+
se = &sit_i->sentries[start];
sit = sit_in_journal(journal, i);
old_valid_blocks = se->valid_blocks;
+ if (IS_NODESEG(se->type))
+ total_node_blocks -= old_valid_blocks;
err = check_block_count(sbi, start, &sit);
if (err)
break;
seg_info_from_raw_sit(se, &sit);
+ if (IS_NODESEG(se->type))
+ total_node_blocks += se->valid_blocks;
if (f2fs_discard_en(sbi)) {
if (is_set_ckpt_flags(sbi, CP_TRIMMED_FLAG)) {
@@ -3664,16 +3756,28 @@ static int build_sit_entries(struct f2fs_sb_info *sbi)
} else {
memcpy(se->discard_map, se->cur_valid_map,
SIT_VBLOCK_MAP_SIZE);
- sbi->discard_blks += old_valid_blocks -
- se->valid_blocks;
+ sbi->discard_blks += old_valid_blocks;
+ sbi->discard_blks -= se->valid_blocks;
}
}
- if (sbi->segs_per_sec > 1)
+ if (sbi->segs_per_sec > 1) {
get_sec_entry(sbi, start)->valid_blocks +=
- se->valid_blocks - old_valid_blocks;
+ se->valid_blocks;
+ get_sec_entry(sbi, start)->valid_blocks -=
+ old_valid_blocks;
+ }
}
up_read(&curseg->journal_rwsem);
+
+ if (!err && total_node_blocks != valid_node_count(sbi)) {
+ f2fs_msg(sbi->sb, KERN_ERR,
+ "SIT is corrupted node# %u vs %u",
+ total_node_blocks, valid_node_count(sbi));
+ set_sbi_flag(sbi, SBI_NEED_FSCK);
+ err = -EINVAL;
+ }
+
return err;
}
@@ -3772,7 +3876,7 @@ static void init_min_max_mtime(struct f2fs_sb_info *sbi)
down_write(&sit_i->sentry_lock);
- sit_i->min_mtime = LLONG_MAX;
+ sit_i->min_mtime = ULLONG_MAX;
for (segno = 0; segno < MAIN_SEGS(sbi); segno += sbi->segs_per_sec) {
unsigned int i;
@@ -3786,11 +3890,11 @@ static void init_min_max_mtime(struct f2fs_sb_info *sbi)
if (sit_i->min_mtime > mtime)
sit_i->min_mtime = mtime;
}
- sit_i->max_mtime = get_mtime(sbi);
+ sit_i->max_mtime = get_mtime(sbi, false);
up_write(&sit_i->sentry_lock);
}
-int build_segment_manager(struct f2fs_sb_info *sbi)
+int f2fs_build_segment_manager(struct f2fs_sb_info *sbi)
{
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
@@ -3822,14 +3926,12 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
sm_info->min_hot_blocks = DEF_MIN_HOT_BLOCKS;
sm_info->min_ssr_sections = reserved_sections(sbi);
- sm_info->trim_sections = DEF_BATCHED_TRIM_SECTIONS;
-
INIT_LIST_HEAD(&sm_info->sit_entry_set);
init_rwsem(&sm_info->curseg_lock);
if (!f2fs_readonly(sbi->sb)) {
- err = create_flush_cmd_control(sbi);
+ err = f2fs_create_flush_cmd_control(sbi);
if (err)
return err;
}
@@ -3954,13 +4056,13 @@ static void destroy_sit_info(struct f2fs_sb_info *sbi)
kfree(sit_i);
}
-void destroy_segment_manager(struct f2fs_sb_info *sbi)
+void f2fs_destroy_segment_manager(struct f2fs_sb_info *sbi)
{
struct f2fs_sm_info *sm_info = SM_I(sbi);
if (!sm_info)
return;
- destroy_flush_cmd_control(sbi, true);
+ f2fs_destroy_flush_cmd_control(sbi, true);
destroy_discard_cmd_control(sbi);
destroy_dirty_segmap(sbi);
destroy_curseg(sbi);
@@ -3970,7 +4072,7 @@ void destroy_segment_manager(struct f2fs_sb_info *sbi)
kfree(sm_info);
}
-int __init create_segment_manager_caches(void)
+int __init f2fs_create_segment_manager_caches(void)
{
discard_entry_slab = f2fs_kmem_cache_create("discard_entry",
sizeof(struct discard_entry));
@@ -4003,7 +4105,7 @@ fail:
return -ENOMEM;
}
-void destroy_segment_manager_caches(void)
+void f2fs_destroy_segment_manager_caches(void)
{
kmem_cache_destroy(sit_entry_set_slab);
kmem_cache_destroy(discard_cmd_slab);
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 3325d07..f18fc82 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -85,7 +85,7 @@
(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & ((sbi)->blocks_per_seg - 1))
#define GET_SEGNO(sbi, blk_addr) \
- ((((blk_addr) == NULL_ADDR) || ((blk_addr) == NEW_ADDR)) ? \
+ ((!is_valid_blkaddr(blk_addr)) ? \
NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \
GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
#define BLKS_PER_SEC(sbi) \
@@ -215,6 +215,8 @@ struct segment_allocation {
#define IS_DUMMY_WRITTEN_PAGE(page) \
(page_private(page) == (unsigned long)DUMMY_WRITTEN_PAGE)
+#define MAX_SKIP_ATOMIC_COUNT 16
+
struct inmem_pages {
struct list_head list;
struct page *page;
@@ -375,6 +377,7 @@ static inline void seg_info_to_sit_page(struct f2fs_sb_info *sbi,
int i;
raw_sit = (struct f2fs_sit_block *)page_address(page);
+ memset(raw_sit, 0, PAGE_SIZE);
for (i = 0; i < end - start; i++) {
rs = &raw_sit->entries[i];
se = get_seg_entry(sbi, start + i);
@@ -742,12 +745,23 @@ static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start)
#endif
}
-static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi)
+static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi,
+ bool base_time)
{
struct sit_info *sit_i = SIT_I(sbi);
- time64_t now = ktime_get_real_seconds();
+ time64_t diff, now = ktime_get_real_seconds();
+
+ if (now >= sit_i->mounted_time)
+ return sit_i->elapsed_time + now - sit_i->mounted_time;
- return sit_i->elapsed_time + now - sit_i->mounted_time;
+ /* system time is set to the past */
+ if (!base_time) {
+ diff = sit_i->mounted_time - now;
+ if (sit_i->elapsed_time >= diff)
+ return sit_i->elapsed_time - diff;
+ return 0;
+ }
+ return sit_i->elapsed_time;
}
static inline void set_summary(struct f2fs_summary *sum, nid_t nid,
@@ -771,15 +785,6 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
- (base + 1) + type;
}
-static inline bool no_fggc_candidate(struct f2fs_sb_info *sbi,
- unsigned int secno)
-{
- if (get_valid_blocks(sbi, GET_SEG_FROM_SEC(sbi, secno), true) >
- sbi->fggc_threshold)
- return true;
- return false;
-}
-
static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno)
{
if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno))
diff --git a/fs/f2fs/shrinker.c b/fs/f2fs/shrinker.c
index 0b5664a..36cfd81 100644
--- a/fs/f2fs/shrinker.c
+++ b/fs/f2fs/shrinker.c
@@ -109,11 +109,11 @@ unsigned long f2fs_shrink_scan(struct shrinker *shrink,
/* shrink clean nat cache entries */
if (freed < nr)
- freed += try_to_free_nats(sbi, nr - freed);
+ freed += f2fs_try_to_free_nats(sbi, nr - freed);
/* shrink free nids cache entries */
if (freed < nr)
- freed += try_to_free_nids(sbi, nr - freed);
+ freed += f2fs_try_to_free_nids(sbi, nr - freed);
spin_lock(&f2fs_list_lock);
p = p->next;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 970ae27..3995e92 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -740,6 +740,10 @@ static int parse_options(struct super_block *sb, char *options)
} else if (strlen(name) == 6 &&
!strncmp(name, "strict", 6)) {
F2FS_OPTION(sbi).fsync_mode = FSYNC_MODE_STRICT;
+ } else if (strlen(name) == 9 &&
+ !strncmp(name, "nobarrier", 9)) {
+ F2FS_OPTION(sbi).fsync_mode =
+ FSYNC_MODE_NOBARRIER;
} else {
kfree(name);
return -EINVAL;
@@ -826,15 +830,14 @@ static struct inode *f2fs_alloc_inode(struct super_block *sb)
/* Initialize f2fs-specific inode info */
atomic_set(&fi->dirty_pages, 0);
- fi->i_current_depth = 1;
init_rwsem(&fi->i_sem);
INIT_LIST_HEAD(&fi->dirty_list);
INIT_LIST_HEAD(&fi->gdirty_list);
INIT_LIST_HEAD(&fi->inmem_ilist);
INIT_LIST_HEAD(&fi->inmem_pages);
mutex_init(&fi->inmem_lock);
- init_rwsem(&fi->dio_rwsem[READ]);
- init_rwsem(&fi->dio_rwsem[WRITE]);
+ init_rwsem(&fi->i_gc_rwsem[READ]);
+ init_rwsem(&fi->i_gc_rwsem[WRITE]);
init_rwsem(&fi->i_mmap_sem);
init_rwsem(&fi->i_xattr_sem);
@@ -862,7 +865,7 @@ static int f2fs_drop_inode(struct inode *inode)
/* some remained atomic pages should discarded */
if (f2fs_is_atomic_file(inode))
- drop_inmem_pages(inode);
+ f2fs_drop_inmem_pages(inode);
/* should remain fi->extent_tree for writepage */
f2fs_destroy_extent_node(inode);
@@ -999,7 +1002,7 @@ static void f2fs_put_super(struct super_block *sb)
struct cp_control cpc = {
.reason = CP_UMOUNT,
};
- write_checkpoint(sbi, &cpc);
+ f2fs_write_checkpoint(sbi, &cpc);
}
/* be sure to wait for any on-going discard commands */
@@ -1009,17 +1012,17 @@ static void f2fs_put_super(struct super_block *sb)
struct cp_control cpc = {
.reason = CP_UMOUNT | CP_TRIMMED,
};
- write_checkpoint(sbi, &cpc);
+ f2fs_write_checkpoint(sbi, &cpc);
}
- /* write_checkpoint can update stat informaion */
+ /* f2fs_write_checkpoint can update stat informaion */
f2fs_destroy_stats(sbi);
/*
* normally superblock is clean, so we need to release this.
* In addition, EIO will skip do checkpoint, we need this as well.
*/
- release_ino_entry(sbi, true);
+ f2fs_release_ino_entry(sbi, true);
f2fs_leave_shrinker(sbi);
mutex_unlock(&sbi->umount_mutex);
@@ -1031,8 +1034,8 @@ static void f2fs_put_super(struct super_block *sb)
iput(sbi->meta_inode);
/* destroy f2fs internal modules */
- destroy_node_manager(sbi);
- destroy_segment_manager(sbi);
+ f2fs_destroy_node_manager(sbi);
+ f2fs_destroy_segment_manager(sbi);
kfree(sbi->ckpt);
@@ -1074,7 +1077,7 @@ int f2fs_sync_fs(struct super_block *sb, int sync)
cpc.reason = __get_cp_reason(sbi);
mutex_lock(&sbi->gc_mutex);
- err = write_checkpoint(sbi, &cpc);
+ err = f2fs_write_checkpoint(sbi, &cpc);
mutex_unlock(&sbi->gc_mutex);
}
f2fs_trace_ios(NULL, 1);
@@ -1477,11 +1480,11 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
*/
if ((*flags & SB_RDONLY) || !test_opt(sbi, BG_GC)) {
if (sbi->gc_thread) {
- stop_gc_thread(sbi);
+ f2fs_stop_gc_thread(sbi);
need_restart_gc = true;
}
} else if (!sbi->gc_thread) {
- err = start_gc_thread(sbi);
+ err = f2fs_start_gc_thread(sbi);
if (err)
goto restore_opts;
need_stop_gc = true;
@@ -1504,9 +1507,9 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
*/
if ((*flags & SB_RDONLY) || !test_opt(sbi, FLUSH_MERGE)) {
clear_opt(sbi, FLUSH_MERGE);
- destroy_flush_cmd_control(sbi, false);
+ f2fs_destroy_flush_cmd_control(sbi, false);
} else {
- err = create_flush_cmd_control(sbi);
+ err = f2fs_create_flush_cmd_control(sbi);
if (err)
goto restore_gc;
}
@@ -1524,11 +1527,11 @@ skip:
return 0;
restore_gc:
if (need_restart_gc) {
- if (start_gc_thread(sbi))
+ if (f2fs_start_gc_thread(sbi))
f2fs_msg(sbi->sb, KERN_WARNING,
"background gc thread has stopped");
} else if (need_stop_gc) {
- stop_gc_thread(sbi);
+ f2fs_stop_gc_thread(sbi);
}
restore_opts:
#ifdef CONFIG_QUOTA
@@ -1800,7 +1803,7 @@ static int f2fs_quota_on(struct super_block *sb, int type, int format_id,
inode = d_inode(path->dentry);
inode_lock(inode);
- F2FS_I(inode)->i_flags |= FS_NOATIME_FL | FS_IMMUTABLE_FL;
+ F2FS_I(inode)->i_flags |= F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL;
inode_set_flags(inode, S_NOATIME | S_IMMUTABLE,
S_NOATIME | S_IMMUTABLE);
inode_unlock(inode);
@@ -1824,7 +1827,7 @@ static int f2fs_quota_off(struct super_block *sb, int type)
goto out_put;
inode_lock(inode);
- F2FS_I(inode)->i_flags &= ~(FS_NOATIME_FL | FS_IMMUTABLE_FL);
+ F2FS_I(inode)->i_flags &= ~(F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL);
inode_set_flags(inode, 0, S_NOATIME | S_IMMUTABLE);
inode_unlock(inode);
f2fs_mark_inode_dirty_sync(inode, false);
@@ -1946,7 +1949,7 @@ static struct inode *f2fs_nfs_get_inode(struct super_block *sb,
struct f2fs_sb_info *sbi = F2FS_SB(sb);
struct inode *inode;
- if (check_nid_range(sbi, ino))
+ if (f2fs_check_nid_range(sbi, ino))
return ERR_PTR(-ESTALE);
/*
@@ -2129,6 +2132,8 @@ static inline bool sanity_check_area_boundary(struct f2fs_sb_info *sbi,
static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
struct buffer_head *bh)
{
+ block_t segment_count, segs_per_sec, secs_per_zone;
+ block_t total_sections, blocks_per_seg;
struct f2fs_super_block *raw_super = (struct f2fs_super_block *)
(bh->b_data + F2FS_SUPER_OFFSET);
struct super_block *sb = sbi->sb;
@@ -2185,6 +2190,72 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
return 1;
}
+ segment_count = le32_to_cpu(raw_super->segment_count);
+ segs_per_sec = le32_to_cpu(raw_super->segs_per_sec);
+ secs_per_zone = le32_to_cpu(raw_super->secs_per_zone);
+ total_sections = le32_to_cpu(raw_super->section_count);
+
+ /* blocks_per_seg should be 512, given the above check */
+ blocks_per_seg = 1 << le32_to_cpu(raw_super->log_blocks_per_seg);
+
+ if (segment_count > F2FS_MAX_SEGMENT ||
+ segment_count < F2FS_MIN_SEGMENTS) {
+ f2fs_msg(sb, KERN_INFO,
+ "Invalid segment count (%u)",
+ segment_count);
+ return 1;
+ }
+
+ if (total_sections > segment_count ||
+ total_sections < F2FS_MIN_SEGMENTS ||
+ segs_per_sec > segment_count || !segs_per_sec) {
+ f2fs_msg(sb, KERN_INFO,
+ "Invalid segment/section count (%u, %u x %u)",
+ segment_count, total_sections, segs_per_sec);
+ return 1;
+ }
+
+ if ((segment_count / segs_per_sec) < total_sections) {
+ f2fs_msg(sb, KERN_INFO,
+ "Small segment_count (%u < %u * %u)",
+ segment_count, segs_per_sec, total_sections);
+ return 1;
+ }
+
+ if (segment_count > (le32_to_cpu(raw_super->block_count) >> 9)) {
+ f2fs_msg(sb, KERN_INFO,
+ "Wrong segment_count / block_count (%u > %u)",
+ segment_count, le32_to_cpu(raw_super->block_count));
+ return 1;
+ }
+
+ if (secs_per_zone > total_sections) {
+ f2fs_msg(sb, KERN_INFO,
+ "Wrong secs_per_zone (%u > %u)",
+ secs_per_zone, total_sections);
+ return 1;
+ }
+ if (le32_to_cpu(raw_super->extension_count) > F2FS_MAX_EXTENSION ||
+ raw_super->hot_ext_count > F2FS_MAX_EXTENSION ||
+ (le32_to_cpu(raw_super->extension_count) +
+ raw_super->hot_ext_count) > F2FS_MAX_EXTENSION) {
+ f2fs_msg(sb, KERN_INFO,
+ "Corrupted extension count (%u + %u > %u)",
+ le32_to_cpu(raw_super->extension_count),
+ raw_super->hot_ext_count,
+ F2FS_MAX_EXTENSION);
+ return 1;
+ }
+
+ if (le32_to_cpu(raw_super->cp_payload) >
+ (blocks_per_seg - F2FS_CP_PACKS)) {
+ f2fs_msg(sb, KERN_INFO,
+ "Insane cp_payload (%u > %u)",
+ le32_to_cpu(raw_super->cp_payload),
+ blocks_per_seg - F2FS_CP_PACKS);
+ return 1;
+ }
+
/* check reserved ino info */
if (le32_to_cpu(raw_super->node_ino) != 1 ||
le32_to_cpu(raw_super->meta_ino) != 2 ||
@@ -2197,13 +2268,6 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
return 1;
}
- if (le32_to_cpu(raw_super->segment_count) > F2FS_MAX_SEGMENT) {
- f2fs_msg(sb, KERN_INFO,
- "Invalid segment count (%u)",
- le32_to_cpu(raw_super->segment_count));
- return 1;
- }
-
/* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */
if (sanity_check_area_boundary(sbi, bh))
return 1;
@@ -2211,7 +2275,7 @@ static int sanity_check_raw_super(struct f2fs_sb_info *sbi,
return 0;
}
-int sanity_check_ckpt(struct f2fs_sb_info *sbi)
+int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
{
unsigned int total, fsmeta;
struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
@@ -2292,13 +2356,15 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
for (i = 0; i < NR_COUNT_TYPE; i++)
atomic_set(&sbi->nr_pages[i], 0);
- atomic_set(&sbi->wb_sync_req, 0);
+ for (i = 0; i < META; i++)
+ atomic_set(&sbi->wb_sync_req[i], 0);
INIT_LIST_HEAD(&sbi->s_list);
mutex_init(&sbi->umount_mutex);
for (i = 0; i < NR_PAGE_TYPE - 1; i++)
for (j = HOT; j < NR_TEMP_TYPE; j++)
mutex_init(&sbi->wio_mutex[i][j]);
+ init_rwsem(&sbi->io_order_lock);
spin_lock_init(&sbi->cp_lock);
sbi->dirty_device = 0;
@@ -2353,8 +2419,10 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, int devi)
#define F2FS_REPORT_NR_ZONES 4096
- zones = f2fs_kzalloc(sbi, sizeof(struct blk_zone) *
- F2FS_REPORT_NR_ZONES, GFP_KERNEL);
+ zones = f2fs_kzalloc(sbi,
+ array_size(F2FS_REPORT_NR_ZONES,
+ sizeof(struct blk_zone)),
+ GFP_KERNEL);
if (!zones)
return -ENOMEM;
@@ -2494,8 +2562,10 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
* Initialize multiple devices information, or single
* zoned block device information.
*/
- sbi->devs = f2fs_kzalloc(sbi, sizeof(struct f2fs_dev_info) *
- max_devices, GFP_KERNEL);
+ sbi->devs = f2fs_kzalloc(sbi,
+ array_size(max_devices,
+ sizeof(struct f2fs_dev_info)),
+ GFP_KERNEL);
if (!sbi->devs)
return -ENOMEM;
@@ -2717,9 +2787,11 @@ try_onemore:
int n = (i == META) ? 1: NR_TEMP_TYPE;
int j;
- sbi->write_io[i] = f2fs_kmalloc(sbi,
- n * sizeof(struct f2fs_bio_info),
- GFP_KERNEL);
+ sbi->write_io[i] =
+ f2fs_kmalloc(sbi,
+ array_size(n,
+ sizeof(struct f2fs_bio_info)),
+ GFP_KERNEL);
if (!sbi->write_io[i]) {
err = -ENOMEM;
goto free_options;
@@ -2759,7 +2831,7 @@ try_onemore:
goto free_io_dummy;
}
- err = get_valid_checkpoint(sbi);
+ err = f2fs_get_valid_checkpoint(sbi);
if (err) {
f2fs_msg(sb, KERN_ERR, "Failed to get valid F2FS checkpoint");
goto free_meta_inode;
@@ -2789,18 +2861,18 @@ try_onemore:
spin_lock_init(&sbi->inode_lock[i]);
}
- init_extent_cache_info(sbi);
+ f2fs_init_extent_cache_info(sbi);
- init_ino_entry_info(sbi);
+ f2fs_init_ino_entry_info(sbi);
/* setup f2fs internal modules */
- err = build_segment_manager(sbi);
+ err = f2fs_build_segment_manager(sbi);
if (err) {
f2fs_msg(sb, KERN_ERR,
"Failed to initialize F2FS segment manager");
goto free_sm;
}
- err = build_node_manager(sbi);
+ err = f2fs_build_node_manager(sbi);
if (err) {
f2fs_msg(sb, KERN_ERR,
"Failed to initialize F2FS node manager");
@@ -2818,7 +2890,7 @@ try_onemore:
sbi->kbytes_written =
le64_to_cpu(seg_i->journal->info.kbytes_written);
- build_gc_manager(sbi);
+ f2fs_build_gc_manager(sbi);
/* get an inode for node space */
sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi));
@@ -2870,7 +2942,7 @@ try_onemore:
}
#endif
/* if there are nt orphan nodes free them */
- err = recover_orphan_inodes(sbi);
+ err = f2fs_recover_orphan_inodes(sbi);
if (err)
goto free_meta;
@@ -2892,7 +2964,7 @@ try_onemore:
if (!retry)
goto skip_recovery;
- err = recover_fsync_data(sbi, false);
+ err = f2fs_recover_fsync_data(sbi, false);
if (err < 0) {
need_fsck = true;
f2fs_msg(sb, KERN_ERR,
@@ -2900,7 +2972,7 @@ try_onemore:
goto free_meta;
}
} else {
- err = recover_fsync_data(sbi, true);
+ err = f2fs_recover_fsync_data(sbi, true);
if (!f2fs_readonly(sb) && err > 0) {
err = -EINVAL;
@@ -2910,7 +2982,7 @@ try_onemore:
}
}
skip_recovery:
- /* recover_fsync_data() cleared this already */
+ /* f2fs_recover_fsync_data() cleared this already */
clear_sbi_flag(sbi, SBI_POR_DOING);
/*
@@ -2919,7 +2991,7 @@ skip_recovery:
*/
if (test_opt(sbi, BG_GC) && !f2fs_readonly(sb)) {
/* After POR, we can run background GC thread.*/
- err = start_gc_thread(sbi);
+ err = f2fs_start_gc_thread(sbi);
if (err)
goto free_meta;
}
@@ -2950,10 +3022,10 @@ free_meta:
#endif
f2fs_sync_inode_meta(sbi);
/*
- * Some dirty meta pages can be produced by recover_orphan_inodes()
+ * Some dirty meta pages can be produced by f2fs_recover_orphan_inodes()
* failed by EIO. Then, iput(node_inode) can trigger balance_fs_bg()
- * followed by write_checkpoint() through f2fs_write_node_pages(), which
- * falls into an infinite loop in sync_meta_pages().
+ * followed by f2fs_write_checkpoint() through f2fs_write_node_pages(), which
+ * falls into an infinite loop in f2fs_sync_meta_pages().
*/
truncate_inode_pages_final(META_MAPPING(sbi));
#ifdef CONFIG_QUOTA
@@ -2966,13 +3038,13 @@ free_root_inode:
free_stats:
f2fs_destroy_stats(sbi);
free_node_inode:
- release_ino_entry(sbi, true);
+ f2fs_release_ino_entry(sbi, true);
truncate_inode_pages_final(NODE_MAPPING(sbi));
iput(sbi->node_inode);
free_nm:
- destroy_node_manager(sbi);
+ f2fs_destroy_node_manager(sbi);
free_sm:
- destroy_segment_manager(sbi);
+ f2fs_destroy_segment_manager(sbi);
free_devices:
destroy_device_list(sbi);
kfree(sbi->ckpt);
@@ -3018,8 +3090,8 @@ static void kill_f2fs_super(struct super_block *sb)
{
if (sb->s_root) {
set_sbi_flag(F2FS_SB(sb), SBI_IS_CLOSE);
- stop_gc_thread(F2FS_SB(sb));
- stop_discard_thread(F2FS_SB(sb));
+ f2fs_stop_gc_thread(F2FS_SB(sb));
+ f2fs_stop_discard_thread(F2FS_SB(sb));
}
kill_block_super(sb);
}
@@ -3057,21 +3129,27 @@ static int __init init_f2fs_fs(void)
{
int err;
+ if (PAGE_SIZE != F2FS_BLKSIZE) {
+ printk("F2FS not supported on PAGE_SIZE(%lu) != %d\n",
+ PAGE_SIZE, F2FS_BLKSIZE);
+ return -EINVAL;
+ }
+
f2fs_build_trace_ios();
err = init_inodecache();
if (err)
goto fail;
- err = create_node_manager_caches();
+ err = f2fs_create_node_manager_caches();
if (err)
goto free_inodecache;
- err = create_segment_manager_caches();
+ err = f2fs_create_segment_manager_caches();
if (err)
goto free_node_manager_caches;
- err = create_checkpoint_caches();
+ err = f2fs_create_checkpoint_caches();
if (err)
goto free_segment_manager_caches;
- err = create_extent_cache();
+ err = f2fs_create_extent_cache();
if (err)
goto free_checkpoint_caches;
err = f2fs_init_sysfs();
@@ -3086,8 +3164,13 @@ static int __init init_f2fs_fs(void)
err = f2fs_create_root_stats();
if (err)
goto free_filesystem;
+ err = f2fs_init_post_read_processing();
+ if (err)
+ goto free_root_stats;
return 0;
+free_root_stats:
+ f2fs_destroy_root_stats();
free_filesystem:
unregister_filesystem(&f2fs_fs_type);
free_shrinker:
@@ -3095,13 +3178,13 @@ free_shrinker:
free_sysfs:
f2fs_exit_sysfs();
free_extent_cache:
- destroy_extent_cache();
+ f2fs_destroy_extent_cache();
free_checkpoint_caches:
- destroy_checkpoint_caches();
+ f2fs_destroy_checkpoint_caches();
free_segment_manager_caches:
- destroy_segment_manager_caches();
+ f2fs_destroy_segment_manager_caches();
free_node_manager_caches:
- destroy_node_manager_caches();
+ f2fs_destroy_node_manager_caches();
free_inodecache:
destroy_inodecache();
fail:
@@ -3110,14 +3193,15 @@ fail:
static void __exit exit_f2fs_fs(void)
{
+ f2fs_destroy_post_read_processing();
f2fs_destroy_root_stats();
unregister_filesystem(&f2fs_fs_type);
unregister_shrinker(&f2fs_shrinker_info);
f2fs_exit_sysfs();
- destroy_extent_cache();
- destroy_checkpoint_caches();
- destroy_segment_manager_caches();
- destroy_node_manager_caches();
+ f2fs_destroy_extent_cache();
+ f2fs_destroy_checkpoint_caches();
+ f2fs_destroy_segment_manager_caches();
+ f2fs_destroy_node_manager_caches();
destroy_inodecache();
f2fs_destroy_trace_ios();
}
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 4b47ca6..2e7e611 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -147,13 +147,13 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
int len = 0, i;
len += snprintf(buf + len, PAGE_SIZE - len,
- "cold file extenstion:\n");
+ "cold file extension:\n");
for (i = 0; i < cold_count; i++)
len += snprintf(buf + len, PAGE_SIZE - len, "%s\n",
extlist[i]);
len += snprintf(buf + len, PAGE_SIZE - len,
- "hot file extenstion:\n");
+ "hot file extension:\n");
for (i = cold_count; i < cold_count + hot_count; i++)
len += snprintf(buf + len, PAGE_SIZE - len, "%s\n",
extlist[i]);
@@ -165,7 +165,7 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
return snprintf(buf, PAGE_SIZE, "%u\n", *ui);
}
-static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
+static ssize_t __sbi_store(struct f2fs_attr *a,
struct f2fs_sb_info *sbi,
const char *buf, size_t count)
{
@@ -201,13 +201,13 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
down_write(&sbi->sb_lock);
- ret = update_extension_list(sbi, name, hot, set);
+ ret = f2fs_update_extension_list(sbi, name, hot, set);
if (ret)
goto out;
ret = f2fs_commit_super(sbi, false);
if (ret)
- update_extension_list(sbi, name, hot, !set);
+ f2fs_update_extension_list(sbi, name, hot, !set);
out:
up_write(&sbi->sb_lock);
return ret ? ret : count;
@@ -245,19 +245,56 @@ out:
return count;
}
+ if (!strcmp(a->attr.name, "trim_sections"))
+ return -EINVAL;
+
+ if (!strcmp(a->attr.name, "gc_urgent")) {
+ if (t >= 1) {
+ sbi->gc_mode = GC_URGENT;
+ if (sbi->gc_thread) {
+ wake_up_interruptible_all(
+ &sbi->gc_thread->gc_wait_queue_head);
+ wake_up_discard_thread(sbi, true);
+ }
+ } else {
+ sbi->gc_mode = GC_NORMAL;
+ }
+ return count;
+ }
+ if (!strcmp(a->attr.name, "gc_idle")) {
+ if (t == GC_IDLE_CB)
+ sbi->gc_mode = GC_IDLE_CB;
+ else if (t == GC_IDLE_GREEDY)
+ sbi->gc_mode = GC_IDLE_GREEDY;
+ else
+ sbi->gc_mode = GC_NORMAL;
+ return count;
+ }
+
*ui = t;
if (!strcmp(a->attr.name, "iostat_enable") && *ui == 0)
f2fs_reset_iostat(sbi);
- if (!strcmp(a->attr.name, "gc_urgent") && t == 1 && sbi->gc_thread) {
- sbi->gc_thread->gc_wake = 1;
- wake_up_interruptible_all(&sbi->gc_thread->gc_wait_queue_head);
- wake_up_discard_thread(sbi, true);
- }
-
return count;
}
+static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
+ struct f2fs_sb_info *sbi,
+ const char *buf, size_t count)
+{
+ ssize_t ret;
+ bool gc_entry = (!strcmp(a->attr.name, "gc_urgent") ||
+ a->struct_type == GC_THREAD);
+
+ if (gc_entry)
+ down_read(&sbi->sb->s_umount);
+ ret = __sbi_store(a, sbi, buf, count);
+ if (gc_entry)
+ up_read(&sbi->sb->s_umount);
+
+ return ret;
+}
+
static ssize_t f2fs_attr_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
@@ -346,8 +383,8 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent_sleep_time,
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time);
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time);
F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
-F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle);
-F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_urgent, gc_urgent);
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle, gc_mode);
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_urgent, gc_mode);
F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards);
F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, discard_granularity, discard_granularity);
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index ae2dfa7..7082718 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -252,7 +252,7 @@ static int read_inline_xattr(struct inode *inode, struct page *ipage,
if (ipage) {
inline_addr = inline_xattr_addr(inode, ipage);
} else {
- page = get_node_page(sbi, inode->i_ino);
+ page = f2fs_get_node_page(sbi, inode->i_ino);
if (IS_ERR(page))
return PTR_ERR(page);
@@ -273,7 +273,7 @@ static int read_xattr_block(struct inode *inode, void *txattr_addr)
void *xattr_addr;
/* The inode already has an extended attribute block. */
- xpage = get_node_page(sbi, xnid);
+ xpage = f2fs_get_node_page(sbi, xnid);
if (IS_ERR(xpage))
return PTR_ERR(xpage);
@@ -397,7 +397,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
int err = 0;
if (hsize > inline_size && !F2FS_I(inode)->i_xattr_nid)
- if (!alloc_nid(sbi, &new_nid))
+ if (!f2fs_alloc_nid(sbi, &new_nid))
return -ENOSPC;
/* write to inline xattr */
@@ -405,9 +405,9 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
if (ipage) {
inline_addr = inline_xattr_addr(inode, ipage);
} else {
- in_page = get_node_page(sbi, inode->i_ino);
+ in_page = f2fs_get_node_page(sbi, inode->i_ino);
if (IS_ERR(in_page)) {
- alloc_nid_failed(sbi, new_nid);
+ f2fs_alloc_nid_failed(sbi, new_nid);
return PTR_ERR(in_page);
}
inline_addr = inline_xattr_addr(inode, in_page);
@@ -417,8 +417,8 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
NODE, true);
/* no need to use xattr node block */
if (hsize <= inline_size) {
- err = truncate_xattr_node(inode);
- alloc_nid_failed(sbi, new_nid);
+ err = f2fs_truncate_xattr_node(inode);
+ f2fs_alloc_nid_failed(sbi, new_nid);
if (err) {
f2fs_put_page(in_page, 1);
return err;
@@ -431,10 +431,10 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
/* write to xattr node block */
if (F2FS_I(inode)->i_xattr_nid) {
- xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid);
+ xpage = f2fs_get_node_page(sbi, F2FS_I(inode)->i_xattr_nid);
if (IS_ERR(xpage)) {
err = PTR_ERR(xpage);
- alloc_nid_failed(sbi, new_nid);
+ f2fs_alloc_nid_failed(sbi, new_nid);
goto in_page_out;
}
f2fs_bug_on(sbi, new_nid);
@@ -442,13 +442,13 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize,
} else {
struct dnode_of_data dn;
set_new_dnode(&dn, inode, NULL, NULL, new_nid);
- xpage = new_node_page(&dn, XATTR_NODE_OFFSET);
+ xpage = f2fs_new_node_page(&dn, XATTR_NODE_OFFSET);
if (IS_ERR(xpage)) {
err = PTR_ERR(xpage);
- alloc_nid_failed(sbi, new_nid);
+ f2fs_alloc_nid_failed(sbi, new_nid);
goto in_page_out;
}
- alloc_nid_done(sbi, new_nid);
+ f2fs_alloc_nid_done(sbi, new_nid);
}
xattr_addr = page_address(xpage);
@@ -693,7 +693,7 @@ int f2fs_setxattr(struct inode *inode, int index, const char *name,
if (err)
return err;
- /* this case is only from init_inode_metadata */
+ /* this case is only from f2fs_init_inode_metadata */
if (ipage)
return __f2fs_setxattr(inode, index, name, value,
size, ipage, flags);
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index ffbbf05..065dc91 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -158,8 +158,14 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock,
err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create, false);
if (err)
return err;
+ if (!phys) {
+ fat_fs_error(sb,
+ "invalid FAT chain (i_pos %lld, last_block %llu)",
+ MSDOS_I(inode)->i_pos,
+ (unsigned long long)last_block);
+ return -EIO;
+ }
- BUG_ON(!phys);
BUG_ON(*max_blocks != mapped_blocks);
set_buffer_new(bh_result);
map_bh(bh_result, sb, phys);
@@ -502,6 +508,7 @@ static int fat_validate_dir(struct inode *dir)
/* doesn't deal with root inode */
int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
{
+ struct timespec ts;
struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
int error;
@@ -552,11 +559,14 @@ int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1))
& ~((loff_t)sbi->cluster_size - 1)) >> 9;
- fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0);
+ fat_time_fat2unix(sbi, &ts, de->time, de->date, 0);
+ inode->i_mtime = timespec_to_timespec64(ts);
if (sbi->options.isvfat) {
- fat_time_fat2unix(sbi, &inode->i_ctime, de->ctime,
+ fat_time_fat2unix(sbi, &ts, de->ctime,
de->cdate, de->ctime_cs);
- fat_time_fat2unix(sbi, &inode->i_atime, 0, de->adate, 0);
+ inode->i_ctime = timespec_to_timespec64(ts);
+ fat_time_fat2unix(sbi, &ts, 0, de->adate, 0);
+ inode->i_atime = timespec_to_timespec64(ts);
} else
inode->i_ctime = inode->i_atime = inode->i_mtime;
@@ -825,6 +835,7 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf)
static int __fat_write_inode(struct inode *inode, int wait)
{
+ struct timespec ts;
struct super_block *sb = inode->i_sb;
struct msdos_sb_info *sbi = MSDOS_SB(sb);
struct buffer_head *bh;
@@ -862,13 +873,16 @@ retry:
raw_entry->size = cpu_to_le32(inode->i_size);
raw_entry->attr = fat_make_attrs(inode);
fat_set_start(raw_entry, MSDOS_I(inode)->i_logstart);
- fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time,
+ ts = timespec64_to_timespec(inode->i_mtime);
+ fat_time_unix2fat(sbi, &ts, &raw_entry->time,
&raw_entry->date, NULL);
if (sbi->options.isvfat) {
__le16 atime;
- fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime,
+ ts = timespec64_to_timespec(inode->i_ctime);
+ fat_time_unix2fat(sbi, &ts, &raw_entry->ctime,
&raw_entry->cdate, &raw_entry->ctime_cs);
- fat_time_unix2fat(sbi, &inode->i_atime, &atime,
+ ts = timespec64_to_timespec(inode->i_atime);
+ fat_time_unix2fat(sbi, &ts, &atime,
&raw_entry->adate, NULL);
}
spin_unlock(&sbi->inode_hash_lock);
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 484ce67..16a832c 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -250,7 +250,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
if (err)
return err;
- dir->i_ctime = dir->i_mtime = *ts;
+ dir->i_ctime = dir->i_mtime = timespec_to_timespec64(*ts);
if (IS_DIRSYNC(dir))
(void)fat_sync_inode(dir);
else
@@ -266,7 +266,8 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
struct super_block *sb = dir->i_sb;
struct inode *inode = NULL;
struct fat_slot_info sinfo;
- struct timespec ts;
+ struct timespec64 ts;
+ struct timespec t;
unsigned char msdos_name[MSDOS_NAME];
int err, is_hid;
@@ -285,7 +286,8 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
}
ts = current_time(dir);
- err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &ts, &sinfo);
+ t = timespec64_to_timespec(ts);
+ err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &t, &sinfo);
if (err)
goto out;
inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
@@ -344,7 +346,8 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
struct fat_slot_info sinfo;
struct inode *inode;
unsigned char msdos_name[MSDOS_NAME];
- struct timespec ts;
+ struct timespec64 ts;
+ struct timespec t;
int err, is_hid, cluster;
mutex_lock(&MSDOS_SB(sb)->s_lock);
@@ -362,12 +365,13 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
}
ts = current_time(dir);
- cluster = fat_alloc_new_dir(dir, &ts);
+ t = timespec64_to_timespec(ts);
+ cluster = fat_alloc_new_dir(dir, &t);
if (cluster < 0) {
err = cluster;
goto out;
}
- err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
+ err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &t, &sinfo);
if (err)
goto out_free;
inc_nlink(dir);
@@ -432,7 +436,7 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
struct msdos_dir_entry *dotdot_de;
struct inode *old_inode, *new_inode;
struct fat_slot_info old_sinfo, sinfo;
- struct timespec ts;
+ struct timespec64 ts;
loff_t new_i_pos;
int err, old_attrs, is_dir, update_dotdot, corrupt = 0;
@@ -499,8 +503,9 @@ static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
new_i_pos = MSDOS_I(new_inode)->i_pos;
fat_detach(new_inode);
} else {
+ struct timespec t = timespec64_to_timespec(ts);
err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0,
- &ts, &sinfo);
+ &t, &sinfo);
if (err)
goto out;
new_i_pos = sinfo.i_pos;
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 4f4362d..9a54691 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -664,7 +664,7 @@ static int vfat_add_entry(struct inode *dir, const struct qstr *qname,
if (len == 0)
return -ENOENT;
- slots = kmalloc(sizeof(*slots) * MSDOS_SLOTS, GFP_NOFS);
+ slots = kmalloc_array(MSDOS_SLOTS, sizeof(*slots), GFP_NOFS);
if (slots == NULL)
return -ENOMEM;
@@ -678,7 +678,7 @@ static int vfat_add_entry(struct inode *dir, const struct qstr *qname,
goto cleanup;
/* update timestamp */
- dir->i_ctime = dir->i_mtime = dir->i_atime = *ts;
+ dir->i_ctime = dir->i_mtime = dir->i_atime = timespec_to_timespec64(*ts);
if (IS_DIRSYNC(dir))
(void)fat_sync_inode(dir);
else
@@ -761,13 +761,15 @@ static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
struct super_block *sb = dir->i_sb;
struct inode *inode;
struct fat_slot_info sinfo;
- struct timespec ts;
+ struct timespec64 ts;
+ struct timespec t;
int err;
mutex_lock(&MSDOS_SB(sb)->s_lock);
ts = current_time(dir);
- err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo);
+ t = timespec64_to_timespec(ts);
+ err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &t, &sinfo);
if (err)
goto out;
inode_inc_iversion(dir);
@@ -850,18 +852,20 @@ static int vfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
struct super_block *sb = dir->i_sb;
struct inode *inode;
struct fat_slot_info sinfo;
- struct timespec ts;
+ struct timespec64 ts;
+ struct timespec t;
int err, cluster;
mutex_lock(&MSDOS_SB(sb)->s_lock);
ts = current_time(dir);
- cluster = fat_alloc_new_dir(dir, &ts);
+ t = timespec64_to_timespec(ts);
+ cluster = fat_alloc_new_dir(dir, &t);
if (cluster < 0) {
err = cluster;
goto out;
}
- err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &ts, &sinfo);
+ err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &t, &sinfo);
if (err)
goto out_free;
inode_inc_iversion(dir);
@@ -899,7 +903,8 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
struct msdos_dir_entry *dotdot_de;
struct inode *old_inode, *new_inode;
struct fat_slot_info old_sinfo, sinfo;
- struct timespec ts;
+ struct timespec64 ts;
+ struct timespec t;
loff_t new_i_pos;
int err, is_dir, update_dotdot, corrupt = 0;
struct super_block *sb = old_dir->i_sb;
@@ -934,8 +939,9 @@ static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
new_i_pos = MSDOS_I(new_inode)->i_pos;
fat_detach(new_inode);
} else {
+ t = timespec64_to_timespec(ts);
err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0,
- &ts, &sinfo);
+ &t, &sinfo);
if (err)
goto out;
new_i_pos = sinfo.i_pos;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index e03ca14..c6b88fa 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -64,9 +64,12 @@ static struct fuse_req *__fuse_request_alloc(unsigned npages, gfp_t flags)
pages = req->inline_pages;
page_descs = req->inline_page_descs;
} else {
- pages = kmalloc(sizeof(struct page *) * npages, flags);
- page_descs = kmalloc(sizeof(struct fuse_page_desc) *
- npages, flags);
+ pages = kmalloc_array(npages, sizeof(struct page *),
+ flags);
+ page_descs =
+ kmalloc_array(npages,
+ sizeof(struct fuse_page_desc),
+ flags);
}
if (!pages || !page_descs) {
@@ -1359,7 +1362,8 @@ static ssize_t fuse_dev_splice_read(struct file *in, loff_t *ppos,
if (!fud)
return -EPERM;
- bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL);
+ bufs = kmalloc_array(pipe->buffers, sizeof(struct pipe_buffer),
+ GFP_KERNEL);
if (!bufs)
return -ENOMEM;
@@ -1940,7 +1944,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
if (!fud)
return -EPERM;
- bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL);
+ bufs = kmalloc_array(pipe->buffers, sizeof(struct pipe_buffer),
+ GFP_KERNEL);
if (!bufs)
return -ENOMEM;
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index ffcaf98..a24df88 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -217,7 +217,7 @@ void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr,
return;
}
- old_mtime = inode->i_mtime;
+ old_mtime = timespec64_to_timespec(inode->i_mtime);
fuse_change_attributes_common(inode, attr, attr_valid);
oldsize = inode->i_size;
diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c
index d9fb0ad..d97ad899 100644
--- a/fs/gfs2/dir.c
+++ b/fs/gfs2/dir.c
@@ -871,7 +871,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh,
struct buffer_head *bh;
struct gfs2_leaf *leaf;
struct gfs2_dirent *dent;
- struct timespec tv = current_time(inode);
+ struct timespec64 tv = current_time(inode);
error = gfs2_alloc_blocks(ip, &bn, &n, 0, NULL);
if (error)
@@ -1055,7 +1055,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name)
/* Change the pointers.
Don't bother distinguishing stuffed from non-stuffed.
This code is complicated enough already. */
- lp = kmalloc(half_len * sizeof(__be64), GFP_NOFS);
+ lp = kmalloc_array(half_len, sizeof(__be64), GFP_NOFS);
if (!lp) {
error = -ENOMEM;
goto fail_brelse;
@@ -1169,7 +1169,7 @@ static int dir_double_exhash(struct gfs2_inode *dip)
if (IS_ERR(hc))
return PTR_ERR(hc);
- hc2 = kmalloc(hsize_bytes * 2, GFP_NOFS | __GFP_NOWARN);
+ hc2 = kmalloc_array(hsize_bytes, 2, GFP_NOFS | __GFP_NOWARN);
if (hc2 == NULL)
hc2 = __vmalloc(hsize_bytes * 2, GFP_NOFS, PAGE_KERNEL);
@@ -1596,7 +1596,7 @@ int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
error = -ENOMEM;
/* 96 is max number of dirents which can be stuffed into an inode */
- darr = kmalloc(96 * sizeof(struct gfs2_dirent *), GFP_NOFS);
+ darr = kmalloc_array(96, sizeof(struct gfs2_dirent *), GFP_NOFS);
if (darr) {
g.pdent = (const struct gfs2_dirent **)darr;
g.offset = 0;
@@ -1802,7 +1802,7 @@ int gfs2_dir_add(struct inode *inode, const struct qstr *name,
struct gfs2_inode *ip = GFS2_I(inode);
struct buffer_head *bh = da->bh;
struct gfs2_dirent *dent = da->dent;
- struct timespec tv;
+ struct timespec64 tv;
struct gfs2_leaf *leaf;
int error;
@@ -1880,7 +1880,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry)
const struct qstr *name = &dentry->d_name;
struct gfs2_dirent *dent, *prev = NULL;
struct buffer_head *bh;
- struct timespec tv = current_time(&dip->i_inode);
+ struct timespec64 tv = current_time(&dip->i_inode);
/* Returns _either_ the entry (if its first in block) or the
previous entry otherwise */
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 097bd3c..4614ee2 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -1303,7 +1303,8 @@ int gfs2_glock_nq_m(unsigned int num_gh, struct gfs2_holder *ghs)
default:
if (num_gh <= 4)
break;
- pph = kmalloc(num_gh * sizeof(struct gfs2_holder *), GFP_NOFS);
+ pph = kmalloc_array(num_gh, sizeof(struct gfs2_holder *),
+ GFP_NOFS);
if (!pph)
return -ENOMEM;
}
diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c
index d8782a7..c63bee9 100644
--- a/fs/gfs2/glops.c
+++ b/fs/gfs2/glops.c
@@ -338,7 +338,7 @@ static int inode_go_demote_ok(const struct gfs2_glock *gl)
static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
{
const struct gfs2_dinode *str = buf;
- struct timespec atime;
+ struct timespec64 atime;
u16 height, depth;
if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr)))
@@ -361,7 +361,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf)
gfs2_set_inode_blocks(&ip->i_inode, be64_to_cpu(str->di_blocks));
atime.tv_sec = be64_to_cpu(str->di_atime);
atime.tv_nsec = be32_to_cpu(str->di_atime_nsec);
- if (timespec_compare(&ip->i_inode.i_atime, &atime) < 0)
+ if (timespec64_compare(&ip->i_inode.i_atime, &atime) < 0)
ip->i_inode.i_atime = atime;
ip->i_inode.i_mtime.tv_sec = be64_to_cpu(str->di_mtime);
ip->i_inode.i_mtime.tv_nsec = be32_to_cpu(str->di_mtime_nsec);
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index e8585df..0efae7a 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -886,7 +886,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
gfs2_write_calc_reserv(ip, sizeof(struct gfs2_quota),
&data_blocks, &ind_blocks);
- ghs = kmalloc(num_qd * sizeof(struct gfs2_holder), GFP_NOFS);
+ ghs = kmalloc_array(num_qd, sizeof(struct gfs2_holder), GFP_NOFS);
if (!ghs)
return -ENOMEM;
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 6bc5cfe..33abcf2 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -2605,8 +2605,9 @@ void gfs2_rlist_alloc(struct gfs2_rgrp_list *rlist, unsigned int state)
{
unsigned int x;
- rlist->rl_ghs = kmalloc(rlist->rl_rgrps * sizeof(struct gfs2_holder),
- GFP_NOFS | __GFP_NOFAIL);
+ rlist->rl_ghs = kmalloc_array(rlist->rl_rgrps,
+ sizeof(struct gfs2_holder),
+ GFP_NOFS | __GFP_NOFAIL);
for (x = 0; x < rlist->rl_rgrps; x++)
gfs2_holder_init(rlist->rl_rgd[x]->rd_gl,
state, 0,
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index cf5c7f3..af0d5b0 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -1097,7 +1097,7 @@ static int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host
int error = 0, err;
memset(sc, 0, sizeof(struct gfs2_statfs_change_host));
- gha = kmalloc(slots * sizeof(struct gfs2_holder), GFP_KERNEL);
+ gha = kmalloc_array(slots, sizeof(struct gfs2_holder), GFP_KERNEL);
if (!gha)
return -ENOMEM;
for (x = 0; x < slots; x++)
diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c
index b3309b8..2a16111d 100644
--- a/fs/hfs/inode.c
+++ b/fs/hfs/inode.c
@@ -351,7 +351,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
inode->i_mode &= ~hsb->s_file_umask;
inode->i_mode |= S_IFREG;
inode->i_ctime = inode->i_atime = inode->i_mtime =
- hfs_m_to_utime(rec->file.MdDat);
+ timespec_to_timespec64(hfs_m_to_utime(rec->file.MdDat));
inode->i_op = &hfs_file_inode_operations;
inode->i_fop = &hfs_file_operations;
inode->i_mapping->a_ops = &hfs_aops;
@@ -362,7 +362,7 @@ static int hfs_read_inode(struct inode *inode, void *data)
HFS_I(inode)->fs_blocks = 0;
inode->i_mode = S_IFDIR | (S_IRWXUGO & ~hsb->s_dir_umask);
inode->i_ctime = inode->i_atime = inode->i_mtime =
- hfs_m_to_utime(rec->dir.MdDat);
+ timespec_to_timespec64(hfs_m_to_utime(rec->dir.MdDat));
inode->i_op = &hfs_dir_inode_operations;
inode->i_fop = &hfs_dir_operations;
break;
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index c0c8d43..c824f70 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -493,9 +493,9 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
hfsplus_get_perms(inode, &folder->permissions, 1);
set_nlink(inode, 1);
inode->i_size = 2 + be32_to_cpu(folder->valence);
- inode->i_atime = hfsp_mt2ut(folder->access_date);
- inode->i_mtime = hfsp_mt2ut(folder->content_mod_date);
- inode->i_ctime = hfsp_mt2ut(folder->attribute_mod_date);
+ inode->i_atime = timespec_to_timespec64(hfsp_mt2ut(folder->access_date));
+ inode->i_mtime = timespec_to_timespec64(hfsp_mt2ut(folder->content_mod_date));
+ inode->i_ctime = timespec_to_timespec64(hfsp_mt2ut(folder->attribute_mod_date));
HFSPLUS_I(inode)->create_date = folder->create_date;
HFSPLUS_I(inode)->fs_blocks = 0;
if (folder->flags & cpu_to_be16(HFSPLUS_HAS_FOLDER_COUNT)) {
@@ -531,9 +531,9 @@ int hfsplus_cat_read_inode(struct inode *inode, struct hfs_find_data *fd)
init_special_inode(inode, inode->i_mode,
be32_to_cpu(file->permissions.dev));
}
- inode->i_atime = hfsp_mt2ut(file->access_date);
- inode->i_mtime = hfsp_mt2ut(file->content_mod_date);
- inode->i_ctime = hfsp_mt2ut(file->attribute_mod_date);
+ inode->i_atime = timespec_to_timespec64(hfsp_mt2ut(file->access_date));
+ inode->i_mtime = timespec_to_timespec64(hfsp_mt2ut(file->content_mod_date));
+ inode->i_ctime = timespec_to_timespec64(hfsp_mt2ut(file->attribute_mod_date));
HFSPLUS_I(inode)->create_date = file->create_date;
} else {
pr_err("bad catalog entry used to create inode\n");
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 3cd85eb..2597b29 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -555,9 +555,9 @@ static int read_name(struct inode *ino, char *name)
set_nlink(ino, st.nlink);
i_uid_write(ino, st.uid);
i_gid_write(ino, st.gid);
- ino->i_atime = st.atime;
- ino->i_mtime = st.mtime;
- ino->i_ctime = st.ctime;
+ ino->i_atime = timespec_to_timespec64(st.atime);
+ ino->i_mtime = timespec_to_timespec64(st.mtime);
+ ino->i_ctime = timespec_to_timespec64(st.ctime);
ino->i_size = st.size;
ino->i_blocks = st.blocks;
return 0;
@@ -838,15 +838,15 @@ static int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
}
if (attr->ia_valid & ATTR_ATIME) {
attrs.ia_valid |= HOSTFS_ATTR_ATIME;
- attrs.ia_atime = attr->ia_atime;
+ attrs.ia_atime = timespec64_to_timespec(attr->ia_atime);
}
if (attr->ia_valid & ATTR_MTIME) {
attrs.ia_valid |= HOSTFS_ATTR_MTIME;
- attrs.ia_mtime = attr->ia_mtime;
+ attrs.ia_mtime = timespec64_to_timespec(attr->ia_mtime);
}
if (attr->ia_valid & ATTR_CTIME) {
attrs.ia_valid |= HOSTFS_ATTR_CTIME;
- attrs.ia_ctime = attr->ia_ctime;
+ attrs.ia_ctime = timespec64_to_timespec(attr->ia_ctime);
}
if (attr->ia_valid & ATTR_ATIME_SET) {
attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET;
diff --git a/fs/hpfs/dnode.c b/fs/hpfs/dnode.c
index a4ad18a..4ada525 100644
--- a/fs/hpfs/dnode.c
+++ b/fs/hpfs/dnode.c
@@ -33,7 +33,8 @@ int hpfs_add_pos(struct inode *inode, loff_t *pos)
if (hpfs_inode->i_rddir_off[i] == pos)
return 0;
if (!(i&0x0f)) {
- if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_NOFS))) {
+ ppos = kmalloc_array(i + 0x11, sizeof(loff_t *), GFP_NOFS);
+ if (!ppos) {
pr_err("out of memory for position list\n");
return -ENOMEM;
}
diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c
index 7c49f1e..ecd9fcc 100644
--- a/fs/hpfs/map.c
+++ b/fs/hpfs/map.c
@@ -115,7 +115,7 @@ __le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp)
int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21;
int i;
__le32 *b;
- if (!(b = kmalloc(n * 512, GFP_KERNEL))) {
+ if (!(b = kmalloc_array(n, 512, GFP_KERNEL))) {
pr_err("can't allocate memory for bitmap directory\n");
return NULL;
}
diff --git a/fs/inode.c b/fs/inode.c
index 0df41bb..2c300e9 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1577,8 +1577,8 @@ static void update_ovl_inode_times(struct dentry *dentry, struct inode *inode,
if (upperdentry) {
struct inode *realinode = d_inode(upperdentry);
- if ((!timespec_equal(&inode->i_mtime, &realinode->i_mtime) ||
- !timespec_equal(&inode->i_ctime, &realinode->i_ctime))) {
+ if ((!timespec64_equal(&inode->i_mtime, &realinode->i_mtime) ||
+ !timespec64_equal(&inode->i_ctime, &realinode->i_ctime))) {
inode->i_mtime = realinode->i_mtime;
inode->i_ctime = realinode->i_ctime;
}
@@ -1601,12 +1601,12 @@ static int relatime_need_update(const struct path *path, struct inode *inode,
/*
* Is mtime younger than atime? If yes, update atime:
*/
- if (timespec_compare(&inode->i_mtime, &inode->i_atime) >= 0)
+ if (timespec64_compare(&inode->i_mtime, &inode->i_atime) >= 0)
return 1;
/*
* Is ctime younger than atime? If yes, update atime:
*/
- if (timespec_compare(&inode->i_ctime, &inode->i_atime) >= 0)
+ if (timespec64_compare(&inode->i_ctime, &inode->i_atime) >= 0)
return 1;
/*
@@ -1621,7 +1621,7 @@ static int relatime_need_update(const struct path *path, struct inode *inode,
return 0;
}
-int generic_update_time(struct inode *inode, struct timespec *time, int flags)
+int generic_update_time(struct inode *inode, struct timespec64 *time, int flags)
{
int iflags = I_DIRTY_TIME;
bool dirty = false;
@@ -1649,9 +1649,9 @@ EXPORT_SYMBOL(generic_update_time);
* This does the actual work of updating an inodes time or version. Must have
* had called mnt_want_write() before calling this.
*/
-static int update_time(struct inode *inode, struct timespec *time, int flags)
+static int update_time(struct inode *inode, struct timespec64 *time, int flags)
{
- int (*update_time)(struct inode *, struct timespec *, int);
+ int (*update_time)(struct inode *, struct timespec64 *, int);
update_time = inode->i_op->update_time ? inode->i_op->update_time :
generic_update_time;
@@ -1672,7 +1672,7 @@ bool __atime_needs_update(const struct path *path, struct inode *inode,
bool rcu)
{
struct vfsmount *mnt = path->mnt;
- struct timespec now;
+ struct timespec64 now;
if (inode->i_flags & S_NOATIME)
return false;
@@ -1695,10 +1695,10 @@ bool __atime_needs_update(const struct path *path, struct inode *inode,
now = current_time(inode);
- if (!relatime_need_update(path, inode, now, rcu))
+ if (!relatime_need_update(path, inode, timespec64_to_timespec(now), rcu))
return false;
- if (timespec_equal(&inode->i_atime, &now))
+ if (timespec64_equal(&inode->i_atime, &now))
return false;
return true;
@@ -1708,7 +1708,7 @@ void touch_atime(const struct path *path)
{
struct vfsmount *mnt = path->mnt;
struct inode *inode = d_inode(path->dentry);
- struct timespec now;
+ struct timespec64 now;
if (!__atime_needs_update(path, inode, false))
return;
@@ -1842,7 +1842,7 @@ EXPORT_SYMBOL(file_remove_privs);
int file_update_time(struct file *file)
{
struct inode *inode = file_inode(file);
- struct timespec now;
+ struct timespec64 now;
int sync_it = 0;
int ret;
@@ -1851,10 +1851,10 @@ int file_update_time(struct file *file)
return 0;
now = current_time(inode);
- if (!timespec_equal(&inode->i_mtime, &now))
+ if (!timespec64_equal(&inode->i_mtime, &now))
sync_it = S_MTIME;
- if (!timespec_equal(&inode->i_ctime, &now))
+ if (!timespec64_equal(&inode->i_ctime, &now))
sync_it |= S_CTIME;
if (IS_I_VERSION(inode) && inode_iversion_need_inc(inode))
@@ -2098,6 +2098,30 @@ void inode_nohighmem(struct inode *inode)
EXPORT_SYMBOL(inode_nohighmem);
/**
+ * timespec64_trunc - Truncate timespec64 to a granularity
+ * @t: Timespec64
+ * @gran: Granularity in ns.
+ *
+ * Truncate a timespec64 to a granularity. Always rounds down. gran must
+ * not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns).
+ */
+struct timespec64 timespec64_trunc(struct timespec64 t, unsigned gran)
+{
+ /* Avoid division in the common cases 1 ns and 1 s. */
+ if (gran == 1) {
+ /* nothing */
+ } else if (gran == NSEC_PER_SEC) {
+ t.tv_nsec = 0;
+ } else if (gran > 1 && gran < NSEC_PER_SEC) {
+ t.tv_nsec -= t.tv_nsec % gran;
+ } else {
+ WARN(1, "illegal file time granularity: %u", gran);
+ }
+ return t;
+}
+EXPORT_SYMBOL(timespec64_trunc);
+
+/**
* current_time - Return FS time
* @inode: inode.
*
@@ -2107,15 +2131,15 @@ EXPORT_SYMBOL(inode_nohighmem);
* Note that inode and inode->sb cannot be NULL.
* Otherwise, the function warns and returns time without truncation.
*/
-struct timespec current_time(struct inode *inode)
+struct timespec64 current_time(struct inode *inode)
{
- struct timespec now = current_kernel_time();
+ struct timespec64 now = current_kernel_time64();
if (unlikely(!inode->i_sb)) {
WARN(1, "current_time() called with uninitialized super_block in the inode");
return now;
}
- return timespec_trunc(now, inode->i_sb->s_time_gran);
+ return timespec64_trunc(now, inode->i_sb->s_time_gran);
}
EXPORT_SYMBOL(current_time);
diff --git a/fs/iomap.c b/fs/iomap.c
index 7d1e9f4..77397b5 100644
--- a/fs/iomap.c
+++ b/fs/iomap.c
@@ -1388,7 +1388,11 @@ int iomap_swapfile_activate(struct swap_info_struct *sis,
loff_t len = ALIGN_DOWN(i_size_read(inode), PAGE_SIZE);
loff_t ret;
- ret = filemap_write_and_wait(inode->i_mapping);
+ /*
+ * Persist all file mapping metadata so that we won't have any
+ * IOMAP_F_DIRTY iomaps.
+ */
+ ret = vfs_fsync(swap_file, 1);
if (ret)
return ret;
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 240779e..a1143e5 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -223,7 +223,7 @@ static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size)
table->hash_size = hash_size;
table->hash_shift = shift;
table->hash_table =
- kmalloc(hash_size * sizeof(struct list_head), GFP_KERNEL);
+ kmalloc_array(hash_size, sizeof(struct list_head), GFP_KERNEL);
if (!table->hash_table) {
kmem_cache_free(jbd2_revoke_table_cache, table);
table = NULL;
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c
index 7ebacf1..093ffbd 100644
--- a/fs/jffs2/acl.c
+++ b/fs/jffs2/acl.c
@@ -133,7 +133,8 @@ static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size)
size_t i;
*size = jffs2_acl_size(acl->a_count);
- header = kmalloc(sizeof(*header) + acl->a_count * sizeof(*entry), GFP_KERNEL);
+ header = kmalloc(struct_size(header, a_entries, acl->a_count),
+ GFP_KERNEL);
if (!header)
return ERR_PTR(-ENOMEM);
header->a_version = cpu_to_je32(JFFS2_ACL_VERSION);
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h
index 2e2b574..12d0271 100644
--- a/fs/jffs2/acl.h
+++ b/fs/jffs2/acl.h
@@ -22,6 +22,7 @@ struct jffs2_acl_entry_short {
struct jffs2_acl_header {
jint32_t a_version;
+ struct jffs2_acl_entry a_entries[];
};
#ifdef CONFIG_JFFS2_FS_POSIX_ACL
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c
index e5a6deb..b2944f9 100644
--- a/fs/jffs2/dir.c
+++ b/fs/jffs2/dir.c
@@ -201,7 +201,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry,
if (ret)
goto fail;
- dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->ctime)));
jffs2_free_raw_inode(ri);
@@ -234,7 +234,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
if (dead_f->inocache)
set_nlink(d_inode(dentry), dead_f->inocache->pino_nlink);
if (!ret)
- dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
return ret;
}
/***********************************************************************/
@@ -268,7 +268,7 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
set_nlink(d_inode(old_dentry), ++f->inocache->pino_nlink);
mutex_unlock(&f->sem);
d_instantiate(dentry, d_inode(old_dentry));
- dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
ihold(d_inode(old_dentry));
}
return ret;
@@ -418,7 +418,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
goto fail;
}
- dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(rd->mctime)));
jffs2_free_raw_dirent(rd);
@@ -561,7 +561,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
goto fail;
}
- dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(rd->mctime)));
inc_nlink(dir_i);
jffs2_free_raw_dirent(rd);
@@ -598,7 +598,7 @@ static int jffs2_rmdir (struct inode *dir_i, struct dentry *dentry)
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
dentry->d_name.len, f, now);
if (!ret) {
- dir_i->i_mtime = dir_i->i_ctime = ITIME(now);
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
clear_nlink(d_inode(dentry));
drop_nlink(dir_i);
}
@@ -733,7 +733,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
goto fail;
}
- dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
+ dir_i->i_mtime = dir_i->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(rd->mctime)));
jffs2_free_raw_dirent(rd);
@@ -853,14 +853,14 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
* caller won't do it on its own since we are returning an error.
*/
d_invalidate(new_dentry);
- new_dir_i->i_mtime = new_dir_i->i_ctime = ITIME(now);
+ new_dir_i->i_mtime = new_dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
return ret;
}
if (d_is_dir(old_dentry))
drop_nlink(old_dir_i);
- new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = ITIME(now);
+ new_dir_i->i_mtime = new_dir_i->i_ctime = old_dir_i->i_mtime = old_dir_i->i_ctime = timespec_to_timespec64(ITIME(now));
return 0;
}
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
index bd0428b..481afd4 100644
--- a/fs/jffs2/file.c
+++ b/fs/jffs2/file.c
@@ -308,7 +308,7 @@ static int jffs2_write_end(struct file *filp, struct address_space *mapping,
inode->i_size = pos + writtenlen;
inode->i_blocks = (inode->i_size + 511) >> 9;
- inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime));
+ inode->i_ctime = inode->i_mtime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->ctime)));
}
}
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c
index eab04ec..0ecfb8e 100644
--- a/fs/jffs2/fs.c
+++ b/fs/jffs2/fs.c
@@ -146,9 +146,9 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
return PTR_ERR(new_metadata);
}
/* It worked. Update the inode */
- inode->i_atime = ITIME(je32_to_cpu(ri->atime));
- inode->i_ctime = ITIME(je32_to_cpu(ri->ctime));
- inode->i_mtime = ITIME(je32_to_cpu(ri->mtime));
+ inode->i_atime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->atime)));
+ inode->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->ctime)));
+ inode->i_mtime = timespec_to_timespec64(ITIME(je32_to_cpu(ri->mtime)));
inode->i_mode = jemode_to_cpu(ri->mode);
i_uid_write(inode, je16_to_cpu(ri->uid));
i_gid_write(inode, je16_to_cpu(ri->gid));
@@ -280,9 +280,9 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
i_uid_write(inode, je16_to_cpu(latest_node.uid));
i_gid_write(inode, je16_to_cpu(latest_node.gid));
inode->i_size = je32_to_cpu(latest_node.isize);
- inode->i_atime = ITIME(je32_to_cpu(latest_node.atime));
- inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));
- inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime));
+ inode->i_atime = timespec_to_timespec64(ITIME(je32_to_cpu(latest_node.atime)));
+ inode->i_mtime = timespec_to_timespec64(ITIME(je32_to_cpu(latest_node.mtime)));
+ inode->i_ctime = timespec_to_timespec64(ITIME(je32_to_cpu(latest_node.ctime)));
set_nlink(inode, f->inocache->pino_nlink);
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 2cfe487..c6821a50 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -1208,7 +1208,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
if (!c->wbuf)
return -ENOMEM;
- c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->oobavail, GFP_KERNEL);
+ c->oobbuf = kmalloc_array(NR_OOB_SCAN_PAGES, c->oobavail, GFP_KERNEL);
if (!c->oobbuf) {
kfree(c->wbuf);
return -ENOMEM;
diff --git a/fs/jfs/jfs_dmap.c b/fs/jfs/jfs_dmap.c
index 2d514c7..49263e2 100644
--- a/fs/jfs/jfs_dmap.c
+++ b/fs/jfs/jfs_dmap.c
@@ -1641,7 +1641,7 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen)
max_ranges = nblocks;
do_div(max_ranges, minlen);
range_cnt = min_t(u64, max_ranges + 1, 32 * 1024);
- totrim = kmalloc(sizeof(struct range2trim) * range_cnt, GFP_NOFS);
+ totrim = kmalloc_array(range_cnt, sizeof(struct range2trim), GFP_NOFS);
if (totrim == NULL) {
jfs_error(bmp->db_ipbmap->i_sb, "no memory for trim array\n");
IWRITE_UNLOCK(ipbmap);
diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c
index de2bcb3..52bae3f 100644
--- a/fs/jfs/jfs_dtree.c
+++ b/fs/jfs/jfs_dtree.c
@@ -594,7 +594,8 @@ int dtSearch(struct inode *ip, struct component_name * key, ino_t * data,
struct component_name ciKey;
struct super_block *sb = ip->i_sb;
- ciKey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t), GFP_NOFS);
+ ciKey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t),
+ GFP_NOFS);
if (!ciKey.name) {
rc = -ENOMEM;
goto dtSearch_Exit2;
@@ -957,7 +958,7 @@ static int dtSplitUp(tid_t tid,
smp = split->mp;
sp = DT_PAGE(ip, smp);
- key.name = kmalloc((JFS_NAME_MAX + 2) * sizeof(wchar_t), GFP_NOFS);
+ key.name = kmalloc_array(JFS_NAME_MAX + 2, sizeof(wchar_t), GFP_NOFS);
if (!key.name) {
DT_PUTPAGE(smp);
rc = -ENOMEM;
@@ -3779,12 +3780,12 @@ static int ciGetLeafPrefixKey(dtpage_t * lp, int li, dtpage_t * rp,
struct component_name lkey;
struct component_name rkey;
- lkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ lkey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t),
GFP_KERNEL);
if (lkey.name == NULL)
return -ENOMEM;
- rkey.name = kmalloc((JFS_NAME_MAX + 1) * sizeof(wchar_t),
+ rkey.name = kmalloc_array(JFS_NAME_MAX + 1, sizeof(wchar_t),
GFP_KERNEL);
if (rkey.name == NULL) {
kfree(lkey.name);
diff --git a/fs/jfs/jfs_unicode.c b/fs/jfs/jfs_unicode.c
index c7de6f5..0148e2e 100644
--- a/fs/jfs/jfs_unicode.c
+++ b/fs/jfs/jfs_unicode.c
@@ -121,7 +121,7 @@ int get_UCSname(struct component_name * uniName, struct dentry *dentry)
return -ENAMETOOLONG;
uniName->name =
- kmalloc((length + 1) * sizeof(wchar_t), GFP_NOFS);
+ kmalloc_array(length + 1, sizeof(wchar_t), GFP_NOFS);
if (uniName->name == NULL)
return -ENOMEM;
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index c60f3d3..a679798 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -491,15 +491,17 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size)
if (size > PSIZE) {
/*
* To keep the rest of the code simple. Allocate a
- * contiguous buffer to work with
+ * contiguous buffer to work with. Make the buffer large
+ * enough to make use of the whole extent.
*/
- ea_buf->xattr = kmalloc(size, GFP_KERNEL);
+ ea_buf->max_size = (size + sb->s_blocksize - 1) &
+ ~(sb->s_blocksize - 1);
+
+ ea_buf->xattr = kmalloc(ea_buf->max_size, GFP_KERNEL);
if (ea_buf->xattr == NULL)
return -ENOMEM;
ea_buf->flag = EA_MALLOC;
- ea_buf->max_size = (size + sb->s_blocksize - 1) &
- ~(sb->s_blocksize - 1);
if (ea_size == 0)
return 0;
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index 89d1dc1..d66cc07 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -779,7 +779,7 @@ int kernfs_add_one(struct kernfs_node *kn)
ps_iattr = parent->iattr;
if (ps_iattr) {
struct iattr *ps_iattrs = &ps_iattr->ia_iattr;
- ktime_get_real_ts(&ps_iattrs->ia_ctime);
+ ktime_get_real_ts64(&ps_iattrs->ia_ctime);
ps_iattrs->ia_mtime = ps_iattrs->ia_ctime;
}
@@ -1306,7 +1306,7 @@ static void __kernfs_remove(struct kernfs_node *kn)
/* update timestamps on the parent */
if (ps_iattr) {
- ktime_get_real_ts(&ps_iattr->ia_iattr.ia_ctime);
+ ktime_get_real_ts64(&ps_iattr->ia_iattr.ia_ctime);
ps_iattr->ia_iattr.ia_mtime =
ps_iattr->ia_iattr.ia_ctime;
}
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c
index a343039..3d73fe9 100644
--- a/fs/kernfs/inode.c
+++ b/fs/kernfs/inode.c
@@ -52,7 +52,7 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
iattrs->ia_uid = GLOBAL_ROOT_UID;
iattrs->ia_gid = GLOBAL_ROOT_GID;
- ktime_get_real_ts(&iattrs->ia_atime);
+ ktime_get_real_ts64(&iattrs->ia_atime);
iattrs->ia_mtime = iattrs->ia_atime;
iattrs->ia_ctime = iattrs->ia_atime;
@@ -176,9 +176,9 @@ static inline void set_inode_attr(struct inode *inode, struct iattr *iattr)
struct super_block *sb = inode->i_sb;
inode->i_uid = iattr->ia_uid;
inode->i_gid = iattr->ia_gid;
- inode->i_atime = timespec_trunc(iattr->ia_atime, sb->s_time_gran);
- inode->i_mtime = timespec_trunc(iattr->ia_mtime, sb->s_time_gran);
- inode->i_ctime = timespec_trunc(iattr->ia_ctime, sb->s_time_gran);
+ inode->i_atime = timespec64_trunc(iattr->ia_atime, sb->s_time_gran);
+ inode->i_mtime = timespec64_trunc(iattr->ia_mtime, sb->s_time_gran);
+ inode->i_ctime = timespec64_trunc(iattr->ia_ctime, sb->s_time_gran);
}
static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode)
diff --git a/fs/locks.c b/fs/locks.c
index 05e211be..db7b691 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1562,7 +1562,7 @@ EXPORT_SYMBOL(__break_lease);
* exclusive leases. The justification is that if someone has an
* exclusive lease, then they could be modifying it.
*/
-void lease_get_mtime(struct inode *inode, struct timespec *time)
+void lease_get_mtime(struct inode *inode, struct timespec64 *time)
{
bool has_lease = false;
struct file_lock_context *ctx;
diff --git a/fs/mbcache.c b/fs/mbcache.c
index bf41e2e..081ccf0 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -353,8 +353,9 @@ struct mb_cache *mb_cache_create(int bucket_bits)
cache->c_max_entries = bucket_count << 4;
INIT_LIST_HEAD(&cache->c_list);
spin_lock_init(&cache->c_list_lock);
- cache->c_hash = kmalloc(bucket_count * sizeof(struct hlist_bl_head),
- GFP_KERNEL);
+ cache->c_hash = kmalloc_array(bucket_count,
+ sizeof(struct hlist_bl_head),
+ GFP_KERNEL);
if (!cache->c_hash) {
kfree(cache);
goto err_out;
diff --git a/fs/namei.c b/fs/namei.c
index 6df1f61..734cef5 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -537,12 +537,12 @@ static int __nd_alloc_stack(struct nameidata *nd)
struct saved *p;
if (nd->flags & LOOKUP_RCU) {
- p= kmalloc(MAXSYMLINKS * sizeof(struct saved),
+ p= kmalloc_array(MAXSYMLINKS, sizeof(struct saved),
GFP_ATOMIC);
if (unlikely(!p))
return -ECHILD;
} else {
- p= kmalloc(MAXSYMLINKS * sizeof(struct saved),
+ p= kmalloc_array(MAXSYMLINKS, sizeof(struct saved),
GFP_KERNEL);
if (unlikely(!p))
return -ENOMEM;
@@ -2464,6 +2464,35 @@ static int lookup_one_len_common(const char *name, struct dentry *base,
}
/**
+ * try_lookup_one_len - filesystem helper to lookup single pathname component
+ * @name: pathname component to lookup
+ * @base: base directory to lookup from
+ * @len: maximum length @len should be interpreted to
+ *
+ * Look up a dentry by name in the dcache, returning NULL if it does not
+ * currently exist. The function does not try to create a dentry.
+ *
+ * Note that this routine is purely a helper for filesystem usage and should
+ * not be called by generic code.
+ *
+ * The caller must hold base->i_mutex.
+ */
+struct dentry *try_lookup_one_len(const char *name, struct dentry *base, int len)
+{
+ struct qstr this;
+ int err;
+
+ WARN_ON_ONCE(!inode_is_locked(base->d_inode));
+
+ err = lookup_one_len_common(name, base, len, &this);
+ if (err)
+ return ERR_PTR(err);
+
+ return lookup_dcache(&this, base, 0);
+}
+EXPORT_SYMBOL(try_lookup_one_len);
+
+/**
* lookup_one_len - filesystem helper to lookup single pathname component
* @name: pathname component to lookup
* @base: base directory to lookup from
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
index a50d781..64c214f 100644
--- a/fs/nfs/callback_proc.c
+++ b/fs/nfs/callback_proc.c
@@ -40,7 +40,9 @@ __be32 nfs4_callback_getattr(void *argp, void *resp,
rpc_peeraddr2str(cps->clp->cl_rpcclient, RPC_DISPLAY_ADDR));
inode = nfs_delegation_find_inode(cps->clp, &args->fh);
- if (inode == NULL) {
+ if (IS_ERR(inode)) {
+ if (inode == ERR_PTR(-EAGAIN))
+ res->status = htonl(NFS4ERR_DELAY);
trace_nfs4_cb_getattr(cps->clp, &args->fh, NULL,
-ntohl(res->status));
goto out;
@@ -54,8 +56,8 @@ __be32 nfs4_callback_getattr(void *argp, void *resp,
res->change_attr = delegation->change_attr;
if (nfs_have_writebacks(inode))
res->change_attr++;
- res->ctime = inode->i_ctime;
- res->mtime = inode->i_mtime;
+ res->ctime = timespec64_to_timespec(inode->i_ctime);
+ res->mtime = timespec64_to_timespec(inode->i_mtime);
res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) &
args->bitmap[0];
res->bitmap[1] = (FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY) &
@@ -86,7 +88,9 @@ __be32 nfs4_callback_recall(void *argp, void *resp,
res = htonl(NFS4ERR_BADHANDLE);
inode = nfs_delegation_find_inode(cps->clp, &args->fh);
- if (inode == NULL) {
+ if (IS_ERR(inode)) {
+ if (inode == ERR_PTR(-EAGAIN))
+ res = htonl(NFS4ERR_DELAY);
trace_nfs4_cb_recall(cps->clp, &args->fh, NULL,
&args->stateid, -ntohl(res));
goto out;
@@ -124,7 +128,6 @@ static struct inode *nfs_layout_find_inode_by_stateid(struct nfs_client *clp,
struct inode *inode;
struct pnfs_layout_hdr *lo;
-restart:
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
list_for_each_entry(lo, &server->layouts, plh_layouts) {
if (stateid != NULL &&
@@ -132,20 +135,20 @@ restart:
continue;
inode = igrab(lo->plh_inode);
if (!inode)
- continue;
+ return ERR_PTR(-EAGAIN);
if (!nfs_sb_active(inode->i_sb)) {
rcu_read_unlock();
spin_unlock(&clp->cl_lock);
iput(inode);
spin_lock(&clp->cl_lock);
rcu_read_lock();
- goto restart;
+ return ERR_PTR(-EAGAIN);
}
return inode;
}
}
- return NULL;
+ return ERR_PTR(-ENOENT);
}
/*
@@ -162,7 +165,6 @@ static struct inode *nfs_layout_find_inode_by_fh(struct nfs_client *clp,
struct inode *inode;
struct pnfs_layout_hdr *lo;
-restart:
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
list_for_each_entry(lo, &server->layouts, plh_layouts) {
nfsi = NFS_I(lo->plh_inode);
@@ -172,20 +174,20 @@ restart:
continue;
inode = igrab(lo->plh_inode);
if (!inode)
- continue;
+ return ERR_PTR(-EAGAIN);
if (!nfs_sb_active(inode->i_sb)) {
rcu_read_unlock();
spin_unlock(&clp->cl_lock);
iput(inode);
spin_lock(&clp->cl_lock);
rcu_read_lock();
- goto restart;
+ return ERR_PTR(-EAGAIN);
}
return inode;
}
}
- return NULL;
+ return ERR_PTR(-ENOENT);
}
static struct inode *nfs_layout_find_inode(struct nfs_client *clp,
@@ -197,7 +199,7 @@ static struct inode *nfs_layout_find_inode(struct nfs_client *clp,
spin_lock(&clp->cl_lock);
rcu_read_lock();
inode = nfs_layout_find_inode_by_stateid(clp, stateid);
- if (!inode)
+ if (inode == ERR_PTR(-ENOENT))
inode = nfs_layout_find_inode_by_fh(clp, fh);
rcu_read_unlock();
spin_unlock(&clp->cl_lock);
@@ -252,8 +254,11 @@ static u32 initiate_file_draining(struct nfs_client *clp,
LIST_HEAD(free_me_list);
ino = nfs_layout_find_inode(clp, &args->cbl_fh, &args->cbl_stateid);
- if (!ino)
- goto out;
+ if (IS_ERR(ino)) {
+ if (ino == ERR_PTR(-EAGAIN))
+ rv = NFS4ERR_DELAY;
+ goto out_noput;
+ }
pnfs_layoutcommit_inode(ino, false);
@@ -299,9 +304,10 @@ unlock:
nfs_commit_inode(ino, 0);
pnfs_put_layout_hdr(lo);
out:
+ nfs_iput_and_deactive(ino);
+out_noput:
trace_nfs4_cb_layoutrecall_file(clp, &args->cbl_fh, ino,
&args->cbl_stateid, -rv);
- nfs_iput_and_deactive(ino);
return rv;
}
@@ -322,6 +328,8 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
static u32 do_callback_layoutrecall(struct nfs_client *clp,
struct cb_layoutrecallargs *args)
{
+ write_seqcount_begin(&clp->cl_callback_count);
+ write_seqcount_end(&clp->cl_callback_count);
if (args->cbl_recall_type == RETURN_FILE)
return initiate_file_draining(clp, args);
return initiate_bulk_draining(clp, args);
@@ -420,11 +428,8 @@ validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot,
return htonl(NFS4ERR_SEQ_FALSE_RETRY);
}
- /* Wraparound */
- if (unlikely(slot->seq_nr == 0xFFFFFFFFU)) {
- if (args->csa_sequenceid == 1)
- return htonl(NFS4_OK);
- } else if (likely(args->csa_sequenceid == slot->seq_nr + 1))
+ /* Note: wraparound relies on seq_nr being of type u32 */
+ if (likely(args->csa_sequenceid == slot->seq_nr + 1))
return htonl(NFS4_OK);
/* Misordered request */
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index bbc91d7..377a616 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -969,7 +969,8 @@ struct nfs_server *nfs_create_server(struct nfs_mount_info *mount_info,
}
if (!(fattr->valid & NFS_ATTR_FATTR)) {
- error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh, fattr, NULL);
+ error = nfs_mod->rpc_ops->getattr(server, mount_info->mntfh,
+ fattr, NULL, NULL);
if (error < 0) {
dprintk("nfs_create_server: getattr error = %d\n", -error);
goto error;
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 1819d0d..f033f3a 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -404,6 +404,10 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred,
trace_nfs4_set_delegation(inode, type);
+ spin_lock(&inode->i_lock);
+ if (NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME))
+ NFS_I(inode)->cache_validity |= NFS_INO_REVAL_FORCED;
+ spin_unlock(&inode->i_lock);
out:
spin_unlock(&clp->cl_lock);
if (delegation != NULL)
@@ -483,38 +487,88 @@ out:
int nfs_client_return_marked_delegations(struct nfs_client *clp)
{
struct nfs_delegation *delegation;
+ struct nfs_delegation *prev;
struct nfs_server *server;
struct inode *inode;
+ struct inode *place_holder = NULL;
+ struct nfs_delegation *place_holder_deleg = NULL;
int err = 0;
restart:
+ /*
+ * To avoid quadratic looping we hold a reference
+ * to an inode place_holder. Each time we restart, we
+ * list nfs_servers from the server of that inode, and
+ * delegation in the server from the delegations of that
+ * inode.
+ * prev is an RCU-protected pointer to a delegation which
+ * wasn't marked for return and might be a good choice for
+ * the next place_holder.
+ */
rcu_read_lock();
- list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
- list_for_each_entry_rcu(delegation, &server->delegations,
- super_list) {
- if (!nfs_delegation_need_return(delegation))
+ prev = NULL;
+ if (place_holder)
+ server = NFS_SERVER(place_holder);
+ else
+ server = list_entry_rcu(clp->cl_superblocks.next,
+ struct nfs_server, client_link);
+ list_for_each_entry_from_rcu(server, &clp->cl_superblocks, client_link) {
+ delegation = NULL;
+ if (place_holder && server == NFS_SERVER(place_holder))
+ delegation = rcu_dereference(NFS_I(place_holder)->delegation);
+ if (!delegation || delegation != place_holder_deleg)
+ delegation = list_entry_rcu(server->delegations.next,
+ struct nfs_delegation, super_list);
+ list_for_each_entry_from_rcu(delegation, &server->delegations, super_list) {
+ struct inode *to_put = NULL;
+
+ if (!nfs_delegation_need_return(delegation)) {
+ prev = delegation;
continue;
+ }
if (!nfs_sb_active(server->super))
- continue;
+ break; /* continue in outer loop */
+
+ if (prev) {
+ struct inode *tmp;
+
+ tmp = nfs_delegation_grab_inode(prev);
+ if (tmp) {
+ to_put = place_holder;
+ place_holder = tmp;
+ place_holder_deleg = prev;
+ }
+ }
+
inode = nfs_delegation_grab_inode(delegation);
if (inode == NULL) {
rcu_read_unlock();
+ if (to_put)
+ iput(to_put);
nfs_sb_deactive(server->super);
goto restart;
}
delegation = nfs_start_delegation_return_locked(NFS_I(inode));
rcu_read_unlock();
+ if (to_put)
+ iput(to_put);
+
err = nfs_end_delegation_return(inode, delegation, 0);
iput(inode);
nfs_sb_deactive(server->super);
+ cond_resched();
if (!err)
goto restart;
set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
+ if (place_holder)
+ iput(place_holder);
return err;
}
}
rcu_read_unlock();
+ if (place_holder)
+ iput(place_holder);
return 0;
}
@@ -802,12 +856,14 @@ nfs_delegation_find_inode_server(struct nfs_server *server,
if (delegation->inode != NULL &&
nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
res = igrab(delegation->inode);
+ spin_unlock(&delegation->lock);
+ if (res != NULL)
+ return res;
+ return ERR_PTR(-EAGAIN);
}
spin_unlock(&delegation->lock);
- if (res != NULL)
- break;
}
- return res;
+ return ERR_PTR(-ENOENT);
}
/**
@@ -822,16 +878,18 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp,
const struct nfs_fh *fhandle)
{
struct nfs_server *server;
- struct inode *res = NULL;
+ struct inode *res;
rcu_read_lock();
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
res = nfs_delegation_find_inode_server(server, fhandle);
- if (res != NULL)
- break;
+ if (res != ERR_PTR(-ENOENT)) {
+ rcu_read_unlock();
+ return res;
+ }
}
rcu_read_unlock();
- return res;
+ return ERR_PTR(-ENOENT);
}
static void nfs_delegation_mark_reclaim_server(struct nfs_server *server)
@@ -887,7 +945,7 @@ restart:
&delegation->flags) == 0)
continue;
if (!nfs_sb_active(server->super))
- continue;
+ break; /* continue in outer loop */
inode = nfs_delegation_grab_inode(delegation);
if (inode == NULL) {
rcu_read_unlock();
@@ -904,6 +962,7 @@ restart:
}
iput(inode);
nfs_sb_deactive(server->super);
+ cond_resched();
goto restart;
}
}
@@ -995,7 +1054,7 @@ restart:
&delegation->flags) == 0)
continue;
if (!nfs_sb_active(server->super))
- continue;
+ break; /* continue in outer loop */
inode = nfs_delegation_grab_inode(delegation);
if (inode == NULL) {
rcu_read_unlock();
@@ -1020,6 +1079,7 @@ restart:
}
iput(inode);
nfs_sb_deactive(server->super);
+ cond_resched();
goto restart;
}
}
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 73f8b43..7a9c144 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1012,13 +1012,25 @@ int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags)
if (IS_AUTOMOUNT(inode))
return 0;
+
+ if (flags & LOOKUP_OPEN) {
+ switch (inode->i_mode & S_IFMT) {
+ case S_IFREG:
+ /* A NFSv4 OPEN will revalidate later */
+ if (server->caps & NFS_CAP_ATOMIC_OPEN)
+ goto out;
+ /* Fallthrough */
+ case S_IFDIR:
+ if (server->flags & NFS_MOUNT_NOCTO)
+ break;
+ /* NFS close-to-open cache consistency validation */
+ goto out_force;
+ }
+ }
+
/* VFS wants an on-the-wire revalidation */
if (flags & LOOKUP_REVAL)
goto out_force;
- /* This is an open(2) */
- if ((flags & LOOKUP_OPEN) && !(server->flags & NFS_MOUNT_NOCTO) &&
- (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
- goto out_force;
out:
return (inode->i_nlink == 0) ? -ENOENT : 0;
out_force:
@@ -1039,13 +1051,15 @@ out_force:
*
* If LOOKUP_RCU prevents us from performing a full check, return 1
* suggesting a reval is needed.
+ *
+ * Note that when creating a new file, or looking up a rename target,
+ * then it shouldn't be necessary to revalidate a negative dentry.
*/
static inline
int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
unsigned int flags)
{
- /* Don't revalidate a negative dentry if we're creating a new file */
- if (flags & LOOKUP_CREATE)
+ if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
return 0;
if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG)
return 1;
@@ -1106,7 +1120,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
goto out_set_verifier;
/* Force a full look up iff the parent directory has changed */
- if (!nfs_is_exclusive_create(dir, flags) &&
+ if (!(flags & (LOOKUP_EXCL | LOOKUP_REVAL)) &&
nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) {
error = nfs_lookup_verify_inode(inode, flags);
if (error) {
@@ -1270,11 +1284,13 @@ static void nfs_drop_nlink(struct inode *inode)
{
spin_lock(&inode->i_lock);
/* drop the inode if we're reasonably sure this is the last link */
- if (inode->i_nlink == 1)
- clear_nlink(inode);
+ if (inode->i_nlink > 0)
+ drop_nlink(inode);
+ NFS_I(inode)->attr_gencount = nfs_inc_attr_generation_counter();
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
| NFS_INO_INVALID_CTIME
- | NFS_INO_INVALID_OTHER;
+ | NFS_INO_INVALID_OTHER
+ | NFS_INO_REVAL_FORCED;
spin_unlock(&inode->i_lock);
}
@@ -1335,7 +1351,7 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
* If we're doing an exclusive create, optimize away the lookup
* but don't hash the dentry.
*/
- if (nfs_is_exclusive_create(dir, flags))
+ if (nfs_is_exclusive_create(dir, flags) || flags & LOOKUP_RENAME_TARGET)
return NULL;
res = ERR_PTR(-ENOMEM);
@@ -1640,7 +1656,8 @@ int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
if (!(fattr->valid & NFS_ATTR_FATTR)) {
struct nfs_server *server = NFS_SB(dentry->d_sb);
- error = server->nfs_client->rpc_ops->getattr(server, fhandle, fattr, NULL);
+ error = server->nfs_client->rpc_ops->getattr(server, fhandle,
+ fattr, NULL, NULL);
if (error < 0)
goto out_error;
}
@@ -2036,7 +2053,15 @@ int nfs_rename(struct inode *old_dir, struct dentry *old_dentry,
} else
error = task->tk_status;
rpc_put_task(task);
- nfs_mark_for_revalidate(old_inode);
+ /* Ensure the inode attributes are revalidated */
+ if (error == 0) {
+ spin_lock(&old_inode->i_lock);
+ NFS_I(old_inode)->attr_gencount = nfs_inc_attr_generation_counter();
+ NFS_I(old_inode)->cache_validity |= NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_CTIME
+ | NFS_INO_REVAL_FORCED;
+ spin_unlock(&old_inode->i_lock);
+ }
out:
if (rehash)
d_rehash(rehash);
diff --git a/fs/nfs/export.c b/fs/nfs/export.c
index ab5de32..deecb67 100644
--- a/fs/nfs/export.c
+++ b/fs/nfs/export.c
@@ -102,7 +102,7 @@ nfs_fh_to_dentry(struct super_block *sb, struct fid *fid,
}
rpc_ops = NFS_SB(sb)->nfs_client->rpc_ops;
- ret = rpc_ops->getattr(NFS_SB(sb), server_fh, fattr, label);
+ ret = rpc_ops->getattr(NFS_SB(sb), server_fh, fattr, label, NULL);
if (ret) {
dprintk("%s: getattr failed %d\n", __func__, ret);
dentry = ERR_PTR(ret);
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index c75ad98..8f00379 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -461,7 +461,7 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
fh_count = be32_to_cpup(p);
fls->mirror_array[i]->fh_versions =
- kzalloc(fh_count * sizeof(struct nfs_fh),
+ kcalloc(fh_count, sizeof(struct nfs_fh),
gfp_flags);
if (fls->mirror_array[i]->fh_versions == NULL) {
rc = -ENOMEM;
@@ -1243,17 +1243,18 @@ static int ff_layout_read_done_cb(struct rpc_task *task,
hdr->ds_clp, hdr->lseg,
hdr->pgio_mirror_idx);
+ clear_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
+ clear_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
switch (err) {
case -NFS4ERR_RESET_TO_PNFS:
if (ff_layout_choose_best_ds_for_read(hdr->lseg,
hdr->pgio_mirror_idx + 1,
&hdr->pgio_mirror_idx))
goto out_eagain;
- ff_layout_read_record_layoutstats_done(task, hdr);
- pnfs_read_resend_pnfs(hdr);
+ set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
return task->tk_status;
case -NFS4ERR_RESET_TO_MDS:
- ff_layout_reset_read(hdr);
+ set_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
return task->tk_status;
case -EAGAIN:
goto out_eagain;
@@ -1403,6 +1404,10 @@ static void ff_layout_read_release(void *data)
struct nfs_pgio_header *hdr = data;
ff_layout_read_record_layoutstats_done(&hdr->task, hdr);
+ if (test_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags))
+ pnfs_read_resend_pnfs(hdr);
+ else if (test_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags))
+ ff_layout_reset_read(hdr);
pnfs_generic_rw_release(data);
}
@@ -1423,12 +1428,14 @@ static int ff_layout_write_done_cb(struct rpc_task *task,
hdr->ds_clp, hdr->lseg,
hdr->pgio_mirror_idx);
+ clear_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
+ clear_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
switch (err) {
case -NFS4ERR_RESET_TO_PNFS:
- ff_layout_reset_write(hdr, true);
+ set_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags);
return task->tk_status;
case -NFS4ERR_RESET_TO_MDS:
- ff_layout_reset_write(hdr, false);
+ set_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags);
return task->tk_status;
case -EAGAIN:
return -EAGAIN;
@@ -1575,6 +1582,10 @@ static void ff_layout_write_release(void *data)
struct nfs_pgio_header *hdr = data;
ff_layout_write_record_layoutstats_done(&hdr->task, hdr);
+ if (test_bit(NFS_IOHDR_RESEND_PNFS, &hdr->flags))
+ ff_layout_reset_write(hdr, true);
+ else if (test_bit(NFS_IOHDR_RESEND_MDS, &hdr->flags))
+ ff_layout_reset_write(hdr, false);
pnfs_generic_rw_release(data);
}
@@ -2347,6 +2358,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = {
.id = LAYOUT_FLEX_FILES,
.name = "LAYOUT_FLEX_FILES",
.owner = THIS_MODULE,
+ .flags = PNFS_LAYOUTGET_ON_OPEN,
.set_layoutdriver = ff_layout_set_layoutdriver,
.alloc_layout_hdr = ff_layout_alloc_layout_hdr,
.free_layout_hdr = ff_layout_free_layout_hdr,
diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
index d62279d..59aa049 100644
--- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c
+++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c
@@ -99,7 +99,8 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
version_count = be32_to_cpup(p);
dprintk("%s: version count %d\n", __func__, version_count);
- ds_versions = kzalloc(version_count * sizeof(struct nfs4_ff_ds_version),
+ ds_versions = kcalloc(version_count,
+ sizeof(struct nfs4_ff_ds_version),
gfp_flags);
if (!ds_versions)
goto out_scratch;
diff --git a/fs/nfs/fscache-index.c b/fs/nfs/fscache-index.c
index 1c5d8d3..666415d 100644
--- a/fs/nfs/fscache-index.c
+++ b/fs/nfs/fscache-index.c
@@ -88,8 +88,8 @@ enum fscache_checkaux nfs_fscache_inode_check_aux(void *cookie_netfs_data,
return FSCACHE_CHECKAUX_OBSOLETE;
memset(&auxdata, 0, sizeof(auxdata));
- auxdata.mtime = nfsi->vfs_inode.i_mtime;
- auxdata.ctime = nfsi->vfs_inode.i_ctime;
+ auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime);
+ auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime);
if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index b55fc79..4dc8878 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -237,8 +237,8 @@ void nfs_fscache_init_inode(struct inode *inode)
return;
memset(&auxdata, 0, sizeof(auxdata));
- auxdata.mtime = nfsi->vfs_inode.i_mtime;
- auxdata.ctime = nfsi->vfs_inode.i_ctime;
+ auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime);
+ auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime);
if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
@@ -262,8 +262,8 @@ void nfs_fscache_clear_inode(struct inode *inode)
dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);
memset(&auxdata, 0, sizeof(auxdata));
- auxdata.mtime = nfsi->vfs_inode.i_mtime;
- auxdata.ctime = nfsi->vfs_inode.i_ctime;
+ auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime);
+ auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime);
fscache_relinquish_cookie(cookie, &auxdata, false);
nfsi->fscache = NULL;
}
@@ -304,8 +304,8 @@ void nfs_fscache_open_file(struct inode *inode, struct file *filp)
return;
memset(&auxdata, 0, sizeof(auxdata));
- auxdata.mtime = nfsi->vfs_inode.i_mtime;
- auxdata.ctime = nfsi->vfs_inode.i_ctime;
+ auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime);
+ auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime);
if (inode_is_open_for_write(inode)) {
dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index bd15d0b..b65aee4 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -195,10 +195,16 @@ bool nfs_check_cache_invalid(struct inode *inode, unsigned long flags)
static void nfs_set_cache_invalid(struct inode *inode, unsigned long flags)
{
struct nfs_inode *nfsi = NFS_I(inode);
- bool have_delegation = nfs_have_delegated_attributes(inode);
+ bool have_delegation = NFS_PROTO(inode)->have_delegation(inode, FMODE_READ);
+
+ if (have_delegation) {
+ if (!(flags & NFS_INO_REVAL_FORCED))
+ flags &= ~NFS_INO_INVALID_OTHER;
+ flags &= ~(NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_SIZE
+ | NFS_INO_REVAL_PAGECACHE);
+ }
- if (have_delegation)
- flags &= ~(NFS_INO_INVALID_CHANGE|NFS_INO_REVAL_PAGECACHE);
if (inode->i_mapping->nrpages == 0)
flags &= ~NFS_INO_INVALID_DATA;
nfsi->cache_validity |= flags;
@@ -448,6 +454,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
/* We can't support update_atime(), since the server will reset it */
inode->i_flags |= S_NOATIME|S_NOCMTIME;
inode->i_mode = fattr->mode;
+ nfsi->cache_validity = 0;
if ((fattr->valid & NFS_ATTR_FATTR_MODE) == 0
&& nfs_server_capable(inode, NFS_CAP_MODE))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_OTHER);
@@ -494,15 +501,15 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
nfsi->read_cache_jiffies = fattr->time_start;
nfsi->attr_gencount = fattr->gencount;
if (fattr->valid & NFS_ATTR_FATTR_ATIME)
- inode->i_atime = fattr->atime;
+ inode->i_atime = timespec_to_timespec64(fattr->atime);
else if (nfs_server_capable(inode, NFS_CAP_ATIME))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME);
if (fattr->valid & NFS_ATTR_FATTR_MTIME)
- inode->i_mtime = fattr->mtime;
+ inode->i_mtime = timespec_to_timespec64(fattr->mtime);
else if (nfs_server_capable(inode, NFS_CAP_MTIME))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
if (fattr->valid & NFS_ATTR_FATTR_CTIME)
- inode->i_ctime = fattr->ctime;
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
else if (nfs_server_capable(inode, NFS_CAP_CTIME))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_CTIME);
if (fattr->valid & NFS_ATTR_FATTR_CHANGE)
@@ -534,6 +541,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st
inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used);
}
+ if (nfsi->cache_validity != 0)
+ nfsi->cache_validity |= NFS_INO_REVAL_FORCED;
+
nfs_setsecurity(inode, fattr, label);
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
@@ -667,9 +677,13 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
spin_lock(&inode->i_lock);
NFS_I(inode)->attr_gencount = fattr->gencount;
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_CTIME);
+ if ((attr->ia_valid & ATTR_SIZE) != 0) {
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
+ nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
+ nfs_vmtruncate(inode, attr->ia_size);
+ }
if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
+ NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_CTIME;
if ((attr->ia_valid & ATTR_MODE) != 0) {
int mode = attr->ia_mode & S_IALLUGO;
mode |= inode->i_mode & ~S_IALLUGO;
@@ -679,13 +693,45 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
inode->i_uid = attr->ia_uid;
if ((attr->ia_valid & ATTR_GID) != 0)
inode->i_gid = attr->ia_gid;
+ if (fattr->valid & NFS_ATTR_FATTR_CTIME)
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_CTIME);
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS
| NFS_INO_INVALID_ACL);
}
- if ((attr->ia_valid & ATTR_SIZE) != 0) {
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
- nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
- nfs_vmtruncate(inode, attr->ia_size);
+ if (attr->ia_valid & (ATTR_ATIME_SET|ATTR_ATIME)) {
+ NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_ATIME
+ | NFS_INO_INVALID_CTIME);
+ if (fattr->valid & NFS_ATTR_FATTR_ATIME)
+ inode->i_atime = timespec_to_timespec64(fattr->atime);
+ else if (attr->ia_valid & ATTR_ATIME_SET)
+ inode->i_atime = attr->ia_atime;
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME);
+
+ if (fattr->valid & NFS_ATTR_FATTR_CTIME)
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_CTIME);
+ }
+ if (attr->ia_valid & (ATTR_MTIME_SET|ATTR_MTIME)) {
+ NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_MTIME
+ | NFS_INO_INVALID_CTIME);
+ if (fattr->valid & NFS_ATTR_FATTR_MTIME)
+ inode->i_mtime = timespec_to_timespec64(fattr->mtime);
+ else if (attr->ia_valid & ATTR_MTIME_SET)
+ inode->i_mtime = attr->ia_mtime;
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
+
+ if (fattr->valid & NFS_ATTR_FATTR_CTIME)
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_CTIME);
}
if (fattr->valid)
nfs_update_inode(inode, fattr);
@@ -1097,7 +1143,8 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
goto out;
}
- status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr, label);
+ status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), fattr,
+ label, inode);
if (status != 0) {
dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Lu) getattr failed, error=%d\n",
inode->i_sb->s_id,
@@ -1304,6 +1351,8 @@ static bool nfs_file_has_buffered_writers(struct nfs_inode *nfsi)
static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
{
+ struct timespec ts;
+
if ((fattr->valid & NFS_ATTR_FATTR_PRECHANGE)
&& (fattr->valid & NFS_ATTR_FATTR_CHANGE)
&& inode_eq_iversion_raw(inode, fattr->pre_change_attr)) {
@@ -1312,16 +1361,18 @@ static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr)
nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
}
/* If we have atomic WCC data, we may update some attributes */
+ ts = timespec64_to_timespec(inode->i_ctime);
if ((fattr->valid & NFS_ATTR_FATTR_PRECTIME)
&& (fattr->valid & NFS_ATTR_FATTR_CTIME)
- && timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) {
- memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+ && timespec_equal(&ts, &fattr->pre_ctime)) {
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
}
+ ts = timespec64_to_timespec(inode->i_mtime);
if ((fattr->valid & NFS_ATTR_FATTR_PREMTIME)
&& (fattr->valid & NFS_ATTR_FATTR_MTIME)
- && timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) {
- memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
+ && timespec_equal(&ts, &fattr->pre_mtime)) {
+ inode->i_mtime = timespec_to_timespec64(fattr->mtime);
if (S_ISDIR(inode->i_mode))
nfs_set_cache_invalid(inode, NFS_INO_INVALID_DATA);
}
@@ -1347,10 +1398,11 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
struct nfs_inode *nfsi = NFS_I(inode);
loff_t cur_size, new_isize;
unsigned long invalid = 0;
+ struct timespec ts;
-
- if (nfs_have_delegated_attributes(inode))
+ if (NFS_PROTO(inode)->have_delegation(inode, FMODE_READ))
return 0;
+
/* Has the inode gone and changed behind our back? */
if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid)
return -ESTALE;
@@ -1363,10 +1415,12 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
invalid |= NFS_INO_INVALID_CHANGE
| NFS_INO_REVAL_PAGECACHE;
- if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&inode->i_mtime, &fattr->mtime))
+ ts = timespec64_to_timespec(inode->i_mtime);
+ if ((fattr->valid & NFS_ATTR_FATTR_MTIME) && !timespec_equal(&ts, &fattr->mtime))
invalid |= NFS_INO_INVALID_MTIME;
- if ((fattr->valid & NFS_ATTR_FATTR_CTIME) && !timespec_equal(&inode->i_ctime, &fattr->ctime))
+ ts = timespec64_to_timespec(inode->i_ctime);
+ if ((fattr->valid & NFS_ATTR_FATTR_CTIME) && !timespec_equal(&ts, &fattr->ctime))
invalid |= NFS_INO_INVALID_CTIME;
if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
@@ -1396,11 +1450,12 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
if ((fattr->valid & NFS_ATTR_FATTR_NLINK) && inode->i_nlink != fattr->nlink)
invalid |= NFS_INO_INVALID_OTHER;
- if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&inode->i_atime, &fattr->atime))
+ ts = timespec64_to_timespec(inode->i_atime);
+ if ((fattr->valid & NFS_ATTR_FATTR_ATIME) && !timespec_equal(&ts, &fattr->atime))
invalid |= NFS_INO_INVALID_ATIME;
if (invalid != 0)
- nfs_set_cache_invalid(inode, invalid | NFS_INO_REVAL_FORCED);
+ nfs_set_cache_invalid(inode, invalid);
nfsi->read_cache_jiffies = fattr->time_start;
return 0;
@@ -1629,7 +1684,8 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr)
nfs_fattr_set_barrier(fattr);
status = nfs_post_op_update_inode_locked(inode, fattr,
NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_CTIME);
+ | NFS_INO_INVALID_CTIME
+ | NFS_INO_REVAL_FORCED);
spin_unlock(&inode->i_lock);
return status;
@@ -1667,12 +1723,12 @@ int nfs_post_op_update_inode_force_wcc_locked(struct inode *inode, struct nfs_fa
}
if ((fattr->valid & NFS_ATTR_FATTR_CTIME) != 0 &&
(fattr->valid & NFS_ATTR_FATTR_PRECTIME) == 0) {
- memcpy(&fattr->pre_ctime, &inode->i_ctime, sizeof(fattr->pre_ctime));
+ fattr->pre_ctime = timespec64_to_timespec(inode->i_ctime);
fattr->valid |= NFS_ATTR_FATTR_PRECTIME;
}
if ((fattr->valid & NFS_ATTR_FATTR_MTIME) != 0 &&
(fattr->valid & NFS_ATTR_FATTR_PREMTIME) == 0) {
- memcpy(&fattr->pre_mtime, &inode->i_mtime, sizeof(fattr->pre_mtime));
+ fattr->pre_mtime = timespec64_to_timespec(inode->i_mtime);
fattr->valid |= NFS_ATTR_FATTR_PREMTIME;
}
if ((fattr->valid & NFS_ATTR_FATTR_SIZE) != 0 &&
@@ -1746,6 +1802,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
unsigned long save_cache_validity;
bool have_writers = nfs_file_has_buffered_writers(nfsi);
bool cache_revalidated = true;
+ bool attr_changed = false;
+ bool have_delegation;
dfprintk(VFS, "NFS: %s(%s/%lu fh_crc=0x%08x ct=%d info=0x%x)\n",
__func__, inode->i_sb->s_id, inode->i_ino,
@@ -1780,6 +1838,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
!IS_AUTOMOUNT(inode))
server->fsid = fattr->fsid;
+ /* Save the delegation state before clearing cache_validity */
+ have_delegation = nfs_have_delegated_attributes(inode);
+
/*
* Update the read time so we don't revalidate too often.
*/
@@ -1802,12 +1863,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
/* More cache consistency checks */
if (fattr->valid & NFS_ATTR_FATTR_CHANGE) {
if (!inode_eq_iversion_raw(inode, fattr->change_attr)) {
- dprintk("NFS: change_attr change on server for file %s/%ld\n",
- inode->i_sb->s_id, inode->i_ino);
/* Could it be a race with writeback? */
- if (!have_writers) {
- invalid |= NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_DATA
+ if (!(have_writers || have_delegation)) {
+ invalid |= NFS_INO_INVALID_DATA
| NFS_INO_INVALID_ACCESS
| NFS_INO_INVALID_ACL;
/* Force revalidate of all attributes */
@@ -1817,8 +1875,12 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
| NFS_INO_INVALID_OTHER;
if (S_ISDIR(inode->i_mode))
nfs_force_lookup_revalidate(inode);
+ dprintk("NFS: change_attr change on server for file %s/%ld\n",
+ inode->i_sb->s_id,
+ inode->i_ino);
}
inode_set_iversion_raw(inode, fattr->change_attr);
+ attr_changed = true;
}
} else {
nfsi->cache_validity |= save_cache_validity &
@@ -1829,7 +1891,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
}
if (fattr->valid & NFS_ATTR_FATTR_MTIME) {
- memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime));
+ inode->i_mtime = timespec_to_timespec64(fattr->mtime);
} else if (server->caps & NFS_CAP_MTIME) {
nfsi->cache_validity |= save_cache_validity &
(NFS_INO_INVALID_MTIME
@@ -1838,7 +1900,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
}
if (fattr->valid & NFS_ATTR_FATTR_CTIME) {
- memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+ inode->i_ctime = timespec_to_timespec64(fattr->ctime);
} else if (server->caps & NFS_CAP_CTIME) {
nfsi->cache_validity |= save_cache_validity &
(NFS_INO_INVALID_CTIME
@@ -1850,13 +1912,14 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
new_isize = nfs_size_to_loff_t(fattr->size);
cur_isize = i_size_read(inode);
- if (new_isize != cur_isize) {
+ if (new_isize != cur_isize && !have_delegation) {
/* Do we perhaps have any outstanding writes, or has
* the file grown beyond our last write? */
if (!nfs_have_writebacks(inode) || new_isize > cur_isize) {
i_size_write(inode, new_isize);
if (!have_writers)
invalid |= NFS_INO_INVALID_DATA;
+ attr_changed = true;
}
dprintk("NFS: isize change on server for file %s/%ld "
"(%Ld to %Ld)\n",
@@ -1875,7 +1938,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_ATIME)
- memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
+ inode->i_atime = timespec_to_timespec64(fattr->atime);
else if (server->caps & NFS_CAP_ATIME) {
nfsi->cache_validity |= save_cache_validity &
(NFS_INO_INVALID_ATIME
@@ -1889,14 +1952,12 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
newmode |= fattr->mode & S_IALLUGO;
inode->i_mode = newmode;
invalid |= NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER;
+ | NFS_INO_INVALID_ACL;
+ attr_changed = true;
}
} else if (server->caps & NFS_CAP_MODE) {
nfsi->cache_validity |= save_cache_validity &
- (NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER
+ (NFS_INO_INVALID_OTHER
| NFS_INO_REVAL_FORCED);
cache_revalidated = false;
}
@@ -1904,15 +1965,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_OWNER) {
if (!uid_eq(inode->i_uid, fattr->uid)) {
invalid |= NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER;
+ | NFS_INO_INVALID_ACL;
inode->i_uid = fattr->uid;
+ attr_changed = true;
}
} else if (server->caps & NFS_CAP_OWNER) {
nfsi->cache_validity |= save_cache_validity &
- (NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER
+ (NFS_INO_INVALID_OTHER
| NFS_INO_REVAL_FORCED);
cache_revalidated = false;
}
@@ -1920,25 +1979,23 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (fattr->valid & NFS_ATTR_FATTR_GROUP) {
if (!gid_eq(inode->i_gid, fattr->gid)) {
invalid |= NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER;
+ | NFS_INO_INVALID_ACL;
inode->i_gid = fattr->gid;
+ attr_changed = true;
}
} else if (server->caps & NFS_CAP_OWNER_GROUP) {
nfsi->cache_validity |= save_cache_validity &
- (NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_INVALID_OTHER
+ (NFS_INO_INVALID_OTHER
| NFS_INO_REVAL_FORCED);
cache_revalidated = false;
}
if (fattr->valid & NFS_ATTR_FATTR_NLINK) {
if (inode->i_nlink != fattr->nlink) {
- invalid |= NFS_INO_INVALID_OTHER;
if (S_ISDIR(inode->i_mode))
invalid |= NFS_INO_INVALID_DATA;
set_nlink(inode, fattr->nlink);
+ attr_changed = true;
}
} else if (server->caps & NFS_CAP_NLINK) {
nfsi->cache_validity |= save_cache_validity &
@@ -1958,7 +2015,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
cache_revalidated = false;
/* Update attrtimeo value if we're out of the unstable period */
- if (invalid & NFS_INO_INVALID_ATTR) {
+ if (attr_changed) {
invalid &= ~NFS_INO_INVALID_ATTR;
nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE);
nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
@@ -1984,9 +2041,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)
|| S_ISLNK(inode->i_mode)))
invalid &= ~NFS_INO_INVALID_DATA;
- if (!NFS_PROTO(inode)->have_delegation(inode, FMODE_READ) ||
- (save_cache_validity & NFS_INO_REVAL_FORCED))
- nfs_set_cache_invalid(inode, invalid);
+ nfs_set_cache_invalid(inode, invalid);
return 0;
out_err:
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c
index 85e4b4a..350675e 100644
--- a/fs/nfs/nfs2xdr.c
+++ b/fs/nfs/nfs2xdr.c
@@ -354,6 +354,7 @@ static __be32 *xdr_time_not_set(__be32 *p)
static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
{
+ struct timespec ts;
__be32 *p;
p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
@@ -375,17 +376,21 @@ static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
else
*p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
- if (attr->ia_valid & ATTR_ATIME_SET)
- p = xdr_encode_time(p, &attr->ia_atime);
- else if (attr->ia_valid & ATTR_ATIME)
- p = xdr_encode_current_server_time(p, &attr->ia_atime);
- else
+ if (attr->ia_valid & ATTR_ATIME_SET) {
+ ts = timespec64_to_timespec(attr->ia_atime);
+ p = xdr_encode_time(p, &ts);
+ } else if (attr->ia_valid & ATTR_ATIME) {
+ ts = timespec64_to_timespec(attr->ia_atime);
+ p = xdr_encode_current_server_time(p, &ts);
+ } else
p = xdr_time_not_set(p);
- if (attr->ia_valid & ATTR_MTIME_SET)
- xdr_encode_time(p, &attr->ia_mtime);
- else if (attr->ia_valid & ATTR_MTIME)
- xdr_encode_current_server_time(p, &attr->ia_mtime);
- else
+ if (attr->ia_valid & ATTR_MTIME_SET) {
+ ts = timespec64_to_timespec(attr->ia_atime);
+ xdr_encode_time(p, &ts);
+ } else if (attr->ia_valid & ATTR_MTIME) {
+ ts = timespec64_to_timespec(attr->ia_mtime);
+ xdr_encode_current_server_time(p, &ts);
+ } else
xdr_time_not_set(p);
}
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index eadf1ab..ec8a9ef 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -101,7 +101,8 @@ nfs3_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
*/
static int
nfs3_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr, struct nfs4_label *label)
+ struct nfs_fattr *fattr, struct nfs4_label *label,
+ struct inode *inode)
{
struct rpc_message msg = {
.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR],
@@ -414,7 +415,9 @@ out:
}
static void
-nfs3_proc_unlink_setup(struct rpc_message *msg, struct dentry *dentry)
+nfs3_proc_unlink_setup(struct rpc_message *msg,
+ struct dentry *dentry,
+ struct inode *inode)
{
msg->rpc_proc = &nfs3_procedures[NFS3PROC_REMOVE];
}
@@ -823,7 +826,8 @@ static int nfs3_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
}
static void nfs3_proc_write_setup(struct nfs_pgio_header *hdr,
- struct rpc_message *msg)
+ struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
msg->rpc_proc = &nfs3_procedures[NFS3PROC_WRITE];
}
@@ -844,7 +848,8 @@ static int nfs3_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
return 0;
}
-static void nfs3_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
+static void nfs3_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
msg->rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT];
}
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 09ee36d..64e4fa3 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -561,6 +561,7 @@ static __be32 *xdr_decode_nfstime3(__be32 *p, struct timespec *timep)
*/
static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
{
+ struct timespec ts;
u32 nbytes;
__be32 *p;
@@ -610,8 +611,10 @@ static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
*p++ = xdr_zero;
if (attr->ia_valid & ATTR_ATIME_SET) {
+ struct timespec ts;
*p++ = xdr_two;
- p = xdr_encode_nfstime3(p, &attr->ia_atime);
+ ts = timespec64_to_timespec(attr->ia_atime);
+ p = xdr_encode_nfstime3(p, &ts);
} else if (attr->ia_valid & ATTR_ATIME) {
*p++ = xdr_one;
} else
@@ -619,7 +622,8 @@ static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
if (attr->ia_valid & ATTR_MTIME_SET) {
*p++ = xdr_two;
- xdr_encode_nfstime3(p, &attr->ia_mtime);
+ ts = timespec64_to_timespec(attr->ia_mtime);
+ xdr_encode_nfstime3(p, &ts);
} else if (attr->ia_valid & ATTR_MTIME) {
*p = xdr_one;
} else
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
index 9c37444..5f59b6f 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -370,6 +370,10 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata)
switch (task->tk_status) {
case 0:
break;
+ case -NFS4ERR_BADHANDLE:
+ case -ESTALE:
+ pnfs_destroy_layout(NFS_I(inode));
+ break;
case -NFS4ERR_EXPIRED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_DELEG_REVOKED:
@@ -462,7 +466,7 @@ int nfs42_proc_layoutstats_generic(struct nfs_server *server,
nfs42_layoutstat_release(data);
return -EAGAIN;
}
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0, 0);
task = rpc_run_task(&task_setup);
if (IS_ERR(task))
return PTR_ERR(task);
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index b374f68..137e18a 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -212,6 +212,31 @@ struct nfs4_state_recovery_ops {
struct rpc_cred *);
};
+struct nfs4_opendata {
+ struct kref kref;
+ struct nfs_openargs o_arg;
+ struct nfs_openres o_res;
+ struct nfs_open_confirmargs c_arg;
+ struct nfs_open_confirmres c_res;
+ struct nfs4_string owner_name;
+ struct nfs4_string group_name;
+ struct nfs4_label *a_label;
+ struct nfs_fattr f_attr;
+ struct nfs4_label *f_label;
+ struct dentry *dir;
+ struct dentry *dentry;
+ struct nfs4_state_owner *owner;
+ struct nfs4_state *state;
+ struct iattr attrs;
+ struct nfs4_layoutget *lgp;
+ unsigned long timestamp;
+ bool rpc_done;
+ bool file_created;
+ bool is_recover;
+ bool cancelled;
+ int rpc_status;
+};
+
struct nfs4_add_xprt_data {
struct nfs_client *clp;
struct rpc_cred *cred;
@@ -251,7 +276,7 @@ extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception
extern int nfs4_call_sync(struct rpc_clnt *, struct nfs_server *,
struct rpc_message *, struct nfs4_sequence_args *,
struct nfs4_sequence_res *, int);
-extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int);
+extern void nfs4_init_sequence(struct nfs4_sequence_args *, struct nfs4_sequence_res *, int, int);
extern int nfs4_proc_setclientid(struct nfs_client *, u32, unsigned short, struct rpc_cred *, struct nfs4_setclientid_res *);
extern int nfs4_proc_setclientid_confirm(struct nfs_client *, struct nfs4_setclientid_res *arg, struct rpc_cred *);
extern int nfs4_proc_get_rootfh(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *, bool);
diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c
index 22dc30a..b6f9d84b 100644
--- a/fs/nfs/nfs4idmap.c
+++ b/fs/nfs/nfs4idmap.c
@@ -343,7 +343,7 @@ static ssize_t nfs_idmap_lookup_name(__u32 id, const char *type, char *buf,
int id_len;
ssize_t ret;
- id_len = snprintf(id_str, sizeof(id_str), "%u", id);
+ id_len = nfs_map_numeric_to_string(id, id_str, sizeof(id_str));
ret = nfs_idmap_get_key(id_str, id_len, type, buf, buflen, idmap);
if (ret < 0)
return -EINVAL;
@@ -627,7 +627,8 @@ static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
if (strcmp(upcall->im_name, im->im_name) != 0)
break;
/* Note: here we store the NUL terminator too */
- len = sprintf(id_str, "%d", im->im_id) + 1;
+ len = 1 + nfs_map_numeric_to_string(im->im_id, id_str,
+ sizeof(id_str));
ret = nfs_idmap_instantiate(key, authkey, id_str, len);
break;
case IDMAP_CONV_IDTONAME:
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b71757e..6dd1468 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -71,6 +71,8 @@
#define NFSDBG_FACILITY NFSDBG_PROC
+#define NFS4_BITMASK_SZ 3
+
#define NFS4_POLL_RETRY_MIN (HZ/10)
#define NFS4_POLL_RETRY_MAX (15*HZ)
@@ -86,12 +88,11 @@
| ATTR_MTIME_SET)
struct nfs4_opendata;
-static int _nfs4_proc_open(struct nfs4_opendata *data);
static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
-static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label);
-static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label);
+static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label, struct inode *inode);
+static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label, struct inode *inode);
static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
struct nfs_fattr *fattr, struct iattr *sattr,
struct nfs_open_context *ctx, struct nfs4_label *ilabel,
@@ -274,6 +275,33 @@ const u32 nfs4_fs_locations_bitmap[3] = {
| FATTR4_WORD1_MOUNTED_ON_FILEID,
};
+static void nfs4_bitmap_copy_adjust(__u32 *dst, const __u32 *src,
+ struct inode *inode)
+{
+ unsigned long cache_validity;
+
+ memcpy(dst, src, NFS4_BITMASK_SZ*sizeof(*dst));
+ if (!inode || !nfs4_have_delegation(inode, FMODE_READ))
+ return;
+
+ cache_validity = READ_ONCE(NFS_I(inode)->cache_validity);
+ if (!(cache_validity & NFS_INO_REVAL_FORCED))
+ cache_validity &= ~(NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_SIZE);
+
+ if (!(cache_validity & NFS_INO_INVALID_SIZE))
+ dst[0] &= ~FATTR4_WORD0_SIZE;
+
+ if (!(cache_validity & NFS_INO_INVALID_CHANGE))
+ dst[0] &= ~FATTR4_WORD0_CHANGE;
+}
+
+static void nfs4_bitmap_copy_adjust_setattr(__u32 *dst,
+ const __u32 *src, struct inode *inode)
+{
+ nfs4_bitmap_copy_adjust(dst, src, inode);
+}
+
static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry,
struct nfs4_readdir_arg *readdir)
{
@@ -407,6 +435,11 @@ static int nfs4_do_handle_exception(struct nfs_server *server,
switch(errorcode) {
case 0:
return 0;
+ case -NFS4ERR_BADHANDLE:
+ case -ESTALE:
+ if (inode != NULL && S_ISREG(inode->i_mode))
+ pnfs_destroy_layout(NFS_I(inode));
+ break;
case -NFS4ERR_DELEG_REVOKED:
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_EXPIRED:
@@ -608,20 +641,16 @@ struct nfs4_call_sync_data {
};
void nfs4_init_sequence(struct nfs4_sequence_args *args,
- struct nfs4_sequence_res *res, int cache_reply)
+ struct nfs4_sequence_res *res, int cache_reply,
+ int privileged)
{
args->sa_slot = NULL;
args->sa_cache_this = cache_reply;
- args->sa_privileged = 0;
+ args->sa_privileged = privileged;
res->sr_slot = NULL;
}
-static void nfs4_set_sequence_privileged(struct nfs4_sequence_args *args)
-{
- args->sa_privileged = 1;
-}
-
static void nfs40_sequence_free_slot(struct nfs4_sequence_res *res)
{
struct nfs4_slot *slot = res->sr_slot;
@@ -746,12 +775,19 @@ static int nfs41_sequence_process(struct rpc_task *task,
slot->slot_nr,
slot->seq_nr);
goto out_retry;
+ case -NFS4ERR_RETRY_UNCACHED_REP:
+ case -NFS4ERR_SEQ_FALSE_RETRY:
+ /*
+ * The server thinks we tried to replay a request.
+ * Retry the call after bumping the sequence ID.
+ */
+ goto retry_new_seq;
case -NFS4ERR_BADSLOT:
/*
* The slot id we used was probably retired. Try again
* using a different slot id.
*/
- if (slot->seq_nr < slot->table->target_highest_slotid)
+ if (slot->slot_nr < slot->table->target_highest_slotid)
goto session_recover;
goto retry_nowait;
case -NFS4ERR_SEQ_MISORDERED:
@@ -770,10 +806,6 @@ static int nfs41_sequence_process(struct rpc_task *task,
goto retry_nowait;
}
goto session_recover;
- case -NFS4ERR_SEQ_FALSE_RETRY:
- if (interrupted)
- goto retry_new_seq;
- goto session_recover;
default:
/* Just update the slot sequence no. */
slot->seq_done = 1;
@@ -1035,7 +1067,7 @@ int nfs4_call_sync(struct rpc_clnt *clnt,
struct nfs4_sequence_res *res,
int cache_reply)
{
- nfs4_init_sequence(args, res, cache_reply);
+ nfs4_init_sequence(args, res, cache_reply, 0);
return nfs4_call_sync_sequence(clnt, server, msg, args, res);
}
@@ -1064,30 +1096,6 @@ static void update_changeattr(struct inode *dir, struct nfs4_change_info *cinfo,
spin_unlock(&dir->i_lock);
}
-struct nfs4_opendata {
- struct kref kref;
- struct nfs_openargs o_arg;
- struct nfs_openres o_res;
- struct nfs_open_confirmargs c_arg;
- struct nfs_open_confirmres c_res;
- struct nfs4_string owner_name;
- struct nfs4_string group_name;
- struct nfs4_label *a_label;
- struct nfs_fattr f_attr;
- struct nfs4_label *f_label;
- struct dentry *dir;
- struct dentry *dentry;
- struct nfs4_state_owner *owner;
- struct nfs4_state *state;
- struct iattr attrs;
- unsigned long timestamp;
- bool rpc_done;
- bool file_created;
- bool is_recover;
- bool cancelled;
- int rpc_status;
-};
-
struct nfs4_open_createattrs {
struct nfs4_label *label;
struct iattr *sattr;
@@ -1268,6 +1276,7 @@ static void nfs4_opendata_free(struct kref *kref)
struct nfs4_opendata, kref);
struct super_block *sb = p->dentry->d_sb;
+ nfs4_lgopen_release(p->lgp);
nfs_free_seqid(p->o_arg.seqid);
nfs4_sequence_free_slot(&p->o_res.seq_res);
if (p->state != NULL)
@@ -2187,13 +2196,12 @@ static int _nfs4_proc_open_confirm(struct nfs4_opendata *data)
};
int status;
- nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1);
+ nfs4_init_sequence(&data->c_arg.seq_args, &data->c_res.seq_res, 1,
+ data->is_recover);
kref_get(&data->kref);
data->rpc_done = false;
data->rpc_status = 0;
data->timestamp = jiffies;
- if (data->is_recover)
- nfs4_set_sequence_privileged(&data->c_arg.seq_args);
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
return PTR_ERR(task);
@@ -2327,7 +2335,8 @@ static const struct rpc_call_ops nfs4_open_ops = {
.rpc_release = nfs4_open_release,
};
-static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
+static int nfs4_run_open_task(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
{
struct inode *dir = d_inode(data->dir);
struct nfs_server *server = NFS_SERVER(dir);
@@ -2350,15 +2359,17 @@ static int nfs4_run_open_task(struct nfs4_opendata *data, int isrecover)
};
int status;
- nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1);
kref_get(&data->kref);
data->rpc_done = false;
data->rpc_status = 0;
data->cancelled = false;
data->is_recover = false;
- if (isrecover) {
- nfs4_set_sequence_privileged(&o_arg->seq_args);
+ if (!ctx) {
+ nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 1);
data->is_recover = true;
+ } else {
+ nfs4_init_sequence(&o_arg->seq_args, &o_res->seq_res, 1, 0);
+ pnfs_lgopen_prepare(data, ctx);
}
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
@@ -2380,7 +2391,7 @@ static int _nfs4_recover_proc_open(struct nfs4_opendata *data)
struct nfs_openres *o_res = &data->o_res;
int status;
- status = nfs4_run_open_task(data, 1);
+ status = nfs4_run_open_task(data, NULL);
if (status != 0 || !data->rpc_done)
return status;
@@ -2441,7 +2452,8 @@ static int nfs4_opendata_access(struct rpc_cred *cred,
/*
* Note: On error, nfs4_proc_open will free the struct nfs4_opendata
*/
-static int _nfs4_proc_open(struct nfs4_opendata *data)
+static int _nfs4_proc_open(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
{
struct inode *dir = d_inode(data->dir);
struct nfs_server *server = NFS_SERVER(dir);
@@ -2449,7 +2461,7 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
struct nfs_openres *o_res = &data->o_res;
int status;
- status = nfs4_run_open_task(data, 0);
+ status = nfs4_run_open_task(data, ctx);
if (!data->rpc_done)
return status;
if (status != 0) {
@@ -2480,7 +2492,8 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
}
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);
+ nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr,
+ o_res->f_label, NULL);
}
return 0;
}
@@ -2800,11 +2813,11 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
seq = raw_seqcount_begin(&sp->so_reclaim_seqcount);
- ret = _nfs4_proc_open(opendata);
+ ret = _nfs4_proc_open(opendata, ctx);
if (ret != 0)
goto out;
- state = nfs4_opendata_to_nfs4_state(opendata);
+ state = _nfs4_opendata_to_nfs4_state(opendata);
ret = PTR_ERR(state);
if (IS_ERR(state))
goto out;
@@ -2838,8 +2851,12 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata,
nfs_inode_attach_open_context(ctx);
if (read_seqcount_retry(&sp->so_reclaim_seqcount, seq))
nfs4_schedule_stateid_recovery(server, state);
+ else
+ pnfs_parse_lgopen(state->inode, opendata->lgp, ctx);
}
+
out:
+ nfs4_sequence_free_slot(&opendata->o_res.seq_res);
return ret;
}
@@ -3039,7 +3056,6 @@ static int _nfs4_do_setattr(struct inode *inode,
};
struct rpc_cred *delegation_cred = NULL;
unsigned long timestamp = jiffies;
- fmode_t fmode;
bool truncate;
int status;
@@ -3047,11 +3063,12 @@ static int _nfs4_do_setattr(struct inode *inode,
/* Servers should only apply open mode checks for file size changes */
truncate = (arg->iap->ia_valid & ATTR_SIZE) ? true : false;
- fmode = truncate ? FMODE_WRITE : FMODE_READ;
+ if (!truncate)
+ goto zero_stateid;
- if (nfs4_copy_delegation_stateid(inode, fmode, &arg->stateid, &delegation_cred)) {
+ if (nfs4_copy_delegation_stateid(inode, FMODE_WRITE, &arg->stateid, &delegation_cred)) {
/* Use that stateid */
- } else if (truncate && ctx != NULL) {
+ } else if (ctx != NULL) {
struct nfs_lock_context *l_ctx;
if (!nfs4_valid_open_stateid(ctx->state))
return -EBADF;
@@ -3063,8 +3080,10 @@ static int _nfs4_do_setattr(struct inode *inode,
nfs_put_lock_context(l_ctx);
if (status == -EIO)
return -EBADF;
- } else
+ } else {
+zero_stateid:
nfs4_stateid_copy(&arg->stateid, &zero_stateid);
+ }
if (delegation_cred)
msg.rpc_cred = delegation_cred;
@@ -3083,12 +3102,13 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
struct nfs4_label *olabel)
{
struct nfs_server *server = NFS_SERVER(inode);
+ __u32 bitmask[NFS4_BITMASK_SZ];
struct nfs4_state *state = ctx ? ctx->state : NULL;
struct nfs_setattrargs arg = {
.fh = NFS_FH(inode),
.iap = sattr,
.server = server,
- .bitmask = server->attr_bitmask,
+ .bitmask = bitmask,
.label = ilabel,
};
struct nfs_setattrres res = {
@@ -3103,11 +3123,11 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
};
int err;
- arg.bitmask = nfs4_bitmask(server, ilabel);
- if (ilabel)
- arg.bitmask = nfs4_bitmask(server, olabel);
-
do {
+ nfs4_bitmap_copy_adjust_setattr(bitmask,
+ nfs4_bitmask(server, olabel),
+ inode);
+
err = _nfs4_do_setattr(inode, &arg, &res, cred, ctx);
switch (err) {
case -NFS4ERR_OPENMODE:
@@ -3274,6 +3294,7 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
struct nfs4_closedata *calldata = data;
struct nfs4_state *state = calldata->state;
struct inode *inode = calldata->inode;
+ struct pnfs_layout_hdr *lo;
bool is_rdonly, is_wronly, is_rdwr;
int call_close = 0;
@@ -3317,6 +3338,12 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
goto out_wait;
}
+ lo = calldata->arg.lr_args ? calldata->arg.lr_args->layout : NULL;
+ if (lo && !pnfs_layout_is_valid(lo)) {
+ calldata->arg.lr_args = NULL;
+ calldata->res.lr_res = NULL;
+ }
+
if (calldata->arg.fmode == 0)
task->tk_msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CLOSE];
@@ -3393,7 +3420,7 @@ int nfs4_do_close(struct nfs4_state *state, gfp_t gfp_mask, int wait)
calldata = kzalloc(sizeof(*calldata), gfp_mask);
if (calldata == NULL)
goto out;
- nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1);
+ nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 1, 0);
calldata->inode = state->inode;
calldata->state = state;
calldata->arg.fh = NFS_FH(state->inode);
@@ -3742,7 +3769,7 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *mntfh,
if (IS_ERR(label))
return PTR_ERR(label);
- error = nfs4_proc_getattr(server, mntfh, fattr, label);
+ error = nfs4_proc_getattr(server, mntfh, fattr, label, NULL);
if (error < 0) {
dprintk("nfs4_get_root: getattr error = %d\n", -error);
goto err_free_label;
@@ -3807,11 +3834,13 @@ out:
}
static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr, struct nfs4_label *label)
+ struct nfs_fattr *fattr, struct nfs4_label *label,
+ struct inode *inode)
{
+ __u32 bitmask[NFS4_BITMASK_SZ];
struct nfs4_getattr_arg args = {
.fh = fhandle,
- .bitmask = server->attr_bitmask,
+ .bitmask = bitmask,
};
struct nfs4_getattr_res res = {
.fattr = fattr,
@@ -3824,19 +3853,20 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
.rpc_resp = &res,
};
- args.bitmask = nfs4_bitmask(server, label);
+ nfs4_bitmap_copy_adjust(bitmask, nfs4_bitmask(server, label), inode);
nfs_fattr_init(fattr);
return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
}
static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr, struct nfs4_label *label)
+ struct nfs_fattr *fattr, struct nfs4_label *label,
+ struct inode *inode)
{
struct nfs4_exception exception = { };
int err;
do {
- err = _nfs4_proc_getattr(server, fhandle, fattr, label);
+ err = _nfs4_proc_getattr(server, fhandle, fattr, label, inode);
trace_nfs4_getattr(server, fhandle, fattr, err);
err = nfs4_handle_exception(server, err,
&exception);
@@ -4089,7 +4119,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry
};
int status = 0;
- if (!nfs_have_delegated_attributes(inode)) {
+ if (!nfs4_have_delegation(inode, FMODE_READ)) {
res.fattr = nfs_alloc_fattr();
if (res.fattr == NULL)
return -ENOMEM;
@@ -4265,15 +4295,16 @@ static int nfs4_proc_rmdir(struct inode *dir, const struct qstr *name)
return err;
}
-static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct dentry *dentry)
+static void nfs4_proc_unlink_setup(struct rpc_message *msg,
+ struct dentry *dentry,
+ struct inode *inode)
{
struct nfs_removeargs *args = msg->rpc_argp;
struct nfs_removeres *res = msg->rpc_resp;
- struct inode *inode = d_inode(dentry);
res->server = NFS_SB(dentry->d_sb);
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE];
- nfs4_init_sequence(&args->seq_args, &res->seq_res, 1);
+ nfs4_init_sequence(&args->seq_args, &res->seq_res, 1, 0);
nfs_fattr_init(res->dir_attr);
@@ -4319,7 +4350,7 @@ static void nfs4_proc_rename_setup(struct rpc_message *msg,
nfs4_inode_return_delegation(new_inode);
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENAME];
res->server = NFS_SB(old_dentry->d_sb);
- nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1);
+ nfs4_init_sequence(&arg->seq_args, &res->seq_res, 1, 0);
}
static void nfs4_proc_rename_rpc_prepare(struct rpc_task *task, struct nfs_renamedata *data)
@@ -4352,11 +4383,12 @@ static int nfs4_proc_rename_done(struct rpc_task *task, struct inode *old_dir,
static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct qstr *name)
{
struct nfs_server *server = NFS_SERVER(inode);
+ __u32 bitmask[NFS4_BITMASK_SZ];
struct nfs4_link_arg arg = {
.fh = NFS_FH(inode),
.dir_fh = NFS_FH(dir),
.name = name,
- .bitmask = server->attr_bitmask,
+ .bitmask = bitmask,
};
struct nfs4_link_res res = {
.server = server,
@@ -4378,9 +4410,9 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, const struct
status = PTR_ERR(res.label);
goto out;
}
- arg.bitmask = nfs4_bitmask(server, res.label);
nfs4_inode_make_writeable(inode);
+ nfs4_bitmap_copy_adjust_setattr(bitmask, nfs4_bitmask(server, res.label), inode);
status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1);
if (!status) {
@@ -4895,7 +4927,7 @@ static void nfs4_proc_read_setup(struct nfs_pgio_header *hdr,
if (!hdr->pgio_done_cb)
hdr->pgio_done_cb = nfs4_read_done_cb;
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ];
- nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 0);
+ nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 0, 0);
}
static int nfs4_proc_pgio_rpc_prepare(struct rpc_task *task,
@@ -4979,7 +5011,8 @@ bool nfs4_write_need_cache_consistency_data(struct nfs_pgio_header *hdr)
}
static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
- struct rpc_message *msg)
+ struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
struct nfs_server *server = NFS_SERVER(hdr->inode);
@@ -4995,7 +5028,8 @@ static void nfs4_proc_write_setup(struct nfs_pgio_header *hdr,
hdr->timestamp = jiffies;
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_WRITE];
- nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 1);
+ nfs4_init_sequence(&hdr->args.seq_args, &hdr->res.seq_res, 1, 0);
+ nfs4_state_protect_write(server->nfs_client, clnt, msg, hdr);
}
static void nfs4_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit_data *data)
@@ -5026,7 +5060,8 @@ static int nfs4_commit_done(struct rpc_task *task, struct nfs_commit_data *data)
return data->commit_done_cb(task, data);
}
-static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
+static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
struct nfs_server *server = NFS_SERVER(data->inode);
@@ -5034,7 +5069,8 @@ static void nfs4_proc_commit_setup(struct nfs_commit_data *data, struct rpc_mess
data->commit_done_cb = nfs4_commit_done_cb;
data->res.server = server;
msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_COMMIT];
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, 0);
+ nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_COMMIT, clnt, msg);
}
struct nfs4_renewdata {
@@ -5391,7 +5427,8 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
*/
spin_lock(&inode->i_lock);
NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
- | NFS_INO_INVALID_CTIME;
+ | NFS_INO_INVALID_CTIME
+ | NFS_INO_REVAL_FORCED;
spin_unlock(&inode->i_lock);
nfs_access_zap_cache(inode);
nfs_zap_acl_cache(inode);
@@ -5591,13 +5628,14 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
return 0;
rcu_read_lock();
- len = 14 + strlen(clp->cl_ipaddr) + 1 +
- strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)) +
+ len = 14 +
+ strlen(clp->cl_rpcclient->cl_nodename) +
1 +
- strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO)) +
+ strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)) +
1;
rcu_read_unlock();
-
+ if (nfs4_client_id_uniquifier[0] != '\0')
+ len += strlen(nfs4_client_id_uniquifier) + 1;
if (len > NFS4_OPAQUE_LIMIT + 1)
return -EINVAL;
@@ -5611,10 +5649,17 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
return -ENOMEM;
rcu_read_lock();
- scnprintf(str, len, "Linux NFSv4.0 %s/%s %s",
- clp->cl_ipaddr,
- rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR),
- rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO));
+ if (nfs4_client_id_uniquifier[0] != '\0')
+ scnprintf(str, len, "Linux NFSv4.0 %s/%s/%s",
+ clp->cl_rpcclient->cl_nodename,
+ nfs4_client_id_uniquifier,
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_ADDR));
+ else
+ scnprintf(str, len, "Linux NFSv4.0 %s/%s",
+ clp->cl_rpcclient->cl_nodename,
+ rpc_peeraddr2str(clp->cl_rpcclient,
+ RPC_DISPLAY_ADDR));
rcu_read_unlock();
clp->cl_owner_id = str;
@@ -5934,12 +5979,19 @@ static void nfs4_delegreturn_release(void *calldata)
static void nfs4_delegreturn_prepare(struct rpc_task *task, void *data)
{
struct nfs4_delegreturndata *d_data;
+ struct pnfs_layout_hdr *lo;
d_data = (struct nfs4_delegreturndata *)data;
if (!d_data->lr.roc && nfs4_wait_on_layoutreturn(d_data->inode, task))
return;
+ lo = d_data->args.lr_args ? d_data->args.lr_args->layout : NULL;
+ if (lo && !pnfs_layout_is_valid(lo)) {
+ d_data->args.lr_args = NULL;
+ d_data->res.lr_res = NULL;
+ }
+
nfs4_setup_sequence(d_data->res.server->nfs_client,
&d_data->args.seq_args,
&d_data->res.seq_res,
@@ -5972,7 +6024,7 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
data = kzalloc(sizeof(*data), GFP_NOFS);
if (data == NULL)
return -ENOMEM;
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, 0);
nfs4_state_protect(server->nfs_client,
NFS_SP4_MACH_CRED_CLEANUP,
@@ -6247,7 +6299,7 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
return ERR_PTR(-ENOMEM);
}
- nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
+ nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1, 0);
msg.rpc_argp = &data->arg;
msg.rpc_resp = &data->res;
task_setup_data.callback_data = data;
@@ -6411,32 +6463,36 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
case 0:
renew_lease(NFS_SERVER(d_inode(data->ctx->dentry)),
data->timestamp);
- if (data->arg.new_lock) {
+ if (data->arg.new_lock && !data->cancelled) {
data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS);
- if (locks_lock_inode_wait(lsp->ls_state->inode, &data->fl) < 0) {
- rpc_restart_call_prepare(task);
+ if (locks_lock_inode_wait(lsp->ls_state->inode, &data->fl) < 0)
break;
- }
}
+
if (data->arg.new_lock_owner != 0) {
nfs_confirm_seqid(&lsp->ls_seqid, 0);
nfs4_stateid_copy(&lsp->ls_stateid, &data->res.stateid);
set_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags);
- } else if (!nfs4_update_lock_stateid(lsp, &data->res.stateid))
- rpc_restart_call_prepare(task);
+ goto out_done;
+ } else if (nfs4_update_lock_stateid(lsp, &data->res.stateid))
+ goto out_done;
+
break;
case -NFS4ERR_BAD_STATEID:
case -NFS4ERR_OLD_STATEID:
case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED:
if (data->arg.new_lock_owner != 0) {
- if (!nfs4_stateid_match(&data->arg.open_stateid,
+ if (nfs4_stateid_match(&data->arg.open_stateid,
&lsp->ls_state->open_stateid))
- rpc_restart_call_prepare(task);
- } else if (!nfs4_stateid_match(&data->arg.lock_stateid,
+ goto out_done;
+ } else if (nfs4_stateid_match(&data->arg.lock_stateid,
&lsp->ls_stateid))
- rpc_restart_call_prepare(task);
+ goto out_done;
}
+ if (!data->cancelled)
+ rpc_restart_call_prepare(task);
+out_done:
dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status);
}
@@ -6509,14 +6565,14 @@ static int _nfs4_do_setlk(struct nfs4_state *state, int cmd, struct file_lock *f
return -ENOMEM;
if (IS_SETLKW(cmd))
data->arg.block = 1;
- nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1);
+ nfs4_init_sequence(&data->arg.seq_args, &data->res.seq_res, 1,
+ recovery_type > NFS_LOCK_NEW);
msg.rpc_argp = &data->arg;
msg.rpc_resp = &data->res;
task_setup_data.callback_data = data;
if (recovery_type > NFS_LOCK_NEW) {
if (recovery_type == NFS_LOCK_RECLAIM)
data->arg.reclaim = NFS_LOCK_RECLAIM;
- nfs4_set_sequence_privileged(&data->arg.seq_args);
} else
data->arg.new_lock = 1;
task = rpc_run_task(&task_setup_data);
@@ -6911,7 +6967,7 @@ nfs4_release_lockowner(struct nfs_server *server, struct nfs4_lock_state *lsp)
msg.rpc_argp = &data->args;
msg.rpc_resp = &data->res;
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 0, 0);
rpc_call_async(server->client, &msg, 0, &nfs4_release_lockowner_ops, data);
}
@@ -7107,8 +7163,7 @@ static int _nfs40_proc_get_locations(struct inode *inode,
locations->server = server;
locations->nlocations = 0;
- nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
- nfs4_set_sequence_privileged(&args.seq_args);
+ nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
status = nfs4_call_sync_sequence(clnt, server, &msg,
&args.seq_args, &res.seq_res);
if (status)
@@ -7161,8 +7216,7 @@ static int _nfs41_proc_get_locations(struct inode *inode,
locations->server = server;
locations->nlocations = 0;
- nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
- nfs4_set_sequence_privileged(&args.seq_args);
+ nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
status = nfs4_call_sync_sequence(clnt, server, &msg,
&args.seq_args, &res.seq_res);
if (status == NFS4_OK &&
@@ -7249,8 +7303,7 @@ static int _nfs40_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
if (res.fh == NULL)
return -ENOMEM;
- nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
- nfs4_set_sequence_privileged(&args.seq_args);
+ nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
status = nfs4_call_sync_sequence(clnt, server, &msg,
&args.seq_args, &res.seq_res);
nfs_free_fhandle(res.fh);
@@ -7291,8 +7344,7 @@ static int _nfs41_proc_fsid_present(struct inode *inode, struct rpc_cred *cred)
if (res.fh == NULL)
return -ENOMEM;
- nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
- nfs4_set_sequence_privileged(&args.seq_args);
+ nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
status = nfs4_call_sync_sequence(clnt, server, &msg,
&args.seq_args, &res.seq_res);
nfs_free_fhandle(res.fh);
@@ -8070,8 +8122,7 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
};
int status;
- nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0);
- nfs4_set_sequence_privileged(&args.la_seq_args);
+ nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0, 1);
task = rpc_run_task(&task_setup);
if (IS_ERR(task))
@@ -8408,10 +8459,8 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp,
calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
if (calldata == NULL)
goto out_put_clp;
- nfs4_init_sequence(&calldata->args, &calldata->res, 0);
+ nfs4_init_sequence(&calldata->args, &calldata->res, 0, is_privileged);
nfs4_sequence_attach_slot(&calldata->args, &calldata->res, slot);
- if (is_privileged)
- nfs4_set_sequence_privileged(&calldata->args);
msg.rpc_argp = &calldata->args;
msg.rpc_resp = &calldata->res;
calldata->clp = clp;
@@ -8563,8 +8612,7 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp,
calldata->clp = clp;
calldata->arg.one_fs = 0;
- nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0);
- nfs4_set_sequence_privileged(&calldata->arg.seq_args);
+ nfs4_init_sequence(&calldata->arg.seq_args, &calldata->res.seq_res, 0, 1);
msg.rpc_argp = &calldata->arg;
msg.rpc_resp = &calldata->res;
task_setup_data.callback_data = calldata;
@@ -8616,6 +8664,8 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
dprintk("--> %s tk_status => %d\n", __func__, -task->tk_status);
+ nfs4_sequence_free_slot(&lgp->res.seq_res);
+
switch (nfs4err) {
case 0:
goto out;
@@ -8680,7 +8730,6 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
goto out;
}
- nfs4_sequence_free_slot(&lgp->res.seq_res);
err = nfs4_handle_exception(server, nfs4err, exception);
if (!status) {
if (exception->retry)
@@ -8693,63 +8742,19 @@ out:
return status;
}
-static size_t max_response_pages(struct nfs_server *server)
+size_t max_response_pages(struct nfs_server *server)
{
u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
return nfs_page_array_len(0, max_resp_sz);
}
-static void nfs4_free_pages(struct page **pages, size_t size)
-{
- int i;
-
- if (!pages)
- return;
-
- for (i = 0; i < size; i++) {
- if (!pages[i])
- break;
- __free_page(pages[i]);
- }
- kfree(pages);
-}
-
-static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
-{
- struct page **pages;
- int i;
-
- pages = kcalloc(size, sizeof(struct page *), gfp_flags);
- if (!pages) {
- dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
- return NULL;
- }
-
- for (i = 0; i < size; i++) {
- pages[i] = alloc_page(gfp_flags);
- if (!pages[i]) {
- dprintk("%s: failed to allocate page\n", __func__);
- nfs4_free_pages(pages, size);
- return NULL;
- }
- }
-
- return pages;
-}
-
static void nfs4_layoutget_release(void *calldata)
{
struct nfs4_layoutget *lgp = calldata;
- struct inode *inode = lgp->args.inode;
- struct nfs_server *server = NFS_SERVER(inode);
- size_t max_pages = max_response_pages(server);
dprintk("--> %s\n", __func__);
nfs4_sequence_free_slot(&lgp->res.seq_res);
- nfs4_free_pages(lgp->args.layout.pages, max_pages);
- pnfs_put_layout_hdr(NFS_I(inode)->layout);
- put_nfs_open_context(lgp->args.ctx);
- kfree(calldata);
+ pnfs_layoutget_free(lgp);
dprintk("<-- %s\n", __func__);
}
@@ -8760,11 +8765,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
};
struct pnfs_layout_segment *
-nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags)
+nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout)
{
struct inode *inode = lgp->args.inode;
struct nfs_server *server = NFS_SERVER(inode);
- size_t max_pages = max_response_pages(server);
struct rpc_task *task;
struct rpc_message msg = {
.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
@@ -8791,35 +8795,28 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags)
/* nfs4_layoutget_release calls pnfs_put_layout_hdr */
pnfs_get_layout_hdr(NFS_I(inode)->layout);
- lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
- if (!lgp->args.layout.pages) {
- nfs4_layoutget_release(lgp);
- return ERR_PTR(-ENOMEM);
- }
- lgp->args.layout.pglen = max_pages * PAGE_SIZE;
-
- lgp->res.layoutp = &lgp->args.layout;
- lgp->res.seq_res.sr_slot = NULL;
- nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
+ nfs4_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0, 0);
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
return ERR_CAST(task);
status = rpc_wait_for_completion_task(task);
- if (status == 0) {
+ if (status != 0)
+ goto out;
+
+ /* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
+ if (task->tk_status < 0 || lgp->res.layoutp->len == 0) {
status = nfs4_layoutget_handle_exception(task, lgp, &exception);
*timeout = exception.timeout;
- }
-
+ } else
+ lseg = pnfs_layout_process(lgp);
+out:
trace_nfs4_layoutget(lgp->args.ctx,
&lgp->args.range,
&lgp->res.range,
&lgp->res.stateid,
status);
- /* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
- if (status == 0 && lgp->res.layoutp->len)
- lseg = pnfs_layout_process(lgp);
rpc_put_task(task);
dprintk("<-- %s status=%d\n", __func__, status);
if (status)
@@ -8837,6 +8834,8 @@ nfs4_layoutreturn_prepare(struct rpc_task *task, void *calldata)
&lrp->args.seq_args,
&lrp->res.seq_res,
task);
+ if (!pnfs_layout_is_valid(lrp->args.layout))
+ rpc_exit(task, 0);
}
static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
@@ -8927,7 +8926,7 @@ int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync)
}
task_setup_data.flags |= RPC_TASK_ASYNC;
}
- nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1);
+ nfs4_init_sequence(&lrp->args.seq_args, &lrp->res.seq_res, 1, 0);
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
return PTR_ERR(task);
@@ -9074,7 +9073,7 @@ nfs4_proc_layoutcommit(struct nfs4_layoutcommit_data *data, bool sync)
}
task_setup_data.flags = RPC_TASK_ASYNC;
}
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, 0);
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
return PTR_ERR(task);
@@ -9254,8 +9253,7 @@ static int _nfs41_test_stateid(struct nfs_server *server,
&rpc_client, &msg);
dprintk("NFS call test_stateid %p\n", stateid);
- nfs4_init_sequence(&args.seq_args, &res.seq_res, 0);
- nfs4_set_sequence_privileged(&args.seq_args);
+ nfs4_init_sequence(&args.seq_args, &res.seq_res, 0, 1);
status = nfs4_call_sync_sequence(rpc_client, server, &msg,
&args.seq_args, &res.seq_res);
if (status != NFS_OK) {
@@ -9347,7 +9345,17 @@ static const struct rpc_call_ops nfs41_free_stateid_ops = {
.rpc_release = nfs41_free_stateid_release,
};
-static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
+/**
+ * nfs41_free_stateid - perform a FREE_STATEID operation
+ *
+ * @server: server / transport on which to perform the operation
+ * @stateid: state ID to release
+ * @cred: credential
+ * @is_recovery: set to true if this call needs to be privileged
+ *
+ * Note: this function is always asynchronous.
+ */
+static int nfs41_free_stateid(struct nfs_server *server,
const nfs4_stateid *stateid,
struct rpc_cred *cred,
bool privileged)
@@ -9363,6 +9371,7 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
.flags = RPC_TASK_ASYNC,
};
struct nfs_free_stateid_data *data;
+ struct rpc_task *task;
nfs4_state_protect(server->nfs_client, NFS_SP4_MACH_CRED_STATEID,
&task_setup.rpc_client, &msg);
@@ -9370,7 +9379,7 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
dprintk("NFS call free_stateid %p\n", stateid);
data = kmalloc(sizeof(*data), GFP_NOFS);
if (!data)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
data->server = server;
nfs4_stateid_copy(&data->args.stateid, stateid);
@@ -9378,31 +9387,8 @@ static struct rpc_task *_nfs41_free_stateid(struct nfs_server *server,
msg.rpc_argp = &data->args;
msg.rpc_resp = &data->res;
- nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1);
- if (privileged)
- nfs4_set_sequence_privileged(&data->args.seq_args);
-
- return rpc_run_task(&task_setup);
-}
-
-/**
- * nfs41_free_stateid - perform a FREE_STATEID operation
- *
- * @server: server / transport on which to perform the operation
- * @stateid: state ID to release
- * @cred: credential
- * @is_recovery: set to true if this call needs to be privileged
- *
- * Note: this function is always asynchronous.
- */
-static int nfs41_free_stateid(struct nfs_server *server,
- const nfs4_stateid *stateid,
- struct rpc_cred *cred,
- bool is_recovery)
-{
- struct rpc_task *task;
-
- task = _nfs41_free_stateid(server, stateid, cred, is_recovery);
+ nfs4_init_sequence(&data->args.seq_args, &data->res.seq_res, 1, privileged);
+ task = rpc_run_task(&task_setup);
if (IS_ERR(task))
return PTR_ERR(task);
rpc_put_task(task);
@@ -9539,7 +9525,8 @@ static const struct nfs4_minor_version_ops nfs_v4_1_minor_ops = {
| NFS_CAP_ATOMIC_OPEN
| NFS_CAP_POSIX_LOCK
| NFS_CAP_STATEID_NFSV41
- | NFS_CAP_ATOMIC_OPEN_V1,
+ | NFS_CAP_ATOMIC_OPEN_V1
+ | NFS_CAP_LGOPEN,
.init_client = nfs41_init_client,
.shutdown_client = nfs41_shutdown_client,
.match_stateid = nfs41_match_stateid,
@@ -9564,6 +9551,7 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = {
| NFS_CAP_POSIX_LOCK
| NFS_CAP_STATEID_NFSV41
| NFS_CAP_ATOMIC_OPEN_V1
+ | NFS_CAP_LGOPEN
| NFS_CAP_ALLOCATE
| NFS_CAP_COPY
| NFS_CAP_DEALLOCATE
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index c10a422..2bf2eaa 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -77,6 +77,14 @@ const nfs4_stateid invalid_stateid = {
.type = NFS4_INVALID_STATEID_TYPE,
};
+const nfs4_stateid current_stateid = {
+ {
+ /* Funky initialiser keeps older gcc versions happy */
+ .data = { 0x0, 0x0, 0x0, 0x1, 0 },
+ },
+ .type = NFS4_SPECIAL_STATEID_TYPE,
+};
+
static DEFINE_MUTEX(nfs_clid_init_mutex);
int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 9b73920..cd41d25 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -65,7 +65,13 @@
/* Mapping from NFS error code to "errno" error code. */
#define errno_NFSERR_IO EIO
+struct compound_hdr;
static int nfs4_stat_to_errno(int);
+static void encode_layoutget(struct xdr_stream *xdr,
+ const struct nfs4_layoutget_args *args,
+ struct compound_hdr *hdr);
+static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
+ struct nfs4_layoutget_res *res);
/* NFSv4 COMPOUND tags are only wanted for debugging purposes */
#ifdef DEBUG
@@ -424,6 +430,8 @@ static int nfs4_stat_to_errno(int);
#define decode_sequence_maxsz 0
#define encode_layoutreturn_maxsz 0
#define decode_layoutreturn_maxsz 0
+#define encode_layoutget_maxsz 0
+#define decode_layoutget_maxsz 0
#endif /* CONFIG_NFS_V4_1 */
#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
@@ -476,14 +484,16 @@ static int nfs4_stat_to_errno(int);
encode_open_maxsz + \
encode_access_maxsz + \
encode_getfh_maxsz + \
- encode_getattr_maxsz)
+ encode_getattr_maxsz + \
+ encode_layoutget_maxsz)
#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_open_maxsz + \
decode_access_maxsz + \
decode_getfh_maxsz + \
- decode_getattr_maxsz)
+ decode_getattr_maxsz + \
+ decode_layoutget_maxsz)
#define NFS4_enc_open_confirm_sz \
(compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
@@ -497,13 +507,15 @@ static int nfs4_stat_to_errno(int);
encode_putfh_maxsz + \
encode_open_maxsz + \
encode_access_maxsz + \
- encode_getattr_maxsz)
+ encode_getattr_maxsz + \
+ encode_layoutget_maxsz)
#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
decode_sequence_maxsz + \
decode_putfh_maxsz + \
decode_open_maxsz + \
decode_access_maxsz + \
- decode_getattr_maxsz)
+ decode_getattr_maxsz + \
+ decode_layoutget_maxsz)
#define NFS4_enc_open_downgrade_sz \
(compound_encode_hdr_maxsz + \
encode_sequence_maxsz + \
@@ -1057,6 +1069,7 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
const struct nfs_server *server,
const uint32_t attrmask[])
{
+ struct timespec ts;
char owner_name[IDMAP_NAMESZ];
char owner_group[IDMAP_NAMESZ];
int owner_namelen = 0;
@@ -1145,14 +1158,16 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
if (iap->ia_valid & ATTR_ATIME_SET) {
*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
- p = xdr_encode_nfstime4(p, &iap->ia_atime);
+ ts = timespec64_to_timespec(iap->ia_atime);
+ p = xdr_encode_nfstime4(p, &ts);
} else
*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
}
if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
if (iap->ia_valid & ATTR_MTIME_SET) {
*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
- p = xdr_encode_nfstime4(p, &iap->ia_mtime);
+ ts = timespec64_to_timespec(iap->ia_mtime);
+ p = xdr_encode_nfstime4(p, &ts);
} else
*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
}
@@ -2070,6 +2085,13 @@ encode_layoutreturn(struct xdr_stream *xdr,
struct compound_hdr *hdr)
{
}
+
+static void
+encode_layoutget(struct xdr_stream *xdr,
+ const struct nfs4_layoutget_args *args,
+ struct compound_hdr *hdr)
+{
+}
#endif /* CONFIG_NFS_V4_1 */
/*
@@ -2316,6 +2338,12 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
if (args->access)
encode_access(xdr, args->access, &hdr);
encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
+ if (args->lg_args) {
+ encode_layoutget(xdr, args->lg_args, &hdr);
+ xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
+ args->lg_args->layout.pages,
+ 0, args->lg_args->layout.pglen);
+ }
encode_nops(&hdr);
}
@@ -2356,6 +2384,12 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
if (args->access)
encode_access(xdr, args->access, &hdr);
encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
+ if (args->lg_args) {
+ encode_layoutget(xdr, args->lg_args, &hdr);
+ xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
+ args->lg_args->layout.pages,
+ 0, args->lg_args->layout.pglen);
+ }
encode_nops(&hdr);
}
@@ -6024,7 +6058,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
status = decode_op_hdr(xdr, OP_LAYOUTGET);
if (status)
- return status;
+ goto out;
p = xdr_inline_decode(xdr, 4);
if (unlikely(!p))
goto out_overflow;
@@ -6037,7 +6071,8 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
if (!layout_count) {
dprintk("%s: server responded with empty layout array\n",
__func__);
- return -EINVAL;
+ status = -EINVAL;
+ goto out;
}
p = xdr_inline_decode(xdr, 28);
@@ -6062,7 +6097,8 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
dprintk("NFS: server cheating in layoutget reply: "
"layout len %u > recvd %u\n",
res->layoutp->len, recvd);
- return -EINVAL;
+ status = -EINVAL;
+ goto out;
}
if (layout_count > 1) {
@@ -6075,10 +6111,13 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
__func__, layout_count);
}
- return 0;
+out:
+ res->status = status;
+ return status;
out_overflow:
print_overflow_msg(__func__, xdr);
- return -EIO;
+ status = -EIO;
+ goto out;
}
static int decode_layoutreturn(struct xdr_stream *xdr,
@@ -6177,6 +6216,13 @@ int decode_layoutreturn(struct xdr_stream *xdr,
{
return 0;
}
+
+static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
+ struct nfs4_layoutget_res *res)
+{
+ return 0;
+}
+
#endif /* CONFIG_NFS_V4_1 */
/*
@@ -6623,6 +6669,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
if (res->access_request)
decode_access(xdr, &res->access_supported, &res->access_result);
decode_getfattr_label(xdr, res->f_attr, res->f_label, res->server);
+ if (res->lg_res)
+ decode_layoutget(xdr, rqstp, res->lg_res);
out:
return status;
}
@@ -6675,6 +6723,8 @@ static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp,
if (res->access_request)
decode_access(xdr, &res->access_supported, &res->access_result);
decode_getfattr(xdr, res->f_attr, res->server);
+ if (res->lg_res)
+ decode_layoutget(xdr, rqstp, res->lg_res);
out:
return status;
}
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index ee723aa..bcc3add 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -37,6 +37,7 @@
#include "nfs4trace.h"
#include "delegation.h"
#include "nfs42.h"
+#include "nfs4_fs.h"
#define NFSDBG_FACILITY NFSDBG_PNFS
#define PNFS_LAYOUTGET_RETRY_TIMEOUT (120*HZ)
@@ -915,45 +916,99 @@ pnfs_layoutgets_blocked(const struct pnfs_layout_hdr *lo)
test_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
}
-/*
- * Get layout from server.
- * for now, assume that whole file layouts are requested.
- * arg->offset: 0
- * arg->length: all ones
- */
-static struct pnfs_layout_segment *
-send_layoutget(struct pnfs_layout_hdr *lo,
+static struct nfs_server *
+pnfs_find_server(struct inode *inode, struct nfs_open_context *ctx)
+{
+ struct nfs_server *server;
+
+ if (inode) {
+ server = NFS_SERVER(inode);
+ } else {
+ struct dentry *parent_dir = dget_parent(ctx->dentry);
+ server = NFS_SERVER(parent_dir->d_inode);
+ dput(parent_dir);
+ }
+ return server;
+}
+
+static void nfs4_free_pages(struct page **pages, size_t size)
+{
+ int i;
+
+ if (!pages)
+ return;
+
+ for (i = 0; i < size; i++) {
+ if (!pages[i])
+ break;
+ __free_page(pages[i]);
+ }
+ kfree(pages);
+}
+
+static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
+{
+ struct page **pages;
+ int i;
+
+ pages = kcalloc(size, sizeof(struct page *), gfp_flags);
+ if (!pages) {
+ dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
+ return NULL;
+ }
+
+ for (i = 0; i < size; i++) {
+ pages[i] = alloc_page(gfp_flags);
+ if (!pages[i]) {
+ dprintk("%s: failed to allocate page\n", __func__);
+ nfs4_free_pages(pages, size);
+ return NULL;
+ }
+ }
+
+ return pages;
+}
+
+static struct nfs4_layoutget *
+pnfs_alloc_init_layoutget_args(struct inode *ino,
struct nfs_open_context *ctx,
- nfs4_stateid *stateid,
+ const nfs4_stateid *stateid,
const struct pnfs_layout_range *range,
- long *timeout, gfp_t gfp_flags)
+ gfp_t gfp_flags)
{
- struct inode *ino = lo->plh_inode;
- struct nfs_server *server = NFS_SERVER(ino);
+ struct nfs_server *server = pnfs_find_server(ino, ctx);
+ size_t max_pages = max_response_pages(server);
struct nfs4_layoutget *lgp;
- loff_t i_size;
dprintk("--> %s\n", __func__);
- /*
- * Synchronously retrieve layout information from server and
- * store in lseg. If we race with a concurrent seqid morphing
- * op, then re-send the LAYOUTGET.
- */
lgp = kzalloc(sizeof(*lgp), gfp_flags);
if (lgp == NULL)
- return ERR_PTR(-ENOMEM);
+ return NULL;
+
+ lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
+ if (!lgp->args.layout.pages) {
+ kfree(lgp);
+ return NULL;
+ }
+ lgp->args.layout.pglen = max_pages * PAGE_SIZE;
+ lgp->res.layoutp = &lgp->args.layout;
- i_size = i_size_read(ino);
+ /* Don't confuse uninitialised result and success */
+ lgp->res.status = -NFS4ERR_DELAY;
lgp->args.minlength = PAGE_SIZE;
if (lgp->args.minlength > range->length)
lgp->args.minlength = range->length;
- if (range->iomode == IOMODE_READ) {
- if (range->offset >= i_size)
- lgp->args.minlength = 0;
- else if (i_size - range->offset < lgp->args.minlength)
- lgp->args.minlength = i_size - range->offset;
+ if (ino) {
+ loff_t i_size = i_size_read(ino);
+
+ if (range->iomode == IOMODE_READ) {
+ if (range->offset >= i_size)
+ lgp->args.minlength = 0;
+ else if (i_size - range->offset < lgp->args.minlength)
+ lgp->args.minlength = i_size - range->offset;
+ }
}
lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;
pnfs_copy_range(&lgp->args.range, range);
@@ -962,9 +1017,21 @@ send_layoutget(struct pnfs_layout_hdr *lo,
lgp->args.ctx = get_nfs_open_context(ctx);
nfs4_stateid_copy(&lgp->args.stateid, stateid);
lgp->gfp_flags = gfp_flags;
- lgp->cred = lo->plh_lc_cred;
+ lgp->cred = get_rpccred(ctx->cred);
+ lgp->callback_count = raw_seqcount_begin(&server->nfs_client->cl_callback_count);
+ return lgp;
+}
- return nfs4_proc_layoutget(lgp, timeout, gfp_flags);
+void pnfs_layoutget_free(struct nfs4_layoutget *lgp)
+{
+ size_t max_pages = lgp->args.layout.pglen / PAGE_SIZE;
+
+ nfs4_free_pages(lgp->args.layout.pages, max_pages);
+ if (lgp->args.inode)
+ pnfs_put_layout_hdr(NFS_I(lgp->args.inode)->layout);
+ put_rpccred(lgp->cred);
+ put_nfs_open_context(lgp->args.ctx);
+ kfree(lgp);
}
static void pnfs_clear_layoutcommit(struct inode *inode,
@@ -1144,7 +1211,7 @@ _pnfs_return_layout(struct inode *ino)
LIST_HEAD(tmp_list);
nfs4_stateid stateid;
int status = 0;
- bool send;
+ bool send, valid_layout;
dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino);
@@ -1165,6 +1232,7 @@ _pnfs_return_layout(struct inode *ino)
goto out_put_layout_hdr;
spin_lock(&ino->i_lock);
}
+ valid_layout = pnfs_layout_is_valid(lo);
pnfs_clear_layoutcommit(ino, &tmp_list);
pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL, 0);
@@ -1178,7 +1246,8 @@ _pnfs_return_layout(struct inode *ino)
}
/* Don't send a LAYOUTRETURN if list was initially empty */
- if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) {
+ if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags) ||
+ !valid_layout) {
spin_unlock(&ino->i_lock);
dprintk("NFS: %s no layout segments to return\n", __func__);
goto out_put_layout_hdr;
@@ -1671,6 +1740,22 @@ static void pnfs_clear_first_layoutget(struct pnfs_layout_hdr *lo)
wake_up_bit(bitlock, NFS_LAYOUT_FIRST_LAYOUTGET);
}
+static void _add_to_server_list(struct pnfs_layout_hdr *lo,
+ struct nfs_server *server)
+{
+ if (list_empty(&lo->plh_layouts)) {
+ struct nfs_client *clp = server->nfs_client;
+
+ /* The lo must be on the clp list if there is any
+ * chance of a CB_LAYOUTRECALL(FILE) coming in.
+ */
+ spin_lock(&clp->cl_lock);
+ if (list_empty(&lo->plh_layouts))
+ list_add_tail(&lo->plh_layouts, &server->layouts);
+ spin_unlock(&clp->cl_lock);
+ }
+}
+
/*
* Layout segment is retreived from the server if not cached.
* The appropriate layout segment is referenced and returned to the caller.
@@ -1694,6 +1779,7 @@ pnfs_update_layout(struct inode *ino,
struct nfs_client *clp = server->nfs_client;
struct pnfs_layout_hdr *lo = NULL;
struct pnfs_layout_segment *lseg = NULL;
+ struct nfs4_layoutget *lgp;
nfs4_stateid stateid;
long timeout = 0;
unsigned long giveup = jiffies + (clp->cl_lease_time << 1);
@@ -1820,15 +1906,7 @@ lookup_again:
atomic_inc(&lo->plh_outstanding);
spin_unlock(&ino->i_lock);
- if (list_empty(&lo->plh_layouts)) {
- /* The lo must be on the clp list if there is any
- * chance of a CB_LAYOUTRECALL(FILE) coming in.
- */
- spin_lock(&clp->cl_lock);
- if (list_empty(&lo->plh_layouts))
- list_add_tail(&lo->plh_layouts, &server->layouts);
- spin_unlock(&clp->cl_lock);
- }
+ _add_to_server_list(lo, server);
pg_offset = arg.offset & ~PAGE_MASK;
if (pg_offset) {
@@ -1838,7 +1916,15 @@ lookup_again:
if (arg.length != NFS4_MAX_UINT64)
arg.length = PAGE_ALIGN(arg.length);
- lseg = send_layoutget(lo, ctx, &stateid, &arg, &timeout, gfp_flags);
+ lgp = pnfs_alloc_init_layoutget_args(ino, ctx, &stateid, &arg, gfp_flags);
+ if (!lgp) {
+ trace_pnfs_update_layout(ino, pos, count, iomode, lo, NULL,
+ PNFS_UPDATE_LAYOUT_NOMEM);
+ atomic_dec(&lo->plh_outstanding);
+ goto out_put_layout_hdr;
+ }
+
+ lseg = nfs4_proc_layoutget(lgp, &timeout);
trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
PNFS_UPDATE_LAYOUT_SEND_LAYOUTGET);
atomic_dec(&lo->plh_outstanding);
@@ -1919,6 +2005,171 @@ pnfs_sanity_check_layout_range(struct pnfs_layout_range *range)
return true;
}
+static struct pnfs_layout_hdr *
+_pnfs_grab_empty_layout(struct inode *ino, struct nfs_open_context *ctx)
+{
+ struct pnfs_layout_hdr *lo;
+
+ spin_lock(&ino->i_lock);
+ lo = pnfs_find_alloc_layout(ino, ctx, GFP_KERNEL);
+ if (!lo)
+ goto out_unlock;
+ if (!test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags))
+ goto out_unlock;
+ if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
+ goto out_unlock;
+ if (pnfs_layoutgets_blocked(lo))
+ goto out_unlock;
+ if (test_and_set_bit(NFS_LAYOUT_FIRST_LAYOUTGET, &lo->plh_flags))
+ goto out_unlock;
+ atomic_inc(&lo->plh_outstanding);
+ spin_unlock(&ino->i_lock);
+ _add_to_server_list(lo, NFS_SERVER(ino));
+ return lo;
+
+out_unlock:
+ spin_unlock(&ino->i_lock);
+ pnfs_put_layout_hdr(lo);
+ return NULL;
+}
+
+extern const nfs4_stateid current_stateid;
+
+static void _lgopen_prepare_attached(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
+{
+ struct inode *ino = data->dentry->d_inode;
+ struct pnfs_layout_range rng = {
+ .iomode = (data->o_arg.fmode & FMODE_WRITE) ?
+ IOMODE_RW: IOMODE_READ,
+ .offset = 0,
+ .length = NFS4_MAX_UINT64,
+ };
+ struct nfs4_layoutget *lgp;
+ struct pnfs_layout_hdr *lo;
+
+ /* Heuristic: don't send layoutget if we have cached data */
+ if (rng.iomode == IOMODE_READ &&
+ (i_size_read(ino) == 0 || ino->i_mapping->nrpages != 0))
+ return;
+
+ lo = _pnfs_grab_empty_layout(ino, ctx);
+ if (!lo)
+ return;
+ lgp = pnfs_alloc_init_layoutget_args(ino, ctx, &current_stateid,
+ &rng, GFP_KERNEL);
+ if (!lgp) {
+ pnfs_clear_first_layoutget(lo);
+ pnfs_put_layout_hdr(lo);
+ return;
+ }
+ data->lgp = lgp;
+ data->o_arg.lg_args = &lgp->args;
+ data->o_res.lg_res = &lgp->res;
+}
+
+static void _lgopen_prepare_floating(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
+{
+ struct pnfs_layout_range rng = {
+ .iomode = (data->o_arg.fmode & FMODE_WRITE) ?
+ IOMODE_RW: IOMODE_READ,
+ .offset = 0,
+ .length = NFS4_MAX_UINT64,
+ };
+ struct nfs4_layoutget *lgp;
+
+ lgp = pnfs_alloc_init_layoutget_args(NULL, ctx, &current_stateid,
+ &rng, GFP_KERNEL);
+ if (!lgp)
+ return;
+ data->lgp = lgp;
+ data->o_arg.lg_args = &lgp->args;
+ data->o_res.lg_res = &lgp->res;
+}
+
+void pnfs_lgopen_prepare(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
+{
+ struct nfs_server *server = NFS_SERVER(data->dir->d_inode);
+
+ if (!(pnfs_enabled_sb(server) &&
+ server->pnfs_curr_ld->flags & PNFS_LAYOUTGET_ON_OPEN))
+ return;
+ /* Could check on max_ops, but currently hardcoded high enough */
+ if (!nfs_server_capable(data->dir->d_inode, NFS_CAP_LGOPEN))
+ return;
+ if (data->state)
+ _lgopen_prepare_attached(data, ctx);
+ else
+ _lgopen_prepare_floating(data, ctx);
+}
+
+void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp,
+ struct nfs_open_context *ctx)
+{
+ struct pnfs_layout_hdr *lo;
+ struct pnfs_layout_segment *lseg;
+ struct nfs_server *srv = NFS_SERVER(ino);
+ u32 iomode;
+
+ if (!lgp)
+ return;
+ dprintk("%s: entered with status %i\n", __func__, lgp->res.status);
+ if (lgp->res.status) {
+ switch (lgp->res.status) {
+ default:
+ break;
+ /*
+ * Halt lgopen attempts if the server doesn't recognise
+ * the "current stateid" value, the layout type, or the
+ * layoutget operation as being valid.
+ * Also if it complains about too many ops in the compound
+ * or of the request/reply being too big.
+ */
+ case -NFS4ERR_BAD_STATEID:
+ case -NFS4ERR_NOTSUPP:
+ case -NFS4ERR_REP_TOO_BIG:
+ case -NFS4ERR_REP_TOO_BIG_TO_CACHE:
+ case -NFS4ERR_REQ_TOO_BIG:
+ case -NFS4ERR_TOO_MANY_OPS:
+ case -NFS4ERR_UNKNOWN_LAYOUTTYPE:
+ srv->caps &= ~NFS_CAP_LGOPEN;
+ }
+ return;
+ }
+ if (!lgp->args.inode) {
+ lo = _pnfs_grab_empty_layout(ino, ctx);
+ if (!lo)
+ return;
+ lgp->args.inode = ino;
+ } else
+ lo = NFS_I(lgp->args.inode)->layout;
+
+ if (read_seqcount_retry(&srv->nfs_client->cl_callback_count,
+ lgp->callback_count))
+ return;
+ lseg = pnfs_layout_process(lgp);
+ if (!IS_ERR(lseg)) {
+ iomode = lgp->args.range.iomode;
+ pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
+ pnfs_put_lseg(lseg);
+ }
+}
+
+void nfs4_lgopen_release(struct nfs4_layoutget *lgp)
+{
+ if (lgp != NULL) {
+ struct inode *inode = lgp->args.inode;
+ if (inode) {
+ struct pnfs_layout_hdr *lo = NFS_I(inode)->layout;
+ atomic_dec(&lo->plh_outstanding);
+ pnfs_clear_first_layoutget(lo);
+ }
+ pnfs_layoutget_free(lgp);
+ }
+}
+
struct pnfs_layout_segment *
pnfs_layout_process(struct nfs4_layoutget *lgp)
{
@@ -1984,8 +2235,6 @@ 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);
}
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index daf6cbf..3fe8142 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -35,6 +35,8 @@
#include <linux/nfs_page.h>
#include <linux/workqueue.h>
+struct nfs4_opendata;
+
enum {
NFS_LSEG_VALID = 0, /* cleared when lseg is recalled/returned */
NFS_LSEG_ROC, /* roc bit received from server */
@@ -110,6 +112,7 @@ enum layoutdriver_policy_flags {
PNFS_LAYOUTRET_ON_SETATTR = 1 << 0,
PNFS_LAYOUTRET_ON_ERROR = 1 << 1,
PNFS_READ_WHOLE_PAGE = 1 << 2,
+ PNFS_LAYOUTGET_ON_OPEN = 1 << 3,
};
struct nfs4_deviceid_node;
@@ -223,10 +226,11 @@ extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
/* nfs4proc.c */
+extern size_t max_response_pages(struct nfs_server *server);
extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
struct pnfs_device *dev,
struct rpc_cred *cred);
-extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags);
+extern struct pnfs_layout_segment* nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout);
extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp, bool sync);
/* pnfs.c */
@@ -246,6 +250,7 @@ size_t pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio,
struct nfs_page *prev, struct nfs_page *req);
void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg);
struct pnfs_layout_segment *pnfs_layout_process(struct nfs4_layoutget *lgp);
+void pnfs_layoutget_free(struct nfs4_layoutget *lgp);
void pnfs_free_lseg_list(struct list_head *tmp_list);
void pnfs_destroy_layout(struct nfs_inode *);
void pnfs_destroy_all_layouts(struct nfs_client *);
@@ -375,6 +380,11 @@ void pnfs_layout_mark_request_commit(struct nfs_page *req,
struct pnfs_layout_segment *lseg,
struct nfs_commit_info *cinfo,
u32 ds_commit_idx);
+void pnfs_lgopen_prepare(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx);
+void pnfs_parse_lgopen(struct inode *ino, struct nfs4_layoutget *lgp,
+ struct nfs_open_context *ctx);
+void nfs4_lgopen_release(struct nfs4_layoutget *lgp);
static inline bool nfs_have_layout(struct inode *inode)
{
@@ -775,6 +785,27 @@ static inline bool nfs4_refresh_layout_stateid(nfs4_stateid *dst,
{
return false;
}
+
+static inline void pnfs_lgopen_prepare(struct nfs4_opendata *data,
+ struct nfs_open_context *ctx)
+{
+}
+
+static inline void pnfs_parse_lgopen(struct inode *ino,
+ struct nfs4_layoutget *lgp,
+ struct nfs_open_context *ctx)
+{
+}
+
+static inline void nfs4_lgopen_release(struct nfs4_layoutget *lgp)
+{
+}
+
+static inline bool pnfs_layout_is_valid(const struct pnfs_layout_hdr *lo)
+{
+ return false;
+}
+
#endif /* CONFIG_NFS_V4_1 */
#if IS_ENABLED(CONFIG_NFS_V4_2)
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 4e93d63..e0c257b 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -99,7 +99,8 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
*/
static int
nfs_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
- struct nfs_fattr *fattr, struct nfs4_label *label)
+ struct nfs_fattr *fattr, struct nfs4_label *label,
+ struct inode *inode)
{
struct rpc_message msg = {
.rpc_proc = &nfs_procedures[NFSPROC_GETATTR],
@@ -321,7 +322,9 @@ nfs_proc_remove(struct inode *dir, struct dentry *dentry)
}
static void
-nfs_proc_unlink_setup(struct rpc_message *msg, struct dentry *dentry)
+nfs_proc_unlink_setup(struct rpc_message *msg,
+ struct dentry *dentry,
+ struct inode *inode)
{
msg->rpc_proc = &nfs_procedures[NFSPROC_REMOVE];
}
@@ -618,7 +621,8 @@ static int nfs_write_done(struct rpc_task *task, struct nfs_pgio_header *hdr)
}
static void nfs_proc_write_setup(struct nfs_pgio_header *hdr,
- struct rpc_message *msg)
+ struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
/* Note: NFSv2 ignores @stable and always uses NFS_FILE_SYNC */
hdr->args.stable = NFS_FILE_SYNC;
@@ -631,7 +635,8 @@ static void nfs_proc_commit_rpc_prepare(struct rpc_task *task, struct nfs_commit
}
static void
-nfs_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg)
+nfs_proc_commit_setup(struct nfs_commit_data *data, struct rpc_message *msg,
+ struct rpc_clnt **clnt)
{
BUG();
}
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c
index bf54fc9..fd61bf0 100644
--- a/fs/nfs/unlink.c
+++ b/fs/nfs/unlink.c
@@ -85,7 +85,7 @@ static const struct rpc_call_ops nfs_unlink_ops = {
.rpc_call_prepare = nfs_unlink_prepare,
};
-static void nfs_do_call_unlink(struct nfs_unlinkdata *data)
+static void nfs_do_call_unlink(struct inode *inode, struct nfs_unlinkdata *data)
{
struct rpc_message msg = {
.rpc_argp = &data->args,
@@ -105,7 +105,7 @@ static void nfs_do_call_unlink(struct nfs_unlinkdata *data)
data->args.fh = NFS_FH(dir);
nfs_fattr_init(data->res.dir_attr);
- NFS_PROTO(dir)->unlink_setup(&msg, data->dentry);
+ NFS_PROTO(dir)->unlink_setup(&msg, data->dentry, inode);
task_setup_data.rpc_client = NFS_CLIENT(dir);
task = rpc_run_task(&task_setup_data);
@@ -113,7 +113,7 @@ static void nfs_do_call_unlink(struct nfs_unlinkdata *data)
rpc_put_task_async(task);
}
-static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
+static int nfs_call_unlink(struct dentry *dentry, struct inode *inode, struct nfs_unlinkdata *data)
{
struct inode *dir = d_inode(dentry->d_parent);
struct dentry *alias;
@@ -153,7 +153,7 @@ static int nfs_call_unlink(struct dentry *dentry, struct nfs_unlinkdata *data)
return ret;
}
data->dentry = alias;
- nfs_do_call_unlink(data);
+ nfs_do_call_unlink(inode, data);
return 1;
}
@@ -231,7 +231,7 @@ nfs_complete_unlink(struct dentry *dentry, struct inode *inode)
dentry->d_fsdata = NULL;
spin_unlock(&dentry->d_lock);
- if (NFS_STALE(inode) || !nfs_call_unlink(dentry, data))
+ if (NFS_STALE(inode) || !nfs_call_unlink(dentry, inode, data))
nfs_free_unlinkdata(data);
}
@@ -448,6 +448,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
unsigned char silly[SILLYNAME_LEN + 1];
unsigned long long fileid;
struct dentry *sdentry;
+ struct inode *inode = d_inode(dentry);
struct rpc_task *task;
int error = -EBUSY;
@@ -485,6 +486,8 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
goto out;
} while (d_inode(sdentry) != NULL); /* need negative lookup */
+ ihold(inode);
+
/* queue unlink first. Can't do this from rpc_release as it
* has to allocate memory
*/
@@ -509,6 +512,12 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
case 0:
/* The rename succeeded */
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+ spin_lock(&inode->i_lock);
+ NFS_I(inode)->attr_gencount = nfs_inc_attr_generation_counter();
+ NFS_I(inode)->cache_validity |= NFS_INO_INVALID_CHANGE
+ | NFS_INO_INVALID_CTIME
+ | NFS_INO_REVAL_FORCED;
+ spin_unlock(&inode->i_lock);
d_move(dentry, sdentry);
break;
case -ERESTARTSYS:
@@ -519,6 +528,7 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry)
}
rpc_put_task(task);
out_dput:
+ iput(inode);
dput(sdentry);
out:
return error;
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 0193053..a057b4f 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1375,12 +1375,9 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
int priority = flush_task_priority(how);
task_setup_data->priority = priority;
- rpc_ops->write_setup(hdr, msg);
+ rpc_ops->write_setup(hdr, msg, &task_setup_data->rpc_client);
trace_nfs_initiate_write(hdr->inode, hdr->io_start, hdr->good_bytes,
hdr->args.stable);
-
- nfs4_state_protect_write(NFS_SERVER(hdr->inode)->nfs_client,
- &task_setup_data->rpc_client, msg, hdr);
}
/* If a nfs_flush_* function fails, it should remove reqs from @head and
@@ -1669,14 +1666,11 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data,
.priority = priority,
};
/* Set up the initial task struct. */
- nfs_ops->commit_setup(data, &msg);
+ nfs_ops->commit_setup(data, &msg, &task_setup_data.rpc_client);
trace_nfs_initiate_commit(data);
dprintk("NFS: initiated commit call\n");
- nfs4_state_protect(NFS_SERVER(data->inode)->nfs_client,
- NFS_SP4_MACH_CRED_COMMIT, &task_setup_data.rpc_client, &msg);
-
task = rpc_run_task(&task_setup_data);
if (IS_ERR(task))
return PTR_ERR(task);
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index a43dfed..4fb1f72 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -121,13 +121,15 @@ nfsd4_block_commit_blocks(struct inode *inode, struct nfsd4_layoutcommit *lcp,
{
loff_t new_size = lcp->lc_last_wr + 1;
struct iattr iattr = { .ia_valid = 0 };
+ struct timespec ts;
int error;
+ ts = timespec64_to_timespec(inode->i_mtime);
if (lcp->lc_mtime.tv_nsec == UTIME_NOW ||
- timespec_compare(&lcp->lc_mtime, &inode->i_mtime) < 0)
- lcp->lc_mtime = current_time(inode);
+ timespec_compare(&lcp->lc_mtime, &ts) < 0)
+ lcp->lc_mtime = timespec64_to_timespec(current_time(inode));
iattr.ia_valid |= ATTR_ATIME | ATTR_CTIME | ATTR_MTIME;
- iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = lcp->lc_mtime;
+ iattr.ia_atime = iattr.ia_ctime = iattr.ia_mtime = timespec_to_timespec64(lcp->lc_mtime);
if (new_size > i_size_read(inode)) {
iattr.ia_valid |= ATTR_SIZE;
@@ -216,13 +218,21 @@ static int nfsd4_scsi_identify_device(struct block_device *bdev,
struct request_queue *q = bdev->bd_disk->queue;
struct request *rq;
struct scsi_request *req;
- size_t bufflen = 252, len, id_len;
+ /*
+ * The allocation length (passed in bytes 3 and 4 of the INQUIRY
+ * command descriptor block) specifies the number of bytes that have
+ * been allocated for the data-in buffer.
+ * 252 is the highest one-byte value that is a multiple of 4.
+ * 65532 is the highest two-byte value that is a multiple of 4.
+ */
+ size_t bufflen = 252, maxlen = 65532, len, id_len;
u8 *buf, *d, type, assoc;
- int error;
+ int retries = 1, error;
if (WARN_ON_ONCE(!blk_queue_scsi_passthrough(q)))
return -EINVAL;
+again:
buf = kzalloc(bufflen, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -255,6 +265,12 @@ static int nfsd4_scsi_identify_device(struct block_device *bdev,
len = (buf[2] << 8) + buf[3] + 4;
if (len > bufflen) {
+ if (len <= maxlen && retries--) {
+ blk_put_request(rq);
+ kfree(buf);
+ bufflen = len;
+ goto again;
+ }
pr_err("pNFS: INQUIRY 0x83 response invalid (len = %zd)\n",
len);
goto out_put_request;
diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h
index 046b3f0..b7559c6 100644
--- a/fs/nfsd/cache.h
+++ b/fs/nfsd/cache.h
@@ -67,11 +67,6 @@ enum {
RC_REPLBUFF,
};
-/*
- * If requests are retransmitted within this interval, they're dropped.
- */
-#define RC_DELAY (HZ/5)
-
/* Cache entries expire after this time period */
#define RC_EXPIRE (120 * HZ)
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 8ceb25a..a1143f7 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -404,8 +404,9 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
if (fsloc->locations_count == 0)
return 0;
- fsloc->locations = kzalloc(fsloc->locations_count
- * sizeof(struct nfsd4_fs_location), GFP_KERNEL);
+ fsloc->locations = kcalloc(fsloc->locations_count,
+ sizeof(struct nfsd4_fs_location),
+ GFP_KERNEL);
if (!fsloc->locations)
return -ENOMEM;
for (i=0; i < fsloc->locations_count; i++) {
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 3192b54..9b973f4 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -165,6 +165,7 @@ static __be32 *
encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
struct kstat *stat)
{
+ struct timespec ts;
*p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
*p++ = htonl((u32) (stat->mode & S_IALLUGO));
*p++ = htonl((u32) stat->nlink);
@@ -180,9 +181,12 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
*p++ = htonl((u32) MINOR(stat->rdev));
p = encode_fsid(p, fhp);
p = xdr_encode_hyper(p, stat->ino);
- p = encode_time3(p, &stat->atime);
- p = encode_time3(p, &stat->mtime);
- p = encode_time3(p, &stat->ctime);
+ ts = timespec64_to_timespec(stat->atime);
+ p = encode_time3(p, &ts);
+ ts = timespec64_to_timespec(stat->mtime);
+ p = encode_time3(p, &ts);
+ ts = timespec64_to_timespec(stat->ctime);
+ p = encode_time3(p, &ts);
return p;
}
@@ -271,8 +275,8 @@ void fill_pre_wcc(struct svc_fh *fhp)
stat.size = inode->i_size;
}
- fhp->fh_pre_mtime = stat.mtime;
- fhp->fh_pre_ctime = stat.ctime;
+ fhp->fh_pre_mtime = timespec64_to_timespec(stat.mtime);
+ fhp->fh_pre_ctime = timespec64_to_timespec(stat.ctime);
fhp->fh_pre_size = stat.size;
fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode);
fhp->fh_pre_saved = true;
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 66eaeb1..9c247fa1 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -510,8 +510,9 @@ nfs4_legacy_state_init(struct net *net)
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
int i;
- nn->reclaim_str_hashtbl = kmalloc(sizeof(struct list_head) *
- CLIENT_HASH_SIZE, GFP_KERNEL);
+ nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!nn->reclaim_str_hashtbl)
return -ENOMEM;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index fc74d6f..8571414 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1807,8 +1807,9 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
clp->cl_name.data = kmemdup(name.data, name.len, GFP_KERNEL);
if (clp->cl_name.data == NULL)
goto err_no_name;
- clp->cl_ownerstr_hashtbl = kmalloc(sizeof(struct list_head) *
- OWNER_HASH_SIZE, GFP_KERNEL);
+ clp->cl_ownerstr_hashtbl = kmalloc_array(OWNER_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!clp->cl_ownerstr_hashtbl)
goto err_no_hashtbl;
for (i = 0; i < OWNER_HASH_SIZE; i++)
@@ -4378,8 +4379,11 @@ nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
spin_unlock(&state_lock);
if (status)
- destroy_unhashed_deleg(dp);
+ goto out_unlock;
+
return dp;
+out_unlock:
+ vfs_setlease(fp->fi_deleg_file, F_UNLCK, NULL, (void **)&dp);
out_clnt_odstate:
put_clnt_odstate(dp->dl_clnt_odstate);
out_stid:
@@ -7093,16 +7097,19 @@ static int nfs4_state_create_net(struct net *net)
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
int i;
- nn->conf_id_hashtbl = kmalloc(sizeof(struct list_head) *
- CLIENT_HASH_SIZE, GFP_KERNEL);
+ nn->conf_id_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!nn->conf_id_hashtbl)
goto err;
- nn->unconf_id_hashtbl = kmalloc(sizeof(struct list_head) *
- CLIENT_HASH_SIZE, GFP_KERNEL);
+ nn->unconf_id_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!nn->unconf_id_hashtbl)
goto err_unconf_id;
- nn->sessionid_hashtbl = kmalloc(sizeof(struct list_head) *
- SESSION_HASH_SIZE, GFP_KERNEL);
+ nn->sessionid_hashtbl = kmalloc_array(SESSION_HASH_SIZE,
+ sizeof(struct list_head),
+ GFP_KERNEL);
if (!nn->sessionid_hashtbl)
goto err_sessionid;
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 1d048dd..a96843c 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -320,6 +320,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
struct iattr *iattr, struct nfs4_acl **acl,
struct xdr_netobj *label, int *umask)
{
+ struct timespec ts;
int expected_len, len = 0;
u32 dummy32;
char *buf;
@@ -421,7 +422,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
switch (dummy32) {
case NFS4_SET_TO_CLIENT_TIME:
len += 12;
- status = nfsd4_decode_time(argp, &iattr->ia_atime);
+ status = nfsd4_decode_time(argp, &ts);
+ iattr->ia_atime = timespec_to_timespec64(ts);
if (status)
return status;
iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
@@ -440,7 +442,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
switch (dummy32) {
case NFS4_SET_TO_CLIENT_TIME:
len += 12;
- status = nfsd4_decode_time(argp, &iattr->ia_mtime);
+ status = nfsd4_decode_time(argp, &ts);
+ iattr->ia_mtime = timespec_to_timespec64(ts);
if (status)
return status;
iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
@@ -1585,6 +1588,8 @@ nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp,
gdev->gd_maxcount = be32_to_cpup(p++);
num = be32_to_cpup(p++);
if (num) {
+ if (num > 1000)
+ goto xdr_error;
READ_BUF(4 * num);
gdev->gd_notify_types = be32_to_cpup(p++);
for (i = 1; i < num; i++) {
@@ -3651,7 +3656,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
nfserr = nfserr_resource;
goto err_no_verf;
}
- maxcount = min_t(u32, readdir->rd_maxcount, INT_MAX);
+ maxcount = svc_max_payload(resp->rqstp);
+ maxcount = min_t(u32, readdir->rd_maxcount, maxcount);
/*
* Note the rfc defines rd_maxcount as the size of the
* READDIR4resok structure, which includes the verifier above
@@ -3665,7 +3671,7 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4
/* RFC 3530 14.2.24 allows us to ignore dircount when it's 0: */
if (!readdir->rd_dircount)
- readdir->rd_dircount = INT_MAX;
+ readdir->rd_dircount = svc_max_payload(resp->rqstp);
readdir->xdr = xdr;
readdir->rd_maxcount = maxcount;
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 334f2ad..dbdeb9d 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -177,7 +177,8 @@ int nfsd_reply_cache_init(void)
drc_hashtbl = kcalloc(hashsize, sizeof(*drc_hashtbl), GFP_KERNEL);
if (!drc_hashtbl) {
- drc_hashtbl = vzalloc(hashsize * sizeof(*drc_hashtbl));
+ drc_hashtbl = vzalloc(array_size(hashsize,
+ sizeof(*drc_hashtbl)));
if (!drc_hashtbl)
goto out_nomem;
}
@@ -394,7 +395,6 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
__wsum csum;
u32 hash = nfsd_cache_hash(xid);
struct nfsd_drc_bucket *b = &drc_hashtbl[hash];
- unsigned long age;
int type = rqstp->rq_cachetype;
int rtn = RC_DOIT;
@@ -461,12 +461,11 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
found_entry:
nfsdstats.rchits++;
/* We found a matching entry which is either in progress or done. */
- age = jiffies - rp->c_timestamp;
lru_put_end(b, rp);
rtn = RC_DROPIT;
- /* Request being processed or excessive rexmits */
- if (rp->c_state == RC_INPROG || age < RC_DELAY)
+ /* Request being processed */
+ if (rp->c_state == RC_INPROG)
goto out;
/* From the hall of fame of impractical attacks:
diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index a43e826..6b2e8b7 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -131,7 +131,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
{
struct dentry *dentry = fhp->fh_dentry;
int type;
- struct timespec time;
+ struct timespec64 time;
u32 f;
type = (stat->mode & S_IFMT);
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 63a1ca4..e2bea2a 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -79,12 +79,11 @@ static void dnotify_recalc_inode_mask(struct fsnotify_mark *fsn_mark)
*/
static int dnotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
+ struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
struct dnotify_mark *dn_mark;
struct dnotify_struct *dn;
struct dnotify_struct **prev;
@@ -95,7 +94,8 @@ static int dnotify_handle_event(struct fsnotify_group *group,
if (!S_ISDIR(inode->i_mode))
return 0;
- BUG_ON(vfsmount_mark);
+ if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
+ return 0;
dn_mark = container_of(inode_mark, struct dnotify_mark, fsn_mark);
@@ -319,7 +319,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
spin_lock(&fsn_mark->lock);
} else {
- error = fsnotify_add_mark_locked(new_fsn_mark, inode, NULL, 0);
+ error = fsnotify_add_inode_mark_locked(new_fsn_mark, inode, 0);
if (error) {
mutex_unlock(&dnotify_group->mark_mutex);
goto out_err;
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index d94e803..f90842e 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -87,17 +87,17 @@ static int fanotify_get_response(struct fsnotify_group *group,
return ret;
}
-static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmnt_mark,
- u32 event_mask,
- const void *data, int data_type)
+static bool fanotify_should_send_event(struct fsnotify_iter_info *iter_info,
+ u32 event_mask, const void *data,
+ int data_type)
{
__u32 marks_mask = 0, marks_ignored_mask = 0;
const struct path *path = data;
+ struct fsnotify_mark *mark;
+ int type;
- pr_debug("%s: inode_mark=%p vfsmnt_mark=%p mask=%x data=%p"
- " data_type=%d\n", __func__, inode_mark, vfsmnt_mark,
- event_mask, data, data_type);
+ pr_debug("%s: report_mask=%x mask=%x data=%p data_type=%d\n",
+ __func__, iter_info->report_mask, event_mask, data, data_type);
/* if we don't have enough info to send an event to userspace say no */
if (data_type != FSNOTIFY_EVENT_PATH)
@@ -108,20 +108,21 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark,
!d_can_lookup(path->dentry))
return false;
- /*
- * if the event is for a child and this inode doesn't care about
- * events on the child, don't send it!
- */
- if (inode_mark &&
- (!(event_mask & FS_EVENT_ON_CHILD) ||
- (inode_mark->mask & FS_EVENT_ON_CHILD))) {
- marks_mask |= inode_mark->mask;
- marks_ignored_mask |= inode_mark->ignored_mask;
- }
+ fsnotify_foreach_obj_type(type) {
+ if (!fsnotify_iter_should_report_type(iter_info, type))
+ continue;
+ mark = iter_info->marks[type];
+ /*
+ * if the event is for a child and this inode doesn't care about
+ * events on the child, don't send it!
+ */
+ if (type == FSNOTIFY_OBJ_TYPE_INODE &&
+ (event_mask & FS_EVENT_ON_CHILD) &&
+ !(mark->mask & FS_EVENT_ON_CHILD))
+ continue;
- if (vfsmnt_mark) {
- marks_mask |= vfsmnt_mark->mask;
- marks_ignored_mask |= vfsmnt_mark->ignored_mask;
+ marks_mask |= mark->mask;
+ marks_ignored_mask |= mark->ignored_mask;
}
if (d_is_dir(path->dentry) &&
@@ -178,8 +179,6 @@ init: __maybe_unused
static int fanotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *fanotify_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
@@ -199,8 +198,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
- if (!fanotify_should_send_event(inode_mark, fanotify_mark, mask, data,
- data_type))
+ if (!fanotify_should_send_event(iter_info, mask, data, data_type))
return 0;
pr_debug("%s: group=%p inode=%p mask=%x\n", __func__, group, inode,
diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c
index d478629..10aac19 100644
--- a/fs/notify/fdinfo.c
+++ b/fs/notify/fdinfo.c
@@ -77,7 +77,7 @@ static void inotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
struct inotify_inode_mark *inode_mark;
struct inode *inode;
- if (!(mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE))
+ if (mark->connector->type != FSNOTIFY_OBJ_TYPE_INODE)
return;
inode_mark = container_of(mark, struct inotify_inode_mark, fsn_mark);
@@ -116,7 +116,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
if (mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY)
mflags |= FAN_MARK_IGNORED_SURV_MODIFY;
- if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_INODE) {
+ if (mark->connector->type == FSNOTIFY_OBJ_TYPE_INODE) {
inode = igrab(mark->connector->inode);
if (!inode)
return;
@@ -126,7 +126,7 @@ static void fanotify_fdinfo(struct seq_file *m, struct fsnotify_mark *mark)
show_mark_fhandle(m, inode);
seq_putc(m, '\n');
iput(inode);
- } else if (mark->connector->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
+ } else if (mark->connector->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
struct mount *mnt = real_mount(mark->connector->mnt);
seq_printf(m, "fanotify mnt_id:%x mflags:%x mask:%x ignored_mask:%x\n",
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 613ec7e..f174397 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -184,8 +184,6 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask
EXPORT_SYMBOL_GPL(__fsnotify_parent);
static int send_to_group(struct inode *to_tell,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
__u32 mask, const void *data,
int data_is, u32 cookie,
const unsigned char *file_name,
@@ -195,48 +193,45 @@ static int send_to_group(struct inode *to_tell,
__u32 test_mask = (mask & ~FS_EVENT_ON_CHILD);
__u32 marks_mask = 0;
__u32 marks_ignored_mask = 0;
+ struct fsnotify_mark *mark;
+ int type;
- if (unlikely(!inode_mark && !vfsmount_mark)) {
- BUG();
+ if (WARN_ON(!iter_info->report_mask))
return 0;
- }
/* clear ignored on inode modification */
if (mask & FS_MODIFY) {
- if (inode_mark &&
- !(inode_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
- inode_mark->ignored_mask = 0;
- if (vfsmount_mark &&
- !(vfsmount_mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
- vfsmount_mark->ignored_mask = 0;
- }
-
- /* does the inode mark tell us to do something? */
- if (inode_mark) {
- group = inode_mark->group;
- marks_mask |= inode_mark->mask;
- marks_ignored_mask |= inode_mark->ignored_mask;
+ fsnotify_foreach_obj_type(type) {
+ if (!fsnotify_iter_should_report_type(iter_info, type))
+ continue;
+ mark = iter_info->marks[type];
+ if (mark &&
+ !(mark->flags & FSNOTIFY_MARK_FLAG_IGNORED_SURV_MODIFY))
+ mark->ignored_mask = 0;
+ }
}
- /* does the vfsmount_mark tell us to do something? */
- if (vfsmount_mark) {
- group = vfsmount_mark->group;
- marks_mask |= vfsmount_mark->mask;
- marks_ignored_mask |= vfsmount_mark->ignored_mask;
+ fsnotify_foreach_obj_type(type) {
+ if (!fsnotify_iter_should_report_type(iter_info, type))
+ continue;
+ mark = iter_info->marks[type];
+ /* does the object mark tell us to do something? */
+ if (mark) {
+ group = mark->group;
+ marks_mask |= mark->mask;
+ marks_ignored_mask |= mark->ignored_mask;
+ }
}
- pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p"
- " vfsmount_mark=%p marks_mask=%x marks_ignored_mask=%x"
+ pr_debug("%s: group=%p to_tell=%p mask=%x marks_mask=%x marks_ignored_mask=%x"
" data=%p data_is=%d cookie=%d\n",
- __func__, group, to_tell, mask, inode_mark, vfsmount_mark,
- marks_mask, marks_ignored_mask, data,
- data_is, cookie);
+ __func__, group, to_tell, mask, marks_mask, marks_ignored_mask,
+ data, data_is, cookie);
if (!(test_mask & marks_mask & ~marks_ignored_mask))
return 0;
- return group->ops->handle_event(group, to_tell, inode_mark,
- vfsmount_mark, mask, data, data_is,
+ return group->ops->handle_event(group, to_tell, mask, data, data_is,
file_name, cookie, iter_info);
}
@@ -264,6 +259,57 @@ static struct fsnotify_mark *fsnotify_next_mark(struct fsnotify_mark *mark)
}
/*
+ * iter_info is a multi head priority queue of marks.
+ * Pick a subset of marks from queue heads, all with the
+ * same group and set the report_mask for selected subset.
+ * Returns the report_mask of the selected subset.
+ */
+static unsigned int fsnotify_iter_select_report_types(
+ struct fsnotify_iter_info *iter_info)
+{
+ struct fsnotify_group *max_prio_group = NULL;
+ struct fsnotify_mark *mark;
+ int type;
+
+ /* Choose max prio group among groups of all queue heads */
+ fsnotify_foreach_obj_type(type) {
+ mark = iter_info->marks[type];
+ if (mark &&
+ fsnotify_compare_groups(max_prio_group, mark->group) > 0)
+ max_prio_group = mark->group;
+ }
+
+ if (!max_prio_group)
+ return 0;
+
+ /* Set the report mask for marks from same group as max prio group */
+ iter_info->report_mask = 0;
+ fsnotify_foreach_obj_type(type) {
+ mark = iter_info->marks[type];
+ if (mark &&
+ fsnotify_compare_groups(max_prio_group, mark->group) == 0)
+ fsnotify_iter_set_report_type(iter_info, type);
+ }
+
+ return iter_info->report_mask;
+}
+
+/*
+ * Pop from iter_info multi head queue, the marks that were iterated in the
+ * current iteration step.
+ */
+static void fsnotify_iter_next(struct fsnotify_iter_info *iter_info)
+{
+ int type;
+
+ fsnotify_foreach_obj_type(type) {
+ if (fsnotify_iter_should_report_type(iter_info, type))
+ iter_info->marks[type] =
+ fsnotify_next_mark(iter_info->marks[type]);
+ }
+}
+
+/*
* This is the main call to fsnotify. The VFS calls into hook specific functions
* in linux/fsnotify.h. Those functions then in turn call here. Here will call
* out to all of the registered fsnotify_group. Those groups can then use the
@@ -307,15 +353,15 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
if ((mask & FS_MODIFY) ||
(test_mask & to_tell->i_fsnotify_mask)) {
- iter_info.inode_mark =
+ iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
fsnotify_first_mark(&to_tell->i_fsnotify_marks);
}
if (mnt && ((mask & FS_MODIFY) ||
(test_mask & mnt->mnt_fsnotify_mask))) {
- iter_info.inode_mark =
+ iter_info.marks[FSNOTIFY_OBJ_TYPE_INODE] =
fsnotify_first_mark(&to_tell->i_fsnotify_marks);
- iter_info.vfsmount_mark =
+ iter_info.marks[FSNOTIFY_OBJ_TYPE_VFSMOUNT] =
fsnotify_first_mark(&mnt->mnt_fsnotify_marks);
}
@@ -324,32 +370,14 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
* ignore masks are properly reflected for mount mark notifications.
* That's why this traversal is so complicated...
*/
- while (iter_info.inode_mark || iter_info.vfsmount_mark) {
- struct fsnotify_mark *inode_mark = iter_info.inode_mark;
- struct fsnotify_mark *vfsmount_mark = iter_info.vfsmount_mark;
-
- if (inode_mark && vfsmount_mark) {
- int cmp = fsnotify_compare_groups(inode_mark->group,
- vfsmount_mark->group);
- if (cmp > 0)
- inode_mark = NULL;
- else if (cmp < 0)
- vfsmount_mark = NULL;
- }
-
- ret = send_to_group(to_tell, inode_mark, vfsmount_mark, mask,
- data, data_is, cookie, file_name,
- &iter_info);
+ while (fsnotify_iter_select_report_types(&iter_info)) {
+ ret = send_to_group(to_tell, mask, data, data_is, cookie,
+ file_name, &iter_info);
if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
goto out;
- if (inode_mark)
- iter_info.inode_mark =
- fsnotify_next_mark(iter_info.inode_mark);
- if (vfsmount_mark)
- iter_info.vfsmount_mark =
- fsnotify_next_mark(iter_info.vfsmount_mark);
+ fsnotify_iter_next(&iter_info);
}
ret = 0;
out:
diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h
index 60f365d..34515d2 100644
--- a/fs/notify/fsnotify.h
+++ b/fs/notify/fsnotify.h
@@ -9,12 +9,6 @@
#include "../mount.h"
-struct fsnotify_iter_info {
- struct fsnotify_mark *inode_mark;
- struct fsnotify_mark *vfsmount_mark;
- int srcu_idx;
-};
-
/* destroy all events sitting in this groups notification queue */
extern void fsnotify_flush_notify(struct fsnotify_group *group);
diff --git a/fs/notify/group.c b/fs/notify/group.c
index b7a4b6a..aa5468f2 100644
--- a/fs/notify/group.c
+++ b/fs/notify/group.c
@@ -67,7 +67,7 @@ void fsnotify_destroy_group(struct fsnotify_group *group)
fsnotify_group_stop_queueing(group);
/* Clear all marks for this group and queue them for destruction */
- fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_ALL_TYPES);
+ fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_ALL_TYPES_MASK);
/*
* Some marks can still be pinned when waiting for response from
diff --git a/fs/notify/inotify/inotify.h b/fs/notify/inotify/inotify.h
index c00d2ca..7e4578d 100644
--- a/fs/notify/inotify/inotify.h
+++ b/fs/notify/inotify/inotify.h
@@ -25,8 +25,6 @@ extern void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
struct fsnotify_group *group);
extern int inotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info);
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
index 40dedb3..9ab6dde 100644
--- a/fs/notify/inotify/inotify_fsnotify.c
+++ b/fs/notify/inotify/inotify_fsnotify.c
@@ -65,12 +65,11 @@ static int inotify_merge(struct list_head *list,
int inotify_handle_event(struct fsnotify_group *group,
struct inode *inode,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
+ struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
struct inotify_inode_mark *i_mark;
struct inotify_event_info *event;
struct fsnotify_event *fsn_event;
@@ -78,7 +77,8 @@ int inotify_handle_event(struct fsnotify_group *group,
int len = 0;
int alloc_len = sizeof(struct inotify_event_info);
- BUG_ON(vfsmount_mark);
+ if (WARN_ON(fsnotify_iter_vfsmount_mark(iter_info)))
+ return 0;
if ((inode_mark->mask & FS_EXCL_UNLINK) &&
(data_type == FSNOTIFY_EVENT_PATH)) {
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index ef32f36..1cf5b77 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -485,10 +485,14 @@ void inotify_ignored_and_remove_idr(struct fsnotify_mark *fsn_mark,
struct fsnotify_group *group)
{
struct inotify_inode_mark *i_mark;
+ struct fsnotify_iter_info iter_info = { };
+
+ fsnotify_iter_set_report_type_mark(&iter_info, FSNOTIFY_OBJ_TYPE_INODE,
+ fsn_mark);
/* Queue ignore event for the watch */
- inotify_handle_event(group, NULL, fsn_mark, NULL, FS_IN_IGNORED,
- NULL, FSNOTIFY_EVENT_NONE, NULL, 0, NULL);
+ inotify_handle_event(group, NULL, FS_IN_IGNORED, NULL,
+ FSNOTIFY_EVENT_NONE, NULL, 0, &iter_info);
i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
/* remove this mark from the idr */
@@ -578,7 +582,7 @@ static int inotify_new_watch(struct fsnotify_group *group,
}
/* we are on the idr, now get on the inode */
- ret = fsnotify_add_mark_locked(&tmp_i_mark->fsn_mark, inode, NULL, 0);
+ ret = fsnotify_add_inode_mark_locked(&tmp_i_mark->fsn_mark, inode, 0);
if (ret) {
/* we failed to get on the inode, get off the idr */
inotify_remove_from_idr(group, tmp_i_mark);
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index e9191b4..61f4c5f 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -119,9 +119,9 @@ static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
if (mark->flags & FSNOTIFY_MARK_FLAG_ATTACHED)
new_mask |= mark->mask;
}
- if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE)
+ if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
conn->inode->i_fsnotify_mask = new_mask;
- else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT)
+ else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT)
real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask;
}
@@ -139,7 +139,7 @@ void fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
spin_lock(&conn->lock);
__fsnotify_recalc_mask(conn);
spin_unlock(&conn->lock);
- if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE)
+ if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
__fsnotify_update_child_dentry_flags(conn->inode);
}
@@ -166,18 +166,18 @@ static struct inode *fsnotify_detach_connector_from_object(
{
struct inode *inode = NULL;
- if (conn->flags & FSNOTIFY_OBJ_TYPE_INODE) {
+ if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) {
inode = conn->inode;
rcu_assign_pointer(inode->i_fsnotify_marks, NULL);
inode->i_fsnotify_mask = 0;
conn->inode = NULL;
- conn->flags &= ~FSNOTIFY_OBJ_TYPE_INODE;
- } else if (conn->flags & FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
+ conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
+ } else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
rcu_assign_pointer(real_mount(conn->mnt)->mnt_fsnotify_marks,
NULL);
real_mount(conn->mnt)->mnt_fsnotify_mask = 0;
conn->mnt = NULL;
- conn->flags &= ~FSNOTIFY_OBJ_TYPE_VFSMOUNT;
+ conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
}
return inode;
@@ -294,12 +294,12 @@ static void fsnotify_put_mark_wake(struct fsnotify_mark *mark)
bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
{
- /* This can fail if mark is being removed */
- if (!fsnotify_get_mark_safe(iter_info->inode_mark))
- return false;
- if (!fsnotify_get_mark_safe(iter_info->vfsmount_mark)) {
- fsnotify_put_mark_wake(iter_info->inode_mark);
- return false;
+ int type;
+
+ fsnotify_foreach_obj_type(type) {
+ /* This can fail if mark is being removed */
+ if (!fsnotify_get_mark_safe(iter_info->marks[type]))
+ goto fail;
}
/*
@@ -310,13 +310,20 @@ bool fsnotify_prepare_user_wait(struct fsnotify_iter_info *iter_info)
srcu_read_unlock(&fsnotify_mark_srcu, iter_info->srcu_idx);
return true;
+
+fail:
+ for (type--; type >= 0; type--)
+ fsnotify_put_mark_wake(iter_info->marks[type]);
+ return false;
}
void fsnotify_finish_user_wait(struct fsnotify_iter_info *iter_info)
{
+ int type;
+
iter_info->srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
- fsnotify_put_mark_wake(iter_info->inode_mark);
- fsnotify_put_mark_wake(iter_info->vfsmount_mark);
+ fsnotify_foreach_obj_type(type)
+ fsnotify_put_mark_wake(iter_info->marks[type]);
}
/*
@@ -442,10 +449,10 @@ static int fsnotify_attach_connector_to_object(
spin_lock_init(&conn->lock);
INIT_HLIST_HEAD(&conn->list);
if (inode) {
- conn->flags = FSNOTIFY_OBJ_TYPE_INODE;
+ conn->type = FSNOTIFY_OBJ_TYPE_INODE;
conn->inode = igrab(inode);
} else {
- conn->flags = FSNOTIFY_OBJ_TYPE_VFSMOUNT;
+ conn->type = FSNOTIFY_OBJ_TYPE_VFSMOUNT;
conn->mnt = mnt;
}
/*
@@ -479,8 +486,7 @@ static struct fsnotify_mark_connector *fsnotify_grab_connector(
if (!conn)
goto out;
spin_lock(&conn->lock);
- if (!(conn->flags & (FSNOTIFY_OBJ_TYPE_INODE |
- FSNOTIFY_OBJ_TYPE_VFSMOUNT))) {
+ if (conn->type == FSNOTIFY_OBJ_TYPE_DETACHED) {
spin_unlock(&conn->lock);
srcu_read_unlock(&fsnotify_mark_srcu, idx);
return NULL;
@@ -646,16 +652,16 @@ struct fsnotify_mark *fsnotify_find_mark(
return NULL;
}
-/* Clear any marks in a group with given type */
+/* Clear any marks in a group with given type mask */
void fsnotify_clear_marks_by_group(struct fsnotify_group *group,
- unsigned int type)
+ unsigned int type_mask)
{
struct fsnotify_mark *lmark, *mark;
LIST_HEAD(to_free);
struct list_head *head = &to_free;
/* Skip selection step if we want to clear all marks. */
- if (type == FSNOTIFY_OBJ_ALL_TYPES) {
+ if (type_mask == FSNOTIFY_OBJ_ALL_TYPES_MASK) {
head = &group->marks_list;
goto clear;
}
@@ -670,7 +676,7 @@ void fsnotify_clear_marks_by_group(struct fsnotify_group *group,
*/
mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
- if (mark->connector->flags & type)
+ if ((1U << mark->connector->type) & type_mask)
list_move(&mark->g_list, &to_free);
}
mutex_unlock(&group->mark_mutex);
diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c
index f8eb043..fbd0090 100644
--- a/fs/ntfs/compress.c
+++ b/fs/ntfs/compress.c
@@ -527,7 +527,7 @@ int ntfs_read_compressed_block(struct page *page)
BUG_ON(ni->type != AT_DATA);
BUG_ON(ni->name_len);
- pages = kmalloc(nr_pages * sizeof(struct page *), GFP_NOFS);
+ pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_NOFS);
/* Allocate memory to store the buffer heads we need. */
bhs_size = cb_size / block_size * sizeof(struct buffer_head *);
diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c
index 1c1ee48..decaf75 100644
--- a/fs/ntfs/inode.c
+++ b/fs/ntfs/inode.c
@@ -667,18 +667,18 @@ static int ntfs_read_locked_inode(struct inode *vi)
* mtime is the last change of the data within the file. Not changed
* when only metadata is changed, e.g. a rename doesn't affect mtime.
*/
- vi->i_mtime = ntfs2utc(si->last_data_change_time);
+ vi->i_mtime = timespec_to_timespec64(ntfs2utc(si->last_data_change_time));
/*
* ctime is the last change of the metadata of the file. This obviously
* always changes, when mtime is changed. ctime can be changed on its
* own, mtime is then not changed, e.g. when a file is renamed.
*/
- vi->i_ctime = ntfs2utc(si->last_mft_change_time);
+ vi->i_ctime = timespec_to_timespec64(ntfs2utc(si->last_mft_change_time));
/*
* Last access to the data within the file. Not changed during a rename
* for example but changed whenever the file is written to.
*/
- vi->i_atime = ntfs2utc(si->last_access_time);
+ vi->i_atime = timespec_to_timespec64(ntfs2utc(si->last_access_time));
/* Find the attribute list attribute if present. */
ntfs_attr_reinit_search_ctx(ctx);
@@ -2804,11 +2804,11 @@ done:
* for real.
*/
if (!IS_NOCMTIME(VFS_I(base_ni)) && !IS_RDONLY(VFS_I(base_ni))) {
- struct timespec now = current_time(VFS_I(base_ni));
+ struct timespec64 now = current_time(VFS_I(base_ni));
int sync_it = 0;
- if (!timespec_equal(&VFS_I(base_ni)->i_mtime, &now) ||
- !timespec_equal(&VFS_I(base_ni)->i_ctime, &now))
+ if (!timespec64_equal(&VFS_I(base_ni)->i_mtime, &now) ||
+ !timespec64_equal(&VFS_I(base_ni)->i_ctime, &now))
sync_it = 1;
VFS_I(base_ni)->i_mtime = now;
VFS_I(base_ni)->i_ctime = now;
@@ -2923,14 +2923,14 @@ int ntfs_setattr(struct dentry *dentry, struct iattr *attr)
}
}
if (ia_valid & ATTR_ATIME)
- vi->i_atime = timespec_trunc(attr->ia_atime,
- vi->i_sb->s_time_gran);
+ vi->i_atime = timespec64_trunc(attr->ia_atime,
+ vi->i_sb->s_time_gran);
if (ia_valid & ATTR_MTIME)
- vi->i_mtime = timespec_trunc(attr->ia_mtime,
- vi->i_sb->s_time_gran);
+ vi->i_mtime = timespec64_trunc(attr->ia_mtime,
+ vi->i_sb->s_time_gran);
if (ia_valid & ATTR_CTIME)
- vi->i_ctime = timespec_trunc(attr->ia_ctime,
- vi->i_sb->s_time_gran);
+ vi->i_ctime = timespec64_trunc(attr->ia_ctime,
+ vi->i_sb->s_time_gran);
mark_inode_dirty(vi);
out:
return err;
@@ -2997,7 +2997,7 @@ int __ntfs_write_inode(struct inode *vi, int sync)
si = (STANDARD_INFORMATION*)((u8*)ctx->attr +
le16_to_cpu(ctx->attr->data.resident.value_offset));
/* Update the access times if they have changed. */
- nt = utc2ntfs(vi->i_mtime);
+ nt = utc2ntfs(timespec64_to_timespec(vi->i_mtime));
if (si->last_data_change_time != nt) {
ntfs_debug("Updating mtime for inode 0x%lx: old = 0x%llx, "
"new = 0x%llx", vi->i_ino, (long long)
@@ -3006,7 +3006,7 @@ int __ntfs_write_inode(struct inode *vi, int sync)
si->last_data_change_time = nt;
modified = true;
}
- nt = utc2ntfs(vi->i_ctime);
+ nt = utc2ntfs(timespec64_to_timespec(vi->i_ctime));
if (si->last_mft_change_time != nt) {
ntfs_debug("Updating ctime for inode 0x%lx: old = 0x%llx, "
"new = 0x%llx", vi->i_ino, (long long)
@@ -3015,7 +3015,7 @@ int __ntfs_write_inode(struct inode *vi, int sync)
si->last_mft_change_time = nt;
modified = true;
}
- nt = utc2ntfs(vi->i_atime);
+ nt = utc2ntfs(timespec64_to_timespec(vi->i_atime));
if (si->last_access_time != nt) {
ntfs_debug("Updating atime for inode 0x%lx: old = 0x%llx, "
"new = 0x%llx", vi->i_ino,
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index e507618..1296f78 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -1078,7 +1078,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
o2net_set_nst_sock_container(&nst, sc);
veclen = caller_veclen + 1;
- vec = kmalloc(sizeof(struct kvec) * veclen, GFP_ATOMIC);
+ vec = kmalloc_array(veclen, sizeof(struct kvec), GFP_ATOMIC);
if (vec == NULL) {
mlog(0, "failed to %zu element kvec!\n", veclen);
ret = -ENOMEM;
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c
index 425081b..2acd58b 100644
--- a/fs/ocfs2/dlm/dlmdomain.c
+++ b/fs/ocfs2/dlm/dlmdomain.c
@@ -86,7 +86,7 @@ static void dlm_free_pagevec(void **vec, int pages)
static void **dlm_alloc_pagevec(int pages)
{
- void **vec = kmalloc(pages * sizeof(void *), GFP_KERNEL);
+ void **vec = kmalloc_array(pages, sizeof(void *), GFP_KERNEL);
int i;
if (!vec)
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 68728de..0ff424c 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -2140,6 +2140,7 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
struct ocfs2_inode_info *oi = OCFS2_I(inode);
struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres;
struct ocfs2_meta_lvb *lvb;
+ struct timespec ts;
lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
@@ -2160,12 +2161,15 @@ static void __ocfs2_stuff_meta_lvb(struct inode *inode)
lvb->lvb_igid = cpu_to_be32(i_gid_read(inode));
lvb->lvb_imode = cpu_to_be16(inode->i_mode);
lvb->lvb_inlink = cpu_to_be16(inode->i_nlink);
+ ts = timespec64_to_timespec(inode->i_atime);
lvb->lvb_iatime_packed =
- cpu_to_be64(ocfs2_pack_timespec(&inode->i_atime));
+ cpu_to_be64(ocfs2_pack_timespec(&ts));
+ ts = timespec64_to_timespec(inode->i_ctime);
lvb->lvb_ictime_packed =
- cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime));
+ cpu_to_be64(ocfs2_pack_timespec(&ts));
+ ts = timespec64_to_timespec(inode->i_mtime);
lvb->lvb_imtime_packed =
- cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime));
+ cpu_to_be64(ocfs2_pack_timespec(&ts));
lvb->lvb_iattr = cpu_to_be32(oi->ip_attr);
lvb->lvb_idynfeatures = cpu_to_be16(oi->ip_dyn_features);
lvb->lvb_igeneration = cpu_to_be32(inode->i_generation);
@@ -2183,6 +2187,7 @@ static void ocfs2_unpack_timespec(struct timespec *spec,
static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
{
+ struct timespec ts;
struct ocfs2_inode_info *oi = OCFS2_I(inode);
struct ocfs2_lock_res *lockres = &oi->ip_inode_lockres;
struct ocfs2_meta_lvb *lvb;
@@ -2210,12 +2215,15 @@ static void ocfs2_refresh_inode_from_lvb(struct inode *inode)
i_gid_write(inode, be32_to_cpu(lvb->lvb_igid));
inode->i_mode = be16_to_cpu(lvb->lvb_imode);
set_nlink(inode, be16_to_cpu(lvb->lvb_inlink));
- ocfs2_unpack_timespec(&inode->i_atime,
+ ocfs2_unpack_timespec(&ts,
be64_to_cpu(lvb->lvb_iatime_packed));
- ocfs2_unpack_timespec(&inode->i_mtime,
+ inode->i_atime = timespec_to_timespec64(ts);
+ ocfs2_unpack_timespec(&ts,
be64_to_cpu(lvb->lvb_imtime_packed));
- ocfs2_unpack_timespec(&inode->i_ctime,
+ inode->i_mtime = timespec_to_timespec64(ts);
+ ocfs2_unpack_timespec(&ts,
be64_to_cpu(lvb->lvb_ictime_packed));
+ inode->i_ctime = timespec_to_timespec64(ts);
spin_unlock(&oi->ip_lock);
}
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index a2a8603..255f758 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -222,7 +222,7 @@ static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end,
int ocfs2_should_update_atime(struct inode *inode,
struct vfsmount *vfsmnt)
{
- struct timespec now;
+ struct timespec64 now;
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
@@ -248,8 +248,8 @@ int ocfs2_should_update_atime(struct inode *inode,
return 0;
if (vfsmnt->mnt_flags & MNT_RELATIME) {
- if ((timespec_compare(&inode->i_atime, &inode->i_mtime) <= 0) ||
- (timespec_compare(&inode->i_atime, &inode->i_ctime) <= 0))
+ if ((timespec64_compare(&inode->i_atime, &inode->i_mtime) <= 0) ||
+ (timespec64_compare(&inode->i_atime, &inode->i_ctime) <= 0))
return 1;
return 0;
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index e5dcea6..bd34756 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -1383,7 +1383,7 @@ static int __ocfs2_recovery_thread(void *arg)
goto bail;
}
- rm_quota = kzalloc(osb->max_slots * sizeof(int), GFP_NOFS);
+ rm_quota = kcalloc(osb->max_slots, sizeof(int), GFP_NOFS);
if (!rm_quota) {
status = -ENOMEM;
goto bail;
diff --git a/fs/ocfs2/sysfile.c b/fs/ocfs2/sysfile.c
index af155c1..5965f38 100644
--- a/fs/ocfs2/sysfile.c
+++ b/fs/ocfs2/sysfile.c
@@ -69,10 +69,11 @@ static struct inode **get_local_system_inode(struct ocfs2_super *osb,
spin_unlock(&osb->osb_lock);
if (unlikely(!local_system_inodes)) {
- local_system_inodes = kzalloc(sizeof(struct inode *) *
- NUM_LOCAL_SYSTEM_INODES *
- osb->max_slots,
- GFP_NOFS);
+ local_system_inodes =
+ kzalloc(array3_size(sizeof(struct inode *),
+ NUM_LOCAL_SYSTEM_INODES,
+ osb->max_slots),
+ GFP_NOFS);
if (!local_system_inodes) {
mlog_errno(-ENOMEM);
/*
diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c
index 74b37cb..33ee8cb 100644
--- a/fs/orangefs/devorangefs-req.c
+++ b/fs/orangefs/devorangefs-req.c
@@ -719,37 +719,6 @@ struct ORANGEFS_dev_map_desc32 {
__s32 count;
};
-static unsigned long translate_dev_map26(unsigned long args, long *error)
-{
- struct ORANGEFS_dev_map_desc32 __user *p32 = (void __user *)args;
- /*
- * Depending on the architecture, allocate some space on the
- * user-call-stack based on our expected layout.
- */
- struct ORANGEFS_dev_map_desc __user *p =
- compat_alloc_user_space(sizeof(*p));
- compat_uptr_t addr;
-
- *error = 0;
- /* get the ptr from the 32 bit user-space */
- if (get_user(addr, &p32->ptr))
- goto err;
- /* try to put that into a 64-bit layout */
- if (put_user(compat_ptr(addr), &p->ptr))
- goto err;
- /* copy the remaining fields */
- if (copy_in_user(&p->total_size, &p32->total_size, sizeof(__s32)))
- goto err;
- if (copy_in_user(&p->size, &p32->size, sizeof(__s32)))
- goto err;
- if (copy_in_user(&p->count, &p32->count, sizeof(__s32)))
- goto err;
- return (unsigned long)p;
-err:
- *error = -EFAULT;
- return 0;
-}
-
/*
* 32 bit user-space apps' ioctl handlers when kernel modules
* is compiled as a 64 bit one
@@ -758,25 +727,26 @@ static long orangefs_devreq_compat_ioctl(struct file *filp, unsigned int cmd,
unsigned long args)
{
long ret;
- unsigned long arg = args;
/* Check for properly constructed commands */
ret = check_ioctl_command(cmd);
if (ret < 0)
return ret;
if (cmd == ORANGEFS_DEV_MAP) {
- /*
- * convert the arguments to what we expect internally
- * in kernel space
- */
- arg = translate_dev_map26(args, &ret);
- if (ret < 0) {
- gossip_err("Could not translate dev map\n");
- return ret;
- }
+ struct ORANGEFS_dev_map_desc desc;
+ struct ORANGEFS_dev_map_desc32 d32;
+
+ if (copy_from_user(&d32, (void __user *)args, sizeof(d32)))
+ return -EFAULT;
+
+ desc.ptr = compat_ptr(d32.ptr);
+ desc.total_size = d32.total_size;
+ desc.size = d32.size;
+ desc.count = d32.count;
+ return orangefs_bufmap_initialize(&desc);
}
/* no other ioctl requires translation */
- return dispatch_ioctl_command(cmd, arg);
+ return dispatch_ioctl_command(cmd, args);
}
#endif /* CONFIG_COMPAT is in .config */
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index d6db252..6e4d2af 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -297,7 +297,7 @@ int orangefs_permission(struct inode *inode, int mask)
return generic_permission(inode, mask);
}
-int orangefs_update_time(struct inode *inode, struct timespec *time, int flags)
+int orangefs_update_time(struct inode *inode, struct timespec64 *time, int flags)
{
struct iattr iattr;
gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_update_time: %pU\n",
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 0045116..17b24ad 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -342,7 +342,7 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
int orangefs_permission(struct inode *inode, int mask);
-int orangefs_update_time(struct inode *, struct timespec *, int);
+int orangefs_update_time(struct inode *, struct timespec64 *, int);
/*
* defined in xattr.c
diff --git a/fs/orangefs/orangefs-sysfs.c b/fs/orangefs/orangefs-sysfs.c
index 079a465..dd28079 100644
--- a/fs/orangefs/orangefs-sysfs.c
+++ b/fs/orangefs/orangefs-sysfs.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Documentation/ABI/stable/orangefs-sysfs:
+ * Documentation/ABI/stable/sysfs-fs-orangefs:
*
* What: /sys/fs/orangefs/perf_counter_reset
* Date: June 2015
diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c
index 1db5b3b..ed16a89 100644
--- a/fs/overlayfs/inode.c
+++ b/fs/overlayfs/inode.c
@@ -416,7 +416,7 @@ int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags)
return err;
}
-int ovl_update_time(struct inode *inode, struct timespec *ts, int flags)
+int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags)
{
if (flags & S_ATIME) {
struct ovl_fs *ofs = inode->i_sb->s_fs_info;
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 08801b4..c993dd8 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -612,7 +612,7 @@ static int ovl_get_index_name_fh(struct ovl_fh *fh, struct qstr *name)
{
char *n, *s;
- n = kzalloc(fh->len * 2, GFP_KERNEL);
+ n = kcalloc(fh->len, 2, GFP_KERNEL);
if (!n)
return -ENOMEM;
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 3c5e9f1..7538b9b 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -325,7 +325,7 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name,
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size);
struct posix_acl *ovl_get_acl(struct inode *inode, int type);
int ovl_open_maybe_copy_up(struct dentry *dentry, unsigned int file_flags);
-int ovl_update_time(struct inode *inode, struct timespec *ts, int flags);
+int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags);
bool ovl_is_private_xattr(const char *name);
struct ovl_inode_params {
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 4aa9ce5..aaffc0c 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -235,6 +235,10 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
if (env_start != arg_end || env_start >= env_end)
env_start = env_end = arg_end;
+ /* .. and limit it to a maximum of one page of slop */
+ if (env_end >= arg_end + PAGE_SIZE)
+ env_end = arg_end + PAGE_SIZE - 1;
+
/* We're not going to care if "*ppos" has high bits set */
pos = arg_start + *ppos;
@@ -254,10 +258,19 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
while (count) {
int got;
size_t size = min_t(size_t, PAGE_SIZE, count);
+ long offset;
- got = access_remote_vm(mm, pos, page, size, FOLL_ANON);
- if (got <= 0)
+ /*
+ * Are we already starting past the official end?
+ * We always include the last byte that is *supposed*
+ * to be NUL
+ */
+ offset = (pos >= arg_end) ? pos - arg_end + 1 : 0;
+
+ got = access_remote_vm(mm, pos - offset, page, size + offset, FOLL_ANON);
+ if (got <= offset)
break;
+ got -= offset;
/* Don't walk past a NUL character once you hit arg_end */
if (pos + got >= arg_end) {
@@ -276,12 +289,17 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
n = arg_end - pos - 1;
/* Cut off at first NUL after 'n' */
- got = n + strnlen(page+n, got-n);
- if (!got)
+ got = n + strnlen(page+n, offset+got-n);
+ if (got < offset)
break;
+ got -= offset;
+
+ /* Include the NUL if it existed */
+ if (got < size)
+ got++;
}
- got -= copy_to_user(buf, page, got);
+ got -= copy_to_user(buf, page+offset, got);
if (unlikely(!got)) {
if (!len)
len = -EFAULT;
@@ -389,7 +407,8 @@ static int proc_pid_stack(struct seq_file *m, struct pid_namespace *ns,
unsigned long *entries;
int err;
- entries = kmalloc(MAX_STACK_TRACE_DEPTH * sizeof(*entries), GFP_KERNEL);
+ entries = kmalloc_array(MAX_STACK_TRACE_DEPTH, sizeof(*entries),
+ GFP_KERNEL);
if (!entries)
return -ENOMEM;
@@ -2438,14 +2457,11 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
for (p = ents; p < last; p++) {
if (p->len != dentry->d_name.len)
continue;
- if (!memcmp(dentry->d_name.name, p->name, p->len))
+ if (!memcmp(dentry->d_name.name, p->name, p->len)) {
+ res = proc_pident_instantiate(dentry, task, p);
break;
+ }
}
- if (p >= last)
- goto out;
-
- res = proc_pident_instantiate(dentry, task, p);
-out:
put_task_struct(task);
out_no_task:
return res;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 7b4d971..6ac1c92 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -409,7 +409,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
if (!ent)
goto out;
- if (qstr.len + 1 <= sizeof(ent->inline_name)) {
+ if (qstr.len + 1 <= SIZEOF_PDE_INLINE_NAME) {
ent->name = ent->inline_name;
} else {
ent->name = kmalloc(qstr.len + 1, GFP_KERNEL);
@@ -740,3 +740,27 @@ void *PDE_DATA(const struct inode *inode)
return __PDE_DATA(inode);
}
EXPORT_SYMBOL(PDE_DATA);
+
+/*
+ * Pull a user buffer into memory and pass it to the file's write handler if
+ * one is supplied. The ->write() method is permitted to modify the
+ * kernel-side buffer.
+ */
+ssize_t proc_simple_write(struct file *f, const char __user *ubuf, size_t size,
+ loff_t *_pos)
+{
+ struct proc_dir_entry *pde = PDE(file_inode(f));
+ char *buf;
+ int ret;
+
+ if (!pde->write)
+ return -EACCES;
+ if (size == 0 || size > PAGE_SIZE - 1)
+ return -EINVAL;
+ buf = memdup_user_nul(ubuf, size);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+ ret = pde->write(f, buf, size);
+ kfree(buf);
+ return ret == 0 ? size : ret;
+}
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 2cf3b74..85ffbd2 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -105,9 +105,8 @@ void __init proc_init_kmemcache(void)
kmem_cache_create("pde_opener", sizeof(struct pde_opener), 0,
SLAB_ACCOUNT|SLAB_PANIC, NULL);
proc_dir_entry_cache = kmem_cache_create_usercopy(
- "proc_dir_entry", sizeof(struct proc_dir_entry), 0, SLAB_PANIC,
- offsetof(struct proc_dir_entry, inline_name),
- sizeof_field(struct proc_dir_entry, inline_name), NULL);
+ "proc_dir_entry", SIZEOF_PDE_SLOT, 0, SLAB_PANIC,
+ OFFSETOF_PDE_NAME, SIZEOF_PDE_INLINE_NAME, NULL);
}
static int proc_show_options(struct seq_file *seq, struct dentry *root)
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 50cb22a..da3dbfa 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -48,6 +48,7 @@ struct proc_dir_entry {
const struct seq_operations *seq_ops;
int (*single_show)(struct seq_file *, void *);
};
+ proc_write_t write;
void *data;
unsigned int state_size;
unsigned int low_ino;
@@ -61,14 +62,20 @@ struct proc_dir_entry {
char *name;
umode_t mode;
u8 namelen;
-#ifdef CONFIG_64BIT
-#define SIZEOF_PDE_INLINE_NAME (192-155)
-#else
-#define SIZEOF_PDE_INLINE_NAME (128-95)
-#endif
- char inline_name[SIZEOF_PDE_INLINE_NAME];
+ char inline_name[];
} __randomize_layout;
+#define OFFSETOF_PDE_NAME offsetof(struct proc_dir_entry, inline_name)
+#define SIZEOF_PDE_SLOT \
+ (OFFSETOF_PDE_NAME + 34 <= 64 ? 64 : \
+ OFFSETOF_PDE_NAME + 34 <= 128 ? 128 : \
+ OFFSETOF_PDE_NAME + 34 <= 192 ? 192 : \
+ OFFSETOF_PDE_NAME + 34 <= 256 ? 256 : \
+ OFFSETOF_PDE_NAME + 34 <= 512 ? 512 : \
+ 0)
+
+#define SIZEOF_PDE_INLINE_NAME (SIZEOF_PDE_SLOT - OFFSETOF_PDE_NAME)
+
extern struct kmem_cache *proc_dir_entry_cache;
void pde_free(struct proc_dir_entry *pde);
@@ -189,6 +196,7 @@ static inline bool is_empty_pde(const struct proc_dir_entry *pde)
{
return S_ISDIR(pde->mode) && !pde->proc_iops;
}
+extern ssize_t proc_simple_write(struct file *, const char __user *, size_t, loff_t *);
/*
* inode.c
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c
index 7d94fa0..d5e0fcb 100644
--- a/fs/proc/proc_net.c
+++ b/fs/proc/proc_net.c
@@ -46,6 +46,9 @@ static int seq_open_net(struct inode *inode, struct file *file)
WARN_ON_ONCE(state_size < sizeof(*p));
+ if (file->f_mode & FMODE_WRITE && !PDE(inode)->write)
+ return -EACCES;
+
net = get_proc_net(inode);
if (!net)
return -ENXIO;
@@ -73,6 +76,7 @@ static int seq_release_net(struct inode *ino, struct file *f)
static const struct file_operations proc_net_seq_fops = {
.open = seq_open_net,
.read = seq_read,
+ .write = proc_simple_write,
.llseek = seq_lseek,
.release = seq_release_net,
};
@@ -93,6 +97,50 @@ struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
}
EXPORT_SYMBOL_GPL(proc_create_net_data);
+/**
+ * proc_create_net_data_write - Create a writable net_ns-specific proc file
+ * @name: The name of the file.
+ * @mode: The file's access mode.
+ * @parent: The parent directory in which to create.
+ * @ops: The seq_file ops with which to read the file.
+ * @write: The write method which which to 'modify' the file.
+ * @data: Data for retrieval by PDE_DATA().
+ *
+ * Create a network namespaced proc file in the @parent directory with the
+ * specified @name and @mode that allows reading of a file that displays a
+ * series of elements and also provides for the file accepting writes that have
+ * some arbitrary effect.
+ *
+ * The functions in the @ops table are used to iterate over items to be
+ * presented and extract the readable content using the seq_file interface.
+ *
+ * The @write function is called with the data copied into a kernel space
+ * scratch buffer and has a NUL appended for convenience. The buffer may be
+ * modified by the @write function. @write should return 0 on success.
+ *
+ * The @data value is accessible from the @show and @write functions by calling
+ * PDE_DATA() on the file inode. The network namespace must be accessed by
+ * calling seq_file_net() on the seq_file struct.
+ */
+struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode,
+ struct proc_dir_entry *parent,
+ const struct seq_operations *ops,
+ proc_write_t write,
+ unsigned int state_size, void *data)
+{
+ struct proc_dir_entry *p;
+
+ p = proc_create_reg(name, mode, &parent, data);
+ if (!p)
+ return NULL;
+ p->proc_fops = &proc_net_seq_fops;
+ p->seq_ops = ops;
+ p->state_size = state_size;
+ p->write = write;
+ return proc_register(parent, p);
+}
+EXPORT_SYMBOL_GPL(proc_create_net_data_write);
+
static int single_open_net(struct inode *inode, struct file *file)
{
struct proc_dir_entry *de = PDE(inode);
@@ -119,6 +167,7 @@ static int single_release_net(struct inode *ino, struct file *f)
static const struct file_operations proc_net_single_fops = {
.open = single_open_net,
.read = seq_read,
+ .write = proc_simple_write,
.llseek = seq_lseek,
.release = single_release_net,
};
@@ -138,6 +187,49 @@ struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
}
EXPORT_SYMBOL_GPL(proc_create_net_single);
+/**
+ * proc_create_net_single_write - Create a writable net_ns-specific proc file
+ * @name: The name of the file.
+ * @mode: The file's access mode.
+ * @parent: The parent directory in which to create.
+ * @show: The seqfile show method with which to read the file.
+ * @write: The write method which which to 'modify' the file.
+ * @data: Data for retrieval by PDE_DATA().
+ *
+ * Create a network-namespaced proc file in the @parent directory with the
+ * specified @name and @mode that allows reading of a file that displays a
+ * single element rather than a series and also provides for the file accepting
+ * writes that have some arbitrary effect.
+ *
+ * The @show function is called to extract the readable content via the
+ * seq_file interface.
+ *
+ * The @write function is called with the data copied into a kernel space
+ * scratch buffer and has a NUL appended for convenience. The buffer may be
+ * modified by the @write function. @write should return 0 on success.
+ *
+ * The @data value is accessible from the @show and @write functions by calling
+ * PDE_DATA() on the file inode. The network namespace must be accessed by
+ * calling seq_file_single_net() on the seq_file struct.
+ */
+struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mode,
+ struct proc_dir_entry *parent,
+ int (*show)(struct seq_file *, void *),
+ proc_write_t write,
+ void *data)
+{
+ struct proc_dir_entry *p;
+
+ p = proc_create_reg(name, mode, &parent, data);
+ if (!p)
+ return NULL;
+ p->proc_fops = &proc_net_single_fops;
+ p->single_show = show;
+ p->write = write;
+ return proc_register(parent, p);
+}
+EXPORT_SYMBOL_GPL(proc_create_net_single_write);
+
static struct net *get_proc_task_net(struct inode *dir)
{
struct task_struct *task;
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 4d765e5..89921a0 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -1426,7 +1426,7 @@ static int register_leaf_sysctl_tables(const char *path, char *pos,
/* If there are mixed files and directories we need a new table */
if (nr_dirs && nr_files) {
struct ctl_table *new;
- files = kzalloc(sizeof(struct ctl_table) * (nr_files + 1),
+ files = kcalloc(nr_files + 1, sizeof(struct ctl_table),
GFP_KERNEL);
if (!files)
goto out;
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 61b7340..f4b1a9d 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -204,8 +204,7 @@ struct proc_dir_entry proc_root = {
.proc_fops = &proc_root_operations,
.parent = &proc_root,
.subdir = RB_ROOT,
- .name = proc_root.inline_name,
- .inline_name = "/proc",
+ .name = "/proc",
};
int pid_ns_prepare_proc(struct pid_namespace *ns)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 597969d..e967901 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1473,7 +1473,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
pm.show_pfn = file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN);
pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
- pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_KERNEL);
+ pm.buffer = kmalloc_array(pm.len, PM_ENTRY_BYTES, GFP_KERNEL);
ret = -ENOMEM;
if (!pm.buffer)
goto out_mm;
diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c
index 3bd12f9..3f723cb 100644
--- a/fs/proc/uptime.c
+++ b/fs/proc/uptime.c
@@ -10,7 +10,7 @@
static int uptime_proc_show(struct seq_file *m, void *v)
{
struct timespec uptime;
- struct timespec idle;
+ struct timespec64 idle;
u64 nsec;
u32 rem;
int i;
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index dc72057..c238ab8 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -328,7 +328,7 @@ void pstore_record_init(struct pstore_record *record,
record->psi = psinfo;
/* Report zeroed timestamp if called before timekeeping has resumed. */
- record->time = ns_to_timespec(ktime_get_real_fast_ns());
+ record->time = ns_to_timespec64(ktime_get_real_fast_ns());
}
/*
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 49b2bc1..bbd1e35 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -153,21 +153,23 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], uint *c, uint max,
return prz;
}
-static int ramoops_read_kmsg_hdr(char *buffer, struct timespec *time,
+static int ramoops_read_kmsg_hdr(char *buffer, struct timespec64 *time,
bool *compressed)
{
char data_type;
int header_length = 0;
- if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu-%c\n%n", &time->tv_sec,
- &time->tv_nsec, &data_type, &header_length) == 3) {
+ if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu-%c\n%n",
+ (time64_t *)&time->tv_sec, &time->tv_nsec, &data_type,
+ &header_length) == 3) {
if (data_type == 'C')
*compressed = true;
else
*compressed = false;
- } else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lu.%lu\n%n",
- &time->tv_sec, &time->tv_nsec, &header_length) == 2) {
- *compressed = false;
+ } else if (sscanf(buffer, RAMOOPS_KERNMSG_HDR "%lld.%lu\n%n",
+ (time64_t *)&time->tv_sec, &time->tv_nsec,
+ &header_length) == 2) {
+ *compressed = false;
} else {
time->tv_sec = 0;
time->tv_nsec = 0;
@@ -360,8 +362,8 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz,
char *hdr;
size_t len;
- hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR "%lu.%lu-%c\n",
- record->time.tv_sec,
+ hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR "%lld.%06lu-%c\n",
+ (time64_t)record->time.tv_sec,
record->time.tv_nsec / 1000,
record->compressed ? 'C' : 'D');
WARN_ON_ONCE(!hdr);
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index d88231e..fc20e06 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -711,21 +711,18 @@ EXPORT_SYMBOL(dquot_quota_sync);
static unsigned long
dqcache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
{
- struct list_head *head;
struct dquot *dquot;
unsigned long freed = 0;
spin_lock(&dq_list_lock);
- head = free_dquots.prev;
- while (head != &free_dquots && sc->nr_to_scan) {
- dquot = list_entry(head, struct dquot, dq_free);
+ while (!list_empty(&free_dquots) && sc->nr_to_scan) {
+ dquot = list_first_entry(&free_dquots, struct dquot, dq_free);
remove_dquot_hash(dquot);
remove_free_dquot(dquot);
remove_inuse(dquot);
do_destroy_dquot(dquot);
sc->nr_to_scan--;
freed++;
- head = free_dquots.prev;
}
spin_unlock(&dq_list_lock);
return freed;
diff --git a/fs/read_write.c b/fs/read_write.c
index e83bd97..153f8f6 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -778,7 +778,7 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
goto out;
}
if (nr_segs > fast_segs) {
- iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
+ iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL);
if (iov == NULL) {
ret = -ENOMEM;
goto out;
@@ -849,7 +849,7 @@ ssize_t compat_rw_copy_check_uvector(int type,
goto out;
if (nr_segs > fast_segs) {
ret = -ENOMEM;
- iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
+ iov = kmalloc_array(nr_segs, sizeof(struct iovec), GFP_KERNEL);
if (iov == NULL)
goto out;
}
diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c
index edc8ef7..bf708ac 100644
--- a/fs/reiserfs/bitmap.c
+++ b/fs/reiserfs/bitmap.c
@@ -1456,7 +1456,7 @@ int reiserfs_init_bitmap_cache(struct super_block *sb)
struct reiserfs_bitmap_info *bitmap;
unsigned int bmap_nr = reiserfs_bmap_count(sb);
- bitmap = vmalloc(sizeof(*bitmap) * bmap_nr);
+ bitmap = vmalloc(array_size(bmap_nr, sizeof(*bitmap)));
if (bitmap == NULL)
return -ENOMEM;
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index b13fc02..132ec44 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1044,7 +1044,8 @@ research:
if (blocks_needed == 1) {
un = &unf_single;
} else {
- un = kzalloc(min(blocks_needed, max_to_insert) * UNFM_P_SIZE, GFP_NOFS);
+ un = kcalloc(min(blocks_needed, max_to_insert),
+ UNFM_P_SIZE, GFP_NOFS);
if (!un) {
un = &unf_single;
blocks_needed = 1;
diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c
index 23148c3..52eb5d2 100644
--- a/fs/reiserfs/journal.c
+++ b/fs/reiserfs/journal.c
@@ -350,7 +350,8 @@ static struct reiserfs_journal_cnode *allocate_cnodes(int num_cnodes)
if (num_cnodes <= 0) {
return NULL;
}
- head = vzalloc(num_cnodes * sizeof(struct reiserfs_journal_cnode));
+ head = vzalloc(array_size(num_cnodes,
+ sizeof(struct reiserfs_journal_cnode)));
if (!head) {
return NULL;
}
@@ -2192,10 +2193,12 @@ static int journal_read_transaction(struct super_block *sb,
* now we know we've got a good transaction, and it was
* inside the valid time ranges
*/
- log_blocks = kmalloc(get_desc_trans_len(desc) *
- sizeof(struct buffer_head *), GFP_NOFS);
- real_blocks = kmalloc(get_desc_trans_len(desc) *
- sizeof(struct buffer_head *), GFP_NOFS);
+ log_blocks = kmalloc_array(get_desc_trans_len(desc),
+ sizeof(struct buffer_head *),
+ GFP_NOFS);
+ real_blocks = kmalloc_array(get_desc_trans_len(desc),
+ sizeof(struct buffer_head *),
+ GFP_NOFS);
if (!log_blocks || !real_blocks) {
brelse(c_bh);
brelse(d_bh);
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 5089dac..97f3fc4 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -1316,7 +1316,7 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry,
int jbegin_count;
umode_t old_inode_mode;
unsigned long savelink = 1;
- struct timespec ctime;
+ struct timespec64 ctime;
if (flags & ~RENAME_NOREPLACE)
return -EINVAL;
diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c
index 6052d32..8096c74 100644
--- a/fs/reiserfs/resize.c
+++ b/fs/reiserfs/resize.c
@@ -120,7 +120,8 @@ int reiserfs_resize(struct super_block *s, unsigned long block_count_new)
* array of bitmap block pointers
*/
bitmap =
- vzalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new);
+ vzalloc(array_size(bmap_nr_new,
+ sizeof(struct reiserfs_bitmap_info)));
if (!bitmap) {
/*
* Journal bitmaps are still supersized, but the
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
index 5dbf532..ff94fad4 100644
--- a/fs/reiserfs/xattr.c
+++ b/fs/reiserfs/xattr.c
@@ -451,10 +451,10 @@ int reiserfs_commit_write(struct file *f, struct page *page,
static void update_ctime(struct inode *inode)
{
- struct timespec now = current_time(inode);
+ struct timespec64 now = current_time(inode);
if (inode_unhashed(inode) || !inode->i_nlink ||
- timespec_equal(&inode->i_ctime, &now))
+ timespec64_equal(&inode->i_ctime, &now))
return;
inode->i_ctime = current_time(inode);
diff --git a/fs/select.c b/fs/select.c
index bc3cc0f..317891f 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -1236,7 +1236,7 @@ static int compat_core_sys_select(int n, compat_ulong_t __user *inp,
size = FDS_BYTES(n);
bits = stack_fds;
if (size > sizeof(stack_fds) / 6) {
- bits = kmalloc(6 * size, GFP_KERNEL);
+ bits = kmalloc_array(6, size, GFP_KERNEL);
ret = -ENOMEM;
if (!bits)
goto out_nofds;
diff --git a/fs/signalfd.c b/fs/signalfd.c
index cbb42f7..4fcd149 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -259,10 +259,8 @@ static const struct file_operations signalfd_fops = {
.llseek = noop_llseek,
};
-static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
- int flags)
+static int do_signalfd4(int ufd, sigset_t *mask, int flags)
{
- sigset_t sigmask;
struct signalfd_ctx *ctx;
/* Check the SFD_* constants for consistency. */
@@ -272,18 +270,15 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
if (flags & ~(SFD_CLOEXEC | SFD_NONBLOCK))
return -EINVAL;
- if (sizemask != sizeof(sigset_t) ||
- copy_from_user(&sigmask, user_mask, sizeof(sigmask)))
- return -EINVAL;
- sigdelsetmask(&sigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
- signotset(&sigmask);
+ sigdelsetmask(mask, sigmask(SIGKILL) | sigmask(SIGSTOP));
+ signotset(mask);
if (ufd == -1) {
ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
- ctx->sigmask = sigmask;
+ ctx->sigmask = *mask;
/*
* When we call this, the initialization must be complete, since
@@ -303,7 +298,7 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
return -EINVAL;
}
spin_lock_irq(&current->sighand->siglock);
- ctx->sigmask = sigmask;
+ ctx->sigmask = *mask;
spin_unlock_irq(&current->sighand->siglock);
wake_up(&current->sighand->signalfd_wqh);
@@ -316,46 +311,51 @@ static int do_signalfd4(int ufd, sigset_t __user *user_mask, size_t sizemask,
SYSCALL_DEFINE4(signalfd4, int, ufd, sigset_t __user *, user_mask,
size_t, sizemask, int, flags)
{
- return do_signalfd4(ufd, user_mask, sizemask, flags);
+ sigset_t mask;
+
+ if (sizemask != sizeof(sigset_t) ||
+ copy_from_user(&mask, user_mask, sizeof(mask)))
+ return -EINVAL;
+ return do_signalfd4(ufd, &mask, flags);
}
SYSCALL_DEFINE3(signalfd, int, ufd, sigset_t __user *, user_mask,
size_t, sizemask)
{
- return do_signalfd4(ufd, user_mask, sizemask, 0);
+ sigset_t mask;
+
+ if (sizemask != sizeof(sigset_t) ||
+ copy_from_user(&mask, user_mask, sizeof(mask)))
+ return -EINVAL;
+ return do_signalfd4(ufd, &mask, 0);
}
#ifdef CONFIG_COMPAT
static long do_compat_signalfd4(int ufd,
- const compat_sigset_t __user *sigmask,
+ const compat_sigset_t __user *user_mask,
compat_size_t sigsetsize, int flags)
{
- sigset_t tmp;
- sigset_t __user *ksigmask;
+ sigset_t mask;
if (sigsetsize != sizeof(compat_sigset_t))
return -EINVAL;
- if (get_compat_sigset(&tmp, sigmask))
- return -EFAULT;
- ksigmask = compat_alloc_user_space(sizeof(sigset_t));
- if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t)))
+ if (get_compat_sigset(&mask, user_mask))
return -EFAULT;
-
- return do_signalfd4(ufd, ksigmask, sizeof(sigset_t), flags);
+ return do_signalfd4(ufd, &mask, flags);
}
COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd,
- const compat_sigset_t __user *, sigmask,
+ const compat_sigset_t __user *, user_mask,
compat_size_t, sigsetsize,
int, flags)
{
- return do_compat_signalfd4(ufd, sigmask, sigsetsize, flags);
+ return do_compat_signalfd4(ufd, user_mask, sigsetsize, flags);
}
COMPAT_SYSCALL_DEFINE3(signalfd, int, ufd,
- const compat_sigset_t __user *,sigmask,
+ const compat_sigset_t __user *, user_mask,
compat_size_t, sigsetsize)
{
- return do_compat_signalfd4(ufd, sigmask, sigsetsize, 0);
+ return do_compat_signalfd4(ufd, user_mask, sigsetsize, 0);
}
#endif
diff --git a/fs/splice.c b/fs/splice.c
index 005d09c..b3daa97 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -259,8 +259,9 @@ int splice_grow_spd(const struct pipe_inode_info *pipe, struct splice_pipe_desc
if (buffers <= PIPE_DEF_BUFFERS)
return 0;
- spd->pages = kmalloc(buffers * sizeof(struct page *), GFP_KERNEL);
- spd->partial = kmalloc(buffers * sizeof(struct partial_page), GFP_KERNEL);
+ spd->pages = kmalloc_array(buffers, sizeof(struct page *), GFP_KERNEL);
+ spd->partial = kmalloc_array(buffers, sizeof(struct partial_page),
+ GFP_KERNEL);
if (spd->pages && spd->partial)
return 0;
@@ -395,7 +396,7 @@ static ssize_t default_file_splice_read(struct file *in, loff_t *ppos,
vec = __vec;
if (nr_pages > PIPE_DEF_BUFFERS) {
- vec = kmalloc(nr_pages * sizeof(struct kvec), GFP_KERNEL);
+ vec = kmalloc_array(nr_pages, sizeof(struct kvec), GFP_KERNEL);
if (unlikely(!vec)) {
res = -ENOMEM;
goto out;
@@ -1242,38 +1243,26 @@ static int pipe_to_user(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
* For lack of a better implementation, implement vmsplice() to userspace
* as a simple copy of the pipes pages to the user iov.
*/
-static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
- unsigned long nr_segs, unsigned int flags)
+static long vmsplice_to_user(struct file *file, struct iov_iter *iter,
+ unsigned int flags)
{
- struct pipe_inode_info *pipe;
- struct splice_desc sd;
- long ret;
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
- struct iov_iter iter;
+ struct pipe_inode_info *pipe = get_pipe_info(file);
+ struct splice_desc sd = {
+ .total_len = iov_iter_count(iter),
+ .flags = flags,
+ .u.data = iter
+ };
+ long ret = 0;
- pipe = get_pipe_info(file);
if (!pipe)
return -EBADF;
- ret = import_iovec(READ, uiov, nr_segs,
- ARRAY_SIZE(iovstack), &iov, &iter);
- if (ret < 0)
- return ret;
-
- sd.total_len = iov_iter_count(&iter);
- sd.len = 0;
- sd.flags = flags;
- sd.u.data = &iter;
- sd.pos = 0;
-
if (sd.total_len) {
pipe_lock(pipe);
ret = __splice_from_pipe(pipe, &sd, pipe_to_user);
pipe_unlock(pipe);
}
- kfree(iov);
return ret;
}
@@ -1282,14 +1271,11 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *uiov,
* as splice-from-memory, where the regular splice is splice-from-file (or
* to file). In both cases the output is a pipe, naturally.
*/
-static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
- unsigned long nr_segs, unsigned int flags)
+static long vmsplice_to_pipe(struct file *file, struct iov_iter *iter,
+ unsigned int flags)
{
struct pipe_inode_info *pipe;
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
- struct iov_iter from;
- long ret;
+ long ret = 0;
unsigned buf_flag = 0;
if (flags & SPLICE_F_GIFT)
@@ -1299,22 +1285,31 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
if (!pipe)
return -EBADF;
- ret = import_iovec(WRITE, uiov, nr_segs,
- ARRAY_SIZE(iovstack), &iov, &from);
- if (ret < 0)
- return ret;
-
pipe_lock(pipe);
ret = wait_for_space(pipe, flags);
if (!ret)
- ret = iter_to_pipe(&from, pipe, buf_flag);
+ ret = iter_to_pipe(iter, pipe, buf_flag);
pipe_unlock(pipe);
if (ret > 0)
wakeup_pipe_readers(pipe);
- kfree(iov);
return ret;
}
+static int vmsplice_type(struct fd f, int *type)
+{
+ if (!f.file)
+ return -EBADF;
+ if (f.file->f_mode & FMODE_WRITE) {
+ *type = WRITE;
+ } else if (f.file->f_mode & FMODE_READ) {
+ *type = READ;
+ } else {
+ fdput(f);
+ return -EBADF;
+ }
+ return 0;
+}
+
/*
* Note that vmsplice only really supports true splicing _from_ user memory
* to a pipe, not the other way around. Splicing from user memory is a simple
@@ -1331,57 +1326,69 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *uiov,
* Currently we punt and implement it as a normal copy, see pipe_to_user().
*
*/
-static long do_vmsplice(int fd, const struct iovec __user *iov,
- unsigned long nr_segs, unsigned int flags)
+static long do_vmsplice(struct file *f, struct iov_iter *iter, unsigned int flags)
{
- struct fd f;
- long error;
-
if (unlikely(flags & ~SPLICE_F_ALL))
return -EINVAL;
- if (unlikely(nr_segs > UIO_MAXIOV))
- return -EINVAL;
- else if (unlikely(!nr_segs))
- return 0;
- error = -EBADF;
- f = fdget(fd);
- if (f.file) {
- if (f.file->f_mode & FMODE_WRITE)
- error = vmsplice_to_pipe(f.file, iov, nr_segs, flags);
- else if (f.file->f_mode & FMODE_READ)
- error = vmsplice_to_user(f.file, iov, nr_segs, flags);
-
- fdput(f);
- }
+ if (!iov_iter_count(iter))
+ return 0;
- return error;
+ if (iov_iter_rw(iter) == WRITE)
+ return vmsplice_to_pipe(f, iter, flags);
+ else
+ return vmsplice_to_user(f, iter, flags);
}
-SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, iov,
+SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
unsigned long, nr_segs, unsigned int, flags)
{
- return do_vmsplice(fd, iov, nr_segs, flags);
+ struct iovec iovstack[UIO_FASTIOV];
+ struct iovec *iov = iovstack;
+ struct iov_iter iter;
+ long error;
+ struct fd f;
+ int type;
+
+ f = fdget(fd);
+ error = vmsplice_type(f, &type);
+ if (error)
+ return error;
+
+ error = import_iovec(type, uiov, nr_segs,
+ ARRAY_SIZE(iovstack), &iov, &iter);
+ if (!error) {
+ error = do_vmsplice(f.file, &iter, flags);
+ kfree(iov);
+ }
+ fdput(f);
+ return error;
}
#ifdef CONFIG_COMPAT
COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, iov32,
unsigned int, nr_segs, unsigned int, flags)
{
- unsigned i;
- struct iovec __user *iov;
- if (nr_segs > UIO_MAXIOV)
- return -EINVAL;
- iov = compat_alloc_user_space(nr_segs * sizeof(struct iovec));
- for (i = 0; i < nr_segs; i++) {
- struct compat_iovec v;
- if (get_user(v.iov_base, &iov32[i].iov_base) ||
- get_user(v.iov_len, &iov32[i].iov_len) ||
- put_user(compat_ptr(v.iov_base), &iov[i].iov_base) ||
- put_user(v.iov_len, &iov[i].iov_len))
- return -EFAULT;
+ struct iovec iovstack[UIO_FASTIOV];
+ struct iovec *iov = iovstack;
+ struct iov_iter iter;
+ long error;
+ struct fd f;
+ int type;
+
+ f = fdget(fd);
+ error = vmsplice_type(f, &type);
+ if (error)
+ return error;
+
+ error = compat_import_iovec(type, iov32, nr_segs,
+ ARRAY_SIZE(iovstack), &iov, &iter);
+ if (!error) {
+ error = do_vmsplice(f.file, &iter, flags);
+ kfree(iov);
}
- return do_vmsplice(fd, iov, nr_segs, flags);
+ fdput(f);
+ return error;
}
#endif
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 4e267cc..9da224d 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -1276,7 +1276,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
.dirtied_ino = 3 };
struct ubifs_budget_req ino_req = { .dirtied_ino = 1,
.dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
- struct timespec time;
+ struct timespec64 time;
unsigned int uninitialized_var(saved_nlink);
struct fscrypt_name old_nm, new_nm;
@@ -1504,7 +1504,7 @@ static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry,
int sync = IS_DIRSYNC(old_dir) || IS_DIRSYNC(new_dir);
struct inode *fst_inode = d_inode(old_dentry);
struct inode *snd_inode = d_inode(new_dentry);
- struct timespec time;
+ struct timespec64 time;
int err;
struct fscrypt_name fst_nm, snd_nm;
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 1acb2ff..fd7eb6f 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1089,14 +1089,14 @@ static void do_attr_changes(struct inode *inode, const struct iattr *attr)
if (attr->ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
if (attr->ia_valid & ATTR_ATIME)
- inode->i_atime = timespec_trunc(attr->ia_atime,
- inode->i_sb->s_time_gran);
+ inode->i_atime = timespec64_trunc(attr->ia_atime,
+ inode->i_sb->s_time_gran);
if (attr->ia_valid & ATTR_MTIME)
- inode->i_mtime = timespec_trunc(attr->ia_mtime,
- inode->i_sb->s_time_gran);
+ inode->i_mtime = timespec64_trunc(attr->ia_mtime,
+ inode->i_sb->s_time_gran);
if (attr->ia_valid & ATTR_CTIME)
- inode->i_ctime = timespec_trunc(attr->ia_ctime,
- inode->i_sb->s_time_gran);
+ inode->i_ctime = timespec64_trunc(attr->ia_ctime,
+ inode->i_sb->s_time_gran);
if (attr->ia_valid & ATTR_MODE) {
umode_t mode = attr->ia_mode;
@@ -1367,8 +1367,9 @@ out:
static inline int mctime_update_needed(const struct inode *inode,
const struct timespec *now)
{
- if (!timespec_equal(&inode->i_mtime, now) ||
- !timespec_equal(&inode->i_ctime, now))
+ struct timespec64 now64 = timespec_to_timespec64(*now);
+ if (!timespec64_equal(&inode->i_mtime, &now64) ||
+ !timespec64_equal(&inode->i_ctime, &now64))
return 1;
return 0;
}
@@ -1380,7 +1381,7 @@ static inline int mctime_update_needed(const struct inode *inode,
*
* This function updates time of the inode.
*/
-int ubifs_update_time(struct inode *inode, struct timespec *time,
+int ubifs_update_time(struct inode *inode, struct timespec64 *time,
int flags)
{
struct ubifs_inode *ui = ubifs_inode(inode);
@@ -1424,7 +1425,7 @@ int ubifs_update_time(struct inode *inode, struct timespec *time,
*/
static int update_mctime(struct inode *inode)
{
- struct timespec now = current_time(inode);
+ struct timespec now = timespec64_to_timespec(current_time(inode));
struct ubifs_inode *ui = ubifs_inode(inode);
struct ubifs_info *c = inode->i_sb->s_fs_info;
@@ -1513,12 +1514,12 @@ static int ubifs_releasepage(struct page *page, gfp_t unused_gfp_flags)
* mmap()d file has taken write protection fault and is being made writable.
* UBIFS must ensure page is budgeted for.
*/
-static int ubifs_vm_page_mkwrite(struct vm_fault *vmf)
+static vm_fault_t 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 = current_time(inode);
+ struct timespec now = timespec64_to_timespec(current_time(inode));
struct ubifs_budget_req req = { .new_page = 1 };
int err, update_time;
@@ -1567,8 +1568,7 @@ static int ubifs_vm_page_mkwrite(struct vm_fault *vmf)
if (unlikely(page->mapping != inode->i_mapping ||
page_offset(page) > i_size_read(inode))) {
/* Page got truncated out from underneath us */
- err = -EINVAL;
- goto out_unlock;
+ goto sigbus;
}
if (PagePrivate(page))
@@ -1597,12 +1597,10 @@ static int ubifs_vm_page_mkwrite(struct vm_fault *vmf)
wait_for_stable_page(page);
return VM_FAULT_LOCKED;
-out_unlock:
+sigbus:
unlock_page(page);
ubifs_release_budget(c, &req);
- if (err)
- err = VM_FAULT_SIGBUS;
- return err;
+ return VM_FAULT_SIGBUS;
}
static const struct vm_operations_struct ubifs_file_vm_ops = {
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 7b35e3d..a03a47c 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -49,7 +49,7 @@
* maximum size. So dark watermark is the amount of free + dirty space in LEB
* which are guaranteed to be reclaimable. If LEB has less space, the GC might
* be unable to reclaim it. So, LEBs with free + dirty greater than dark
- * watermark are "good" LEBs from GC's point of few. The other LEBs are not so
+ * watermark are "good" LEBs from GC's point of view. The other LEBs are not so
* good, and GC takes extra care when moving them.
*/
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 04c4ec6..07b4956 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -98,9 +98,8 @@ static inline void zero_trun_node_unused(struct ubifs_trun_node *trun)
*
* This function reserves space in journal head @head. If the reservation
* succeeded, the journal head stays locked and later has to be unlocked using
- * 'release_head()'. 'write_node()' and 'write_head()' functions also unlock
- * it. Returns zero in case of success, %-EAGAIN if commit has to be done, and
- * other negative error codes in case of other failures.
+ * 'release_head()'. Returns zero in case of success, %-EAGAIN if commit has to
+ * be done, and other negative error codes in case of other failures.
*/
static int reserve_space(struct ubifs_info *c, int jhead, int len)
{
@@ -1283,10 +1282,11 @@ static int truncate_data_node(const struct ubifs_info *c, const struct inode *in
int *new_len)
{
void *buf;
- int err, dlen, compr_type, out_len, old_dlen;
+ int err, compr_type;
+ u32 dlen, out_len, old_dlen;
out_len = le32_to_cpu(dn->size);
- buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS);
+ buf = kmalloc_array(out_len, WORST_COMPR_FACTOR, GFP_NOFS);
if (!buf)
return -ENOMEM;
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index 8c795e6..7cffa12 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -167,10 +167,10 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
* @lnum: LEB number of the bud
* @offs: starting offset of the bud
*
- * This function writes reference node for the new bud LEB @lnum it to the log,
- * and adds it to the buds tress. It also makes sure that log size does not
+ * This function writes a reference node for the new bud LEB @lnum to the log,
+ * and adds it to the buds trees. It also makes sure that log size does not
* exceed the 'c->max_bud_bytes' limit. Returns zero in case of success,
- * %-EAGAIN if commit is required, and a negative error codes in case of
+ * %-EAGAIN if commit is required, and a negative error code in case of
* failure.
*/
int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 9a51710..8e99dad 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -628,11 +628,12 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
/* Needed by 'ubifs_pack_lsave()' */
c->main_first = c->leb_cnt - *main_lebs;
- lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_KERNEL);
+ lsave = kmalloc_array(c->lsave_cnt, sizeof(int), GFP_KERNEL);
pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_KERNEL);
nnode = kzalloc(sizeof(struct ubifs_nnode), GFP_KERNEL);
buf = vmalloc(c->leb_size);
- ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
+ ltab = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops),
+ c->lpt_lebs));
if (!pnode || !nnode || !buf || !ltab || !lsave) {
err = -ENOMEM;
goto out;
@@ -1626,7 +1627,8 @@ static int lpt_init_rd(struct ubifs_info *c)
{
int err, i;
- c->ltab = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
+ c->ltab = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops),
+ c->lpt_lebs));
if (!c->ltab)
return -ENOMEM;
@@ -1636,15 +1638,17 @@ static int lpt_init_rd(struct ubifs_info *c)
return -ENOMEM;
for (i = 0; i < LPROPS_HEAP_CNT; i++) {
- c->lpt_heap[i].arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ,
- GFP_KERNEL);
+ c->lpt_heap[i].arr = kmalloc_array(LPT_HEAP_SZ,
+ sizeof(void *),
+ GFP_KERNEL);
if (!c->lpt_heap[i].arr)
return -ENOMEM;
c->lpt_heap[i].cnt = 0;
c->lpt_heap[i].max_cnt = LPT_HEAP_SZ;
}
- c->dirty_idx.arr = kmalloc(sizeof(void *) * LPT_HEAP_SZ, GFP_KERNEL);
+ c->dirty_idx.arr = kmalloc_array(LPT_HEAP_SZ, sizeof(void *),
+ GFP_KERNEL);
if (!c->dirty_idx.arr)
return -ENOMEM;
c->dirty_idx.cnt = 0;
@@ -1688,7 +1692,8 @@ static int lpt_init_wr(struct ubifs_info *c)
{
int err, i;
- c->ltab_cmt = vmalloc(sizeof(struct ubifs_lpt_lprops) * c->lpt_lebs);
+ c->ltab_cmt = vmalloc(array_size(sizeof(struct ubifs_lpt_lprops),
+ c->lpt_lebs));
if (!c->ltab_cmt)
return -ENOMEM;
@@ -1697,7 +1702,7 @@ static int lpt_init_wr(struct ubifs_info *c)
return -ENOMEM;
if (c->big_lpt) {
- c->lsave = kmalloc(sizeof(int) * c->lsave_cnt, GFP_NOFS);
+ c->lsave = kmalloc_array(c->lsave_cnt, sizeof(int), GFP_NOFS);
if (!c->lsave)
return -ENOMEM;
err = read_lsave(c);
@@ -1939,8 +1944,8 @@ int ubifs_lpt_scan_nolock(struct ubifs_info *c, int start_lnum, int end_lnum,
return err;
}
- path = kmalloc(sizeof(struct lpt_scan_node) * (c->lpt_hght + 1),
- GFP_NOFS);
+ path = kmalloc_array(c->lpt_hght + 1, sizeof(struct lpt_scan_node),
+ GFP_NOFS);
if (!path)
return -ENOMEM;
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index 235654c..78da65b 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -619,7 +619,7 @@ static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c,
/**
* pnode_lookup - lookup a pnode in the LPT.
* @c: UBIFS file-system description object
- * @i: pnode number (0 to main_lebs - 1)
+ * @i: pnode number (0 to (main_lebs - 1) / UBIFS_LPT_FANOUT))
*
* This function returns a pointer to the pnode on success or a negative
* error code on failure.
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index ae5c02f..85c2a43 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -223,9 +223,6 @@ static int apply_replay_entry(struct ubifs_info *c, struct replay_entry *r)
dbg_mntk(&r->key, "LEB %d:%d len %d deletion %d sqnum %llu key ",
r->lnum, r->offs, r->len, r->deletion, r->sqnum);
- /* Set c->replay_sqnum to help deal with dangling branches. */
- c->replay_sqnum = r->sqnum;
-
if (is_hash_key(c, &r->key)) {
if (r->deletion)
err = ubifs_tnc_remove_nm(c, &r->key, &r->nm);
@@ -1037,7 +1034,7 @@ int ubifs_replay_journal(struct ubifs_info *c)
* The head of the log must always start with the
* "commit start" node on a properly formatted UBIFS.
* But we found no nodes at all, which means that
- * someting went wrong and we cannot proceed mounting
+ * something went wrong and we cannot proceed mounting
* the file-system.
*/
ubifs_err(c, "no UBIFS nodes found at the log head LEB %d:%d, possibly corrupted",
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 6c397a3..c5466c7 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1196,7 +1196,8 @@ static int mount_ubifs(struct ubifs_info *c)
* never exceed 64.
*/
err = -ENOMEM;
- c->bottom_up_buf = kmalloc(BOTTOM_UP_HEIGHT * sizeof(int), GFP_KERNEL);
+ c->bottom_up_buf = kmalloc_array(BOTTOM_UP_HEIGHT, sizeof(int),
+ GFP_KERNEL);
if (!c->bottom_up_buf)
goto out_free;
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index ba3d0e0..4a21e7f 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -1104,8 +1104,9 @@ static struct ubifs_znode *dirty_cow_bottom_up(struct ubifs_info *c,
ubifs_assert(znode);
if (c->zroot.znode->level > BOTTOM_UP_HEIGHT) {
kfree(c->bottom_up_buf);
- c->bottom_up_buf = kmalloc(c->zroot.znode->level * sizeof(int),
- GFP_NOFS);
+ c->bottom_up_buf = kmalloc_array(c->zroot.znode->level,
+ sizeof(int),
+ GFP_NOFS);
if (!c->bottom_up_buf)
return ERR_PTR(-ENOMEM);
path = c->bottom_up_buf;
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index aa31f60..a9df94a 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -366,7 +366,8 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
dbg_gc("%d znodes to write", cnt);
- c->gap_lebs = kmalloc(sizeof(int) * (c->lst.idx_lebs + 1), GFP_NOFS);
+ c->gap_lebs = kmalloc_array(c->lst.idx_lebs + 1, sizeof(int),
+ GFP_NOFS);
if (!c->gap_lebs)
return -ENOMEM;
@@ -674,7 +675,7 @@ static int alloc_idx_lebs(struct ubifs_info *c, int cnt)
dbg_cmt("need about %d empty LEBS for TNC commit", leb_cnt);
if (!leb_cnt)
return 0;
- c->ilebs = kmalloc(leb_cnt * sizeof(int), GFP_NOFS);
+ c->ilebs = kmalloc_array(leb_cnt, sizeof(int), GFP_NOFS);
if (!c->ilebs)
return -ENOMEM;
for (i = 0; i < leb_cnt; i++) {
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 5ee7af8..04bf84d 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1206,7 +1206,6 @@ struct ubifs_debug_info;
* @replay_list: temporary list used during journal replay
* @replay_buds: list of buds to replay
* @cs_sqnum: sequence number of first node in the log (commit start node)
- * @replay_sqnum: sequence number of node currently being replayed
* @unclean_leb_list: LEBs to recover when re-mounting R/O mounted FS to R/W
* mode
* @rcvrd_mst_node: recovered master node to write when re-mounting R/O mounted
@@ -1438,7 +1437,6 @@ struct ubifs_info {
struct list_head replay_list;
struct list_head replay_buds;
unsigned long long cs_sqnum;
- unsigned long long replay_sqnum;
struct list_head unclean_leb_list;
struct ubifs_mst_node *rcvrd_mst_node;
struct rb_root size_tree;
@@ -1740,7 +1738,7 @@ int ubifs_calc_dark(const struct ubifs_info *c, int spc);
int ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync);
int ubifs_setattr(struct dentry *dentry, struct iattr *attr);
#ifdef CONFIG_UBIFS_ATIME_SUPPORT
-int ubifs_update_time(struct inode *inode, struct timespec *time, int flags);
+int ubifs_update_time(struct inode *inode, struct timespec64 *time, int flags);
#endif
/* dir.c */
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index 759f1a2..6f720fd 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -139,7 +139,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
inode->i_op = &empty_iops;
inode->i_fop = &empty_fops;
- inode->i_flags |= S_SYNC | S_NOATIME | S_NOCMTIME | S_NOQUOTA;
+ inode->i_flags |= S_SYNC | S_NOATIME | S_NOCMTIME;
ui = ubifs_inode(inode);
ui->xattr = 1;
ui->flags |= UBIFS_XATTR_FL;
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index 1b961b1..fcda0fc 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -533,8 +533,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb,
udf_write_aext(table, &epos, &eloc,
(etype << 30) | elen, 1);
} else
- udf_delete_aext(table, epos, eloc,
- (etype << 30) | elen);
+ udf_delete_aext(table, epos);
} else {
alloc_count = 0;
}
@@ -630,7 +629,7 @@ static udf_pblk_t udf_table_new_block(struct super_block *sb,
if (goal_elen)
udf_write_aext(table, &goal_epos, &goal_eloc, goal_elen, 1);
else
- udf_delete_aext(table, goal_epos, goal_eloc, goal_elen);
+ udf_delete_aext(table, goal_epos);
brelse(goal_epos.bh);
udf_add_free_space(sb, partition, -1);
diff --git a/fs/udf/directory.c b/fs/udf/directory.c
index 0a98a23..d952301 100644
--- a/fs/udf/directory.c
+++ b/fs/udf/directory.c
@@ -141,10 +141,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
fibh->ebh->b_data,
sizeof(struct fileIdentDesc) + fibh->soffset);
- fi_len = (sizeof(struct fileIdentDesc) +
- cfi->lengthFileIdent +
- le16_to_cpu(cfi->lengthOfImpUse) + 3) & ~3;
-
+ fi_len = udf_dir_entry_len(cfi);
*nf_pos += fi_len - (fibh->eoffset - fibh->soffset);
fibh->eoffset = fibh->soffset + fi_len;
} else {
@@ -152,6 +149,9 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos,
sizeof(struct fileIdentDesc));
}
}
+ /* Got last entry outside of dir size - fs is corrupted! */
+ if (*nf_pos > dir->i_size)
+ return NULL;
return fi;
}
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index b7a0d4b..5656902 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -124,8 +124,8 @@ struct inode *udf_new_inode(struct inode *dir, umode_t mode)
iinfo->i_alloc_type = ICBTAG_FLAG_AD_SHORT;
else
iinfo->i_alloc_type = ICBTAG_FLAG_AD_LONG;
- inode->i_mtime = inode->i_atime = inode->i_ctime =
- iinfo->i_crtime = current_time(inode);
+ inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
+ iinfo->i_crtime = timespec64_to_timespec(inode->i_mtime);
if (unlikely(insert_inode_locked(inode) < 0)) {
make_bad_inode(inode);
iput(inode);
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index c80765d..9915a58 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1147,8 +1147,7 @@ static void udf_update_extents(struct inode *inode, struct kernel_long_ad *laarr
if (startnum > endnum) {
for (i = 0; i < (startnum - endnum); i++)
- udf_delete_aext(inode, *epos, laarr[i].extLocation,
- laarr[i].extLength);
+ udf_delete_aext(inode, *epos);
} else if (startnum < endnum) {
for (i = 0; i < (endnum - startnum); i++) {
udf_insert_aext(inode, *epos, laarr[i].extLocation,
@@ -1271,6 +1270,7 @@ static int udf_read_inode(struct inode *inode, bool hidden_inode)
struct udf_inode_info *iinfo = UDF_I(inode);
struct udf_sb_info *sbi = UDF_SB(inode->i_sb);
struct kernel_lb_addr *iloc = &iinfo->i_location;
+ struct timespec ts;
unsigned int link_count;
unsigned int indirections = 0;
int bs = inode->i_sb->s_blocksize;
@@ -1443,15 +1443,12 @@ reread:
inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9);
- if (!udf_disk_stamp_to_time(&inode->i_atime, fe->accessTime))
- inode->i_atime = sbi->s_record_time;
-
- if (!udf_disk_stamp_to_time(&inode->i_mtime,
- fe->modificationTime))
- inode->i_mtime = sbi->s_record_time;
-
- if (!udf_disk_stamp_to_time(&inode->i_ctime, fe->attrTime))
- inode->i_ctime = sbi->s_record_time;
+ udf_disk_stamp_to_time(&ts, fe->accessTime);
+ inode->i_atime = timespec_to_timespec64(ts);
+ udf_disk_stamp_to_time(&ts, fe->modificationTime);
+ inode->i_mtime = timespec_to_timespec64(ts);
+ udf_disk_stamp_to_time(&ts, fe->attrTime);
+ inode->i_ctime = timespec_to_timespec64(ts);
iinfo->i_unique = le64_to_cpu(fe->uniqueID);
iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr);
@@ -1461,18 +1458,13 @@ reread:
inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9);
- if (!udf_disk_stamp_to_time(&inode->i_atime, efe->accessTime))
- inode->i_atime = sbi->s_record_time;
-
- if (!udf_disk_stamp_to_time(&inode->i_mtime,
- efe->modificationTime))
- inode->i_mtime = sbi->s_record_time;
-
- if (!udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime))
- iinfo->i_crtime = sbi->s_record_time;
-
- if (!udf_disk_stamp_to_time(&inode->i_ctime, efe->attrTime))
- inode->i_ctime = sbi->s_record_time;
+ udf_disk_stamp_to_time(&ts, efe->accessTime);
+ inode->i_atime = timespec_to_timespec64(ts);
+ udf_disk_stamp_to_time(&ts, efe->modificationTime);
+ inode->i_mtime = timespec_to_timespec64(ts);
+ udf_disk_stamp_to_time(&iinfo->i_crtime, efe->createTime);
+ udf_disk_stamp_to_time(&ts, efe->attrTime);
+ inode->i_ctime = timespec_to_timespec64(ts);
iinfo->i_unique = le64_to_cpu(efe->uniqueID);
iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr);
@@ -1722,9 +1714,12 @@ static int udf_update_inode(struct inode *inode, int do_sync)
inode->i_sb->s_blocksize - sizeof(struct fileEntry));
fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
- udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime);
- udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime);
- udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime);
+ udf_time_to_disk_stamp(&fe->accessTime,
+ timespec64_to_timespec(inode->i_atime));
+ udf_time_to_disk_stamp(&fe->modificationTime,
+ timespec64_to_timespec(inode->i_mtime));
+ udf_time_to_disk_stamp(&fe->attrTime,
+ timespec64_to_timespec(inode->i_ctime));
memset(&(fe->impIdent), 0, sizeof(struct regid));
strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER);
fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX;
@@ -1743,14 +1738,17 @@ static int udf_update_inode(struct inode *inode, int do_sync)
efe->objectSize = cpu_to_le64(inode->i_size);
efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded);
- udf_adjust_time(iinfo, inode->i_atime);
- udf_adjust_time(iinfo, inode->i_mtime);
- udf_adjust_time(iinfo, inode->i_ctime);
+ udf_adjust_time(iinfo, timespec64_to_timespec(inode->i_atime));
+ udf_adjust_time(iinfo, timespec64_to_timespec(inode->i_mtime));
+ udf_adjust_time(iinfo, timespec64_to_timespec(inode->i_ctime));
- udf_time_to_disk_stamp(&efe->accessTime, inode->i_atime);
- udf_time_to_disk_stamp(&efe->modificationTime, inode->i_mtime);
+ udf_time_to_disk_stamp(&efe->accessTime,
+ timespec64_to_timespec(inode->i_atime));
+ udf_time_to_disk_stamp(&efe->modificationTime,
+ timespec64_to_timespec(inode->i_mtime));
udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime);
- udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime);
+ udf_time_to_disk_stamp(&efe->attrTime,
+ timespec64_to_timespec(inode->i_ctime));
memset(&(efe->impIdent), 0, sizeof(efe->impIdent));
strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER);
@@ -2177,14 +2175,15 @@ static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos,
return (nelen >> 30);
}
-int8_t udf_delete_aext(struct inode *inode, struct extent_position epos,
- struct kernel_lb_addr eloc, uint32_t elen)
+int8_t udf_delete_aext(struct inode *inode, struct extent_position epos)
{
struct extent_position oepos;
int adsize;
int8_t etype;
struct allocExtDesc *aed;
struct udf_inode_info *iinfo;
+ struct kernel_lb_addr eloc;
+ uint32_t elen;
if (epos.bh) {
get_bh(epos.bh);
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index c586026..06f37dd 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -351,8 +351,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
loff_t f_pos;
loff_t size = udf_ext0_offset(dir) + dir->i_size;
int nfidlen;
- uint8_t lfi;
- uint16_t liu;
udf_pblk_t block;
struct kernel_lb_addr eloc;
uint32_t elen = 0;
@@ -383,7 +381,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
namelen = 0;
}
- nfidlen = (sizeof(struct fileIdentDesc) + namelen + 3) & ~3;
+ nfidlen = ALIGN(sizeof(struct fileIdentDesc) + namelen, UDF_NAME_PAD);
f_pos = udf_ext0_offset(dir);
@@ -424,12 +422,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
goto out_err;
}
- liu = le16_to_cpu(cfi->lengthOfImpUse);
- lfi = cfi->lengthFileIdent;
-
if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
- if (((sizeof(struct fileIdentDesc) +
- liu + lfi + 3) & ~3) == nfidlen) {
+ if (udf_dir_entry_len(cfi) == nfidlen) {
cfi->descTag.tagSerialNum = cpu_to_le16(1);
cfi->fileVersionNum = cpu_to_le16(1);
cfi->fileCharacteristics = 0;
@@ -1201,9 +1195,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry,
if (dir_fi) {
dir_fi->icb.extLocation = cpu_to_lelb(UDF_I(new_dir)->i_location);
- udf_update_tag((char *)dir_fi,
- (sizeof(struct fileIdentDesc) +
- le16_to_cpu(dir_fi->lengthOfImpUse) + 3) & ~3);
+ udf_update_tag((char *)dir_fi, udf_dir_entry_len(dir_fi));
if (old_iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
mark_inode_dirty(old_inode);
else
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 0d27d41..0c504c8 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -862,6 +862,9 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
struct buffer_head *bh;
uint16_t ident;
int ret = -ENOMEM;
+#ifdef UDFFS_DEBUG
+ struct timestamp *ts;
+#endif
outstr = kmalloc(128, GFP_NOFS);
if (!outstr)
@@ -880,15 +883,15 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
pvoldesc = (struct primaryVolDesc *)bh->b_data;
- if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time,
- pvoldesc->recordingDateAndTime)) {
+ udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time,
+ pvoldesc->recordingDateAndTime);
#ifdef UDFFS_DEBUG
- struct timestamp *ts = &pvoldesc->recordingDateAndTime;
- udf_debug("recording time %04u/%02u/%02u %02u:%02u (%x)\n",
- le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,
- ts->minute, le16_to_cpu(ts->typeAndTimezone));
+ ts = &pvoldesc->recordingDateAndTime;
+ udf_debug("recording time %04u/%02u/%02u %02u:%02u (%x)\n",
+ le16_to_cpu(ts->year), ts->month, ts->day, ts->hour,
+ ts->minute, le16_to_cpu(ts->typeAndTimezone));
#endif
- }
+
ret = udf_dstrCS0toChar(sb, outstr, 31, pvoldesc->volIdent, 32);
if (ret < 0)
@@ -1585,7 +1588,7 @@ static struct udf_vds_record *handle_partition_descriptor(
struct udf_vds_record *new_loc;
unsigned int new_size = ALIGN(partnum, PART_DESC_ALLOC_STEP);
- new_loc = kzalloc(sizeof(*new_loc) * new_size, GFP_KERNEL);
+ new_loc = kcalloc(new_size, sizeof(*new_loc), GFP_KERNEL);
if (!new_loc)
return ERR_PTR(-ENOMEM);
memcpy(new_loc, data->part_descs_loc,
@@ -1644,8 +1647,9 @@ static noinline int udf_process_sequence(
memset(data.vds, 0, sizeof(struct udf_vds_record) * VDS_POS_LENGTH);
data.size_part_descs = PART_DESC_ALLOC_STEP;
- data.part_descs_loc = kzalloc(sizeof(*data.part_descs_loc) *
- data.size_part_descs, GFP_KERNEL);
+ data.part_descs_loc = kcalloc(data.size_part_descs,
+ sizeof(*data.part_descs_loc),
+ GFP_KERNEL);
if (!data.part_descs_loc)
return -ENOMEM;
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index fc8d1b3..84c47dd 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -132,6 +132,12 @@ struct inode *udf_find_metadata_inode_efe(struct super_block *sb,
extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *,
struct fileIdentDesc *, struct udf_fileident_bh *,
uint8_t *, uint8_t *);
+static inline unsigned int udf_dir_entry_len(struct fileIdentDesc *cfi)
+{
+ return ALIGN(sizeof(struct fileIdentDesc) +
+ le16_to_cpu(cfi->lengthOfImpUse) + cfi->lengthFileIdent,
+ UDF_NAME_PAD);
+}
/* file.c */
extern long udf_ioctl(struct file *, unsigned int, unsigned long);
@@ -167,8 +173,7 @@ extern int udf_add_aext(struct inode *, struct extent_position *,
struct kernel_lb_addr *, uint32_t, int);
extern void udf_write_aext(struct inode *, struct extent_position *,
struct kernel_lb_addr *, uint32_t, int);
-extern int8_t udf_delete_aext(struct inode *, struct extent_position,
- struct kernel_lb_addr, uint32_t);
+extern int8_t udf_delete_aext(struct inode *, struct extent_position);
extern int8_t udf_next_aext(struct inode *, struct extent_position *,
struct kernel_lb_addr *, uint32_t *, int);
extern int8_t udf_current_aext(struct inode *, struct extent_position *,
@@ -253,8 +258,8 @@ extern struct long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int);
extern struct short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int);
/* udftime.c */
-extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest,
+extern void udf_disk_stamp_to_time(struct timespec *dest,
struct timestamp src);
-extern struct timestamp *udf_time_to_disk_stamp(struct timestamp *dest, struct timespec src);
+extern void udf_time_to_disk_stamp(struct timestamp *dest, struct timespec src);
#endif /* __UDF_DECL_H */
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
index 0927a4b..67b33ac 100644
--- a/fs/udf/udftime.c
+++ b/fs/udf/udftime.c
@@ -40,7 +40,7 @@
#include <linux/kernel.h>
#include <linux/time.h>
-struct timespec *
+void
udf_disk_stamp_to_time(struct timespec *dest, struct timestamp src)
{
u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone);
@@ -67,10 +67,9 @@ udf_disk_stamp_to_time(struct timespec *dest, struct timestamp src)
* recorded with bogus sub-second values.
*/
dest->tv_nsec %= NSEC_PER_SEC;
- return dest;
}
-struct timestamp *
+void
udf_time_to_disk_stamp(struct timestamp *dest, struct timespec ts)
{
long seconds;
@@ -79,9 +78,6 @@ udf_time_to_disk_stamp(struct timestamp *dest, struct timespec ts)
offset = -sys_tz.tz_minuteswest;
- if (!dest)
- return NULL;
-
dest->typeAndTimezone = cpu_to_le16(0x1000 | (offset & 0x0FFF));
seconds = ts.tv_sec + offset * 60;
@@ -97,7 +93,6 @@ udf_time_to_disk_stamp(struct timestamp *dest, struct timespec ts)
dest->centiseconds * 10000) / 100;
dest->microseconds = (ts.tv_nsec / 1000 - dest->centiseconds * 10000 -
dest->hundredsOfMicroseconds * 100);
- return dest;
}
/* EOF */
diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index 8254b8b..4880881 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -541,7 +541,9 @@ static int ufs_read_cylinder_structures(struct super_block *sb)
* Read cylinder group (we read only first fragment from block
* at this time) and prepare internal data structures for cg caching.
*/
- if (!(sbi->s_ucg = kmalloc (sizeof(struct buffer_head *) * uspi->s_ncg, GFP_NOFS)))
+ sbi->s_ucg = kmalloc_array(uspi->s_ncg, sizeof(struct buffer_head *),
+ GFP_NOFS);
+ if (!sbi->s_ucg)
goto failed;
for (i = 0; i < uspi->s_ncg; i++)
sbi->s_ucg[i] = NULL;
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile
index e8d67a4..2f3f75a 100644
--- a/fs/xfs/Makefile
+++ b/fs/xfs/Makefile
@@ -1,20 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
#
# Copyright (c) 2000-2005 Silicon Graphics, Inc.
# 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 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it would be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write the Free Software Foundation,
-# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-#
ccflags-y += -I$(src) # needed for trace events
ccflags-y += -I$(src)/libxfs
@@ -62,6 +50,7 @@ xfs-y += $(addprefix libxfs/, \
xfs_sb.o \
xfs_symlink_remote.o \
xfs_trans_resv.o \
+ xfs_types.o \
)
# xfs_rtbitmap is shared with libxfs
xfs-$(CONFIG_XFS_RT) += $(addprefix libxfs/, \
diff --git a/fs/xfs/kmem.c b/fs/xfs/kmem.c
index 7bace03..fdd9d6e 100644
--- a/fs/xfs/kmem.c
+++ b/fs/xfs/kmem.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/mm.h>
#include <linux/sched/mm.h>
diff --git a/fs/xfs/kmem.h b/fs/xfs/kmem.h
index 6023b59..8e6b3ba 100644
--- a/fs/xfs/kmem.h
+++ b/fs/xfs/kmem.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SUPPORT_KMEM_H__
#define __XFS_SUPPORT_KMEM_H__
diff --git a/fs/xfs/libxfs/xfs_ag_resv.c b/fs/xfs/libxfs/xfs_ag_resv.c
index 03885a9..84db76e 100644
--- a/fs/xfs/libxfs/xfs_ag_resv.c
+++ b/fs/xfs/libxfs/xfs_ag_resv.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_ag_resv.h b/fs/xfs/libxfs/xfs_ag_resv.h
index 938f2f9..4619b55 100644
--- a/fs/xfs/libxfs/xfs_ag_resv.h
+++ b/fs/xfs/libxfs/xfs_ag_resv.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_AG_RESV_H__
#define __XFS_AG_RESV_H__
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index dc9dd38..eef4662 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -227,15 +215,37 @@ xfs_alloc_get_rec(
xfs_extlen_t *len, /* output: length of extent */
int *stat) /* output: success/failure */
{
+ struct xfs_mount *mp = cur->bc_mp;
+ xfs_agnumber_t agno = cur->bc_private.a.agno;
union xfs_btree_rec *rec;
int error;
error = xfs_btree_get_rec(cur, &rec, stat);
- if (!error && *stat == 1) {
- *bno = be32_to_cpu(rec->alloc.ar_startblock);
- *len = be32_to_cpu(rec->alloc.ar_blockcount);
- }
- return error;
+ if (error || !(*stat))
+ return error;
+ if (rec->alloc.ar_blockcount == 0)
+ goto out_bad_rec;
+
+ *bno = be32_to_cpu(rec->alloc.ar_startblock);
+ *len = be32_to_cpu(rec->alloc.ar_blockcount);
+
+ /* check for valid extent range, including overflow */
+ if (!xfs_verify_agbno(mp, agno, *bno))
+ goto out_bad_rec;
+ if (*bno > *bno + *len)
+ goto out_bad_rec;
+ if (!xfs_verify_agbno(mp, agno, *bno + *len - 1))
+ goto out_bad_rec;
+
+ return 0;
+
+out_bad_rec:
+ xfs_warn(mp,
+ "%s Freespace BTree record corruption in AG %d detected!",
+ cur->bc_btnum == XFS_BTNUM_BNO ? "Block" : "Size", agno);
+ xfs_warn(mp,
+ "start block 0x%x block count 0x%x", *bno, *len);
+ return -EFSCORRUPTED;
}
/*
@@ -3113,55 +3123,6 @@ xfs_alloc_query_all(
return xfs_btree_query_all(cur, xfs_alloc_query_range_helper, &query);
}
-/* Find the size of the AG, in blocks. */
-xfs_agblock_t
-xfs_ag_block_count(
- struct xfs_mount *mp,
- xfs_agnumber_t agno)
-{
- ASSERT(agno < mp->m_sb.sb_agcount);
-
- if (agno < mp->m_sb.sb_agcount - 1)
- return mp->m_sb.sb_agblocks;
- return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks);
-}
-
-/*
- * Verify that an AG block number pointer neither points outside the AG
- * nor points at static metadata.
- */
-bool
-xfs_verify_agbno(
- struct xfs_mount *mp,
- xfs_agnumber_t agno,
- xfs_agblock_t agbno)
-{
- xfs_agblock_t eoag;
-
- eoag = xfs_ag_block_count(mp, agno);
- if (agbno >= eoag)
- return false;
- if (agbno <= XFS_AGFL_BLOCK(mp))
- return false;
- return true;
-}
-
-/*
- * Verify that an FS block number pointer neither points outside the
- * filesystem nor points at static AG metadata.
- */
-bool
-xfs_verify_fsbno(
- struct xfs_mount *mp,
- xfs_fsblock_t fsbno)
-{
- xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno);
-
- if (agno >= mp->m_sb.sb_agcount)
- return false;
- return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
-}
-
/* Is there a record covering a given extent? */
int
xfs_alloc_has_record(
diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h
index 0747adc..e716c99 100644
--- a/fs/xfs/libxfs/xfs_alloc.h
+++ b/fs/xfs/libxfs/xfs_alloc.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ALLOC_H__
#define __XFS_ALLOC_H__
@@ -254,10 +242,6 @@ int xfs_alloc_query_range(struct xfs_btree_cur *cur,
xfs_alloc_query_range_fn fn, void *priv);
int xfs_alloc_query_all(struct xfs_btree_cur *cur, xfs_alloc_query_range_fn fn,
void *priv);
-xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
-bool xfs_verify_agbno(struct xfs_mount *mp, xfs_agnumber_t agno,
- xfs_agblock_t agbno);
-bool xfs_verify_fsbno(struct xfs_mount *mp, xfs_fsblock_t fsbno);
int xfs_alloc_has_record(struct xfs_btree_cur *cur, xfs_agblock_t bno,
xfs_extlen_t len, bool *exist);
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c
index 18aec7a..4e59cc8 100644
--- a/fs/xfs/libxfs/xfs_alloc_btree.c
+++ b/fs/xfs/libxfs/xfs_alloc_btree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -242,7 +230,6 @@ xfs_allocbt_init_ptr_from_cur(
struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno));
- ASSERT(agf->agf_roots[cur->bc_btnum] != 0);
ptr->s = agf->agf_roots[cur->bc_btnum];
}
diff --git a/fs/xfs/libxfs/xfs_alloc_btree.h b/fs/xfs/libxfs/xfs_alloc_btree.h
index 2fd5472..c9305eb 100644
--- a/fs/xfs/libxfs/xfs_alloc_btree.h
+++ b/fs/xfs/libxfs/xfs_alloc_btree.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ALLOC_BTREE_H__
#define __XFS_ALLOC_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c
index c3d02a6..99590f6 100644
--- a/fs/xfs/libxfs/xfs_attr.c
+++ b/fs/xfs/libxfs/xfs_attr.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index 2135b8e..76e9004 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -477,7 +465,7 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes)
* A data fork btree root must have space for at least
* MINDBTPTRS key/ptr pairs if the data fork is small or empty.
*/
- minforkoff = MAX(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
+ minforkoff = max(dsize, XFS_BMDR_SPACE_CALC(MINDBTPTRS));
minforkoff = roundup(minforkoff, 8) >> 3;
/* attr fork btree root can have at least this many key/ptr pairs */
@@ -803,9 +791,8 @@ xfs_attr_shortform_to_leaf(
ASSERT(blkno == 0);
error = xfs_attr3_leaf_create(args, blkno, &bp);
if (error) {
- error = xfs_da_shrink_inode(args, 0, bp);
- bp = NULL;
- if (error)
+ /* xfs_attr3_leaf_create may not have instantiated a block */
+ if (bp && (xfs_da_shrink_inode(args, 0, bp) != 0))
goto out;
xfs_idata_realloc(dp, size, XFS_ATTR_FORK); /* try to put */
memcpy(ifp->if_u1.if_data, tmpbuffer, size); /* it back */
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h
index 4da08af..7b74e18 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.h
+++ b/fs/xfs/libxfs/xfs_attr_leaf.h
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ATTR_LEAF_H__
#define __XFS_ATTR_LEAF_H__
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index 83a6d3c..bf2e037 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_attr_remote.h b/fs/xfs/libxfs/xfs_attr_remote.h
index 5a9acfa..9d20b66 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.h
+++ b/fs/xfs/libxfs/xfs_attr_remote.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ATTR_REMOTE_H__
#define __XFS_ATTR_REMOTE_H__
diff --git a/fs/xfs/libxfs/xfs_attr_sf.h b/fs/xfs/libxfs/xfs_attr_sf.h
index afd684a..aafa4fe 100644
--- a/fs/xfs/libxfs/xfs_attr_sf.h
+++ b/fs/xfs/libxfs/xfs_attr_sf.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ATTR_SF_H__
#define __XFS_ATTR_SF_H__
diff --git a/fs/xfs/libxfs/xfs_bit.c b/fs/xfs/libxfs/xfs_bit.c
index 0a94cce..40ce5f3 100644
--- a/fs/xfs/libxfs/xfs_bit.c
+++ b/fs/xfs/libxfs/xfs_bit.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_log_format.h"
diff --git a/fs/xfs/libxfs/xfs_bit.h b/fs/xfs/libxfs/xfs_bit.h
index 61c6b20..99017b8 100644
--- a/fs/xfs/libxfs/xfs_bit.h
+++ b/fs/xfs/libxfs/xfs_bit.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BIT_H__
#define __XFS_BIT_H__
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 7b0e2b5..01628f0 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1248,7 +1236,6 @@ xfs_iread_extents(
num_recs = xfs_btree_get_numrecs(block);
if (unlikely(i + num_recs > nextents)) {
- ASSERT(i + num_recs <= nextents);
xfs_warn(ip->i_mount,
"corrupt dinode %Lu, (btree extents).",
(unsigned long long) ip->i_ino);
@@ -2936,7 +2923,7 @@ xfs_bmap_extsize_align(
* perform this alignment, or if a truncate shot us in the
* foot.
*/
- temp = do_mod(orig_off, extsz);
+ div_u64_rem(orig_off, extsz, &temp);
if (temp) {
align_alen += temp;
align_off -= temp;
@@ -3480,7 +3467,7 @@ xfs_bmap_btalloc(
xfs_rmap_skip_owner_update(&args.oinfo);
/* Trim the allocation back to the maximum an AG can fit. */
- args.maxlen = MIN(ap->length, mp->m_ag_max_usable);
+ args.maxlen = min(ap->length, mp->m_ag_max_usable);
args.firstblock = *ap->firstblock;
blen = 0;
if (nullfb) {
@@ -3510,15 +3497,17 @@ xfs_bmap_btalloc(
/* apply extent size hints if obtained earlier */
if (align) {
args.prod = align;
- if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod)))
- args.mod = (xfs_extlen_t)(args.prod - args.mod);
+ div_u64_rem(ap->offset, args.prod, &args.mod);
+ if (args.mod)
+ args.mod = args.prod - args.mod;
} else if (mp->m_sb.sb_blocksize >= PAGE_SIZE) {
args.prod = 1;
args.mod = 0;
} else {
args.prod = PAGE_SIZE >> mp->m_sb.sb_blocklog;
- if ((args.mod = (xfs_extlen_t)(do_mod(ap->offset, args.prod))))
- args.mod = (xfs_extlen_t)(args.prod - args.mod);
+ div_u64_rem(ap->offset, args.prod, &args.mod);
+ if (args.mod)
+ args.mod = args.prod - args.mod;
}
/*
* If we are not low on available data blocks, and the
@@ -4966,13 +4955,15 @@ xfs_bmap_del_extent_real(
if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) {
xfs_fsblock_t bno;
xfs_filblks_t len;
+ xfs_extlen_t mod;
+
+ bno = div_u64_rem(del->br_startblock, mp->m_sb.sb_rextsize,
+ &mod);
+ ASSERT(mod == 0);
+ len = div_u64_rem(del->br_blockcount, mp->m_sb.sb_rextsize,
+ &mod);
+ ASSERT(mod == 0);
- ASSERT(do_mod(del->br_blockcount, mp->m_sb.sb_rextsize) == 0);
- ASSERT(do_mod(del->br_startblock, mp->m_sb.sb_rextsize) == 0);
- bno = del->br_startblock;
- len = del->br_blockcount;
- do_div(bno, mp->m_sb.sb_rextsize);
- do_div(len, mp->m_sb.sb_rextsize);
error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len);
if (error)
goto done;
@@ -5309,9 +5300,12 @@ __xfs_bunmapi(
del.br_blockcount = max_len;
}
+ if (!isrt)
+ goto delete;
+
sum = del.br_startblock + del.br_blockcount;
- if (isrt &&
- (mod = do_mod(sum, mp->m_sb.sb_rextsize))) {
+ div_u64_rem(sum, mp->m_sb.sb_rextsize, &mod);
+ if (mod) {
/*
* Realtime extent not lined up at the end.
* The extent could have been split into written
@@ -5358,7 +5352,8 @@ __xfs_bunmapi(
goto error0;
goto nodelete;
}
- if (isrt && (mod = do_mod(del.br_startblock, mp->m_sb.sb_rextsize))) {
+ div_u64_rem(del.br_startblock, mp->m_sb.sb_rextsize, &mod);
+ if (mod) {
/*
* Realtime extent is lined up at the end but not
* at the front. We'll get rid of full extents if
@@ -5427,6 +5422,7 @@ __xfs_bunmapi(
}
}
+delete:
if (wasdel) {
error = xfs_bmap_del_extent_delay(ip, whichfork, &icur,
&got, &del);
diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h
index 2c233f9..99dddbd 100644
--- a/fs/xfs/libxfs/xfs_bmap.h
+++ b/fs/xfs/libxfs/xfs_bmap.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BMAP_H__
#define __XFS_BMAP_H__
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c
index ac9d4ae..e1a2d9c 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.c
+++ b/fs/xfs/libxfs/xfs_bmap_btree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h
index fb3cd2d..29b407d 100644
--- a/fs/xfs/libxfs/xfs_bmap_btree.h
+++ b/fs/xfs/libxfs/xfs_bmap_btree.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BMAP_BTREE_H__
#define __XFS_BMAP_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index c825c81..34c6d7b 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -234,7 +222,6 @@ xfs_btree_check_sptr(
return xfs_verify_agbno(cur->bc_mp, cur->bc_private.a.agno, agbno);
}
-#ifdef DEBUG
/*
* Check that a given (indexed) btree pointer at a certain level of a
* btree is valid and doesn't point past where it should.
@@ -247,17 +234,31 @@ xfs_btree_check_ptr(
int level)
{
if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
- XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
- xfs_btree_check_lptr(cur,
- be64_to_cpu((&ptr->l)[index]), level));
+ if (xfs_btree_check_lptr(cur, be64_to_cpu((&ptr->l)[index]),
+ level))
+ return 0;
+ xfs_err(cur->bc_mp,
+"Inode %llu fork %d: Corrupt btree %d pointer at level %d index %d.",
+ cur->bc_private.b.ip->i_ino,
+ cur->bc_private.b.whichfork, cur->bc_btnum,
+ level, index);
} else {
- XFS_WANT_CORRUPTED_RETURN(cur->bc_mp,
- xfs_btree_check_sptr(cur,
- be32_to_cpu((&ptr->s)[index]), level));
+ if (xfs_btree_check_sptr(cur, be32_to_cpu((&ptr->s)[index]),
+ level))
+ return 0;
+ xfs_err(cur->bc_mp,
+"AG %u: Corrupt btree %d pointer at level %d index %d.",
+ cur->bc_private.a.agno, cur->bc_btnum,
+ level, index);
}
- return 0;
+ return -EFSCORRUPTED;
}
+
+#ifdef DEBUG
+# define xfs_btree_debug_check_ptr xfs_btree_check_ptr
+#else
+# define xfs_btree_debug_check_ptr(...) (0)
#endif
/*
@@ -988,22 +989,30 @@ xfs_btree_readahead(
return xfs_btree_readahead_sblock(cur, lr, block);
}
-STATIC xfs_daddr_t
+STATIC int
xfs_btree_ptr_to_daddr(
struct xfs_btree_cur *cur,
- union xfs_btree_ptr *ptr)
+ union xfs_btree_ptr *ptr,
+ xfs_daddr_t *daddr)
{
- if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
- ASSERT(ptr->l != cpu_to_be64(NULLFSBLOCK));
+ xfs_fsblock_t fsbno;
+ xfs_agblock_t agbno;
+ int error;
- return XFS_FSB_TO_DADDR(cur->bc_mp, be64_to_cpu(ptr->l));
- } else {
- ASSERT(cur->bc_private.a.agno != NULLAGNUMBER);
- ASSERT(ptr->s != cpu_to_be32(NULLAGBLOCK));
+ error = xfs_btree_check_ptr(cur, ptr, 0, 1);
+ if (error)
+ return error;
- return XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno,
- be32_to_cpu(ptr->s));
+ if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
+ fsbno = be64_to_cpu(ptr->l);
+ *daddr = XFS_FSB_TO_DADDR(cur->bc_mp, fsbno);
+ } else {
+ agbno = be32_to_cpu(ptr->s);
+ *daddr = XFS_AGB_TO_DADDR(cur->bc_mp, cur->bc_private.a.agno,
+ agbno);
}
+
+ return 0;
}
/*
@@ -1018,8 +1027,11 @@ xfs_btree_readahead_ptr(
union xfs_btree_ptr *ptr,
xfs_extlen_t count)
{
- xfs_buf_readahead(cur->bc_mp->m_ddev_targp,
- xfs_btree_ptr_to_daddr(cur, ptr),
+ xfs_daddr_t daddr;
+
+ if (xfs_btree_ptr_to_daddr(cur, ptr, &daddr))
+ return;
+ xfs_buf_readahead(cur->bc_mp->m_ddev_targp, daddr,
cur->bc_mp->m_bsize * count, cur->bc_ops->buf_ops);
}
@@ -1282,11 +1294,14 @@ xfs_btree_get_buf_block(
{
struct xfs_mount *mp = cur->bc_mp;
xfs_daddr_t d;
+ int error;
/* need to sort out how callers deal with failures first */
ASSERT(!(flags & XBF_TRYLOCK));
- d = xfs_btree_ptr_to_daddr(cur, ptr);
+ error = xfs_btree_ptr_to_daddr(cur, ptr, &d);
+ if (error)
+ return error;
*bpp = xfs_trans_get_buf(cur->bc_tp, mp->m_ddev_targp, d,
mp->m_bsize, flags);
@@ -1317,7 +1332,9 @@ xfs_btree_read_buf_block(
/* need to sort out how callers deal with failures first */
ASSERT(!(flags & XBF_TRYLOCK));
- d = xfs_btree_ptr_to_daddr(cur, ptr);
+ error = xfs_btree_ptr_to_daddr(cur, ptr, &d);
+ if (error)
+ return error;
error = xfs_trans_read_buf(mp, cur->bc_tp, mp->m_ddev_targp, d,
mp->m_bsize, flags, bpp,
cur->bc_ops->buf_ops);
@@ -1764,6 +1781,7 @@ xfs_btree_lookup_get_block(
struct xfs_btree_block **blkp) /* return btree block */
{
struct xfs_buf *bp; /* buffer pointer for btree block */
+ xfs_daddr_t daddr;
int error = 0;
/* special case the root block if in an inode */
@@ -1780,7 +1798,10 @@ xfs_btree_lookup_get_block(
* Otherwise throw it away and get a new one.
*/
bp = cur->bc_bufs[level];
- if (bp && XFS_BUF_ADDR(bp) == xfs_btree_ptr_to_daddr(cur, pp)) {
+ error = xfs_btree_ptr_to_daddr(cur, pp, &daddr);
+ if (error)
+ return error;
+ if (bp && XFS_BUF_ADDR(bp) == daddr) {
*blkp = XFS_BUF_TO_BLOCK(bp);
return 0;
}
@@ -1896,7 +1917,13 @@ xfs_btree_lookup(
high = xfs_btree_get_numrecs(block);
if (!high) {
/* Block is empty, must be an empty leaf. */
- ASSERT(level == 0 && cur->bc_nlevels == 1);
+ if (level != 0 || cur->bc_nlevels != 1) {
+ XFS_CORRUPTION_ERROR(__func__,
+ XFS_ERRLEVEL_LOW,
+ cur->bc_mp, block,
+ sizeof(*block));
+ return -EFSCORRUPTED;
+ }
cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
*stat = 0;
@@ -1946,11 +1973,10 @@ xfs_btree_lookup(
keyno = 1;
pp = xfs_btree_ptr_addr(cur, keyno, block);
-#ifdef DEBUG
- error = xfs_btree_check_ptr(cur, pp, 0, level);
+ error = xfs_btree_debug_check_ptr(cur, pp, 0, level);
if (error)
goto error0;
-#endif
+
cur->bc_ptrs[level] = keyno;
}
}
@@ -2354,11 +2380,11 @@ xfs_btree_lshift(
lpp = xfs_btree_ptr_addr(cur, lrecs, left);
rpp = xfs_btree_ptr_addr(cur, 1, right);
-#ifdef DEBUG
- error = xfs_btree_check_ptr(cur, rpp, 0, level);
+
+ error = xfs_btree_debug_check_ptr(cur, rpp, 0, level);
if (error)
goto error0;
-#endif
+
xfs_btree_copy_keys(cur, lkp, rkp, 1);
xfs_btree_copy_ptrs(cur, lpp, rpp, 1);
@@ -2393,15 +2419,14 @@ xfs_btree_lshift(
XFS_BTREE_STATS_ADD(cur, moves, rrecs - 1);
if (level > 0) {
/* It's a nonleaf. operate on keys and ptrs */
-#ifdef DEBUG
int i; /* loop index */
for (i = 0; i < rrecs; i++) {
- error = xfs_btree_check_ptr(cur, rpp, i + 1, level);
+ error = xfs_btree_debug_check_ptr(cur, rpp, i + 1, level);
if (error)
goto error0;
}
-#endif
+
xfs_btree_shift_keys(cur,
xfs_btree_key_addr(cur, 2, right),
-1, rrecs);
@@ -2541,22 +2566,18 @@ xfs_btree_rshift(
rkp = xfs_btree_key_addr(cur, 1, right);
rpp = xfs_btree_ptr_addr(cur, 1, right);
-#ifdef DEBUG
for (i = rrecs - 1; i >= 0; i--) {
- error = xfs_btree_check_ptr(cur, rpp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, rpp, i, level);
if (error)
goto error0;
}
-#endif
xfs_btree_shift_keys(cur, rkp, 1, rrecs);
xfs_btree_shift_ptrs(cur, rpp, 1, rrecs);
-#ifdef DEBUG
- error = xfs_btree_check_ptr(cur, lpp, 0, level);
+ error = xfs_btree_debug_check_ptr(cur, lpp, 0, level);
if (error)
goto error0;
-#endif
/* Now put the new data in, and log it. */
xfs_btree_copy_keys(cur, rkp, lkp, 1);
@@ -2661,9 +2682,7 @@ __xfs_btree_split(
int rrecs;
int src_index;
int error; /* error return value */
-#ifdef DEBUG
int i;
-#endif
XFS_BTREE_STATS_INC(cur, split);
@@ -2729,13 +2748,11 @@ __xfs_btree_split(
rkp = xfs_btree_key_addr(cur, 1, right);
rpp = xfs_btree_ptr_addr(cur, 1, right);
-#ifdef DEBUG
for (i = src_index; i < rrecs; i++) {
- error = xfs_btree_check_ptr(cur, lpp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, lpp, i, level);
if (error)
goto error0;
}
-#endif
/* Copy the keys & pointers to the new block. */
xfs_btree_copy_keys(cur, rkp, lkp, rrecs);
@@ -2923,9 +2940,7 @@ xfs_btree_new_iroot(
union xfs_btree_ptr nptr; /* new block addr */
int level; /* btree level */
int error; /* error return code */
-#ifdef DEBUG
int i; /* loop counter */
-#endif
XFS_BTREE_STATS_INC(cur, newroot);
@@ -2972,20 +2987,18 @@ xfs_btree_new_iroot(
xfs_btree_copy_keys(cur, ckp, kp, xfs_btree_get_numrecs(cblock));
cpp = xfs_btree_ptr_addr(cur, 1, cblock);
-#ifdef DEBUG
for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) {
- error = xfs_btree_check_ptr(cur, pp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, pp, i, level);
if (error)
goto error0;
}
-#endif
+
xfs_btree_copy_ptrs(cur, cpp, pp, xfs_btree_get_numrecs(cblock));
-#ifdef DEBUG
- error = xfs_btree_check_ptr(cur, &nptr, 0, level);
+ error = xfs_btree_debug_check_ptr(cur, &nptr, 0, level);
if (error)
goto error0;
-#endif
+
xfs_btree_copy_ptrs(cur, pp, &nptr, 1);
xfs_iroot_realloc(cur->bc_private.b.ip,
@@ -3229,9 +3242,7 @@ xfs_btree_insrec(
int ptr; /* key/record index */
int numrecs;/* number of records */
int error; /* error return value */
-#ifdef DEBUG
int i;
-#endif
xfs_daddr_t old_bn;
ncur = NULL;
@@ -3321,22 +3332,18 @@ xfs_btree_insrec(
kp = xfs_btree_key_addr(cur, ptr, block);
pp = xfs_btree_ptr_addr(cur, ptr, block);
-#ifdef DEBUG
for (i = numrecs - ptr; i >= 0; i--) {
- error = xfs_btree_check_ptr(cur, pp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, pp, i, level);
if (error)
return error;
}
-#endif
xfs_btree_shift_keys(cur, kp, 1, numrecs - ptr + 1);
xfs_btree_shift_ptrs(cur, pp, 1, numrecs - ptr + 1);
-#ifdef DEBUG
- error = xfs_btree_check_ptr(cur, ptrp, 0, level);
+ error = xfs_btree_debug_check_ptr(cur, ptrp, 0, level);
if (error)
goto error0;
-#endif
/* Now put the new data in, bump numrecs and log it. */
xfs_btree_copy_keys(cur, kp, key, 1);
@@ -3524,8 +3531,8 @@ xfs_btree_kill_iroot(
int error;
#ifdef DEBUG
union xfs_btree_ptr ptr;
- int i;
#endif
+ int i;
ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
ASSERT(cur->bc_nlevels > 1);
@@ -3581,13 +3588,13 @@ xfs_btree_kill_iroot(
pp = xfs_btree_ptr_addr(cur, 1, block);
cpp = xfs_btree_ptr_addr(cur, 1, cblock);
-#ifdef DEBUG
+
for (i = 0; i < numrecs; i++) {
- error = xfs_btree_check_ptr(cur, cpp, i, level - 1);
+ error = xfs_btree_debug_check_ptr(cur, cpp, i, level - 1);
if (error)
return error;
}
-#endif
+
xfs_btree_copy_ptrs(cur, pp, cpp, numrecs);
error = xfs_btree_free_block(cur, cbp);
@@ -3721,13 +3728,11 @@ xfs_btree_delrec(
lkp = xfs_btree_key_addr(cur, ptr + 1, block);
lpp = xfs_btree_ptr_addr(cur, ptr + 1, block);
-#ifdef DEBUG
for (i = 0; i < numrecs - ptr; i++) {
- error = xfs_btree_check_ptr(cur, lpp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, lpp, i, level);
if (error)
goto error0;
}
-#endif
if (ptr < numrecs) {
xfs_btree_shift_keys(cur, lkp, -1, numrecs - ptr);
@@ -4060,13 +4065,13 @@ xfs_btree_delrec(
lpp = xfs_btree_ptr_addr(cur, lrecs + 1, left);
rkp = xfs_btree_key_addr(cur, 1, right);
rpp = xfs_btree_ptr_addr(cur, 1, right);
-#ifdef DEBUG
+
for (i = 1; i < rrecs; i++) {
- error = xfs_btree_check_ptr(cur, rpp, i, level);
+ error = xfs_btree_debug_check_ptr(cur, rpp, i, level);
if (error)
goto error0;
}
-#endif
+
xfs_btree_copy_keys(cur, lkp, rkp, rrecs);
xfs_btree_copy_ptrs(cur, lpp, rpp, rrecs);
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index d7911efe..0a4fdf7 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BTREE_H__
#define __XFS_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index ea187b4..8a30140 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -305,9 +293,11 @@ xfs_da3_node_read(
type = XFS_BLFT_DIR_LEAFN_BUF;
break;
default:
- type = 0;
- ASSERT(0);
- break;
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW,
+ tp->t_mountp, info, sizeof(*info));
+ xfs_trans_brelse(tp, *bpp);
+ *bpp = NULL;
+ return -EFSCORRUPTED;
}
xfs_trans_buf_set_type(tp, *bpp, type);
}
@@ -2091,7 +2081,7 @@ xfs_da_grow_inode_int(
*/
mapp = kmem_alloc(sizeof(*mapp) * count, KM_SLEEP);
for (b = *bno, mapi = 0; b < *bno + count; ) {
- nmap = MIN(XFS_BMAP_MAX_NMAP, count);
+ nmap = min(XFS_BMAP_MAX_NMAP, count);
c = (int)(*bno + count - b);
error = xfs_bmapi_write(tp, dp, b, c,
xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA,
diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h
index ae6de17..2826007 100644
--- a/fs/xfs/libxfs/xfs_da_btree.h
+++ b/fs/xfs/libxfs/xfs_da_btree.h
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DA_BTREE_H__
#define __XFS_DA_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_da_format.c b/fs/xfs/libxfs/xfs_da_format.c
index 6d77d1a..b39053d 100644
--- a/fs/xfs/libxfs/xfs_da_format.c
+++ b/fs/xfs/libxfs/xfs_da_format.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h
index 7e77299..5d5bf3b 100644
--- a/fs/xfs/libxfs/xfs_da_format.h
+++ b/fs/xfs/libxfs/xfs_da_format.h
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DA_FORMAT_H__
#define __XFS_DA_FORMAT_H__
diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c
index 3daf175..c3e5bff 100644
--- a/fs/xfs/libxfs/xfs_defer.c
+++ b/fs/xfs/libxfs/xfs_defer.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h
index e70725b..a02b2b7 100644
--- a/fs/xfs/libxfs/xfs_defer.h
+++ b/fs/xfs/libxfs/xfs_defer.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_DEFER_H__
#define __XFS_DEFER_H__
diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c
index 92f94e1..59169af 100644
--- a/fs/xfs/libxfs/xfs_dir2.c
+++ b/fs/xfs/libxfs/xfs_dir2.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h
index 989e95a..ed38531 100644
--- a/fs/xfs/libxfs/xfs_dir2.h
+++ b/fs/xfs/libxfs/xfs_dir2.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DIR2_H__
#define __XFS_DIR2_H__
diff --git a/fs/xfs/libxfs/xfs_dir2_block.c b/fs/xfs/libxfs/xfs_dir2_block.c
index 875893d..30ed591 100644
--- a/fs/xfs/libxfs/xfs_dir2_block.c
+++ b/fs/xfs/libxfs/xfs_dir2_block.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -514,8 +502,8 @@ xfs_dir2_block_addname(
if (mid - lowstale)
memmove(&blp[lowstale], &blp[lowstale + 1],
(mid - lowstale) * sizeof(*blp));
- lfloglow = MIN(lowstale, lfloglow);
- lfloghigh = MAX(mid, lfloghigh);
+ lfloglow = min(lowstale, lfloglow);
+ lfloghigh = max(mid, lfloghigh);
}
/*
* Move entries toward the high-numbered stale entry.
@@ -526,8 +514,8 @@ xfs_dir2_block_addname(
if (highstale - mid)
memmove(&blp[mid + 1], &blp[mid],
(highstale - mid) * sizeof(*blp));
- lfloglow = MIN(mid, lfloglow);
- lfloghigh = MAX(highstale, lfloghigh);
+ lfloglow = min(mid, lfloglow);
+ lfloghigh = max(highstale, lfloghigh);
}
be32_add_cpu(&btp->stale, -1);
}
diff --git a/fs/xfs/libxfs/xfs_dir2_data.c b/fs/xfs/libxfs/xfs_dir2_data.c
index cb67ec7..01162c6 100644
--- a/fs/xfs/libxfs/xfs_dir2_data.c
+++ b/fs/xfs/libxfs/xfs_dir2_data.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -33,6 +21,11 @@
#include "xfs_cksum.h"
#include "xfs_log.h"
+static xfs_failaddr_t xfs_dir2_data_freefind_verify(
+ struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf,
+ struct xfs_dir2_data_unused *dup,
+ struct xfs_dir2_data_free **bf_ent);
+
/*
* Check the consistency of the data block.
* The input can also be a block-format directory.
@@ -147,6 +140,8 @@ __xfs_dir3_data_check(
* doesn't need to be there.
*/
if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
+ xfs_failaddr_t fa;
+
if (lastfree != 0)
return __this_address;
if (endp < p + be16_to_cpu(dup->length))
@@ -154,7 +149,9 @@ __xfs_dir3_data_check(
if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
(char *)dup - (char *)hdr)
return __this_address;
- dfp = xfs_dir2_data_freefind(hdr, bf, dup);
+ fa = xfs_dir2_data_freefind_verify(hdr, bf, dup, &dfp);
+ if (fa)
+ return fa;
if (dfp) {
i = (int)(dfp - bf);
if ((freeseen & (1 << i)) != 0)
@@ -242,7 +239,8 @@ xfs_dir3_data_check(
if (!fa)
return;
xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,
- bp->b_addr, __FILE__, __LINE__, fa);
+ bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__,
+ fa);
ASSERT(0);
}
#endif
@@ -381,55 +379,79 @@ xfs_dir3_data_readahead(
}
/*
- * Given a data block and an unused entry from that block,
- * return the bestfree entry if any that corresponds to it.
+ * Find the bestfree entry that exactly coincides with unused directory space
+ * or a verifier error because the bestfree data are bad.
*/
-xfs_dir2_data_free_t *
-xfs_dir2_data_freefind(
- struct xfs_dir2_data_hdr *hdr, /* data block header */
- struct xfs_dir2_data_free *bf, /* bestfree table pointer */
- struct xfs_dir2_data_unused *dup) /* unused space */
+static xfs_failaddr_t
+xfs_dir2_data_freefind_verify(
+ struct xfs_dir2_data_hdr *hdr,
+ struct xfs_dir2_data_free *bf,
+ struct xfs_dir2_data_unused *dup,
+ struct xfs_dir2_data_free **bf_ent)
{
- xfs_dir2_data_free_t *dfp; /* bestfree entry */
- xfs_dir2_data_aoff_t off; /* offset value needed */
-#ifdef DEBUG
- int matched; /* matched the value */
- int seenzero; /* saw a 0 bestfree entry */
-#endif
+ struct xfs_dir2_data_free *dfp;
+ xfs_dir2_data_aoff_t off;
+ bool matched = false;
+ bool seenzero = false;
+ *bf_ent = NULL;
off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
-#ifdef DEBUG
/*
* Validate some consistency in the bestfree table.
* Check order, non-overlapping entries, and if we find the
* one we're looking for it has to be exact.
*/
- ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
- hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
- hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
- hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));
- for (dfp = &bf[0], seenzero = matched = 0;
- dfp < &bf[XFS_DIR2_DATA_FD_COUNT];
- dfp++) {
+ for (dfp = &bf[0]; dfp < &bf[XFS_DIR2_DATA_FD_COUNT]; dfp++) {
if (!dfp->offset) {
- ASSERT(!dfp->length);
- seenzero = 1;
+ if (dfp->length)
+ return __this_address;
+ seenzero = true;
continue;
}
- ASSERT(seenzero == 0);
+ if (seenzero)
+ return __this_address;
if (be16_to_cpu(dfp->offset) == off) {
- matched = 1;
- ASSERT(dfp->length == dup->length);
- } else if (off < be16_to_cpu(dfp->offset))
- ASSERT(off + be16_to_cpu(dup->length) <= be16_to_cpu(dfp->offset));
- else
- ASSERT(be16_to_cpu(dfp->offset) + be16_to_cpu(dfp->length) <= off);
- ASSERT(matched || be16_to_cpu(dfp->length) >= be16_to_cpu(dup->length));
- if (dfp > &bf[0])
- ASSERT(be16_to_cpu(dfp[-1].length) >= be16_to_cpu(dfp[0].length));
+ matched = true;
+ if (dfp->length != dup->length)
+ return __this_address;
+ } else if (be16_to_cpu(dfp->offset) > off) {
+ if (off + be16_to_cpu(dup->length) >
+ be16_to_cpu(dfp->offset))
+ return __this_address;
+ } else {
+ if (be16_to_cpu(dfp->offset) +
+ be16_to_cpu(dfp->length) > off)
+ return __this_address;
+ }
+ if (!matched &&
+ be16_to_cpu(dfp->length) < be16_to_cpu(dup->length))
+ return __this_address;
+ if (dfp > &bf[0] &&
+ be16_to_cpu(dfp[-1].length) < be16_to_cpu(dfp[0].length))
+ return __this_address;
}
-#endif
+
+ /* Looks ok so far; now try to match up with a bestfree entry. */
+ *bf_ent = xfs_dir2_data_freefind(hdr, bf, dup);
+ return NULL;
+}
+
+/*
+ * Given a data block and an unused entry from that block,
+ * return the bestfree entry if any that corresponds to it.
+ */
+xfs_dir2_data_free_t *
+xfs_dir2_data_freefind(
+ struct xfs_dir2_data_hdr *hdr, /* data block header */
+ struct xfs_dir2_data_free *bf, /* bestfree table pointer */
+ struct xfs_dir2_data_unused *dup) /* unused space */
+{
+ xfs_dir2_data_free_t *dfp; /* bestfree entry */
+ xfs_dir2_data_aoff_t off; /* offset value needed */
+
+ off = (xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr);
+
/*
* If this is smaller than the smallest bestfree entry,
* it can't be there since they're sorted.
@@ -1124,7 +1146,7 @@ xfs_dir2_data_use_free(
return 0;
corrupt:
xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, args->dp->i_mount,
- hdr, __FILE__, __LINE__, fa);
+ hdr, sizeof(*hdr), __FILE__, __LINE__, fa);
return -EFSCORRUPTED;
}
diff --git a/fs/xfs/libxfs/xfs_dir2_leaf.c b/fs/xfs/libxfs/xfs_dir2_leaf.c
index 50fc9c0..1728a3e 100644
--- a/fs/xfs/libxfs/xfs_dir2_leaf.c
+++ b/fs/xfs/libxfs/xfs_dir2_leaf.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -81,7 +69,8 @@ xfs_dir3_leaf_check(
if (!fa)
return;
xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,
- bp->b_addr, __FILE__, __LINE__, fa);
+ bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__,
+ fa);
ASSERT(0);
}
#else
@@ -601,8 +590,8 @@ xfs_dir3_leaf_find_entry(
(index - lowstale - 1) *
sizeof(xfs_dir2_leaf_entry_t));
}
- *lfloglow = MIN(lowstale, *lfloglow);
- *lfloghigh = MAX(index - 1, *lfloghigh);
+ *lfloglow = min(lowstale, *lfloglow);
+ *lfloghigh = max(index - 1, *lfloghigh);
leafhdr->stale--;
return &ents[index - 1];
}
@@ -621,8 +610,8 @@ xfs_dir3_leaf_find_entry(
memmove(&ents[index + 1], &ents[index],
(highstale - index) * sizeof(xfs_dir2_leaf_entry_t));
}
- *lfloglow = MIN(index, *lfloglow);
- *lfloghigh = MAX(highstale, *lfloghigh);
+ *lfloglow = min(index, *lfloglow);
+ *lfloghigh = max(highstale, *lfloghigh);
leafhdr->stale--;
return &ents[index];
}
@@ -872,7 +861,6 @@ xfs_dir2_leaf_addname(
*/
dup = (xfs_dir2_data_unused_t *)
((char *)hdr + be16_to_cpu(bf[0].offset));
- ASSERT(be16_to_cpu(dup->length) >= length);
needscan = needlog = 0;
/*
* Mark the initial part of our freespace in use for the new entry.
diff --git a/fs/xfs/libxfs/xfs_dir2_node.c b/fs/xfs/libxfs/xfs_dir2_node.c
index 9df096c..2daf874 100644
--- a/fs/xfs/libxfs/xfs_dir2_node.c
+++ b/fs/xfs/libxfs/xfs_dir2_node.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -84,7 +72,8 @@ xfs_dir3_leaf_check(
if (!fa)
return;
xfs_corruption_error(__func__, XFS_ERRLEVEL_LOW, dp->i_mount,
- bp->b_addr, __FILE__, __LINE__, fa);
+ bp->b_addr, BBTOB(bp->b_length), __FILE__, __LINE__,
+ fa);
ASSERT(0);
}
#else
diff --git a/fs/xfs/libxfs/xfs_dir2_priv.h b/fs/xfs/libxfs/xfs_dir2_priv.h
index 753aeee..59f9fb2 100644
--- a/fs/xfs/libxfs/xfs_dir2_priv.h
+++ b/fs/xfs/libxfs/xfs_dir2_priv.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DIR2_PRIV_H__
#define __XFS_DIR2_PRIV_H__
diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c
index 0c75a7f..585dfdb 100644
--- a/fs/xfs/libxfs/xfs_dir2_sf.c
+++ b/fs/xfs/libxfs/xfs_dir2_sf.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c
index cce520b..d293f37 100644
--- a/fs/xfs/libxfs/xfs_dquot_buf.c
+++ b/fs/xfs/libxfs/xfs_dquot_buf.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_errortag.h b/fs/xfs/libxfs/xfs_errortag.h
index d47b916..b9974e7 100644
--- a/fs/xfs/libxfs/xfs_errortag.h
+++ b/fs/xfs/libxfs/xfs_errortag.h
@@ -1,21 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* Copyright (C) 2017 Oracle.
* 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
- * 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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_ERRORTAG_H_
#define __XFS_ERRORTAG_H_
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index c1cb29a..1c5a8aa 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_FORMAT_H__
#define __XFS_FORMAT_H__
diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h
index dddc75e..f3aa593 100644
--- a/fs/xfs/libxfs/xfs_fs.h
+++ b/fs/xfs/libxfs/xfs_fs.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: LGPL-2.1
/*
* Copyright (c) 1995-2005 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_FS_H__
#define __XFS_FS_H__
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 4ca4ff7..0d968e8 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -133,16 +121,45 @@ xfs_inobt_get_rec(
struct xfs_inobt_rec_incore *irec,
int *stat)
{
+ struct xfs_mount *mp = cur->bc_mp;
+ xfs_agnumber_t agno = cur->bc_private.a.agno;
union xfs_btree_rec *rec;
int error;
+ uint64_t realfree;
error = xfs_btree_get_rec(cur, &rec, stat);
if (error || *stat == 0)
return error;
- xfs_inobt_btrec_to_irec(cur->bc_mp, rec, irec);
+ xfs_inobt_btrec_to_irec(mp, rec, irec);
+
+ if (!xfs_verify_agino(mp, agno, irec->ir_startino))
+ goto out_bad_rec;
+ if (irec->ir_count < XFS_INODES_PER_HOLEMASK_BIT ||
+ irec->ir_count > XFS_INODES_PER_CHUNK)
+ goto out_bad_rec;
+ if (irec->ir_freecount > XFS_INODES_PER_CHUNK)
+ goto out_bad_rec;
+
+ /* if there are no holes, return the first available offset */
+ if (!xfs_inobt_issparse(irec->ir_holemask))
+ realfree = irec->ir_free;
+ else
+ realfree = irec->ir_free & xfs_inobt_irec_to_allocmask(irec);
+ if (hweight64(realfree) != irec->ir_freecount)
+ goto out_bad_rec;
return 0;
+
+out_bad_rec:
+ xfs_warn(mp,
+ "%s Inode BTree record corruption in AG %d detected!",
+ cur->bc_btnum == XFS_BTNUM_INO ? "Used" : "Free", agno);
+ xfs_warn(mp,
+"start inode 0x%x, count 0x%x, free 0x%x freemask 0x%llx, holemask 0x%x",
+ irec->ir_startino, irec->ir_count, irec->ir_freecount,
+ irec->ir_free, irec->ir_holemask);
+ return -EFSCORRUPTED;
}
/*
@@ -880,6 +897,7 @@ sparse_alloc:
be32_add_cpu(&agi->agi_freecount, newlen);
pag = xfs_perag_get(args.mp, agno);
pag->pagi_freecount += newlen;
+ pag->pagi_count += newlen;
xfs_perag_put(pag);
agi->agi_newino = cpu_to_be32(newino);
@@ -1974,6 +1992,7 @@ xfs_difree_inobt(
xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT);
pag = xfs_perag_get(mp, agno);
pag->pagi_freecount -= ilen - 1;
+ pag->pagi_count -= ilen;
xfs_perag_put(pag);
xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, -ilen);
xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1));
@@ -2477,26 +2496,13 @@ xfs_ialloc_log_agi(
}
}
-#ifdef DEBUG
-STATIC void
-xfs_check_agi_unlinked(
- struct xfs_agi *agi)
-{
- int i;
-
- for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)
- ASSERT(agi->agi_unlinked[i]);
-}
-#else
-#define xfs_check_agi_unlinked(agi)
-#endif
-
static xfs_failaddr_t
xfs_agi_verify(
struct xfs_buf *bp)
{
struct xfs_mount *mp = bp->b_target->bt_mount;
struct xfs_agi *agi = XFS_BUF_TO_AGI(bp);
+ int i;
if (xfs_sb_version_hascrc(&mp->m_sb)) {
if (!uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_meta_uuid))
@@ -2532,7 +2538,13 @@ xfs_agi_verify(
if (bp->b_pag && be32_to_cpu(agi->agi_seqno) != bp->b_pag->pag_agno)
return __this_address;
- xfs_check_agi_unlinked(agi);
+ for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
+ if (agi->agi_unlinked[i] == NULLAGINO)
+ continue;
+ if (!xfs_verify_ino(mp, be32_to_cpu(agi->agi_unlinked[i])))
+ return __this_address;
+ }
+
return NULL;
}
@@ -2664,96 +2676,6 @@ xfs_ialloc_pagi_init(
return 0;
}
-/* Calculate the first and last possible inode number in an AG. */
-void
-xfs_ialloc_agino_range(
- struct xfs_mount *mp,
- xfs_agnumber_t agno,
- xfs_agino_t *first,
- xfs_agino_t *last)
-{
- xfs_agblock_t bno;
- xfs_agblock_t eoag;
-
- eoag = xfs_ag_block_count(mp, agno);
-
- /*
- * Calculate the first inode, which will be in the first
- * cluster-aligned block after the AGFL.
- */
- bno = round_up(XFS_AGFL_BLOCK(mp) + 1,
- xfs_ialloc_cluster_alignment(mp));
- *first = XFS_OFFBNO_TO_AGINO(mp, bno, 0);
-
- /*
- * Calculate the last inode, which will be at the end of the
- * last (aligned) cluster that can be allocated in the AG.
- */
- bno = round_down(eoag, xfs_ialloc_cluster_alignment(mp));
- *last = XFS_OFFBNO_TO_AGINO(mp, bno, 0) - 1;
-}
-
-/*
- * Verify that an AG inode number pointer neither points outside the AG
- * nor points at static metadata.
- */
-bool
-xfs_verify_agino(
- struct xfs_mount *mp,
- xfs_agnumber_t agno,
- xfs_agino_t agino)
-{
- xfs_agino_t first;
- xfs_agino_t last;
-
- xfs_ialloc_agino_range(mp, agno, &first, &last);
- return agino >= first && agino <= last;
-}
-
-/*
- * Verify that an FS inode number pointer neither points outside the
- * filesystem nor points at static AG metadata.
- */
-bool
-xfs_verify_ino(
- struct xfs_mount *mp,
- xfs_ino_t ino)
-{
- xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino);
- xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino);
-
- if (agno >= mp->m_sb.sb_agcount)
- return false;
- if (XFS_AGINO_TO_INO(mp, agno, agino) != ino)
- return false;
- return xfs_verify_agino(mp, agno, agino);
-}
-
-/* Is this an internal inode number? */
-bool
-xfs_internal_inum(
- struct xfs_mount *mp,
- xfs_ino_t ino)
-{
- return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
- (xfs_sb_version_hasquota(&mp->m_sb) &&
- xfs_is_quota_inode(&mp->m_sb, ino));
-}
-
-/*
- * Verify that a directory entry's inode number doesn't point at an internal
- * inode, empty space, or static AG metadata.
- */
-bool
-xfs_verify_dir_ino(
- struct xfs_mount *mp,
- xfs_ino_t ino)
-{
- if (xfs_internal_inum(mp, ino))
- return false;
- return xfs_verify_ino(mp, ino);
-}
-
/* Is there an inode record covering a given range of inode numbers? */
int
xfs_ialloc_has_inode_record(
diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h
index 77fffce..90b09c5 100644
--- a/fs/xfs/libxfs/xfs_ialloc.h
+++ b/fs/xfs/libxfs/xfs_ialloc.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IALLOC_H__
#define __XFS_IALLOC_H__
@@ -181,12 +169,5 @@ int xfs_inobt_insert_rec(struct xfs_btree_cur *cur, uint16_t holemask,
int *stat);
int xfs_ialloc_cluster_alignment(struct xfs_mount *mp);
-void xfs_ialloc_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
- xfs_agino_t *first, xfs_agino_t *last);
-bool xfs_verify_agino(struct xfs_mount *mp, xfs_agnumber_t agno,
- xfs_agino_t agino);
-bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino);
-bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino);
-bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino);
#endif /* __XFS_IALLOC_H__ */
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index b04c555..a5237af 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.h b/fs/xfs/libxfs/xfs_ialloc_btree.h
index 4acdd54..bf8f0c4 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.h
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IALLOC_BTREE_H__
#define __XFS_IALLOC_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_iext_tree.c b/fs/xfs/libxfs/xfs_iext_tree.c
index b0f3179..b80c63f 100644
--- a/fs/xfs/libxfs/xfs_iext_tree.c
+++ b/fs/xfs/libxfs/xfs_iext_tree.c
@@ -1,14 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2017 Christoph Hellwig.
- *
- * 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/cache.h>
diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c
index 1201107..d38d724 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.c
+++ b/fs/xfs/libxfs/xfs_inode_buf.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -201,11 +189,6 @@ xfs_imap_to_bp(
ASSERT(buf_flags & XBF_TRYLOCK);
return error;
}
-
- if (error == -EFSCORRUPTED &&
- (iget_flags & XFS_IGET_UNTRUSTED))
- return -EINVAL;
-
xfs_warn(mp, "%s: xfs_trans_read_buf() returned error %d.",
__func__, error);
return error;
@@ -397,6 +380,7 @@ xfs_dinode_verify(
xfs_ino_t ino,
struct xfs_dinode *dip)
{
+ xfs_failaddr_t fa;
uint16_t mode;
uint16_t flags;
uint64_t flags2;
@@ -513,6 +497,12 @@ xfs_dinode_verify(
return __this_address;
}
+ /* extent size hint validation */
+ fa = xfs_inode_validate_extsize(mp, be32_to_cpu(dip->di_extsize),
+ mode, flags);
+ if (fa)
+ return fa;
+
/* only version 3 or greater inodes are extensively verified here */
if (dip->di_version < 3)
return NULL;
@@ -521,7 +511,7 @@ xfs_dinode_verify(
/* don't allow reflink/cowextsize if we don't have reflink */
if ((flags2 & (XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE)) &&
- !xfs_sb_version_hasreflink(&mp->m_sb))
+ !xfs_sb_version_hasreflink(&mp->m_sb))
return __this_address;
/* only regular files get reflink */
@@ -536,6 +526,12 @@ xfs_dinode_verify(
if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags2 & XFS_DIFLAG2_DAX))
return __this_address;
+ /* COW extent size hint validation */
+ fa = xfs_inode_validate_cowextsize(mp, be32_to_cpu(dip->di_cowextsize),
+ mode, flags, flags2);
+ if (fa)
+ return fa;
+
return NULL;
}
diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h
index d9a376a..ab0f841 100644
--- a/fs/xfs/libxfs/xfs_inode_buf.h
+++ b/fs/xfs/libxfs/xfs_inode_buf.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_INODE_BUF_H__
#define __XFS_INODE_BUF_H__
diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c
index 701c42a..183ec0c 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.c
+++ b/fs/xfs/libxfs/xfs_inode_fork.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/log2.h>
diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h
index dd8aba0..781b160 100644
--- a/fs/xfs/libxfs/xfs_inode_fork.h
+++ b/fs/xfs/libxfs/xfs_inode_fork.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_INODE_FORK_H__
#define __XFS_INODE_FORK_H__
diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h
index 349d9f8..79bb798 100644
--- a/fs/xfs/libxfs/xfs_log_format.h
+++ b/fs/xfs/libxfs/xfs_log_format.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_LOG_FORMAT_H__
#define __XFS_LOG_FORMAT_H__
diff --git a/fs/xfs/libxfs/xfs_log_recover.h b/fs/xfs/libxfs/xfs_log_recover.h
index 66948a9..f3d18ea 100644
--- a/fs/xfs/libxfs/xfs_log_recover.h
+++ b/fs/xfs/libxfs/xfs_log_recover.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_LOG_RECOVER_H__
#define __XFS_LOG_RECOVER_H__
diff --git a/fs/xfs/libxfs/xfs_log_rlimit.c b/fs/xfs/libxfs/xfs_log_rlimit.c
index cc4cbe2..1b542ec 100644
--- a/fs/xfs/libxfs/xfs_log_rlimit.c
+++ b/fs/xfs/libxfs/xfs_log_rlimit.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2013 Jie Liu.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_quota_defs.h b/fs/xfs/libxfs/xfs_quota_defs.h
index d4af280..4bfdd5f 100644
--- a/fs/xfs/libxfs/xfs_quota_defs.h
+++ b/fs/xfs/libxfs/xfs_quota_defs.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_QUOTA_DEFS_H__
#define __XFS_QUOTA_DEFS_H__
diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c
index 418d532..9dda6fd 100644
--- a/fs/xfs/libxfs/xfs_refcount.c
+++ b/fs/xfs/libxfs/xfs_refcount.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -125,16 +111,53 @@ xfs_refcount_get_rec(
struct xfs_refcount_irec *irec,
int *stat)
{
+ struct xfs_mount *mp = cur->bc_mp;
+ xfs_agnumber_t agno = cur->bc_private.a.agno;
union xfs_btree_rec *rec;
int error;
+ xfs_agblock_t realstart;
error = xfs_btree_get_rec(cur, &rec, stat);
- if (!error && *stat == 1) {
- xfs_refcount_btrec_to_irec(rec, irec);
- trace_xfs_refcount_get(cur->bc_mp, cur->bc_private.a.agno,
- irec);
+ if (error || !*stat)
+ return error;
+
+ xfs_refcount_btrec_to_irec(rec, irec);
+
+ agno = cur->bc_private.a.agno;
+ if (irec->rc_blockcount == 0 || irec->rc_blockcount > MAXREFCEXTLEN)
+ goto out_bad_rec;
+
+ /* handle special COW-staging state */
+ realstart = irec->rc_startblock;
+ if (realstart & XFS_REFC_COW_START) {
+ if (irec->rc_refcount != 1)
+ goto out_bad_rec;
+ realstart &= ~XFS_REFC_COW_START;
+ } else if (irec->rc_refcount < 2) {
+ goto out_bad_rec;
}
- return error;
+
+ /* check for valid extent range, including overflow */
+ if (!xfs_verify_agbno(mp, agno, realstart))
+ goto out_bad_rec;
+ if (realstart > realstart + irec->rc_blockcount)
+ goto out_bad_rec;
+ if (!xfs_verify_agbno(mp, agno, realstart + irec->rc_blockcount - 1))
+ goto out_bad_rec;
+
+ if (irec->rc_refcount == 0 || irec->rc_refcount > MAXREFCOUNT)
+ goto out_bad_rec;
+
+ trace_xfs_refcount_get(cur->bc_mp, cur->bc_private.a.agno, irec);
+ return 0;
+
+out_bad_rec:
+ xfs_warn(mp,
+ "Refcount BTree record corruption in AG %d detected!", agno);
+ xfs_warn(mp,
+ "Start block 0x%x, block count 0x%x, references 0x%x",
+ irec->rc_startblock, irec->rc_blockcount, irec->rc_refcount);
+ return -EFSCORRUPTED;
}
/*
diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h
index a92ad90..5fef744 100644
--- a/fs/xfs/libxfs/xfs_refcount.h
+++ b/fs/xfs/libxfs/xfs_refcount.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_REFCOUNT_H__
#define __XFS_REFCOUNT_H__
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c
index 375abfe..b719379 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.c
+++ b/fs/xfs/libxfs/xfs_refcount_btree.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -192,7 +178,6 @@ xfs_refcountbt_init_ptr_from_cur(
struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno));
- ASSERT(agf->agf_refcount_root != 0);
ptr->s = agf->agf_refcount_root;
}
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.h b/fs/xfs/libxfs/xfs_refcount_btree.h
index 2bc4694..d2852b6 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.h
+++ b/fs/xfs/libxfs/xfs_refcount_btree.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_REFCOUNT_BTREE_H__
#define __XFS_REFCOUNT_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c
index c0644f1..d4460b0 100644
--- a/fs/xfs/libxfs/xfs_rmap.c
+++ b/fs/xfs/libxfs/xfs_rmap.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -39,6 +27,7 @@
#include "xfs_extent_busy.h"
#include "xfs_bmap.h"
#include "xfs_inode.h"
+#include "xfs_ialloc.h"
/*
* Lookup the first record less than or equal to [bno, len, owner, offset]
@@ -203,6 +192,8 @@ xfs_rmap_get_rec(
struct xfs_rmap_irec *irec,
int *stat)
{
+ struct xfs_mount *mp = cur->bc_mp;
+ xfs_agnumber_t agno = cur->bc_private.a.agno;
union xfs_btree_rec *rec;
int error;
@@ -210,7 +201,43 @@ xfs_rmap_get_rec(
if (error || !*stat)
return error;
- return xfs_rmap_btrec_to_irec(rec, irec);
+ if (xfs_rmap_btrec_to_irec(rec, irec))
+ goto out_bad_rec;
+
+ if (irec->rm_blockcount == 0)
+ goto out_bad_rec;
+ if (irec->rm_startblock <= XFS_AGFL_BLOCK(mp)) {
+ if (irec->rm_owner != XFS_RMAP_OWN_FS)
+ goto out_bad_rec;
+ if (irec->rm_blockcount != XFS_AGFL_BLOCK(mp) + 1)
+ goto out_bad_rec;
+ } else {
+ /* check for valid extent range, including overflow */
+ if (!xfs_verify_agbno(mp, agno, irec->rm_startblock))
+ goto out_bad_rec;
+ if (irec->rm_startblock >
+ irec->rm_startblock + irec->rm_blockcount)
+ goto out_bad_rec;
+ if (!xfs_verify_agbno(mp, agno,
+ irec->rm_startblock + irec->rm_blockcount - 1))
+ goto out_bad_rec;
+ }
+
+ if (!(xfs_verify_ino(mp, irec->rm_owner) ||
+ (irec->rm_owner <= XFS_RMAP_OWN_FS &&
+ irec->rm_owner >= XFS_RMAP_OWN_MIN)))
+ goto out_bad_rec;
+
+ return 0;
+out_bad_rec:
+ xfs_warn(mp,
+ "Reverse Mapping BTree record corruption in AG %d detected!",
+ agno);
+ xfs_warn(mp,
+ "Owner 0x%llx, flags 0x%x, start block 0x%x block count 0x%x",
+ irec->rm_owner, irec->rm_flags, irec->rm_startblock,
+ irec->rm_blockcount);
+ return -EFSCORRUPTED;
}
struct xfs_find_left_neighbor_info {
diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h
index 43e506f..9f19454 100644
--- a/fs/xfs/libxfs/xfs_rmap.h
+++ b/fs/xfs/libxfs/xfs_rmap.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_RMAP_H__
#define __XFS_RMAP_H__
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c
index d756e0b..221a88e 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.c
+++ b/fs/xfs/libxfs/xfs_rmap_btree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -234,7 +222,6 @@ xfs_rmapbt_init_ptr_from_cur(
struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno));
- ASSERT(agf->agf_roots[cur->bc_btnum] != 0);
ptr->s = agf->agf_roots[cur->bc_btnum];
}
diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h
index d68d96e..50198b6 100644
--- a/fs/xfs/libxfs/xfs_rmap_btree.h
+++ b/fs/xfs/libxfs/xfs_rmap_btree.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_RMAP_BTREE_H__
#define __XFS_RMAP_BTREE_H__
diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c
index 369eeb7..65fc4ed 100644
--- a/fs/xfs/libxfs/xfs_rtbitmap.c
+++ b/fs/xfs/libxfs/xfs_rtbitmap.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1092,18 +1080,6 @@ xfs_rtalloc_query_all(
return xfs_rtalloc_query_range(tp, &keys[0], &keys[1], fn, priv);
}
-/*
- * Verify that an realtime block number pointer doesn't point off the
- * end of the realtime device.
- */
-bool
-xfs_verify_rtbno(
- struct xfs_mount *mp,
- xfs_rtblock_t rtbno)
-{
- return rtbno < mp->m_sb.sb_rblocks;
-}
-
/* Is the given extent all free? */
int
xfs_rtalloc_extent_is_free(
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index d485e14..350119e 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -278,6 +266,22 @@ xfs_mount_validate_sb(
return -EFSCORRUPTED;
}
+ if (sbp->sb_unit) {
+ if (!xfs_sb_version_hasdalign(sbp) ||
+ sbp->sb_unit > sbp->sb_width ||
+ (sbp->sb_width % sbp->sb_unit) != 0) {
+ xfs_notice(mp, "SB stripe unit sanity check failed");
+ return -EFSCORRUPTED;
+ }
+ } else if (xfs_sb_version_hasdalign(sbp)) {
+ xfs_notice(mp, "SB stripe alignment sanity check failed");
+ return -EFSCORRUPTED;
+ } else if (sbp->sb_width) {
+ xfs_notice(mp, "SB stripe width sanity check failed");
+ return -EFSCORRUPTED;
+ }
+
+
if (xfs_sb_version_hascrc(&mp->m_sb) &&
sbp->sb_blocksize < XFS_MIN_CRC_BLOCKSIZE) {
xfs_notice(mp, "v5 SB sanity check failed");
@@ -767,7 +771,7 @@ xfs_sb_mount_common(
mp->m_refc_mnr[1] = mp->m_refc_mxr[1] / 2;
mp->m_bsize = XFS_FSB_TO_BB(mp, 1);
- mp->m_ialloc_inos = (int)MAX((uint16_t)XFS_INODES_PER_CHUNK,
+ mp->m_ialloc_inos = max_t(uint16_t, XFS_INODES_PER_CHUNK,
sbp->sb_inopblock);
mp->m_ialloc_blks = mp->m_ialloc_inos >> sbp->sb_inopblog;
@@ -970,14 +974,16 @@ xfs_sync_sb_buf(
struct xfs_mount *mp)
{
struct xfs_trans *tp;
+ struct xfs_buf *bp;
int error;
error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, 0, &tp);
if (error)
return error;
+ bp = xfs_trans_getsb(tp, mp, 0);
xfs_log_sb(tp);
- xfs_trans_bhold(tp, mp->m_sb_bp);
+ xfs_trans_bhold(tp, bp);
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp);
if (error)
@@ -985,9 +991,9 @@ xfs_sync_sb_buf(
/*
* write out the sb buffer to get the changes to disk
*/
- error = xfs_bwrite(mp->m_sb_bp);
+ error = xfs_bwrite(bp);
out:
- xfs_buf_relse(mp->m_sb_bp);
+ xfs_buf_relse(bp);
return error;
}
diff --git a/fs/xfs/libxfs/xfs_sb.h b/fs/xfs/libxfs/xfs_sb.h
index 244e016..13564d6 100644
--- a/fs/xfs/libxfs/xfs_sb.h
+++ b/fs/xfs/libxfs/xfs_sb.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SB_H__
#define __XFS_SB_H__
diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h
index ae99c26..22089f1 100644
--- a/fs/xfs/libxfs/xfs_shared.h
+++ b/fs/xfs/libxfs/xfs_shared.h
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SHARED_H__
#define __XFS_SHARED_H__
diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
index 5ef5f35..95374ab 100644
--- a/fs/xfs/libxfs/xfs_symlink_remote.c
+++ b/fs/xfs/libxfs/xfs_symlink_remote.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2012-2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c
index 3bccdf7..f99a7ae 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.c
+++ b/fs/xfs/libxfs/xfs_trans_resv.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* Copyright (C) 2010 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -248,7 +236,7 @@ xfs_calc_write_reservation(
struct xfs_mount *mp)
{
return XFS_DQUOT_LOGRES(mp) +
- MAX((xfs_calc_inode_res(mp, 1) +
+ max((xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
XFS_FSB_TO_B(mp, 1)) +
xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
@@ -275,7 +263,7 @@ xfs_calc_itruncate_reservation(
struct xfs_mount *mp)
{
return XFS_DQUOT_LOGRES(mp) +
- MAX((xfs_calc_inode_res(mp, 1) +
+ max((xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1,
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
@@ -300,7 +288,7 @@ xfs_calc_rename_reservation(
struct xfs_mount *mp)
{
return XFS_DQUOT_LOGRES(mp) +
- MAX((xfs_calc_inode_res(mp, 4) +
+ max((xfs_calc_inode_res(mp, 4) +
xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) +
@@ -340,7 +328,7 @@ xfs_calc_link_reservation(
{
return XFS_DQUOT_LOGRES(mp) +
xfs_calc_iunlink_remove_reservation(mp) +
- MAX((xfs_calc_inode_res(mp, 2) +
+ max((xfs_calc_inode_res(mp, 2) +
xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
@@ -378,7 +366,7 @@ xfs_calc_remove_reservation(
{
return XFS_DQUOT_LOGRES(mp) +
xfs_calc_iunlink_add_reservation(mp) +
- MAX((xfs_calc_inode_res(mp, 1) +
+ max((xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) +
@@ -436,7 +424,7 @@ STATIC uint
xfs_calc_icreate_reservation(xfs_mount_t *mp)
{
return XFS_DQUOT_LOGRES(mp) +
- MAX(xfs_calc_icreate_resv_alloc(mp),
+ max(xfs_calc_icreate_resv_alloc(mp),
xfs_calc_create_resv_modify(mp));
}
@@ -644,7 +632,7 @@ STATIC uint
xfs_calc_attrinval_reservation(
struct xfs_mount *mp)
{
- return MAX((xfs_calc_inode_res(mp, 1) +
+ return max((xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK),
XFS_FSB_TO_B(mp, 1))),
(xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
@@ -708,7 +696,7 @@ xfs_calc_attrrm_reservation(
struct xfs_mount *mp)
{
return XFS_DQUOT_LOGRES(mp) +
- MAX((xfs_calc_inode_res(mp, 1) +
+ max((xfs_calc_inode_res(mp, 1) +
xfs_calc_buf_res(XFS_DA_NODE_MAXDEPTH,
XFS_FSB_TO_B(mp, 1)) +
(uint)XFS_FSB_TO_B(mp,
diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h
index b7e5357..7241ab2 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.h
+++ b/fs/xfs/libxfs/xfs_trans_resv.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_TRANS_RESV_H__
#define __XFS_TRANS_RESV_H__
diff --git a/fs/xfs/libxfs/xfs_trans_space.h b/fs/xfs/libxfs/xfs_trans_space.h
index d787c67..a62fb95 100644
--- a/fs/xfs/libxfs/xfs_trans_space.h
+++ b/fs/xfs/libxfs/xfs_trans_space.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_TRANS_SPACE_H__
#define __XFS_TRANS_SPACE_H__
diff --git a/fs/xfs/libxfs/xfs_types.c b/fs/xfs/libxfs/xfs_types.c
new file mode 100644
index 0000000..2e2a243
--- /dev/null
+++ b/fs/xfs/libxfs/xfs_types.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
+ * Copyright (C) 2017 Oracle.
+ * All Rights Reserved.
+ */
+#include "xfs.h"
+#include "xfs_fs.h"
+#include "xfs_format.h"
+#include "xfs_log_format.h"
+#include "xfs_shared.h"
+#include "xfs_trans_resv.h"
+#include "xfs_bit.h"
+#include "xfs_sb.h"
+#include "xfs_mount.h"
+#include "xfs_defer.h"
+#include "xfs_inode.h"
+#include "xfs_btree.h"
+#include "xfs_rmap.h"
+#include "xfs_alloc_btree.h"
+#include "xfs_alloc.h"
+#include "xfs_ialloc.h"
+
+/* Find the size of the AG, in blocks. */
+xfs_agblock_t
+xfs_ag_block_count(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno)
+{
+ ASSERT(agno < mp->m_sb.sb_agcount);
+
+ if (agno < mp->m_sb.sb_agcount - 1)
+ return mp->m_sb.sb_agblocks;
+ return mp->m_sb.sb_dblocks - (agno * mp->m_sb.sb_agblocks);
+}
+
+/*
+ * Verify that an AG block number pointer neither points outside the AG
+ * nor points at static metadata.
+ */
+bool
+xfs_verify_agbno(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno,
+ xfs_agblock_t agbno)
+{
+ xfs_agblock_t eoag;
+
+ eoag = xfs_ag_block_count(mp, agno);
+ if (agbno >= eoag)
+ return false;
+ if (agbno <= XFS_AGFL_BLOCK(mp))
+ return false;
+ return true;
+}
+
+/*
+ * Verify that an FS block number pointer neither points outside the
+ * filesystem nor points at static AG metadata.
+ */
+bool
+xfs_verify_fsbno(
+ struct xfs_mount *mp,
+ xfs_fsblock_t fsbno)
+{
+ xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, fsbno);
+
+ if (agno >= mp->m_sb.sb_agcount)
+ return false;
+ return xfs_verify_agbno(mp, agno, XFS_FSB_TO_AGBNO(mp, fsbno));
+}
+
+/* Calculate the first and last possible inode number in an AG. */
+void
+xfs_agino_range(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno,
+ xfs_agino_t *first,
+ xfs_agino_t *last)
+{
+ xfs_agblock_t bno;
+ xfs_agblock_t eoag;
+
+ eoag = xfs_ag_block_count(mp, agno);
+
+ /*
+ * Calculate the first inode, which will be in the first
+ * cluster-aligned block after the AGFL.
+ */
+ bno = round_up(XFS_AGFL_BLOCK(mp) + 1,
+ xfs_ialloc_cluster_alignment(mp));
+ *first = XFS_OFFBNO_TO_AGINO(mp, bno, 0);
+
+ /*
+ * Calculate the last inode, which will be at the end of the
+ * last (aligned) cluster that can be allocated in the AG.
+ */
+ bno = round_down(eoag, xfs_ialloc_cluster_alignment(mp));
+ *last = XFS_OFFBNO_TO_AGINO(mp, bno, 0) - 1;
+}
+
+/*
+ * Verify that an AG inode number pointer neither points outside the AG
+ * nor points at static metadata.
+ */
+bool
+xfs_verify_agino(
+ struct xfs_mount *mp,
+ xfs_agnumber_t agno,
+ xfs_agino_t agino)
+{
+ xfs_agino_t first;
+ xfs_agino_t last;
+
+ xfs_agino_range(mp, agno, &first, &last);
+ return agino >= first && agino <= last;
+}
+
+/*
+ * Verify that an FS inode number pointer neither points outside the
+ * filesystem nor points at static AG metadata.
+ */
+bool
+xfs_verify_ino(
+ struct xfs_mount *mp,
+ xfs_ino_t ino)
+{
+ xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ino);
+ xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ino);
+
+ if (agno >= mp->m_sb.sb_agcount)
+ return false;
+ if (XFS_AGINO_TO_INO(mp, agno, agino) != ino)
+ return false;
+ return xfs_verify_agino(mp, agno, agino);
+}
+
+/* Is this an internal inode number? */
+bool
+xfs_internal_inum(
+ struct xfs_mount *mp,
+ xfs_ino_t ino)
+{
+ return ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
+ (xfs_sb_version_hasquota(&mp->m_sb) &&
+ xfs_is_quota_inode(&mp->m_sb, ino));
+}
+
+/*
+ * Verify that a directory entry's inode number doesn't point at an internal
+ * inode, empty space, or static AG metadata.
+ */
+bool
+xfs_verify_dir_ino(
+ struct xfs_mount *mp,
+ xfs_ino_t ino)
+{
+ if (xfs_internal_inum(mp, ino))
+ return false;
+ return xfs_verify_ino(mp, ino);
+}
+
+/*
+ * Verify that an realtime block number pointer doesn't point off the
+ * end of the realtime device.
+ */
+bool
+xfs_verify_rtbno(
+ struct xfs_mount *mp,
+ xfs_rtblock_t rtbno)
+{
+ return rtbno < mp->m_sb.sb_rblocks;
+}
diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h
index ea18449..4055d62 100644
--- a/fs/xfs/libxfs/xfs_types.h
+++ b/fs/xfs/libxfs/xfs_types.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_TYPES_H__
#define __XFS_TYPES_H__
@@ -159,4 +147,23 @@ typedef struct xfs_bmbt_irec
xfs_exntst_t br_state; /* extent state */
} xfs_bmbt_irec_t;
+/*
+ * Type verifier functions
+ */
+struct xfs_mount;
+
+xfs_agblock_t xfs_ag_block_count(struct xfs_mount *mp, xfs_agnumber_t agno);
+bool xfs_verify_agbno(struct xfs_mount *mp, xfs_agnumber_t agno,
+ xfs_agblock_t agbno);
+bool xfs_verify_fsbno(struct xfs_mount *mp, xfs_fsblock_t fsbno);
+
+void xfs_agino_range(struct xfs_mount *mp, xfs_agnumber_t agno,
+ xfs_agino_t *first, xfs_agino_t *last);
+bool xfs_verify_agino(struct xfs_mount *mp, xfs_agnumber_t agno,
+ xfs_agino_t agino);
+bool xfs_verify_ino(struct xfs_mount *mp, xfs_ino_t ino);
+bool xfs_internal_inum(struct xfs_mount *mp, xfs_ino_t ino);
+bool xfs_verify_dir_ino(struct xfs_mount *mp, xfs_ino_t ino);
+bool xfs_verify_rtbno(struct xfs_mount *mp, xfs_rtblock_t rtbno);
+
#endif /* __XFS_TYPES_H__ */
diff --git a/fs/xfs/mrlock.h b/fs/xfs/mrlock.h
index e3c92d1..79155ee 100644
--- a/fs/xfs/mrlock.h
+++ b/fs/xfs/mrlock.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SUPPORT_MRLOCK_H__
#define __XFS_SUPPORT_MRLOCK_H__
diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c
index 1f71793..9bb0745 100644
--- a/fs/xfs/scrub/agheader.c
+++ b/fs/xfs/scrub/agheader.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -881,7 +867,7 @@ xfs_scrub_agi(
}
/* Check inode counters */
- xfs_ialloc_agino_range(mp, agno, &first_agino, &last_agino);
+ xfs_agino_range(mp, agno, &first_agino, &last_agino);
icount = be32_to_cpu(agi->agi_count);
if (icount > last_agino - first_agino + 1 ||
icount < be32_to_cpu(agi->agi_freecount))
diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c
index 8b91e9e..117eeda 100644
--- a/fs/xfs/scrub/agheader_repair.c
+++ b/fs/xfs/scrub/agheader_repair.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/alloc.c b/fs/xfs/scrub/alloc.c
index 941a0a5..50e4f7f 100644
--- a/fs/xfs/scrub/alloc.c
+++ b/fs/xfs/scrub/alloc.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/attr.c b/fs/xfs/scrub/attr.c
index 84b6d6b..de51cf8 100644
--- a/fs/xfs/scrub/attr.c
+++ b/fs/xfs/scrub/attr.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c
index eeadb33..3d08589 100644
--- a/fs/xfs/scrub/bmap.c
+++ b/fs/xfs/scrub/bmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/btree.c b/fs/xfs/scrub/btree.c
index 2d29dce..5b47204 100644
--- a/fs/xfs/scrub/btree.c
+++ b/fs/xfs/scrub/btree.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/btree.h b/fs/xfs/scrub/btree.h
index e2b868e..9566275 100644
--- a/fs/xfs/scrub/btree.h
+++ b/fs/xfs/scrub/btree.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_BTREE_H__
#define __XFS_SCRUB_BTREE_H__
diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c
index 41198a5..70e70c6 100644
--- a/fs/xfs/scrub/common.c
+++ b/fs/xfs/scrub/common.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/common.h b/fs/xfs/scrub/common.h
index 76bb2d1..2172bd5 100644
--- a/fs/xfs/scrub/common.h
+++ b/fs/xfs/scrub/common.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_COMMON_H__
#define __XFS_SCRUB_COMMON_H__
diff --git a/fs/xfs/scrub/dabtree.c b/fs/xfs/scrub/dabtree.c
index bffdb7d..d700c4d 100644
--- a/fs/xfs/scrub/dabtree.c
+++ b/fs/xfs/scrub/dabtree.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/dabtree.h b/fs/xfs/scrub/dabtree.h
index d31468d..365f9f0 100644
--- a/fs/xfs/scrub/dabtree.h
+++ b/fs/xfs/scrub/dabtree.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_DABTREE_H__
#define __XFS_SCRUB_DABTREE_H__
diff --git a/fs/xfs/scrub/dir.c b/fs/xfs/scrub/dir.c
index 1a4309b..8632477 100644
--- a/fs/xfs/scrub/dir.c
+++ b/fs/xfs/scrub/dir.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/ialloc.c b/fs/xfs/scrub/ialloc.c
index 00a834d..13d43d1 100644
--- a/fs/xfs/scrub/ialloc.c
+++ b/fs/xfs/scrub/ialloc.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c
index 0c696f7..7a62085 100644
--- a/fs/xfs/scrub/inode.c
+++ b/fs/xfs/scrub/inode.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/parent.c b/fs/xfs/scrub/parent.c
index 77c6b22..e2bda58 100644
--- a/fs/xfs/scrub/parent.c
+++ b/fs/xfs/scrub/parent.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/quota.c b/fs/xfs/scrub/quota.c
index 15ae4d2..6ff906a 100644
--- a/fs/xfs/scrub/quota.c
+++ b/fs/xfs/scrub/quota.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c
index 324a5f1..607a9fa 100644
--- a/fs/xfs/scrub/refcount.c
+++ b/fs/xfs/scrub/refcount.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/repair.c b/fs/xfs/scrub/repair.c
index e3e8fba..326be4e 100644
--- a/fs/xfs/scrub/repair.c
+++ b/fs/xfs/scrub/repair.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/repair.h b/fs/xfs/scrub/repair.h
index f2b0895..ef47826 100644
--- a/fs/xfs/scrub/repair.h
+++ b/fs/xfs/scrub/repair.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_REPAIR_H__
#define __XFS_SCRUB_REPAIR_H__
diff --git a/fs/xfs/scrub/rmap.c b/fs/xfs/scrub/rmap.c
index b376a9a..c6d7632 100644
--- a/fs/xfs/scrub/rmap.c
+++ b/fs/xfs/scrub/rmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/rtbitmap.c b/fs/xfs/scrub/rtbitmap.c
index 40f462a..1f86e02 100644
--- a/fs/xfs/scrub/rtbitmap.c
+++ b/fs/xfs/scrub/rtbitmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/scrub.c b/fs/xfs/scrub/scrub.c
index 36db098..58ae76b 100644
--- a/fs/xfs/scrub/scrub.c
+++ b/fs/xfs/scrub/scrub.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h
index 636424d..b295edd 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_SCRUB_H__
#define __XFS_SCRUB_SCRUB_H__
diff --git a/fs/xfs/scrub/symlink.c b/fs/xfs/scrub/symlink.c
index 3aa3d60..570a898 100644
--- a/fs/xfs/scrub/symlink.c
+++ b/fs/xfs/scrub/symlink.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/trace.c b/fs/xfs/scrub/trace.c
index 86daed0..7c76d8b 100644
--- a/fs/xfs/scrub/trace.c
+++ b/fs/xfs/scrub/trace.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h
index 794d56b..cec3e5e 100644
--- a/fs/xfs/scrub/trace.h
+++ b/fs/xfs/scrub/trace.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM xfs_scrub
diff --git a/fs/xfs/scrub/xfs_scrub.h b/fs/xfs/scrub/xfs_scrub.h
index e00e0ea..2897ba3 100644
--- a/fs/xfs/scrub/xfs_scrub.h
+++ b/fs/xfs/scrub/xfs_scrub.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_SCRUB_H__
#define __XFS_SCRUB_H__
diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h
index 5ff7f22..583a9f5 100644
--- a/fs/xfs/xfs.h
+++ b/fs/xfs/xfs.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_H__
#define __XFS_H__
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 3354140..8039e35 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2008, Christoph Hellwig
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 0432731..94615e3 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2001-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ACL_H__
#define __XFS_ACL_H__
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index ca69037..8eb3ba3 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_shared.h"
@@ -543,8 +531,19 @@ xfs_submit_ioend(
{
/* Convert CoW extents to regular */
if (!status && ioend->io_type == XFS_IO_COW) {
+ /*
+ * Yuk. This can do memory allocation, but is not a
+ * transactional operation so everything is done in GFP_KERNEL
+ * context. That can deadlock, because we hold pages in
+ * writeback state and GFP_KERNEL allocations can block on them.
+ * Hence we must operate in nofs conditions here.
+ */
+ unsigned nofs_flag;
+
+ nofs_flag = memalloc_nofs_save();
status = xfs_reflink_convert_cow(XFS_I(ioend->io_inode),
ioend->io_offset, ioend->io_size);
+ memalloc_nofs_restore(nofs_flag);
}
/* Reserve log space if we might write beyond the on-disk inode size. */
diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h
index 694c85b..25bc6d4 100644
--- a/fs/xfs/xfs_aops.h
+++ b/fs/xfs/xfs_aops.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2005-2006 Silicon Graphics, Inc.
* All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_AOPS_H__
#define __XFS_AOPS_H__
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h
index d07bf27..033ff8c 100644
--- a/fs/xfs/xfs_attr.h
+++ b/fs/xfs/xfs_attr.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ATTR_H__
#define __XFS_ATTR_H__
diff --git a/fs/xfs/xfs_attr_inactive.c b/fs/xfs/xfs_attr_inactive.c
index 52818ea..7ce1005 100644
--- a/fs/xfs/xfs_attr_inactive.c
+++ b/fs/xfs/xfs_attr_inactive.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
index 3e59a34..f9ca801 100644
--- a/fs/xfs/xfs_attr_list.c
+++ b/fs/xfs/xfs_attr_list.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -139,7 +127,8 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
((char *)sfe >= ((char *)sf + dp->i_afp->if_bytes)))) {
XFS_CORRUPTION_ERROR("xfs_attr_shortform_list",
XFS_ERRLEVEL_LOW,
- context->dp->i_mount, sfe);
+ context->dp->i_mount, sfe,
+ sizeof(*sfe));
kmem_free(sbuf);
return -EFSCORRUPTED;
}
@@ -241,7 +230,7 @@ xfs_attr_node_list_lookup(
if (magic != XFS_DA_NODE_MAGIC &&
magic != XFS_DA3_NODE_MAGIC) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
- node);
+ node, sizeof(*node));
goto out_corruptbuf;
}
diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c
index 618bb71..956ebd5 100644
--- a/fs/xfs/xfs_bmap_item.c
+++ b/fs/xfs/xfs_bmap_item.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_bmap_item.h b/fs/xfs/xfs_bmap_item.h
index 24b354a..fd1a1b1 100644
--- a/fs/xfs/xfs_bmap_item.h
+++ b/fs/xfs/xfs_bmap_item.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_BMAP_ITEM_H__
#define __XFS_BMAP_ITEM_H__
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 06badcb..c35009a 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2012 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -92,6 +80,7 @@ xfs_bmap_rtalloc(
int error; /* error return value */
xfs_mount_t *mp; /* mount point structure */
xfs_extlen_t prod = 0; /* product factor for allocators */
+ xfs_extlen_t mod = 0; /* product factor for allocators */
xfs_extlen_t ralen = 0; /* realtime allocation length */
xfs_extlen_t align; /* minimum allocation alignment */
xfs_rtblock_t rtb;
@@ -111,7 +100,8 @@ xfs_bmap_rtalloc(
* If the offset & length are not perfectly aligned
* then kill prod, it will just get us in trouble.
*/
- if (do_mod(ap->offset, align) || ap->length % align)
+ div_u64_rem(ap->offset, align, &mod);
+ if (mod || ap->length % align)
prod = 1;
/*
* Set ralen to be the actual requested length in rtextents.
@@ -948,9 +938,11 @@ xfs_alloc_file_space(
do_div(s, extsz);
s *= extsz;
e = startoffset_fsb + allocatesize_fsb;
- if ((temp = do_mod(startoffset_fsb, extsz)))
+ div_u64_rem(startoffset_fsb, extsz, &temp);
+ if (temp)
e += temp;
- if ((temp = do_mod(e, extsz)))
+ div_u64_rem(e, extsz, &temp);
+ if (temp)
e += extsz - temp;
} else {
s = 0;
@@ -1111,7 +1103,7 @@ xfs_adjust_extent_unmap_boundaries(
if (nimap && imap.br_startblock != HOLESTARTBLOCK) {
ASSERT(imap.br_startblock != DELAYSTARTBLOCK);
- mod = do_mod(imap.br_startblock, mp->m_sb.sb_rextsize);
+ div_u64_rem(imap.br_startblock, mp->m_sb.sb_rextsize, &mod);
if (mod)
*startoffset_fsb += mp->m_sb.sb_rextsize - mod;
}
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h
index 4d4ae48..87363d1 100644
--- a/fs/xfs/xfs_bmap_util.h
+++ b/fs/xfs/xfs_bmap_util.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BMAP_UTIL_H__
#define __XFS_BMAP_UTIL_H__
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 5179ab9..e9c058e 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include <linux/stddef.h>
@@ -33,7 +21,6 @@
#include <linux/migrate.h>
#include <linux/backing-dev.h>
#include <linux/freezer.h>
-#include <linux/sched/mm.h>
#include "xfs_format.h"
#include "xfs_log_format.h"
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index f5f2b71..d24dbd4 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BUF_H__
#define __XFS_BUF_H__
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index c231137..1c9d139 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -842,7 +830,7 @@ xfs_buf_item_log_segment(
* of the last bit to be set in this word plus one.
*/
if (bit) {
- end_bit = MIN(bit + bits_to_set, (uint)NBWORD);
+ end_bit = min(bit + bits_to_set, (uint)NBWORD);
mask = ((1U << (end_bit - bit)) - 1) << bit;
*wordp |= mask;
wordp++;
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 643f53d..3f7d7b7 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_BUF_ITEM_H__
#define __XFS_BUF_ITEM_H__
diff --git a/fs/xfs/xfs_dir2_readdir.c b/fs/xfs/xfs_dir2_readdir.c
index b6ae359..5142e64 100644
--- a/fs/xfs/xfs_dir2_readdir.c
+++ b/fs/xfs/xfs_dir2_readdir.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* Copyright (c) 2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c
index 7b68e6c..678a5fcd 100644
--- a/fs/xfs/xfs_discard.c
+++ b/fs/xfs/xfs_discard.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2010 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 2567391..0973a04 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index bdd6bd9..64bd864 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DQUOT_H__
#define __XFS_DQUOT_H__
diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c
index 8eb7415..7dedd17 100644
--- a/fs/xfs/xfs_dquot_item.c
+++ b/fs/xfs/xfs_dquot_item.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_dquot_item.h b/fs/xfs/xfs_dquot_item.h
index 502e946..db9df71 100644
--- a/fs/xfs/xfs_dquot_item.h
+++ b/fs/xfs/xfs_dquot_item.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_DQUOT_ITEM_H__
#define __XFS_DQUOT_ITEM_H__
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c
index 7975634..0470114 100644
--- a/fs/xfs/xfs_error.c
+++ b/fs/xfs/xfs_error.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
@@ -334,13 +322,14 @@ xfs_corruption_error(
const char *tag,
int level,
struct xfs_mount *mp,
- void *p,
+ void *buf,
+ size_t bufsize,
const char *filename,
int linenum,
xfs_failaddr_t failaddr)
{
if (level <= xfs_error_level)
- xfs_hex_dump(p, XFS_CORRUPTION_DUMP_LEN);
+ xfs_hex_dump(buf, bufsize);
xfs_error_report(tag, level, mp, filename, linenum, failaddr);
xfs_alert(mp, "Corruption detected. Unmount and run xfs_repair");
}
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h
index ce39134..246d3e9 100644
--- a/fs/xfs/xfs_error.h
+++ b/fs/xfs/xfs_error.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ERROR_H__
#define __XFS_ERROR_H__
@@ -24,8 +12,9 @@ extern void xfs_error_report(const char *tag, int level, struct xfs_mount *mp,
const char *filename, int linenum,
xfs_failaddr_t failaddr);
extern void xfs_corruption_error(const char *tag, int level,
- struct xfs_mount *mp, void *p, const char *filename,
- int linenum, xfs_failaddr_t failaddr);
+ struct xfs_mount *mp, void *buf, size_t bufsize,
+ const char *filename, int linenum,
+ xfs_failaddr_t failaddr);
extern void xfs_buf_verifier_error(struct xfs_buf *bp, int error,
const char *name, void *buf, size_t bufsz,
xfs_failaddr_t failaddr);
@@ -37,8 +26,8 @@ extern void xfs_inode_verifier_error(struct xfs_inode *ip, int error,
#define XFS_ERROR_REPORT(e, lvl, mp) \
xfs_error_report(e, lvl, mp, __FILE__, __LINE__, __return_address)
-#define XFS_CORRUPTION_ERROR(e, lvl, mp, mem) \
- xfs_corruption_error(e, lvl, mp, mem, \
+#define XFS_CORRUPTION_ERROR(e, lvl, mp, buf, bufsize) \
+ xfs_corruption_error(e, lvl, mp, buf, bufsize, \
__FILE__, __LINE__, __return_address)
#define XFS_ERRLEVEL_OFF 0
diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c
index eed698a..3cf4682 100644
--- a/fs/xfs/xfs_export.c
+++ b/fs/xfs/xfs_export.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2004-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
@@ -140,15 +128,24 @@ xfs_nfs_get_inode(
*/
error = xfs_iget(mp, NULL, ino, XFS_IGET_UNTRUSTED, 0, &ip);
if (error) {
+
/*
* EINVAL means the inode cluster doesn't exist anymore.
- * This implies the filehandle is stale, so we should
- * translate it here.
+ * EFSCORRUPTED means the metadata pointing to the inode cluster
+ * or the inode cluster itself is corrupt. This implies the
+ * filehandle is stale, so we should translate it here.
* We don't use ESTALE directly down the chain to not
* confuse applications using bulkstat that expect EINVAL.
*/
- if (error == -EINVAL || error == -ENOENT)
+ switch (error) {
+ case -EINVAL:
+ case -ENOENT:
+ case -EFSCORRUPTED:
error = -ESTALE;
+ break;
+ default:
+ break;
+ }
return ERR_PTR(error);
}
diff --git a/fs/xfs/xfs_export.h b/fs/xfs/xfs_export.h
index 3272b6a..64471a3 100644
--- a/fs/xfs/xfs_export.h
+++ b/fs/xfs/xfs_export.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_EXPORT_H__
#define __XFS_EXPORT_H__
diff --git a/fs/xfs/xfs_extent_busy.c b/fs/xfs/xfs_extent_busy.c
index 13e3d1a..0ed6837 100644
--- a/fs/xfs/xfs_extent_busy.c
+++ b/fs/xfs/xfs_extent_busy.c
@@ -1,21 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2010 David Chinner.
* Copyright (c) 2011 Christoph Hellwig.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_extent_busy.h b/fs/xfs/xfs_extent_busy.h
index 60195ea..990ab38 100644
--- a/fs/xfs/xfs_extent_busy.h
+++ b/fs/xfs/xfs_extent_busy.h
@@ -1,21 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2010 David Chinner.
* Copyright (c) 2011 Christoph Hellwig.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_EXTENT_BUSY_H__
#define __XFS_EXTENT_BUSY_H__
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c
index a889b55..d9da66c 100644
--- a/fs/xfs/xfs_extfree_item.c
+++ b/fs/xfs/xfs_extfree_item.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h
index a32c794..2a6a895 100644
--- a/fs/xfs/xfs_extfree_item.h
+++ b/fs/xfs/xfs_extfree_item.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_EXTFREE_ITEM_H__
#define __XFS_EXTFREE_ITEM_H__
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index bed07df..a3e7767 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c
index 3f8722e..2d2c5ab 100644
--- a/fs/xfs/xfs_filestream.c
+++ b/fs/xfs/xfs_filestream.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
* Copyright (c) 2014 Christoph Hellwig.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
diff --git a/fs/xfs/xfs_filestream.h b/fs/xfs/xfs_filestream.h
index 2ef4340..5cc7665 100644
--- a/fs/xfs/xfs_filestream.h
+++ b/fs/xfs/xfs_filestream.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_FILESTREAM_H__
#define __XFS_FILESTREAM_H__
diff --git a/fs/xfs/xfs_fsmap.c b/fs/xfs/xfs_fsmap.c
index 0299feb..c34fa9c 100644
--- a/fs/xfs/xfs_fsmap.c
+++ b/fs/xfs/xfs_fsmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_fsmap.h b/fs/xfs/xfs_fsmap.h
index 0b9bf82..c6c5773 100644
--- a/fs/xfs/xfs_fsmap.h
+++ b/fs/xfs/xfs_fsmap.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2017 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_FSMAP_H__
#define __XFS_FSMAP_H__
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index bc7ef18..a7afcad 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h
index 20484ed..d023db0 100644
--- a/fs/xfs/xfs_fsops.h
+++ b/fs/xfs/xfs_fsops.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_FSOPS_H__
#define __XFS_FSOPS_H__
diff --git a/fs/xfs/xfs_globals.c b/fs/xfs/xfs_globals.c
index fdde17a..5169e84 100644
--- a/fs/xfs/xfs_globals.c
+++ b/fs/xfs/xfs_globals.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_sysctl.h"
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 164350d..47f417d 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
index d69a0f5..26c0626 100644
--- a/fs/xfs/xfs_icache.h
+++ b/fs/xfs/xfs_icache.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef XFS_SYNC_H
#define XFS_SYNC_H 1
diff --git a/fs/xfs/xfs_icreate_item.c b/fs/xfs/xfs_icreate_item.c
index 5da9599..8381d34 100644
--- a/fs/xfs/xfs_icreate_item.c
+++ b/fs/xfs/xfs_icreate_item.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2008-2010, 2013 Dave Chinner
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_icreate_item.h b/fs/xfs/xfs_icreate_item.h
index 59e89f8..a50d0b0 100644
--- a/fs/xfs/xfs_icreate_item.h
+++ b/fs/xfs/xfs_icreate_item.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2008-2010, Dave Chinner
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef XFS_ICREATE_ITEM_H
#define XFS_ICREATE_ITEM_H 1
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 05207a6..7a96c4e0 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/log2.h>
#include <linux/iversion.h>
@@ -773,7 +761,7 @@ xfs_ialloc(
xfs_inode_t *ip;
uint flags;
int error;
- struct timespec tv;
+ struct timespec64 tv;
struct inode *inode;
/*
@@ -2090,10 +2078,15 @@ xfs_iunlink_remove(
* list this inode will go on.
*/
agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
- ASSERT(agino != 0);
+ if (!xfs_verify_agino(mp, agno, agino))
+ return -EFSCORRUPTED;
bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
- ASSERT(agi->agi_unlinked[bucket_index] != cpu_to_be32(NULLAGINO));
- ASSERT(agi->agi_unlinked[bucket_index]);
+ if (!xfs_verify_agino(mp, agno,
+ be32_to_cpu(agi->agi_unlinked[bucket_index]))) {
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
+ agi, sizeof(*agi));
+ return -EFSCORRUPTED;
+ }
if (be32_to_cpu(agi->agi_unlinked[bucket_index]) == agino) {
/*
@@ -2171,8 +2164,12 @@ xfs_iunlink_remove(
last_offset = imap.im_boffset;
next_agino = be32_to_cpu(last_dip->di_next_unlinked);
- ASSERT(next_agino != NULLAGINO);
- ASSERT(next_agino != 0);
+ if (!xfs_verify_agino(mp, agno, next_agino)) {
+ XFS_CORRUPTION_ERROR(__func__,
+ XFS_ERRLEVEL_LOW, mp,
+ last_dip, sizeof(*last_dip));
+ return -EFSCORRUPTED;
+ }
}
/*
@@ -2261,7 +2258,7 @@ xfs_ifree_cluster(
*/
ioffset = inum - xic->first_ino;
if ((xic->alloc & XFS_INOBT_MASK(ioffset)) == 0) {
- ASSERT(do_mod(ioffset, inodes_per_cluster) == 0);
+ ASSERT(ioffset % inodes_per_cluster == 0);
continue;
}
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index a91d9fb..2ed63a4 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_INODE_H__
#define __XFS_INODE_H__
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c
index 3e5b857..2389c34 100644
--- a/fs/xfs/xfs_inode_item.c
+++ b/fs/xfs/xfs_inode_item.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h
index b72373a..27081eb 100644
--- a/fs/xfs/xfs_inode_item.h
+++ b/fs/xfs/xfs_inode_item.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_INODE_ITEM_H__
#define __XFS_INODE_ITEM_H__
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 32b6805..0ef5ece 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1094,12 +1082,14 @@ xfs_ioctl_setattr_dax_invalidate(
/*
* It is only valid to set the DAX flag on regular files and
* directories on filesystems where the block size is equal to the page
- * size. On directories it serves as an inherit hint.
+ * size. On directories it serves as an inherited hint so we don't
+ * have to check the device for dax support or flush pagecache.
*/
if (fa->fsx_xflags & FS_XFLAG_DAX) {
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
return -EINVAL;
- if (!bdev_dax_supported(xfs_find_bdev_for_inode(VFS_I(ip)),
+ if (S_ISREG(inode->i_mode) &&
+ !bdev_dax_supported(xfs_find_bdev_for_inode(VFS_I(ip)),
sb->s_blocksize))
return -EINVAL;
}
@@ -1110,6 +1100,9 @@ xfs_ioctl_setattr_dax_invalidate(
if (!(fa->fsx_xflags & FS_XFLAG_DAX) && !IS_DAX(inode))
return 0;
+ if (S_ISDIR(inode->i_mode))
+ return 0;
+
/* lock, flush and invalidate mapping in preparation for flag change */
xfs_ilock(ip, XFS_MMAPLOCK_EXCL | XFS_IOLOCK_EXCL);
error = filemap_write_and_wait(inode->i_mapping);
@@ -1819,13 +1812,13 @@ xfs_ioc_getlabel(
/* Paranoia */
BUILD_BUG_ON(sizeof(sbp->sb_fname) > FSLABEL_MAX);
+ /* 1 larger than sb_fname, so this ensures a trailing NUL char */
+ memset(label, 0, sizeof(label));
spin_lock(&mp->m_sb_lock);
- strncpy(label, sbp->sb_fname, sizeof(sbp->sb_fname));
+ strncpy(label, sbp->sb_fname, XFSLABEL_MAX);
spin_unlock(&mp->m_sb_lock);
- /* xfs on-disk label is 12 chars, be sure we send a null to user */
- label[XFSLABEL_MAX] = '\0';
- if (copy_to_user(user_label, label, sizeof(sbp->sb_fname)))
+ if (copy_to_user(user_label, label, sizeof(label)))
return -EFAULT;
return 0;
}
@@ -1861,7 +1854,7 @@ xfs_ioc_setlabel(
spin_lock(&mp->m_sb_lock);
memset(sbp->sb_fname, 0, sizeof(sbp->sb_fname));
- strncpy(sbp->sb_fname, label, sizeof(sbp->sb_fname));
+ memcpy(sbp->sb_fname, label, len);
spin_unlock(&mp->m_sb_lock);
/*
diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h
index 8de879f..4b17f67 100644
--- a/fs/xfs/xfs_ioctl.h
+++ b/fs/xfs/xfs_ioctl.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2008 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IOCTL_H__
#define __XFS_IOCTL_H__
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index 10fbde3..fba115f 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2004-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/compat.h>
#include <linux/ioctl.h>
diff --git a/fs/xfs/xfs_ioctl32.h b/fs/xfs/xfs_ioctl32.h
index 5492bcf..d28fa82 100644
--- a/fs/xfs/xfs_ioctl32.h
+++ b/fs/xfs/xfs_ioctl32.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2004-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IOCTL32_H__
#define __XFS_IOCTL32_H__
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index c6ce6f9..49f5492 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2016 Christoph Hellwig.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/iomap.h>
#include "xfs.h"
@@ -200,7 +188,7 @@ xfs_iomap_write_direct(
goto out_unlock;
} else {
if (nmaps && (imap->br_startblock == HOLESTARTBLOCK))
- last_fsb = MIN(last_fsb, (xfs_fileoff_t)
+ last_fsb = min(last_fsb, (xfs_fileoff_t)
imap->br_blockcount +
imap->br_startoff);
}
@@ -488,8 +476,8 @@ xfs_iomap_prealloc_size(
* The shift throttle value is set to the maximum value as determined by
* the global low free space values and per-quota low free space values.
*/
- alloc_blocks = MIN(alloc_blocks, qblocks);
- shift = MAX(shift, qshift);
+ alloc_blocks = min(alloc_blocks, qblocks);
+ shift = max(shift, qshift);
if (shift)
alloc_blocks >>= shift;
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h
index ee53506..83474c9 100644
--- a/fs/xfs/xfs_iomap.h
+++ b/fs/xfs/xfs_iomap.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2003-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IOMAP_H__
#define __XFS_IOMAP_H__
@@ -42,10 +30,10 @@ xfs_aligned_fsb_count(
if (extsz) {
xfs_extlen_t align;
- align = do_mod(offset_fsb, extsz);
+ div_u64_rem(offset_fsb, extsz, &align);
if (align)
count_fsb += align;
- align = do_mod(count_fsb, extsz);
+ div_u64_rem(count_fsb, extsz, &align);
if (align)
count_fsb += extsz - align;
}
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 3b4be06..0fa29f3 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1054,7 +1042,7 @@ xfs_vn_setattr(
STATIC int
xfs_vn_update_time(
struct inode *inode,
- struct timespec *now,
+ struct timespec64 *now,
int flags)
{
struct xfs_inode *ip = XFS_I(inode);
@@ -1274,6 +1262,14 @@ xfs_setup_inode(
xfs_diflags_to_iflags(inode, ip);
if (S_ISDIR(inode->i_mode)) {
+ /*
+ * We set the i_rwsem class here to avoid potential races with
+ * lockdep_annotate_inode_mutex_key() reinitialising the lock
+ * after a filehandle lookup has already found the inode in
+ * cache before it has been unlocked via unlock_new_inode().
+ */
+ lockdep_set_class(&inode->i_rwsem,
+ &inode->i_sb->s_type->i_mutex_dir_key);
lockdep_set_class(&ip->i_lock.mr_lock, &xfs_dir_ilock_class);
ip->d_ops = ip->i_mount->m_dir_inode_ops;
} else {
diff --git a/fs/xfs/xfs_iops.h b/fs/xfs/xfs_iops.h
index 0259a38..4d24ff3 100644
--- a/fs/xfs/xfs_iops.h
+++ b/fs/xfs/xfs_iops.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_IOPS_H__
#define __XFS_IOPS_H__
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index d583105..24f4f1c 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -571,7 +559,7 @@ xfs_inumbers(
*lastino != XFS_AGINO_TO_INO(mp, agno, agino))
return error;
- bcount = MIN(left, (int)(PAGE_SIZE / sizeof(*buffer)));
+ bcount = min(left, (int)(PAGE_SIZE / sizeof(*buffer)));
buffer = kmem_zalloc(bcount * sizeof(*buffer), KM_SLEEP);
do {
struct xfs_inobt_rec_incore r;
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h
index 6ea8b39..8a82228 100644
--- a/fs/xfs/xfs_itable.h
+++ b/fs/xfs/xfs_itable.h
@@ -1,18 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2001 Silicon Graphics, Inc. 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ITABLE_H__
#define __XFS_ITABLE_H__
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index bee51a1..edbd5a2 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_LINUX__
#define __XFS_LINUX__
@@ -38,6 +26,7 @@ typedef __u32 xfs_nlink_t;
#include <linux/semaphore.h>
#include <linux/mm.h>
+#include <linux/sched/mm.h>
#include <linux/kernel.h>
#include <linux/blkdev.h>
#include <linux/slab.h>
@@ -151,8 +140,6 @@ typedef __u32 xfs_nlink_t;
#define XFS_PROJID_DEFAULT 0
-#define MIN(a,b) (min(a,b))
-#define MAX(a,b) (max(a,b))
#define howmany(x, y) (((x)+((y)-1))/(y))
static inline void delay(long ticks)
@@ -220,25 +207,6 @@ static inline xfs_dev_t linux_to_xfs_dev_t(dev_t dev)
#define xfs_sort(a,n,s,fn) sort(a,n,s,fn,NULL)
#define xfs_stack_trace() dump_stack()
-/* Side effect free 64 bit mod operation */
-static inline __u32 xfs_do_mod(void *a, __u32 b, int n)
-{
- switch (n) {
- case 4:
- return *(__u32 *)a % b;
- case 8:
- {
- __u64 c = *(__u64 *)a;
- return do_div(c, b);
- }
- }
-
- /* NOTREACHED */
- return 0;
-}
-
-#define do_mod(a, b) xfs_do_mod(&(a), (b), sizeof(a))
-
static inline uint64_t roundup_64(uint64_t x, uint32_t y)
{
x += y - 1;
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index c21039f..5e56f3b 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1641,8 +1629,8 @@ xlog_grant_push_ail(
* log, and 256 blocks.
*/
free_threshold = BTOBB(need_bytes);
- free_threshold = MAX(free_threshold, (log->l_logBBsize >> 2));
- free_threshold = MAX(free_threshold, 256);
+ free_threshold = max(free_threshold, (log->l_logBBsize >> 2));
+ free_threshold = max(free_threshold, 256);
if (free_blocks >= free_threshold)
return;
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h
index fa8ad31..3c1f6a8 100644
--- a/fs/xfs/xfs_log.h
+++ b/fs/xfs/xfs_log.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_LOG_H__
#define __XFS_LOG_H__
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index c156877..d3884e0 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -1,18 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2010 Red Hat, Inc. 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index 1299759..b5f82cb 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_LOG_PRIV_H__
#define __XFS_LOG_PRIV_H__
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 06a09cb..b181b5f 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -1248,6 +1236,25 @@ xlog_verify_head(
}
/*
+ * We need to make sure we handle log wrapping properly, so we can't use the
+ * calculated logbno directly. Make sure it wraps to the correct bno inside the
+ * log.
+ *
+ * The log is limited to 32 bit sizes, so we use the appropriate modulus
+ * operation here and cast it back to a 64 bit daddr on return.
+ */
+static inline xfs_daddr_t
+xlog_wrap_logbno(
+ struct xlog *log,
+ xfs_daddr_t bno)
+{
+ int mod;
+
+ div_s64_rem(bno, log->l_logBBsize, &mod);
+ return mod;
+}
+
+/*
* Check whether the head of the log points to an unmount record. In other
* words, determine whether the log is clean. If so, update the in-core state
* appropriately.
@@ -1295,12 +1302,13 @@ xlog_check_unmount_rec(
} else {
hblks = 1;
}
- after_umount_blk = rhead_blk + hblks + BTOBB(be32_to_cpu(rhead->h_len));
- after_umount_blk = do_mod(after_umount_blk, log->l_logBBsize);
+
+ after_umount_blk = xlog_wrap_logbno(log,
+ rhead_blk + hblks + BTOBB(be32_to_cpu(rhead->h_len)));
+
if (*head_blk == after_umount_blk &&
be32_to_cpu(rhead->h_num_logops) == 1) {
- umount_data_blk = rhead_blk + hblks;
- umount_data_blk = do_mod(umount_data_blk, log->l_logBBsize);
+ umount_data_blk = xlog_wrap_logbno(log, rhead_blk + hblks);
error = xlog_bread(log, umount_data_blk, 1, bp, &offset);
if (error)
return error;
@@ -1816,7 +1824,7 @@ xlog_clear_stale_blocks(
* we don't waste all day writing from the head to the tail
* for no reason.
*/
- max_distance = MIN(max_distance, tail_distance);
+ max_distance = min(max_distance, tail_distance);
if ((head_block + max_distance) <= log->l_logBBsize) {
/*
@@ -2884,14 +2892,14 @@ xlog_recover_buffer_pass2(
* buffers in the log can be a different size if the log was generated
* by an older kernel using unclustered inode buffers or a newer kernel
* running with a different inode cluster size. Regardless, if the
- * the inode buffer size isn't MAX(blocksize, mp->m_inode_cluster_size)
+ * the inode buffer size isn't max(blocksize, mp->m_inode_cluster_size)
* for *our* value of mp->m_inode_cluster_size, then we need to keep
* the buffer out of the buffer cache so that the buffer won't
* overlap with future reads of those inodes.
*/
if (XFS_DINODE_MAGIC ==
be16_to_cpu(*((__be16 *)xfs_buf_offset(bp, 0))) &&
- (BBTOB(bp->b_io_length) != MAX(log->l_mp->m_sb.sb_blocksize,
+ (BBTOB(bp->b_io_length) != max(log->l_mp->m_sb.sb_blocksize,
(uint32_t)log->l_mp->m_inode_cluster_size))) {
xfs_buf_stale(bp);
error = xfs_bwrite(bp);
@@ -3115,7 +3123,8 @@ xlog_recover_inode_pass2(
if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) &&
(ldip->di_format != XFS_DINODE_FMT_BTREE)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(3)",
- XFS_ERRLEVEL_LOW, mp, ldip);
+ XFS_ERRLEVEL_LOW, mp, ldip,
+ sizeof(*ldip));
xfs_alert(mp,
"%s: Bad regular inode log record, rec ptr "PTR_FMT", "
"ino ptr = "PTR_FMT", ino bp = "PTR_FMT", ino %Ld",
@@ -3128,7 +3137,8 @@ xlog_recover_inode_pass2(
(ldip->di_format != XFS_DINODE_FMT_BTREE) &&
(ldip->di_format != XFS_DINODE_FMT_LOCAL)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(4)",
- XFS_ERRLEVEL_LOW, mp, ldip);
+ XFS_ERRLEVEL_LOW, mp, ldip,
+ sizeof(*ldip));
xfs_alert(mp,
"%s: Bad dir inode log record, rec ptr "PTR_FMT", "
"ino ptr = "PTR_FMT", ino bp = "PTR_FMT", ino %Ld",
@@ -3139,7 +3149,8 @@ xlog_recover_inode_pass2(
}
if (unlikely(ldip->di_nextents + ldip->di_anextents > ldip->di_nblocks)){
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(5)",
- XFS_ERRLEVEL_LOW, mp, ldip);
+ XFS_ERRLEVEL_LOW, mp, ldip,
+ sizeof(*ldip));
xfs_alert(mp,
"%s: Bad inode log record, rec ptr "PTR_FMT", dino ptr "PTR_FMT", "
"dino bp "PTR_FMT", ino %Ld, total extents = %d, nblocks = %Ld",
@@ -3151,7 +3162,8 @@ xlog_recover_inode_pass2(
}
if (unlikely(ldip->di_forkoff > mp->m_sb.sb_inodesize)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(6)",
- XFS_ERRLEVEL_LOW, mp, ldip);
+ XFS_ERRLEVEL_LOW, mp, ldip,
+ sizeof(*ldip));
xfs_alert(mp,
"%s: Bad inode log record, rec ptr "PTR_FMT", dino ptr "PTR_FMT", "
"dino bp "PTR_FMT", ino %Ld, forkoff 0x%x", __func__,
@@ -3162,7 +3174,8 @@ xlog_recover_inode_pass2(
isize = xfs_log_dinode_size(ldip->di_version);
if (unlikely(item->ri_buf[1].i_len > isize)) {
XFS_CORRUPTION_ERROR("xlog_recover_inode_pass2(7)",
- XFS_ERRLEVEL_LOW, mp, ldip);
+ XFS_ERRLEVEL_LOW, mp, ldip,
+ sizeof(*ldip));
xfs_alert(mp,
"%s: Bad inode log record length %d, rec ptr "PTR_FMT,
__func__, item->ri_buf[1].i_len, item);
@@ -5466,9 +5479,7 @@ xlog_do_recovery_pass(
*/
if (blk_no + bblks <= log->l_logBBsize ||
blk_no >= log->l_logBBsize) {
- /* mod blk_no in case the header wrapped and
- * pushed it beyond the end of the log */
- rblk_no = do_mod(blk_no, log->l_logBBsize);
+ rblk_no = xlog_wrap_logbno(log, blk_no);
error = xlog_bread(log, rblk_no, bblks, dbp,
&offset);
if (error)
diff --git a/fs/xfs/xfs_message.c b/fs/xfs/xfs_message.c
index e68bd10..576c375 100644
--- a/fs/xfs/xfs_message.c
+++ b/fs/xfs/xfs_message.c
@@ -1,18 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2011 Red Hat, Inc. 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 73ed8fe..a337825 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -874,9 +862,12 @@ xfs_mountfs(
* Get and sanity-check the root inode.
* Save the pointer to it in the mount structure.
*/
- error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip);
+ error = xfs_iget(mp, NULL, sbp->sb_rootino, XFS_IGET_UNTRUSTED,
+ XFS_ILOCK_EXCL, &rip);
if (error) {
- xfs_warn(mp, "failed to read root inode");
+ xfs_warn(mp,
+ "Failed to read root inode 0x%llx, error %d",
+ sbp->sb_rootino, -error);
goto out_log_dealloc;
}
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 10b90bb..245349d 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_MOUNT_H__
#define __XFS_MOUNT_H__
@@ -283,7 +271,7 @@ xfs_preferred_iosize(xfs_mount_t *mp)
return (mp->m_swidth ?
(mp->m_swidth << mp->m_sb.sb_blocklog) :
((mp->m_flags & XFS_MOUNT_DFLT_IOSIZE) ?
- (1 << (int)MAX(mp->m_readio_log, mp->m_writeio_log)) :
+ (1 << (int)max(mp->m_readio_log, mp->m_writeio_log)) :
PAGE_SIZE));
}
diff --git a/fs/xfs/xfs_mru_cache.c b/fs/xfs/xfs_mru_cache.c
index 70eea7a..7473881 100644
--- a/fs/xfs/xfs_mru_cache.c
+++ b/fs/xfs/xfs_mru_cache.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_mru_cache.h"
diff --git a/fs/xfs/xfs_mru_cache.h b/fs/xfs/xfs_mru_cache.h
index b3f3fbd..f1fde1e 100644
--- a/fs/xfs/xfs_mru_cache.h
+++ b/fs/xfs/xfs_mru_cache.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2006-2007 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_MRU_CACHE_H__
#define __XFS_MRU_CACHE_H__
diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h
index 0492436..d3e04d2 100644
--- a/fs/xfs/xfs_ondisk.h
+++ b/fs/xfs/xfs_ondisk.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2016 Oracle.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_ONDISK_H
#define __XFS_ONDISK_H
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index c3e014b..9ceb85c 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index e3129b2..3ccf0fb 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_QM_H__
#define __XFS_QM_H__
diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c
index 36b89e2..73a1d77 100644
--- a/fs/xfs/xfs_qm_bhv.c
+++ b/fs/xfs/xfs_qm_bhv.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 3e05d30..abc8a21 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/capability.h>
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 3edf52b..55b7982 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_QUOTA_H__
#define __XFS_QUOTA_H__
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index c93fc91..205fbb2 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2008, Christoph Hellwig
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_format.h"
diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c
index e5866b7..472a73e9 100644
--- a/fs/xfs/xfs_refcount_item.c
+++ b/fs/xfs/xfs_refcount_item.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h
index 0e53273..dd830b6 100644
--- a/fs/xfs/xfs_refcount_item.h
+++ b/fs/xfs/xfs_refcount_item.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_REFCOUNT_ITEM_H__
#define __XFS_REFCOUNT_ITEM_H__
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 713e857..592fb20 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index 701487b..1532827 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_REFLINK_H
#define __XFS_REFLINK_H 1
diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c
index e5b5b3e..127dc9c 100644
--- a/fs/xfs/xfs_rmap_item.c
+++ b/fs/xfs/xfs_rmap_item.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_rmap_item.h b/fs/xfs/xfs_rmap_item.h
index 340c968..7e482ba 100644
--- a/fs/xfs/xfs_rmap_item.h
+++ b/fs/xfs/xfs_rmap_item.h
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __XFS_RMAP_ITEM_H__
#define __XFS_RMAP_ITEM_H__
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 488719d..329d4d2 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -313,8 +301,12 @@ xfs_rtallocate_extent_block(
/*
* If size should be a multiple of prod, make that so.
*/
- if (prod > 1 && (p = do_mod(bestlen, prod)))
- bestlen -= p;
+ if (prod > 1) {
+ div_u64_rem(bestlen, prod, &p);
+ if (p)
+ bestlen -= p;
+ }
+
/*
* Allocate besti for bestlen & return that.
*/
@@ -1275,7 +1267,7 @@ xfs_rtpick_extent(
b = (mp->m_sb.sb_rextents * ((resid << 1) + 1ULL)) >>
(log2 + 1);
if (b >= mp->m_sb.sb_rextents)
- b = do_mod(b, mp->m_sb.sb_rextents);
+ div64_u64_rem(b, mp->m_sb.sb_rextents, &b);
if (b + len > mp->m_sb.sb_rextents)
b = mp->m_sb.sb_rextents - len;
}
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h
index 52632ab..93e77b2 100644
--- a/fs/xfs/xfs_rtalloc.h
+++ b/fs/xfs/xfs_rtalloc.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_RTALLOC_H__
#define __XFS_RTALLOC_H__
diff --git a/fs/xfs/xfs_stats.c b/fs/xfs/xfs_stats.c
index 1cc7990..4e44231 100644
--- a/fs/xfs/xfs_stats.c
+++ b/fs/xfs/xfs_stats.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include <linux/proc_fs.h>
diff --git a/fs/xfs/xfs_stats.h b/fs/xfs/xfs_stats.h
index f64d0ae..130db07 100644
--- a/fs/xfs/xfs_stats.h
+++ b/fs/xfs/xfs_stats.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_STATS_H__
#define __XFS_STATS_H__
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index ed67389..9d791f1 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
@@ -1148,7 +1136,7 @@ xfs_fs_statfs(
statp->f_bavail = statp->f_bfree;
fakeinos = statp->f_bfree << sbp->sb_inopblog;
- statp->f_files = MIN(icount + fakeinos, (uint64_t)XFS_MAXINUMBER);
+ statp->f_files = min(icount + fakeinos, (uint64_t)XFS_MAXINUMBER);
if (mp->m_maxicount)
statp->f_files = min_t(typeof(statp->f_files),
statp->f_files,
diff --git a/fs/xfs/xfs_super.h b/fs/xfs/xfs_super.h
index 8cee8e8..21cb49a 100644
--- a/fs/xfs/xfs_super.h
+++ b/fs/xfs/xfs_super.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SUPER_H__
#define __XFS_SUPER_H__
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index aed03da..3783afc 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2006 Silicon Graphics, Inc.
* Copyright (c) 2012-2013 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_shared.h"
diff --git a/fs/xfs/xfs_symlink.h b/fs/xfs/xfs_symlink.h
index aeaee89..9743d8c 100644
--- a/fs/xfs/xfs_symlink.h
+++ b/fs/xfs/xfs_symlink.h
@@ -1,18 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2012 Red Hat, Inc. 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SYMLINK_H
#define __XFS_SYMLINK_H 1
diff --git a/fs/xfs/xfs_sysctl.c b/fs/xfs/xfs_sysctl.c
index afe1f66..0cc034d 100644
--- a/fs/xfs/xfs_sysctl.c
+++ b/fs/xfs/xfs_sysctl.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2001-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include <linux/sysctl.h>
diff --git a/fs/xfs/xfs_sysctl.h b/fs/xfs/xfs_sysctl.h
index b53a33e..1684881 100644
--- a/fs/xfs/xfs_sysctl.h
+++ b/fs/xfs/xfs_sysctl.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2001-2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SYSCTL_H__
#define __XFS_SYSCTL_H__
diff --git a/fs/xfs/xfs_sysfs.c b/fs/xfs/xfs_sysfs.c
index 2d5cd25..cd6a994 100644
--- a/fs/xfs/xfs_sysfs.c
+++ b/fs/xfs/xfs_sysfs.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
diff --git a/fs/xfs/xfs_sysfs.h b/fs/xfs/xfs_sysfs.h
index d046371..e9f810f 100644
--- a/fs/xfs/xfs_sysfs.h
+++ b/fs/xfs/xfs_sysfs.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_SYSFS_H__
diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c
index 35f3546..cb6489c 100644
--- a/fs/xfs/xfs_trace.c
+++ b/fs/xfs/xfs_trace.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2009, Christoph Hellwig
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 9d4c4ca..972d45d 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2009, Christoph Hellwig
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM xfs
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index fc7ba75..e040af1 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
* Copyright (C) 2010 Red Hat, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index 29706b8..6526314 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_TRANS_H__
#define __XFS_TRANS_H__
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 41e280e..55326f9 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* Copyright (c) 2008 Dave Chinner
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_bmap.c b/fs/xfs/xfs_trans_bmap.c
index 230a21d..a15a5cd 100644
--- a/fs/xfs/xfs_trans_bmap.c
+++ b/fs/xfs/xfs_trans_bmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index a8ddb4e..15919f6 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index c381c02..c23257a 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000-2002 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c
index 2f44a08..bd66c76 100644
--- a/fs/xfs/xfs_trans_extfree.c
+++ b/fs/xfs/xfs_trans_extfree.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c
index f7bd796..5429273 100644
--- a/fs/xfs/xfs_trans_inode.c
+++ b/fs/xfs/xfs_trans_inode.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
#include "xfs_fs.h"
@@ -70,7 +58,7 @@ xfs_trans_ichgtime(
int flags)
{
struct inode *inode = VFS_I(ip);
- struct timespec tv;
+ struct timespec64 tv;
ASSERT(tp);
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index 9717ae7..091eae9 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2000,2002,2005 Silicon Graphics, Inc.
* 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 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __XFS_TRANS_PRIV_H__
#define __XFS_TRANS_PRIV_H__
diff --git a/fs/xfs/xfs_trans_refcount.c b/fs/xfs/xfs_trans_refcount.c
index c7f8e82..46dd4fc 100644
--- a/fs/xfs/xfs_trans_refcount.c
+++ b/fs/xfs/xfs_trans_refcount.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c
index 5831ca0..726d8e2 100644
--- a/fs/xfs/xfs_trans_rmap.c
+++ b/fs/xfs/xfs_trans_rmap.c
@@ -1,21 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2016 Oracle. All Rights Reserved.
- *
* Author: Darrick J. Wong <darrick.wong@oracle.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 would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "xfs.h"
#include "xfs_fs.h"
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index 0594db4..63ee1d5 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -1,19 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2008 Christoph Hellwig.
* Portions Copyright (C) 2000-2008 Silicon Graphics, 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.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "xfs.h"
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h
index 0a6c5bd..3a26aa7 100644
--- a/include/acpi/acoutput.h
+++ b/include/acpi/acoutput.h
@@ -80,7 +80,8 @@
#define ACPI_LV_ALLOCATIONS 0x00100000
#define ACPI_LV_FUNCTIONS 0x00200000
#define ACPI_LV_OPTIMIZATIONS 0x00400000
-#define ACPI_LV_VERBOSITY2 0x00700000 | ACPI_LV_VERBOSITY1
+#define ACPI_LV_PARSE_TREES 0x00800000
+#define ACPI_LV_VERBOSITY2 0x00F00000 | ACPI_LV_VERBOSITY1
#define ACPI_LV_ALL ACPI_LV_VERBOSITY2
/* Trace verbosity level 3 [Threading, I/O, and Interrupts] */
@@ -131,6 +132,7 @@
#define ACPI_DB_TABLES ACPI_DEBUG_LEVEL (ACPI_LV_TABLES)
#define ACPI_DB_FUNCTIONS ACPI_DEBUG_LEVEL (ACPI_LV_FUNCTIONS)
#define ACPI_DB_OPTIMIZATIONS ACPI_DEBUG_LEVEL (ACPI_LV_OPTIMIZATIONS)
+#define ACPI_DB_PARSE_TREES ACPI_DEBUG_LEVEL (ACPI_LV_PARSE_TREES)
#define ACPI_DB_VALUES ACPI_DEBUG_LEVEL (ACPI_LV_VALUES)
#define ACPI_DB_OBJECTS ACPI_DEBUG_LEVEL (ACPI_LV_OBJECTS)
#define ACPI_DB_ALLOCATIONS ACPI_DEBUG_LEVEL (ACPI_LV_ALLOCATIONS)
diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h
index 77d71bd..48d84f0 100644
--- a/include/acpi/acpixf.h
+++ b/include/acpi/acpixf.h
@@ -12,7 +12,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20180508
+#define ACPI_CA_VERSION 0x20180531
#include <acpi/acconfig.h>
#include <acpi/actypes.h>
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index 876012d..c50ef7e 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -67,7 +67,7 @@
* IORT - IO Remapping Table
*
* Conforms to "IO Remapping Table System Software on ARM Platforms",
- * Document number: ARM DEN 0049C, May 2017
+ * Document number: ARM DEN 0049D, March 2018
*
******************************************************************************/
@@ -98,7 +98,8 @@ enum acpi_iort_node_type {
ACPI_IORT_NODE_NAMED_COMPONENT = 0x01,
ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02,
ACPI_IORT_NODE_SMMU = 0x03,
- ACPI_IORT_NODE_SMMU_V3 = 0x04
+ ACPI_IORT_NODE_SMMU_V3 = 0x04,
+ ACPI_IORT_NODE_PMCG = 0x05
};
struct acpi_iort_id_mapping {
@@ -152,10 +153,17 @@ struct acpi_iort_named_component {
char device_name[1]; /* Path of namespace object */
};
+/* Masks for Flags field above */
+
+#define ACPI_IORT_NC_STALL_SUPPORTED (1)
+#define ACPI_IORT_NC_PASID_BITS (31<<1)
+
struct acpi_iort_root_complex {
u64 memory_properties; /* Memory access properties */
u32 ats_attribute;
u32 pci_segment_number;
+ u8 memory_address_limit; /* Memory address size limit */
+ u8 reserved[3]; /* Reserved, must be zero */
};
/* Values for ats_attribute field above */
@@ -209,9 +217,7 @@ struct acpi_iort_smmu_v3 {
u32 pri_gsiv;
u32 gerr_gsiv;
u32 sync_gsiv;
- u8 pxm;
- u8 reserved1;
- u16 reserved2;
+ u32 pxm;
u32 id_mapping_index;
};
@@ -224,9 +230,16 @@ struct acpi_iort_smmu_v3 {
/* Masks for Flags field above */
#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE (1)
-#define ACPI_IORT_SMMU_V3_HTTU_OVERRIDE (1<<1)
+#define ACPI_IORT_SMMU_V3_HTTU_OVERRIDE (3<<1)
#define ACPI_IORT_SMMU_V3_PXM_VALID (1<<3)
+struct acpi_iort_pmcg {
+ u64 page0_base_address;
+ u32 overflow_gsiv;
+ u32 node_reference;
+ u64 page1_base_address;
+};
+
/*******************************************************************************
*
* IVRS - I/O Virtualization Reporting Structure
diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h
index 2b1bafa..66ceb12 100644
--- a/include/acpi/actypes.h
+++ b/include/acpi/actypes.h
@@ -1272,6 +1272,7 @@ typedef enum {
#define ACPI_OSI_WIN_10 0x0D
#define ACPI_OSI_WIN_10_RS1 0x0E
#define ACPI_OSI_WIN_10_RS2 0x0F
+#define ACPI_OSI_WIN_10_RS3 0x10
/* Definitions of getopt */
diff --git a/include/acpi/processor.h b/include/acpi/processor.h
index 40a916e..1194a4c 100644
--- a/include/acpi/processor.h
+++ b/include/acpi/processor.h
@@ -309,7 +309,7 @@ static inline void acpi_processor_ppc_exit(void)
{
return;
}
-static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr,
+static inline void acpi_processor_ppc_has_changed(struct acpi_processor *pr,
int event_flag)
{
static unsigned int printout = 1;
@@ -320,7 +320,6 @@ static inline int acpi_processor_ppc_has_changed(struct acpi_processor *pr,
"Consider compiling CPUfreq support into your kernel.\n");
printout = 0;
}
- return 0;
}
static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
{
diff --git a/include/asm-generic/qspinlock_types.h b/include/asm-generic/qspinlock_types.h
index 0763f06..d10f1e7 100644
--- a/include/asm-generic/qspinlock_types.h
+++ b/include/asm-generic/qspinlock_types.h
@@ -63,7 +63,7 @@ typedef struct qspinlock {
/*
* Initializier
*/
-#define __ARCH_SPIN_LOCK_UNLOCKED { .val = ATOMIC_INIT(0) }
+#define __ARCH_SPIN_LOCK_UNLOCKED { { .val = ATOMIC_INIT(0) } }
/*
* Bitfields in the atomic value:
diff --git a/include/dt-bindings/memory/tegra114-mc.h b/include/dt-bindings/memory/tegra114-mc.h
index 27c8386..dfe99c8 100644
--- a/include/dt-bindings/memory/tegra114-mc.h
+++ b/include/dt-bindings/memory/tegra114-mc.h
@@ -23,4 +23,21 @@
#define TEGRA_SWGROUP_EMUCIF 18
#define TEGRA_SWGROUP_TSEC 19
+#define TEGRA114_MC_RESET_AVPC 0
+#define TEGRA114_MC_RESET_DC 1
+#define TEGRA114_MC_RESET_DCB 2
+#define TEGRA114_MC_RESET_EPP 3
+#define TEGRA114_MC_RESET_2D 4
+#define TEGRA114_MC_RESET_HC 5
+#define TEGRA114_MC_RESET_HDA 6
+#define TEGRA114_MC_RESET_ISP 7
+#define TEGRA114_MC_RESET_MPCORE 8
+#define TEGRA114_MC_RESET_MPCORELP 9
+#define TEGRA114_MC_RESET_MPE 10
+#define TEGRA114_MC_RESET_3D 11
+#define TEGRA114_MC_RESET_3D2 12
+#define TEGRA114_MC_RESET_PPCS 13
+#define TEGRA114_MC_RESET_VDE 14
+#define TEGRA114_MC_RESET_VI 15
+
#endif
diff --git a/include/dt-bindings/memory/tegra124-mc.h b/include/dt-bindings/memory/tegra124-mc.h
index f534d7c..186e6b7 100644
--- a/include/dt-bindings/memory/tegra124-mc.h
+++ b/include/dt-bindings/memory/tegra124-mc.h
@@ -29,4 +29,29 @@
#define TEGRA_SWGROUP_VIC 24
#define TEGRA_SWGROUP_VI 25
+#define TEGRA124_MC_RESET_AFI 0
+#define TEGRA124_MC_RESET_AVPC 1
+#define TEGRA124_MC_RESET_DC 2
+#define TEGRA124_MC_RESET_DCB 3
+#define TEGRA124_MC_RESET_HC 4
+#define TEGRA124_MC_RESET_HDA 5
+#define TEGRA124_MC_RESET_ISP2 6
+#define TEGRA124_MC_RESET_MPCORE 7
+#define TEGRA124_MC_RESET_MPCORELP 8
+#define TEGRA124_MC_RESET_MSENC 9
+#define TEGRA124_MC_RESET_PPCS 10
+#define TEGRA124_MC_RESET_SATA 11
+#define TEGRA124_MC_RESET_VDE 12
+#define TEGRA124_MC_RESET_VI 13
+#define TEGRA124_MC_RESET_VIC 14
+#define TEGRA124_MC_RESET_XUSB_HOST 15
+#define TEGRA124_MC_RESET_XUSB_DEV 16
+#define TEGRA124_MC_RESET_TSEC 17
+#define TEGRA124_MC_RESET_SDMMC1 18
+#define TEGRA124_MC_RESET_SDMMC2 19
+#define TEGRA124_MC_RESET_SDMMC3 20
+#define TEGRA124_MC_RESET_SDMMC4 21
+#define TEGRA124_MC_RESET_ISP2B 22
+#define TEGRA124_MC_RESET_GPU 23
+
#endif
diff --git a/include/dt-bindings/memory/tegra20-mc.h b/include/dt-bindings/memory/tegra20-mc.h
new file mode 100644
index 0000000..35e131e
--- /dev/null
+++ b/include/dt-bindings/memory/tegra20-mc.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef DT_BINDINGS_MEMORY_TEGRA20_MC_H
+#define DT_BINDINGS_MEMORY_TEGRA20_MC_H
+
+#define TEGRA20_MC_RESET_AVPC 0
+#define TEGRA20_MC_RESET_DC 1
+#define TEGRA20_MC_RESET_DCB 2
+#define TEGRA20_MC_RESET_EPP 3
+#define TEGRA20_MC_RESET_2D 4
+#define TEGRA20_MC_RESET_HC 5
+#define TEGRA20_MC_RESET_ISP 6
+#define TEGRA20_MC_RESET_MPCORE 7
+#define TEGRA20_MC_RESET_MPEA 8
+#define TEGRA20_MC_RESET_MPEB 9
+#define TEGRA20_MC_RESET_MPEC 10
+#define TEGRA20_MC_RESET_3D 11
+#define TEGRA20_MC_RESET_PPCS 12
+#define TEGRA20_MC_RESET_VDE 13
+#define TEGRA20_MC_RESET_VI 14
+
+#endif
diff --git a/include/dt-bindings/memory/tegra210-mc.h b/include/dt-bindings/memory/tegra210-mc.h
index 4490f7c..cacf056 100644
--- a/include/dt-bindings/memory/tegra210-mc.h
+++ b/include/dt-bindings/memory/tegra210-mc.h
@@ -34,4 +34,35 @@
#define TEGRA_SWGROUP_ETR 29
#define TEGRA_SWGROUP_TSECB 30
+#define TEGRA210_MC_RESET_AFI 0
+#define TEGRA210_MC_RESET_AVPC 1
+#define TEGRA210_MC_RESET_DC 2
+#define TEGRA210_MC_RESET_DCB 3
+#define TEGRA210_MC_RESET_HC 4
+#define TEGRA210_MC_RESET_HDA 5
+#define TEGRA210_MC_RESET_ISP2 6
+#define TEGRA210_MC_RESET_MPCORE 7
+#define TEGRA210_MC_RESET_NVENC 8
+#define TEGRA210_MC_RESET_PPCS 9
+#define TEGRA210_MC_RESET_SATA 10
+#define TEGRA210_MC_RESET_VI 11
+#define TEGRA210_MC_RESET_VIC 12
+#define TEGRA210_MC_RESET_XUSB_HOST 13
+#define TEGRA210_MC_RESET_XUSB_DEV 14
+#define TEGRA210_MC_RESET_A9AVP 15
+#define TEGRA210_MC_RESET_TSEC 16
+#define TEGRA210_MC_RESET_SDMMC1 17
+#define TEGRA210_MC_RESET_SDMMC2 18
+#define TEGRA210_MC_RESET_SDMMC3 19
+#define TEGRA210_MC_RESET_SDMMC4 20
+#define TEGRA210_MC_RESET_ISP2B 21
+#define TEGRA210_MC_RESET_GPU 22
+#define TEGRA210_MC_RESET_NVDEC 23
+#define TEGRA210_MC_RESET_APE 24
+#define TEGRA210_MC_RESET_SE 25
+#define TEGRA210_MC_RESET_NVJPG 26
+#define TEGRA210_MC_RESET_AXIAP 27
+#define TEGRA210_MC_RESET_ETR 28
+#define TEGRA210_MC_RESET_TSECB 29
+
#endif
diff --git a/include/dt-bindings/memory/tegra30-mc.h b/include/dt-bindings/memory/tegra30-mc.h
index 3cac819..169f005 100644
--- a/include/dt-bindings/memory/tegra30-mc.h
+++ b/include/dt-bindings/memory/tegra30-mc.h
@@ -22,4 +22,23 @@
#define TEGRA_SWGROUP_MPCORE 17
#define TEGRA_SWGROUP_ISP 18
+#define TEGRA30_MC_RESET_AFI 0
+#define TEGRA30_MC_RESET_AVPC 1
+#define TEGRA30_MC_RESET_DC 2
+#define TEGRA30_MC_RESET_DCB 3
+#define TEGRA30_MC_RESET_EPP 4
+#define TEGRA30_MC_RESET_2D 5
+#define TEGRA30_MC_RESET_HC 6
+#define TEGRA30_MC_RESET_HDA 7
+#define TEGRA30_MC_RESET_ISP 8
+#define TEGRA30_MC_RESET_MPCORE 9
+#define TEGRA30_MC_RESET_MPCORELP 10
+#define TEGRA30_MC_RESET_MPE 11
+#define TEGRA30_MC_RESET_3D 12
+#define TEGRA30_MC_RESET_3D2 13
+#define TEGRA30_MC_RESET_PPCS 14
+#define TEGRA30_MC_RESET_SATA 15
+#define TEGRA30_MC_RESET_VDE 16
+#define TEGRA30_MC_RESET_VI 17
+
#endif
diff --git a/include/dt-bindings/power/px30-power.h b/include/dt-bindings/power/px30-power.h
new file mode 100644
index 0000000..30917a9
--- /dev/null
+++ b/include/dt-bindings/power/px30-power.h
@@ -0,0 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_BINDINGS_POWER_PX30_POWER_H__
+#define __DT_BINDINGS_POWER_PX30_POWER_H__
+
+/* VD_CORE */
+#define PX30_PD_A35_0 0
+#define PX30_PD_A35_1 1
+#define PX30_PD_A35_2 2
+#define PX30_PD_A35_3 3
+#define PX30_PD_SCU 4
+
+/* VD_LOGIC */
+#define PX30_PD_USB 5
+#define PX30_PD_DDR 6
+#define PX30_PD_SDCARD 7
+#define PX30_PD_CRYPTO 8
+#define PX30_PD_GMAC 9
+#define PX30_PD_MMC_NAND 10
+#define PX30_PD_VPU 11
+#define PX30_PD_VO 12
+#define PX30_PD_VI 13
+#define PX30_PD_GPU 14
+
+/* VD_PMU */
+#define PX30_PD_PMU 15
+
+#endif
diff --git a/include/dt-bindings/power/r8a77470-sysc.h b/include/dt-bindings/power/r8a77470-sysc.h
new file mode 100644
index 0000000..8bf4db1
--- /dev/null
+++ b/include/dt-bindings/power/r8a77470-sysc.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+#ifndef __DT_BINDINGS_POWER_R8A77470_SYSC_H__
+#define __DT_BINDINGS_POWER_R8A77470_SYSC_H__
+
+/*
+ * These power domain indices match the numbers of the interrupt bits
+ * representing the power areas in the various Interrupt Registers
+ * (e.g. SYSCISR, Interrupt Status Register)
+ */
+
+#define R8A77470_PD_CA7_CPU0 5
+#define R8A77470_PD_CA7_CPU1 6
+#define R8A77470_PD_SGX 20
+#define R8A77470_PD_CA7_SCU 21
+
+/* Always-on power area */
+#define R8A77470_PD_ALWAYS_ON 32
+
+#endif /* __DT_BINDINGS_POWER_R8A77470_SYSC_H__ */
diff --git a/include/dt-bindings/power/r8a77990-sysc.h b/include/dt-bindings/power/r8a77990-sysc.h
new file mode 100644
index 0000000..944d85b
--- /dev/null
+++ b/include/dt-bindings/power/r8a77990-sysc.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018 Renesas Electronics Corp.
+ */
+#ifndef __DT_BINDINGS_POWER_R8A77990_SYSC_H__
+#define __DT_BINDINGS_POWER_R8A77990_SYSC_H__
+
+/*
+ * These power domain indices match the numbers of the interrupt bits
+ * representing the power areas in the various Interrupt Registers
+ * (e.g. SYSCISR, Interrupt Status Register)
+ */
+
+#define R8A77990_PD_CA53_CPU0 5
+#define R8A77990_PD_CA53_CPU1 6
+#define R8A77990_PD_CR7 13
+#define R8A77990_PD_A3VC 14
+#define R8A77990_PD_3DG_A 17
+#define R8A77990_PD_3DG_B 18
+#define R8A77990_PD_CA53_SCU 21
+#define R8A77990_PD_A2VC1 26
+
+/* Always-on power area */
+#define R8A77990_PD_ALWAYS_ON 32
+
+#endif /* __DT_BINDINGS_POWER_R8A77990_SYSC_H__ */
diff --git a/include/dt-bindings/power/rk3036-power.h b/include/dt-bindings/power/rk3036-power.h
new file mode 100644
index 0000000..0bc6b5d
--- /dev/null
+++ b/include/dt-bindings/power/rk3036-power.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_BINDINGS_POWER_RK3036_POWER_H__
+#define __DT_BINDINGS_POWER_RK3036_POWER_H__
+
+#define RK3036_PD_MSCH 0
+#define RK3036_PD_CORE 1
+#define RK3036_PD_PERI 2
+#define RK3036_PD_VIO 3
+#define RK3036_PD_VPU 4
+#define RK3036_PD_GPU 5
+#define RK3036_PD_SYS 6
+
+#endif
diff --git a/include/dt-bindings/power/rk3128-power.h b/include/dt-bindings/power/rk3128-power.h
new file mode 100644
index 0000000..c051dc3
--- /dev/null
+++ b/include/dt-bindings/power/rk3128-power.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_BINDINGS_POWER_RK3128_POWER_H__
+#define __DT_BINDINGS_POWER_RK3128_POWER_H__
+
+/* VD_CORE */
+#define RK3128_PD_CORE 0
+
+/* VD_LOGIC */
+#define RK3128_PD_VIO 1
+#define RK3128_PD_VIDEO 2
+#define RK3128_PD_GPU 3
+#define RK3128_PD_MSCH 4
+
+#endif
diff --git a/include/dt-bindings/power/rk3228-power.h b/include/dt-bindings/power/rk3228-power.h
new file mode 100644
index 0000000..6a8dc1b
--- /dev/null
+++ b/include/dt-bindings/power/rk3228-power.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __DT_BINDINGS_POWER_RK3228_POWER_H__
+#define __DT_BINDINGS_POWER_RK3228_POWER_H__
+
+/**
+ * RK3228 idle id Summary.
+ */
+
+#define RK3228_PD_CORE 0
+#define RK3228_PD_MSCH 1
+#define RK3228_PD_BUS 2
+#define RK3228_PD_SYS 3
+#define RK3228_PD_VIO 4
+#define RK3228_PD_VOP 5
+#define RK3228_PD_VPU 6
+#define RK3228_PD_RKVDEC 7
+#define RK3228_PD_GPU 8
+#define RK3228_PD_PERI 9
+#define RK3228_PD_GMAC 10
+
+#endif
diff --git a/include/keys/asymmetric-subtype.h b/include/keys/asymmetric-subtype.h
index 2480469..e0a9c23 100644
--- a/include/keys/asymmetric-subtype.h
+++ b/include/keys/asymmetric-subtype.h
@@ -1,6 +1,6 @@
/* Asymmetric public-key cryptography key subtype
*
- * See Documentation/security/asymmetric-keys.txt
+ * See Documentation/crypto/asymmetric-keys.txt
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
diff --git a/include/keys/asymmetric-type.h b/include/keys/asymmetric-type.h
index b382407..1cb77cd 100644
--- a/include/keys/asymmetric-type.h
+++ b/include/keys/asymmetric-type.h
@@ -1,6 +1,6 @@
/* Asymmetric Public-key cryptography key type interface
*
- * See Documentation/security/asymmetric-keys.txt
+ * See Documentation/crypto/asymmetric-keys.txt
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index e7efe12..cfdd248 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -28,7 +28,7 @@
#include <linux/irqchip/arm-gic-v4.h>
-#define VGIC_V3_MAX_CPUS 255
+#define VGIC_V3_MAX_CPUS 512
#define VGIC_V2_MAX_CPUS 8
#define VGIC_NR_IRQS_LEGACY 256
#define VGIC_NR_SGIS 16
@@ -201,6 +201,14 @@ struct vgic_its {
struct vgic_state_iter;
+struct vgic_redist_region {
+ u32 index;
+ gpa_t base;
+ u32 count; /* number of redistributors or 0 if single region */
+ u32 free_index; /* index of the next free redistributor */
+ struct list_head list;
+};
+
struct vgic_dist {
bool in_kernel;
bool ready;
@@ -220,10 +228,7 @@ struct vgic_dist {
/* either a GICv2 CPU interface */
gpa_t vgic_cpu_base;
/* or a number of GICv3 redistributor regions */
- struct {
- gpa_t vgic_redist_base;
- gpa_t vgic_redist_free_offset;
- };
+ struct list_head rd_regions;
};
/* distributor enabled */
@@ -311,6 +316,7 @@ struct vgic_cpu {
*/
struct vgic_io_device rd_iodev;
struct vgic_io_device sgi_iodev;
+ struct vgic_redist_region *rdreg;
/* Contains the attributes and gpa of the LPI pending tables. */
u64 pendbaser;
@@ -332,7 +338,6 @@ 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);
void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
int kvm_vgic_map_resources(struct kvm *kvm);
int kvm_vgic_hyp_init(void);
diff --git a/include/linux/assoc_array.h b/include/linux/assoc_array.h
index a89df3b..65e3832 100644
--- a/include/linux/assoc_array.h
+++ b/include/linux/assoc_array.h
@@ -1,6 +1,6 @@
/* Generic associative array implementation.
*
- * See Documentation/assoc_array.txt for information.
+ * See Documentation/core-api/assoc_array.rst for information.
*
* Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
diff --git a/include/linux/assoc_array_priv.h b/include/linux/assoc_array_priv.h
index 711275e..a00a065 100644
--- a/include/linux/assoc_array_priv.h
+++ b/include/linux/assoc_array_priv.h
@@ -1,6 +1,6 @@
/* Private definitions for the generic associative array implementation.
*
- * See Documentation/assoc_array.txt for information.
+ * See Documentation/core-api/assoc_array.rst for information.
*
* Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
index 0c27515..8124815 100644
--- a/include/linux/atmdev.h
+++ b/include/linux/atmdev.h
@@ -214,6 +214,7 @@ struct atmphy_ops {
struct atm_skb_data {
struct atm_vcc *vcc; /* ATM VCC */
unsigned long atm_options; /* ATM layer options */
+ unsigned int acct_truesize; /* truesize accounted to vcc */
};
#define VCC_HTABLE_SIZE 32
@@ -241,6 +242,20 @@ void vcc_insert_socket(struct sock *sk);
void atm_dev_release_vccs(struct atm_dev *dev);
+static inline void atm_account_tx(struct atm_vcc *vcc, struct sk_buff *skb)
+{
+ /*
+ * Because ATM skbs may not belong to a sock (and we don't
+ * necessarily want to), skb->truesize may be adjusted,
+ * escaping the hack in pskb_expand_head() which avoids
+ * doing so for some cases. So stash the value of truesize
+ * at the time we accounted it, and atm_pop_raw() can use
+ * that value later, in case it changes.
+ */
+ refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
+ ATM_SKB(skb)->acct_truesize = skb->truesize;
+ ATM_SKB(skb)->atm_options = vcc->atm_options;
+}
static inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
{
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index 0bd432a..2425176 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -22,7 +22,6 @@ struct dentry;
*/
enum wb_state {
WB_registered, /* bdi_register() was done */
- WB_shutting_down, /* wb_shutdown() in progress */
WB_writeback_running, /* Writeback is in progress */
WB_has_dirty_io, /* Dirty inodes on ->b_{dirty|io|more_io} */
WB_start_all, /* nr_pages == 0 (all) work pending */
@@ -189,6 +188,7 @@ struct backing_dev_info {
#ifdef CONFIG_CGROUP_WRITEBACK
struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */
struct rb_root cgwb_congested_tree; /* their congested states */
+ struct mutex cgwb_release_mutex; /* protect shutdown of wb structs */
#else
struct bdi_writeback_congested *wb_congested;
#endif
diff --git a/include/linux/backlight.h b/include/linux/backlight.h
index 2baab6f..7fbf053 100644
--- a/include/linux/backlight.h
+++ b/include/linux/backlight.h
@@ -84,10 +84,6 @@ struct backlight_properties {
#define BL_CORE_SUSPENDED (1 << 0) /* backlight is suspended */
#define BL_CORE_FBBLANK (1 << 1) /* backlight is under an fb blank event */
-#define BL_CORE_DRIVER4 (1 << 28) /* reserved for driver specific use */
-#define BL_CORE_DRIVER3 (1 << 29) /* reserved for driver specific use */
-#define BL_CORE_DRIVER2 (1 << 30) /* reserved for driver specific use */
-#define BL_CORE_DRIVER1 (1 << 31) /* reserved for driver specific use */
};
diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h
index fb35517..e3147eb 100644
--- a/include/linux/blk-mq.h
+++ b/include/linux/blk-mq.h
@@ -281,8 +281,6 @@ void blk_freeze_queue_start(struct request_queue *q);
void blk_mq_freeze_queue_wait(struct request_queue *q);
int blk_mq_freeze_queue_wait_timeout(struct request_queue *q,
unsigned long timeout);
-int blk_mq_tagset_iter(struct blk_mq_tag_set *set, void *data,
- int (reinit_request)(void *, struct request *));
int blk_mq_map_queues(struct blk_mq_tag_set *set);
void blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set, int nr_hw_queues);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index bca3a92..9154570 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -127,6 +127,8 @@ typedef __u32 __bitwise req_flags_t;
#define RQF_ZONE_WRITE_LOCKED ((__force req_flags_t)(1 << 19))
/* already slept for hybrid poll */
#define RQF_MQ_POLL_SLEPT ((__force req_flags_t)(1 << 20))
+/* ->timeout has been called, don't expire again */
+#define RQF_TIMED_OUT ((__force req_flags_t)(1 << 21))
/* flags that prevent us from merging requests: */
#define RQF_NOMERGE_FLAGS \
@@ -560,7 +562,6 @@ struct request_queue {
unsigned int dma_alignment;
struct blk_queue_tag *queue_tags;
- struct list_head tag_busy_list;
unsigned int nr_sorted;
unsigned int in_flight[2];
@@ -1373,7 +1374,6 @@ extern void blk_queue_end_tag(struct request_queue *, struct request *);
extern int blk_queue_init_tags(struct request_queue *, int, struct blk_queue_tag *, int);
extern void blk_queue_free_tags(struct request_queue *);
extern int blk_queue_resize_tags(struct request_queue *, int);
-extern void blk_queue_invalidate_tags(struct request_queue *);
extern struct blk_queue_tag *blk_init_tags(int, int);
extern void blk_free_tags(struct blk_queue_tag *);
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 995c3b1..7df32a3 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -488,12 +488,15 @@ void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
/* Map specifics */
struct xdp_buff;
+struct sk_buff;
struct bpf_dtab_netdev *__dev_map_lookup_elem(struct bpf_map *map, u32 key);
void __dev_map_insert_ctx(struct bpf_map *map, u32 index);
void __dev_map_flush(struct bpf_map *map);
int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
struct net_device *dev_rx);
+int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
+ struct bpf_prog *xdp_prog);
struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key);
void __cpu_map_insert_ctx(struct bpf_map *map, u32 index);
@@ -586,6 +589,15 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
return 0;
}
+struct sk_buff;
+
+static inline int dev_map_generic_redirect(struct bpf_dtab_netdev *dst,
+ struct sk_buff *skb,
+ struct bpf_prog *xdp_prog)
+{
+ return 0;
+}
+
static inline
struct bpf_cpu_map_entry *__cpu_map_lookup_elem(struct bpf_map *map, u32 key)
{
diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h
index 7ecfc88..4903deb 100644
--- a/include/linux/ceph/ceph_fs.h
+++ b/include/linux/ceph/ceph_fs.h
@@ -628,6 +628,7 @@ int ceph_flags_to_mode(int flags);
CEPH_CAP_XATTR_SHARED)
#define CEPH_STAT_CAP_INLINE_DATA (CEPH_CAP_FILE_SHARED | \
CEPH_CAP_FILE_RD)
+#define CEPH_STAT_RSTAT CEPH_CAP_FILE_WREXTEND
#define CEPH_CAP_ANY_SHARED (CEPH_CAP_AUTH_SHARED | \
CEPH_CAP_LINK_SHARED | \
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
index 96bb322..0d6ee04 100644
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -170,6 +170,7 @@ struct ceph_osd_request {
u64 r_tid; /* unique for this client */
struct rb_node r_node;
struct rb_node r_mc_node; /* map check */
+ struct work_struct r_complete_work;
struct ceph_osd *r_osd;
struct ceph_osd_request_target r_t;
@@ -201,7 +202,6 @@ 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 */
@@ -347,6 +347,8 @@ struct ceph_osd_client {
struct rb_root linger_map_checks;
atomic_t num_requests;
atomic_t num_homeless;
+ bool abort_on_full; /* abort w/ ENOSPC when full */
+ int abort_err;
struct delayed_work timeout_work;
struct delayed_work osds_timeout_work;
#ifdef CONFIG_DEBUG_FS
@@ -359,6 +361,7 @@ struct ceph_osd_client {
struct ceph_msgpool msgpool_op_reply;
struct workqueue_struct *notify_wq;
+ struct workqueue_struct *completion_wq;
};
static inline bool ceph_osdmap_flag(struct ceph_osd_client *osdc, int flag)
@@ -378,6 +381,7 @@ extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc,
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);
+void ceph_osdc_abort_requests(struct ceph_osd_client *osdc, int err);
extern void osd_req_op_init(struct ceph_osd_request *osd_req,
unsigned int which, u16 opcode, u32 flags);
@@ -440,7 +444,7 @@ extern void osd_req_op_cls_response_data_pages(struct ceph_osd_request *,
struct page **pages, u64 length,
u32 alignment, bool pages_from_pool,
bool own_pages);
-extern void osd_req_op_cls_init(struct ceph_osd_request *osd_req,
+extern int osd_req_op_cls_init(struct ceph_osd_request *osd_req,
unsigned int which, u16 opcode,
const char *class, const char *method);
extern int osd_req_op_xattr_init(struct ceph_osd_request *osd_req, unsigned int which,
diff --git a/include/linux/ceph/osdmap.h b/include/linux/ceph/osdmap.h
index e71fb22..5675b1f 100644
--- a/include/linux/ceph/osdmap.h
+++ b/include/linux/ceph/osdmap.h
@@ -279,10 +279,10 @@ bool ceph_osds_changed(const struct ceph_osds *old_acting,
const struct ceph_osds *new_acting,
bool any_change);
-int __ceph_object_locator_to_pg(struct ceph_pg_pool_info *pi,
- const struct ceph_object_id *oid,
- const struct ceph_object_locator *oloc,
- struct ceph_pg *raw_pgid);
+void __ceph_object_locator_to_pg(struct ceph_pg_pool_info *pi,
+ const struct ceph_object_id *oid,
+ const struct ceph_object_locator *oloc,
+ struct ceph_pg *raw_pgid);
int ceph_object_locator_to_pg(struct ceph_osdmap *osdmap,
const struct ceph_object_id *oid,
const struct ceph_object_locator *oloc,
diff --git a/include/linux/circ_buf.h b/include/linux/circ_buf.h
index 7cf262a..b3233e8 100644
--- a/include/linux/circ_buf.h
+++ b/include/linux/circ_buf.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * See Documentation/circular-buffers.txt for more information.
+ * See Documentation/core-api/circular-buffers.rst for more information.
*/
#ifndef _LINUX_CIRC_BUF_H
diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h
index b67bf6a..3c5a4cb 100644
--- a/include/linux/dma-contiguous.h
+++ b/include/linux/dma-contiguous.h
@@ -48,7 +48,7 @@
* CMA should not be used by the device drivers directly. It is
* only a helper framework for dma-mapping subsystem.
*
- * For more information, see kernel-docs in drivers/base/dma-contiguous.c
+ * For more information, see kernel-docs in kernel/dma/contiguous.c
*/
#ifdef __KERNEL__
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 45fc0f5..b615df5 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -19,6 +19,7 @@
#include <linux/cryptohash.h>
#include <linux/set_memory.h>
#include <linux/kallsyms.h>
+#include <linux/if_vlan.h>
#include <net/sch_generic.h>
@@ -469,7 +470,8 @@ struct sock_fprog_kern {
};
struct bpf_binary_header {
- unsigned int pages;
+ u16 pages;
+ u16 locked:1;
u8 image[];
};
@@ -671,15 +673,18 @@ bpf_ctx_narrow_access_ok(u32 off, u32 size, u32 size_default)
#define bpf_classic_proglen(fprog) (fprog->len * sizeof(fprog->filter[0]))
-#ifdef CONFIG_ARCH_HAS_SET_MEMORY
static inline void bpf_prog_lock_ro(struct bpf_prog *fp)
{
+#ifdef CONFIG_ARCH_HAS_SET_MEMORY
fp->locked = 1;
- WARN_ON_ONCE(set_memory_ro((unsigned long)fp, fp->pages));
+ if (set_memory_ro((unsigned long)fp, fp->pages))
+ fp->locked = 0;
+#endif
}
static inline void bpf_prog_unlock_ro(struct bpf_prog *fp)
{
+#ifdef CONFIG_ARCH_HAS_SET_MEMORY
if (fp->locked) {
WARN_ON_ONCE(set_memory_rw((unsigned long)fp, fp->pages));
/* In case set_memory_rw() fails, we want to be the first
@@ -687,34 +692,30 @@ static inline void bpf_prog_unlock_ro(struct bpf_prog *fp)
*/
fp->locked = 0;
}
+#endif
}
static inline void bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr)
{
- WARN_ON_ONCE(set_memory_ro((unsigned long)hdr, hdr->pages));
-}
-
-static inline void bpf_jit_binary_unlock_ro(struct bpf_binary_header *hdr)
-{
- WARN_ON_ONCE(set_memory_rw((unsigned long)hdr, hdr->pages));
-}
-#else
-static inline void bpf_prog_lock_ro(struct bpf_prog *fp)
-{
-}
-
-static inline void bpf_prog_unlock_ro(struct bpf_prog *fp)
-{
-}
-
-static inline void bpf_jit_binary_lock_ro(struct bpf_binary_header *hdr)
-{
+#ifdef CONFIG_ARCH_HAS_SET_MEMORY
+ hdr->locked = 1;
+ if (set_memory_ro((unsigned long)hdr, hdr->pages))
+ hdr->locked = 0;
+#endif
}
static inline void bpf_jit_binary_unlock_ro(struct bpf_binary_header *hdr)
{
+#ifdef CONFIG_ARCH_HAS_SET_MEMORY
+ if (hdr->locked) {
+ WARN_ON_ONCE(set_memory_rw((unsigned long)hdr, hdr->pages));
+ /* In case set_memory_rw() fails, we want to be the first
+ * to crash here instead of some random place later on.
+ */
+ hdr->locked = 0;
+ }
+#endif
}
-#endif /* CONFIG_ARCH_HAS_SET_MEMORY */
static inline struct bpf_binary_header *
bpf_jit_binary_hdr(const struct bpf_prog *fp)
@@ -725,6 +726,22 @@ bpf_jit_binary_hdr(const struct bpf_prog *fp)
return (void *)addr;
}
+#ifdef CONFIG_ARCH_HAS_SET_MEMORY
+static inline int bpf_prog_check_pages_ro_single(const struct bpf_prog *fp)
+{
+ if (!fp->locked)
+ return -ENOLCK;
+ if (fp->jited) {
+ const struct bpf_binary_header *hdr = bpf_jit_binary_hdr(fp);
+
+ if (!hdr->locked)
+ return -ENOLCK;
+ }
+
+ return 0;
+}
+#endif
+
int sk_filter_trim_cap(struct sock *sk, struct sk_buff *skb, unsigned int cap);
static inline int sk_filter(struct sock *sk, struct sk_buff *skb)
{
@@ -786,6 +803,21 @@ static inline bool bpf_dump_raw_ok(void)
struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
const struct bpf_insn *patch, u32 len);
+static inline int __xdp_generic_ok_fwd_dev(struct sk_buff *skb,
+ struct net_device *fwd)
+{
+ unsigned int len;
+
+ if (unlikely(!(fwd->flags & IFF_UP)))
+ return -ENETDOWN;
+
+ len = fwd->mtu + fwd->hard_header_len + VLAN_HLEN;
+ if (skb->len > len)
+ return -EMSGSIZE;
+
+ return 0;
+}
+
/* The pair of xdp_do_redirect and xdp_do_flush_map MUST be called in the
* same cpu context. Further for best results no more than a single map
* for the do_redirect/do_flush pair should be used. This limitation is
@@ -961,6 +993,9 @@ static inline void bpf_prog_kallsyms_del(struct bpf_prog *fp)
}
#endif /* CONFIG_BPF_JIT */
+void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp);
+void bpf_prog_kallsyms_del_all(struct bpf_prog *fp);
+
#define BPF_ANC BIT(15)
static inline bool bpf_needs_clear_a(const struct sock_filter *first)
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7207de8..5c91108 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -207,9 +207,9 @@ struct iattr {
kuid_t ia_uid;
kgid_t ia_gid;
loff_t ia_size;
- struct timespec ia_atime;
- struct timespec ia_mtime;
- struct timespec ia_ctime;
+ struct timespec64 ia_atime;
+ struct timespec64 ia_mtime;
+ struct timespec64 ia_ctime;
/*
* Not an attribute, but an auxiliary info for filesystems wanting to
@@ -604,9 +604,9 @@ struct inode {
};
dev_t i_rdev;
loff_t i_size;
- struct timespec i_atime;
- struct timespec i_mtime;
- struct timespec i_ctime;
+ struct timespec64 i_atime;
+ struct timespec64 i_mtime;
+ struct timespec64 i_ctime;
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
unsigned short i_bytes;
unsigned int i_blkbits;
@@ -1093,7 +1093,7 @@ extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct
extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl);
extern int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl);
extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type);
-extern void lease_get_mtime(struct inode *, struct timespec *time);
+extern void lease_get_mtime(struct inode *, struct timespec64 *time);
extern int generic_setlease(struct file *, long, struct file_lock **, void **priv);
extern int vfs_setlease(struct file *, long, struct file_lock **, void **);
extern int lease_modify(struct file_lock *, int, struct list_head *);
@@ -1208,7 +1208,8 @@ static inline int __break_lease(struct inode *inode, unsigned int mode, unsigned
return 0;
}
-static inline void lease_get_mtime(struct inode *inode, struct timespec *time)
+static inline void lease_get_mtime(struct inode *inode,
+ struct timespec64 *time)
{
return;
}
@@ -1478,7 +1479,8 @@ 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_time(struct inode *inode);
+extern struct timespec64 timespec64_trunc(struct timespec64 t, unsigned gran);
+extern struct timespec64 current_time(struct inode *inode);
/*
* Snapshotting support.
@@ -1773,7 +1775,7 @@ struct inode_operations {
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
u64 len);
- int (*update_time)(struct inode *, struct timespec *, int);
+ int (*update_time)(struct inode *, struct timespec64 *, int);
int (*atomic_open)(struct inode *, struct dentry *,
struct file *, unsigned open_flag,
umode_t create_mode, int *opened);
@@ -2217,7 +2219,7 @@ extern int current_umask(void);
extern void ihold(struct inode * inode);
extern void iput(struct inode *);
-extern int generic_update_time(struct inode *, struct timespec *, int);
+extern int generic_update_time(struct inode *, struct timespec64 *, int);
/* /sys/fs */
extern struct kobject *fs_kobj;
diff --git a/include/linux/fscrypt_notsupp.h b/include/linux/fscrypt_notsupp.h
index 25b6492..ee8b43e 100644
--- a/include/linux/fscrypt_notsupp.h
+++ b/include/linux/fscrypt_notsupp.h
@@ -25,6 +25,10 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
}
/* crypto.c */
+static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
+{
+}
+
static inline struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *inode,
gfp_t gfp_flags)
{
@@ -150,10 +154,13 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
}
/* bio.c */
-static inline void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *ctx,
- struct bio *bio)
+static inline void fscrypt_decrypt_bio(struct bio *bio)
+{
+}
+
+static inline void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
+ struct bio *bio)
{
- return;
}
static inline void fscrypt_pullback_bio_page(struct page **page, bool restore)
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index 5080cb1..6456c6b 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -59,6 +59,7 @@ static inline bool fscrypt_dummy_context_enabled(struct inode *inode)
}
/* crypto.c */
+extern void fscrypt_enqueue_decrypt_work(struct work_struct *);
extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
extern void fscrypt_release_ctx(struct fscrypt_ctx *);
extern struct page *fscrypt_encrypt_page(const struct inode *, struct page *,
@@ -174,7 +175,9 @@ static inline bool fscrypt_match_name(const struct fscrypt_name *fname,
}
/* bio.c */
-extern void fscrypt_decrypt_bio_pages(struct fscrypt_ctx *, struct bio *);
+extern void fscrypt_decrypt_bio(struct bio *);
+extern void fscrypt_enqueue_decrypt_bio(struct fscrypt_ctx *ctx,
+ struct bio *bio);
extern void fscrypt_pullback_bio_page(struct page **, bool);
extern int fscrypt_zeroout_range(const struct inode *, pgoff_t, sector_t,
unsigned int);
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index e64c029..b38964a 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -98,8 +98,6 @@ struct fsnotify_iter_info;
struct fsnotify_ops {
int (*handle_event)(struct fsnotify_group *group,
struct inode *inode,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info);
@@ -201,6 +199,57 @@ struct fsnotify_group {
#define FSNOTIFY_EVENT_PATH 1
#define FSNOTIFY_EVENT_INODE 2
+enum fsnotify_obj_type {
+ FSNOTIFY_OBJ_TYPE_INODE,
+ FSNOTIFY_OBJ_TYPE_VFSMOUNT,
+ FSNOTIFY_OBJ_TYPE_COUNT,
+ FSNOTIFY_OBJ_TYPE_DETACHED = FSNOTIFY_OBJ_TYPE_COUNT
+};
+
+#define FSNOTIFY_OBJ_TYPE_INODE_FL (1U << FSNOTIFY_OBJ_TYPE_INODE)
+#define FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL (1U << FSNOTIFY_OBJ_TYPE_VFSMOUNT)
+#define FSNOTIFY_OBJ_ALL_TYPES_MASK ((1U << FSNOTIFY_OBJ_TYPE_COUNT) - 1)
+
+struct fsnotify_iter_info {
+ struct fsnotify_mark *marks[FSNOTIFY_OBJ_TYPE_COUNT];
+ unsigned int report_mask;
+ int srcu_idx;
+};
+
+static inline bool fsnotify_iter_should_report_type(
+ struct fsnotify_iter_info *iter_info, int type)
+{
+ return (iter_info->report_mask & (1U << type));
+}
+
+static inline void fsnotify_iter_set_report_type(
+ struct fsnotify_iter_info *iter_info, int type)
+{
+ iter_info->report_mask |= (1U << type);
+}
+
+static inline void fsnotify_iter_set_report_type_mark(
+ struct fsnotify_iter_info *iter_info, int type,
+ struct fsnotify_mark *mark)
+{
+ iter_info->marks[type] = mark;
+ iter_info->report_mask |= (1U << type);
+}
+
+#define FSNOTIFY_ITER_FUNCS(name, NAME) \
+static inline struct fsnotify_mark *fsnotify_iter_##name##_mark( \
+ struct fsnotify_iter_info *iter_info) \
+{ \
+ return (iter_info->report_mask & FSNOTIFY_OBJ_TYPE_##NAME##_FL) ? \
+ iter_info->marks[FSNOTIFY_OBJ_TYPE_##NAME] : NULL; \
+}
+
+FSNOTIFY_ITER_FUNCS(inode, INODE)
+FSNOTIFY_ITER_FUNCS(vfsmount, VFSMOUNT)
+
+#define fsnotify_foreach_obj_type(type) \
+ for (type = 0; type < FSNOTIFY_OBJ_TYPE_COUNT; type++)
+
/*
* Inode / vfsmount point to this structure which tracks all marks attached to
* the inode / vfsmount. The reference to inode / vfsmount is held by this
@@ -209,11 +258,7 @@ struct fsnotify_group {
*/
struct fsnotify_mark_connector {
spinlock_t lock;
-#define FSNOTIFY_OBJ_TYPE_INODE 0x01
-#define FSNOTIFY_OBJ_TYPE_VFSMOUNT 0x02
-#define FSNOTIFY_OBJ_ALL_TYPES (FSNOTIFY_OBJ_TYPE_INODE | \
- FSNOTIFY_OBJ_TYPE_VFSMOUNT)
- unsigned int flags; /* Type of object [lock] */
+ unsigned int type; /* Type of object [lock] */
union { /* Object pointer [lock] */
struct inode *inode;
struct vfsmount *mnt;
@@ -356,7 +401,21 @@ extern struct fsnotify_mark *fsnotify_find_mark(
extern int fsnotify_add_mark(struct fsnotify_mark *mark, struct inode *inode,
struct vfsmount *mnt, int allow_dups);
extern int fsnotify_add_mark_locked(struct fsnotify_mark *mark,
- struct inode *inode, struct vfsmount *mnt, int allow_dups);
+ struct inode *inode, struct vfsmount *mnt,
+ int allow_dups);
+/* attach the mark to the inode */
+static inline int fsnotify_add_inode_mark(struct fsnotify_mark *mark,
+ struct inode *inode,
+ int allow_dups)
+{
+ return fsnotify_add_mark(mark, inode, NULL, allow_dups);
+}
+static inline int fsnotify_add_inode_mark_locked(struct fsnotify_mark *mark,
+ struct inode *inode,
+ int allow_dups)
+{
+ return fsnotify_add_mark_locked(mark, inode, NULL, allow_dups);
+}
/* given a group and a mark, flag mark to be freed when all references are dropped */
extern void fsnotify_destroy_mark(struct fsnotify_mark *mark,
struct fsnotify_group *group);
@@ -369,12 +428,12 @@ extern void fsnotify_clear_marks_by_group(struct fsnotify_group *group, unsigned
/* run all the marks in a group, and clear all of the vfsmount marks */
static inline void fsnotify_clear_vfsmount_marks_by_group(struct fsnotify_group *group)
{
- fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT);
+ fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_VFSMOUNT_FL);
}
/* run all the marks in a group, and clear all of the inode marks */
static inline void fsnotify_clear_inode_marks_by_group(struct fsnotify_group *group)
{
- fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE);
+ fsnotify_clear_marks_by_group(group, FSNOTIFY_OBJ_TYPE_INODE_FL);
}
extern void fsnotify_get_mark(struct fsnotify_mark *mark);
extern void fsnotify_put_mark(struct fsnotify_mark *mark);
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 9c3c9a3..8154f49 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Ftrace header. For implementation details beyond the random comments
- * scattered below, see: Documentation/trace/ftrace-design.txt
+ * scattered below, see: Documentation/trace/ftrace-design.rst
*/
#ifndef _LINUX_FTRACE_H
diff --git a/include/linux/hwspinlock.h b/include/linux/hwspinlock.h
index 859d673..57537e6 100644
--- a/include/linux/hwspinlock.h
+++ b/include/linux/hwspinlock.h
@@ -1,18 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* Hardware spinlock public header
*
* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
*
* Contact: Ohad Ben-Cohen <ohad@wizery.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 __LINUX_HWSPINLOCK_H
@@ -24,6 +16,7 @@
/* hwspinlock mode argument */
#define HWLOCK_IRQSTATE 0x01 /* Disable interrupts, save state */
#define HWLOCK_IRQ 0x02 /* Disable interrupts, don't save state */
+#define HWLOCK_RAW 0x03
struct device;
struct device_node;
@@ -176,6 +169,25 @@ static inline int hwspin_trylock_irq(struct hwspinlock *hwlock)
}
/**
+ * hwspin_trylock_raw() - attempt to lock a specific hwspinlock
+ * @hwlock: an hwspinlock which we want to trylock
+ *
+ * This function attempts to lock an hwspinlock, and will immediately fail
+ * if the hwspinlock is already taken.
+ *
+ * Caution: User must protect the routine of getting hardware lock with mutex
+ * or spinlock to avoid dead-lock, that will let user can do some time-consuming
+ * or sleepable operations under the hardware lock.
+ *
+ * Returns 0 if we successfully locked the hwspinlock, -EBUSY if
+ * the hwspinlock was already taken, and -EINVAL if @hwlock is invalid.
+ */
+static inline int hwspin_trylock_raw(struct hwspinlock *hwlock)
+{
+ return __hwspin_trylock(hwlock, HWLOCK_RAW, NULL);
+}
+
+/**
* hwspin_trylock() - attempt to lock a specific hwspinlock
* @hwlock: an hwspinlock which we want to trylock
*
@@ -243,6 +255,29 @@ int hwspin_lock_timeout_irq(struct hwspinlock *hwlock, unsigned int to)
}
/**
+ * hwspin_lock_timeout_raw() - lock an hwspinlock with timeout limit
+ * @hwlock: the hwspinlock to be locked
+ * @to: timeout value in msecs
+ *
+ * This function locks the underlying @hwlock. If the @hwlock
+ * is already taken, the function will busy loop waiting for it to
+ * be released, but give up when @timeout msecs have elapsed.
+ *
+ * Caution: User must protect the routine of getting hardware lock with mutex
+ * or spinlock to avoid dead-lock, that will let user can do some time-consuming
+ * or sleepable operations under the hardware lock.
+ *
+ * Returns 0 when the @hwlock was successfully taken, and an appropriate
+ * error code otherwise (most notably an -ETIMEDOUT if the @hwlock is still
+ * busy after @timeout msecs). The function will never sleep.
+ */
+static inline
+int hwspin_lock_timeout_raw(struct hwspinlock *hwlock, unsigned int to)
+{
+ return __hwspin_lock_timeout(hwlock, to, HWLOCK_RAW, NULL);
+}
+
+/**
* hwspin_lock_timeout() - lock an hwspinlock with timeout limit
* @hwlock: the hwspinlock to be locked
* @to: timeout value in msecs
@@ -302,6 +337,21 @@ static inline void hwspin_unlock_irq(struct hwspinlock *hwlock)
}
/**
+ * hwspin_unlock_raw() - unlock hwspinlock
+ * @hwlock: a previously-acquired hwspinlock which we want to unlock
+ *
+ * This function will unlock a specific hwspinlock.
+ *
+ * @hwlock must be already locked (e.g. by hwspin_trylock()) before calling
+ * this function: it is a bug to call unlock on a @hwlock that is already
+ * unlocked.
+ */
+static inline void hwspin_unlock_raw(struct hwspinlock *hwlock)
+{
+ __hwspin_unlock(hwlock, HWLOCK_RAW, NULL);
+}
+
+/**
* hwspin_unlock() - unlock hwspinlock
* @hwlock: a previously-acquired hwspinlock which we want to unlock
*
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 11b5612..3a3012f 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -35,6 +35,7 @@
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/interrupt.h>
+#include <linux/reciprocal_div.h>
#define MAX_PAGE_BUFFER_COUNT 32
#define MAX_MULTIPAGE_BUFFER_COUNT 32 /* 128K */
@@ -120,6 +121,7 @@ struct hv_ring_buffer {
struct hv_ring_buffer_info {
struct hv_ring_buffer *ring_buffer;
u32 ring_size; /* Include the shared header */
+ struct reciprocal_value ring_size_div10_reciprocal;
spinlock_t ring_lock;
u32 ring_datasize; /* < ring_size */
@@ -154,6 +156,16 @@ static inline u32 hv_get_bytes_to_write(const struct hv_ring_buffer_info *rbi)
return write;
}
+static inline u32 hv_get_avail_to_write_percent(
+ const struct hv_ring_buffer_info *rbi)
+{
+ u32 avail_write = hv_get_bytes_to_write(rbi);
+
+ return reciprocal_divide(
+ (avail_write << 3) + (avail_write << 1),
+ rbi->ring_size_div10_reciprocal);
+}
+
/*
* VMBUS version is 32 bit entity broken up into
* two 16 bit quantities: major_number. minor_number.
diff --git a/include/linux/i2c-pnx.h b/include/linux/i2c-pnx.h
deleted file mode 100644
index 5388326..0000000
--- a/include/linux/i2c-pnx.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Header file for I2C support on PNX010x/4008.
- *
- * Author: Dennis Kovalev <dkovalev@ru.mvista.com>
- *
- * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-
-#ifndef __I2C_PNX_H__
-#define __I2C_PNX_H__
-
-struct platform_device;
-struct clk;
-
-struct i2c_pnx_mif {
- int ret; /* Return value */
- int mode; /* Interface mode */
- struct completion complete; /* I/O completion */
- struct timer_list timer; /* Timeout */
- u8 * buf; /* Data buffer */
- int len; /* Length of data buffer */
- int order; /* RX Bytes to order via TX */
-};
-
-struct i2c_pnx_algo_data {
- void __iomem *ioaddr;
- struct i2c_pnx_mif mif;
- int last;
- struct clk *clk;
- struct i2c_adapter adapter;
- int irq;
- u32 timeout;
-};
-
-#endif /* __I2C_PNX_H__ */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index 44ad14e..254cd34 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -394,7 +394,6 @@ static inline bool i2c_detect_slave_mode(struct device *dev) { return false; }
* @addr: stored in i2c_client.addr
* @dev_name: Overrides the default <busnr>-<addr> dev_name if set
* @platform_data: stored in i2c_client.dev.platform_data
- * @archdata: copied into i2c_client.dev.archdata
* @of_node: pointer to OpenFirmware device node
* @fwnode: device node supplied by the platform firmware
* @properties: additional device properties for the device
@@ -419,7 +418,6 @@ struct i2c_board_info {
unsigned short addr;
const char *dev_name;
void *platform_data;
- struct dev_archdata *archdata;
struct device_node *of_node;
struct fwnode_handle *fwnode;
const struct property_entry *properties;
@@ -903,6 +901,9 @@ extern const struct of_device_id
*i2c_of_match_device(const struct of_device_id *matches,
struct i2c_client *client);
+int of_i2c_get_board_info(struct device *dev, struct device_node *node,
+ struct i2c_board_info *info);
+
#else
static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
@@ -927,6 +928,13 @@ static inline const struct of_device_id
return NULL;
}
+static inline int of_i2c_get_board_info(struct device *dev,
+ struct device_node *node,
+ struct i2c_board_info *info)
+{
+ return -ENOTSUPP;
+}
+
#endif /* CONFIG_OF */
#if IS_ENABLED(CONFIG_ACPI)
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 4bd2f34..201de12 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -503,6 +503,7 @@ struct irq_chip {
* IRQCHIP_SKIP_SET_WAKE: Skip chip.irq_set_wake(), for this irq chip
* IRQCHIP_ONESHOT_SAFE: One shot does not require mask/unmask
* IRQCHIP_EOI_THREADED: Chip requires eoi() on unmask in threaded mode
+ * IRQCHIP_SUPPORTS_LEVEL_MSI Chip can provide two doorbells for Level MSIs
*/
enum {
IRQCHIP_SET_TYPE_MASKED = (1 << 0),
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index 25b33b6..dd1e40d 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -145,11 +145,6 @@ static inline void *irq_desc_get_handler_data(struct irq_desc *desc)
return desc->irq_common_data.handler_data;
}
-static inline struct msi_desc *irq_desc_get_msi_desc(struct irq_desc *desc)
-{
- return desc->irq_common_data.msi_desc;
-}
-
/*
* Architectures call this to let the generic IRQ layer
* handle an interrupt.
diff --git a/include/linux/kcov.h b/include/linux/kcov.h
index 3ecf6f5..b76a180 100644
--- a/include/linux/kcov.h
+++ b/include/linux/kcov.h
@@ -22,13 +22,27 @@ enum kcov_mode {
KCOV_MODE_TRACE_CMP = 3,
};
+#define KCOV_IN_CTXSW (1 << 30)
+
void kcov_task_init(struct task_struct *t);
void kcov_task_exit(struct task_struct *t);
+#define kcov_prepare_switch(t) \
+do { \
+ (t)->kcov_mode |= KCOV_IN_CTXSW; \
+} while (0)
+
+#define kcov_finish_switch(t) \
+do { \
+ (t)->kcov_mode &= ~KCOV_IN_CTXSW; \
+} while (0)
+
#else
static inline void kcov_task_init(struct task_struct *t) {}
static inline void kcov_task_exit(struct task_struct *t) {}
+static inline void kcov_prepare_switch(struct task_struct *t) {}
+static inline void kcov_finish_switch(struct task_struct *t) {}
#endif /* CONFIG_KCOV */
#endif /* _LINUX_KCOV_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index d231232..941dc0a 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -666,7 +666,7 @@ do { \
* your code. (Extra memory is used for special buffers that are
* allocated when trace_printk() is used.)
*
- * A little optization trick is done here. If there's only one
+ * A little optimization trick is done here. If there's only one
* argument, there's no need to scan the string for printf formats.
* The trace_puts() will suffice. But how can we take advantage of
* using trace_puts() when trace_printk() has only one argument?
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 6d6e79c..4ee7bc5 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -19,6 +19,7 @@
#include <linux/preempt.h>
#include <linux/msi.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
#include <linux/rcupdate.h>
#include <linux/ratelimit.h>
#include <linux/err.h>
@@ -730,13 +731,16 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu);
void kvm_flush_remote_tlbs(struct kvm *kvm);
void kvm_reload_remote_mmus(struct kvm *kvm);
+
+bool kvm_make_vcpus_request_mask(struct kvm *kvm, unsigned int req,
+ unsigned long *vcpu_bitmap, cpumask_var_t tmp);
bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req);
long kvm_arch_dev_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg);
long kvm_arch_vcpu_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg);
-int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf);
+vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf);
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext);
@@ -808,6 +812,10 @@ bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu);
int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
#ifndef __KVM_HAVE_ARCH_VM_ALLOC
+/*
+ * All architectures that want to use vzalloc currently also
+ * need their own kvm_arch_alloc_vm implementation.
+ */
static inline struct kvm *kvm_arch_alloc_vm(void)
{
return kzalloc(sizeof(struct kvm), GFP_KERNEL);
@@ -1270,4 +1278,13 @@ static inline long kvm_arch_vcpu_async_ioctl(struct file *filp,
void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
unsigned long start, unsigned long end);
+#ifdef CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE
+int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu);
+#else
+static inline int kvm_arch_vcpu_run_pid_change(struct kvm_vcpu *vcpu)
+{
+ return 0;
+}
+#endif /* CONFIG_HAVE_KVM_VCPU_RUN_PID_CHANGE */
+
#endif
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 9db9043..8b8946d 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -1130,6 +1130,8 @@ extern void ata_sas_async_probe(struct ata_port *ap);
extern int ata_sas_sync_probe(struct ata_port *ap);
extern int ata_sas_port_init(struct ata_port *);
extern int ata_sas_port_start(struct ata_port *ap);
+extern int ata_sas_tport_add(struct device *parent, struct ata_port *ap);
+extern void ata_sas_tport_delete(struct ata_port *ap);
extern void ata_sas_port_stop(struct ata_port *ap);
extern int ata_sas_slave_configure(struct scsi_device *, struct ata_port *);
extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, struct ata_port *ap);
diff --git a/include/linux/linkage.h b/include/linux/linkage.h
index f68db9e..d7618c4 100644
--- a/include/linux/linkage.h
+++ b/include/linux/linkage.h
@@ -24,16 +24,16 @@
#ifndef cond_syscall
#define cond_syscall(x) asm( \
- ".weak " VMLINUX_SYMBOL_STR(x) "\n\t" \
- ".set " VMLINUX_SYMBOL_STR(x) "," \
- VMLINUX_SYMBOL_STR(sys_ni_syscall))
+ ".weak " __stringify(x) "\n\t" \
+ ".set " __stringify(x) "," \
+ __stringify(sys_ni_syscall))
#endif
#ifndef SYSCALL_ALIAS
#define SYSCALL_ALIAS(alias, name) asm( \
- ".globl " VMLINUX_SYMBOL_STR(alias) "\n\t" \
- ".set " VMLINUX_SYMBOL_STR(alias) "," \
- VMLINUX_SYMBOL_STR(name))
+ ".globl " __stringify(alias) "\n\t" \
+ ".set " __stringify(alias) "," \
+ __stringify(name))
#endif
#define __page_aligned_data __section(.data..page_aligned) __aligned(PAGE_SIZE)
diff --git a/include/linux/log2.h b/include/linux/log2.h
index 41a1ae0..2af7f778 100644
--- a/include/linux/log2.h
+++ b/include/linux/log2.h
@@ -72,16 +72,13 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
}
/**
- * ilog2 - log base 2 of 32-bit or a 64-bit unsigned value
+ * const_ilog2 - log base 2 of 32-bit or a 64-bit constant unsigned value
* @n: parameter
*
- * constant-capable log of base 2 calculation
- * - this can be used to initialise global variables from constant data, hence
- * the massive ternary operator construction
- *
- * selects the appropriately-sized optimised version depending on sizeof(n)
+ * Use this where sparse expects a true constant expression, e.g. for array
+ * indices.
*/
-#define ilog2(n) \
+#define const_ilog2(n) \
( \
__builtin_constant_p(n) ? ( \
(n) < 2 ? 0 : \
@@ -147,10 +144,26 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
(n) & (1ULL << 4) ? 4 : \
(n) & (1ULL << 3) ? 3 : \
(n) & (1ULL << 2) ? 2 : \
- 1 ) : \
- (sizeof(n) <= 4) ? \
- __ilog2_u32(n) : \
- __ilog2_u64(n) \
+ 1) : \
+ -1)
+
+/**
+ * ilog2 - log base 2 of 32-bit or a 64-bit unsigned value
+ * @n: parameter
+ *
+ * constant-capable log of base 2 calculation
+ * - this can be used to initialise global variables from constant data, hence
+ * the massive ternary operator construction
+ *
+ * selects the appropriately-sized optimised version depending on sizeof(n)
+ */
+#define ilog2(n) \
+( \
+ __builtin_constant_p(n) ? \
+ const_ilog2(n) : \
+ (sizeof(n) <= 4) ? \
+ __ilog2_u32(n) : \
+ __ilog2_u64(n) \
)
/**
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
index 4f52ec755..6c6fb11 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -53,6 +53,7 @@ enum memcg_memory_event {
MEMCG_HIGH,
MEMCG_MAX,
MEMCG_OOM,
+ MEMCG_OOM_KILL,
MEMCG_SWAP_MAX,
MEMCG_SWAP_FAIL,
MEMCG_NR_MEMORY_EVENTS,
@@ -720,11 +721,8 @@ static inline void count_memcg_event_mm(struct mm_struct *mm,
rcu_read_lock();
memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
- if (likely(memcg)) {
+ if (likely(memcg))
count_memcg_events(memcg, idx, 1);
- if (idx == OOM_KILL)
- cgroup_file_notify(&memcg->events_file);
- }
rcu_read_unlock();
}
@@ -735,6 +733,21 @@ static inline void memcg_memory_event(struct mem_cgroup *memcg,
cgroup_file_notify(&memcg->events_file);
}
+static inline void memcg_memory_event_mm(struct mm_struct *mm,
+ enum memcg_memory_event event)
+{
+ struct mem_cgroup *memcg;
+
+ if (mem_cgroup_disabled())
+ return;
+
+ rcu_read_lock();
+ memcg = mem_cgroup_from_task(rcu_dereference(mm->owner));
+ if (likely(memcg))
+ memcg_memory_event(memcg, event);
+ rcu_read_unlock();
+}
+
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
void mem_cgroup_split_huge_fixup(struct page *head);
#endif
@@ -756,6 +769,11 @@ static inline void memcg_memory_event(struct mem_cgroup *memcg,
{
}
+static inline void memcg_memory_event_mm(struct mm_struct *mm,
+ enum memcg_memory_event event)
+{
+}
+
static inline enum mem_cgroup_protection mem_cgroup_protected(
struct mem_cgroup *root, struct mem_cgroup *memcg)
{
diff --git a/include/linux/memory.h b/include/linux/memory.h
index 31ca3e2..a6ddefc 100644
--- a/include/linux/memory.h
+++ b/include/linux/memory.h
@@ -38,6 +38,7 @@ struct memory_block {
int arch_get_memory_phys_device(unsigned long start_pfn);
unsigned long memory_block_size_bytes(void);
+int set_memory_block_size_order(unsigned int order);
/* These states are exposed to userspace as text strings in sysfs */
#define MEM_ONLINE (1<<0) /* exposed to userspace */
diff --git a/include/linux/mfd/arizona/pdata.h b/include/linux/mfd/arizona/pdata.h
index f72dc53..0013075 100644
--- a/include/linux/mfd/arizona/pdata.h
+++ b/include/linux/mfd/arizona/pdata.h
@@ -56,6 +56,7 @@
#define ARIZONA_MAX_PDM_SPK 2
struct regulator_init_data;
+struct gpio_desc;
struct arizona_micbias {
int mV; /** Regulated voltage */
@@ -77,7 +78,7 @@ struct arizona_micd_range {
};
struct arizona_pdata {
- int reset; /** GPIO controlling /RESET, if any */
+ struct gpio_desc *reset; /** GPIO controlling /RESET, if any */
/** Regulator configuration for MICVDD */
struct arizona_micsupp_pdata micvdd;
diff --git a/include/linux/mfd/as3711.h b/include/linux/mfd/as3711.h
index 34cc858..ddd0b95 100644
--- a/include/linux/mfd/as3711.h
+++ b/include/linux/mfd/as3711.h
@@ -108,9 +108,9 @@ struct as3711_regulator_pdata {
};
struct as3711_bl_pdata {
- const char *su1_fb;
+ bool su1_fb;
int su1_max_uA;
- const char *su2_fb;
+ bool su2_fb;
int su2_max_uA;
enum as3711_su2_feedback su2_feedback;
enum as3711_su2_fbprot su2_fbprot;
diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h
index 82bf774..517e60e 100644
--- a/include/linux/mfd/axp20x.h
+++ b/include/linux/mfd/axp20x.h
@@ -592,11 +592,11 @@ enum axp806_irqs {
AXP806_IRQ_DCDCC_V_LOW,
AXP806_IRQ_DCDCD_V_LOW,
AXP806_IRQ_DCDCE_V_LOW,
- AXP806_IRQ_PWROK_LONG,
- AXP806_IRQ_PWROK_SHORT,
+ AXP806_IRQ_POK_LONG,
+ AXP806_IRQ_POK_SHORT,
AXP806_IRQ_WAKEUP,
- AXP806_IRQ_PWROK_FALL,
- AXP806_IRQ_PWROK_RISE,
+ AXP806_IRQ_POK_FALL,
+ AXP806_IRQ_POK_RISE,
};
enum axp809_irqs {
@@ -642,7 +642,7 @@ struct axp20x_dev {
struct regmap_irq_chip_data *regmap_irqc;
long variant;
int nr_cells;
- struct mfd_cell *cells;
+ const struct mfd_cell *cells;
const struct regmap_config *regmap_cfg;
const struct regmap_irq_chip *regmap_irq_chip;
};
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index f09e9cf..32421df 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -329,23 +329,7 @@ extern struct attribute_group cros_ec_vbc_attr_group;
/* debugfs stuff */
int cros_ec_debugfs_init(struct cros_ec_dev *ec);
void cros_ec_debugfs_remove(struct cros_ec_dev *ec);
-
-/* ACPI GPE handler */
-#ifdef CONFIG_ACPI
-
-int cros_ec_acpi_install_gpe_handler(struct device *dev);
-void cros_ec_acpi_remove_gpe_handler(void);
-void cros_ec_acpi_clear_gpe(void);
-
-#else /* CONFIG_ACPI */
-
-static inline int cros_ec_acpi_install_gpe_handler(struct device *dev)
-{
- return -ENODEV;
-}
-static inline void cros_ec_acpi_remove_gpe_handler(void) {}
-static inline void cros_ec_acpi_clear_gpe(void) {}
-
-#endif /* CONFIG_ACPI */
+void cros_ec_debugfs_suspend(struct cros_ec_dev *ec);
+void cros_ec_debugfs_resume(struct cros_ec_dev *ec);
#endif /* __LINUX_MFD_CROS_EC_H */
diff --git a/include/linux/mfd/rave-sp.h b/include/linux/mfd/rave-sp.h
index 796fb97..fe0ce7b 100644
--- a/include/linux/mfd/rave-sp.h
+++ b/include/linux/mfd/rave-sp.h
@@ -21,6 +21,7 @@ enum rave_sp_command {
RAVE_SP_CMD_STATUS = 0xA0,
RAVE_SP_CMD_SW_WDT = 0xA1,
RAVE_SP_CMD_PET_WDT = 0xA2,
+ RAVE_SP_CMD_SET_BACKLIGHT = 0xA6,
RAVE_SP_CMD_RESET = 0xA7,
RAVE_SP_CMD_RESET_REASON = 0xA8,
diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h
index 2aadab6..067d146 100644
--- a/include/linux/mfd/stm32-timers.h
+++ b/include/linux/mfd/stm32-timers.h
@@ -8,6 +8,8 @@
#define _LINUX_STM32_GPTIMER_H_
#include <linux/clk.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
#include <linux/regmap.h>
#define TIM_CR1 0x00 /* Control Register 1 */
@@ -27,6 +29,8 @@
#define TIM_CCR3 0x3C /* Capt/Comp Register 3 */
#define TIM_CCR4 0x40 /* Capt/Comp Register 4 */
#define TIM_BDTR 0x44 /* Break and Dead-Time Reg */
+#define TIM_DCR 0x48 /* DMA control register */
+#define TIM_DMAR 0x4C /* DMA register for transfer */
#define TIM_CR1_CEN BIT(0) /* Counter Enable */
#define TIM_CR1_DIR BIT(4) /* Counter Direction */
@@ -36,17 +40,35 @@
#define TIM_SMCR_SMS (BIT(0) | BIT(1) | BIT(2)) /* Slave mode selection */
#define TIM_SMCR_TS (BIT(4) | BIT(5) | BIT(6)) /* Trigger selection */
#define TIM_DIER_UIE BIT(0) /* Update interrupt */
+#define TIM_DIER_UDE BIT(8) /* Update DMA request Enable */
+#define TIM_DIER_CC1DE BIT(9) /* CC1 DMA request Enable */
+#define TIM_DIER_CC2DE BIT(10) /* CC2 DMA request Enable */
+#define TIM_DIER_CC3DE BIT(11) /* CC3 DMA request Enable */
+#define TIM_DIER_CC4DE BIT(12) /* CC4 DMA request Enable */
+#define TIM_DIER_COMDE BIT(13) /* COM DMA request Enable */
+#define TIM_DIER_TDE BIT(14) /* Trigger DMA request Enable */
#define TIM_SR_UIF BIT(0) /* Update interrupt flag */
#define TIM_EGR_UG BIT(0) /* Update Generation */
#define TIM_CCMR_PE BIT(3) /* Channel Preload Enable */
#define TIM_CCMR_M1 (BIT(6) | BIT(5)) /* Channel PWM Mode 1 */
+#define TIM_CCMR_CC1S (BIT(0) | BIT(1)) /* Capture/compare 1 sel */
+#define TIM_CCMR_IC1PSC GENMASK(3, 2) /* Input capture 1 prescaler */
+#define TIM_CCMR_CC2S (BIT(8) | BIT(9)) /* Capture/compare 2 sel */
+#define TIM_CCMR_IC2PSC GENMASK(11, 10) /* Input capture 2 prescaler */
+#define TIM_CCMR_CC1S_TI1 BIT(0) /* IC1/IC3 selects TI1/TI3 */
+#define TIM_CCMR_CC1S_TI2 BIT(1) /* IC1/IC3 selects TI2/TI4 */
+#define TIM_CCMR_CC2S_TI2 BIT(8) /* IC2/IC4 selects TI2/TI4 */
+#define TIM_CCMR_CC2S_TI1 BIT(9) /* IC2/IC4 selects TI1/TI3 */
#define TIM_CCER_CC1E BIT(0) /* Capt/Comp 1 out Ena */
#define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */
#define TIM_CCER_CC1NE BIT(2) /* Capt/Comp 1N out Ena */
#define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */
#define TIM_CCER_CC2E BIT(4) /* Capt/Comp 2 out Ena */
+#define TIM_CCER_CC2P BIT(5) /* Capt/Comp 2 Polarity */
#define TIM_CCER_CC3E BIT(8) /* Capt/Comp 3 out Ena */
+#define TIM_CCER_CC3P BIT(9) /* Capt/Comp 3 Polarity */
#define TIM_CCER_CC4E BIT(12) /* Capt/Comp 4 out Ena */
+#define TIM_CCER_CC4P BIT(13) /* Capt/Comp 4 Polarity */
#define TIM_CCER_CCXE (BIT(0) | BIT(4) | BIT(8) | BIT(12))
#define TIM_BDTR_BKE BIT(12) /* Break input enable */
#define TIM_BDTR_BKP BIT(13) /* Break input polarity */
@@ -56,8 +78,11 @@
#define TIM_BDTR_BK2F (BIT(20) | BIT(21) | BIT(22) | BIT(23))
#define TIM_BDTR_BK2E BIT(24) /* Break 2 input enable */
#define TIM_BDTR_BK2P BIT(25) /* Break 2 input polarity */
+#define TIM_DCR_DBA GENMASK(4, 0) /* DMA base addr */
+#define TIM_DCR_DBL GENMASK(12, 8) /* DMA burst len */
#define MAX_TIM_PSC 0xFFFF
+#define MAX_TIM_ICPSC 0x3
#define TIM_CR2_MMS_SHIFT 4
#define TIM_CR2_MMS2_SHIFT 20
#define TIM_SMCR_TS_SHIFT 4
@@ -65,9 +90,54 @@
#define TIM_BDTR_BKF_SHIFT 16
#define TIM_BDTR_BK2F_SHIFT 20
+enum stm32_timers_dmas {
+ STM32_TIMERS_DMA_CH1,
+ STM32_TIMERS_DMA_CH2,
+ STM32_TIMERS_DMA_CH3,
+ STM32_TIMERS_DMA_CH4,
+ STM32_TIMERS_DMA_UP,
+ STM32_TIMERS_DMA_TRIG,
+ STM32_TIMERS_DMA_COM,
+ STM32_TIMERS_MAX_DMAS,
+};
+
+/**
+ * struct stm32_timers_dma - STM32 timer DMA handling.
+ * @completion: end of DMA transfer completion
+ * @phys_base: control registers physical base address
+ * @lock: protect DMA access
+ * @chan: DMA channel in use
+ * @chans: DMA channels available for this timer instance
+ */
+struct stm32_timers_dma {
+ struct completion completion;
+ phys_addr_t phys_base;
+ struct mutex lock;
+ struct dma_chan *chan;
+ struct dma_chan *chans[STM32_TIMERS_MAX_DMAS];
+};
+
struct stm32_timers {
struct clk *clk;
struct regmap *regmap;
u32 max_arr;
+ struct stm32_timers_dma dma; /* Only to be used by the parent */
};
+
+#if IS_REACHABLE(CONFIG_MFD_STM32_TIMERS)
+int stm32_timers_dma_burst_read(struct device *dev, u32 *buf,
+ enum stm32_timers_dmas id, u32 reg,
+ unsigned int num_reg, unsigned int bursts,
+ unsigned long tmo_ms);
+#else
+static inline int stm32_timers_dma_burst_read(struct device *dev, u32 *buf,
+ enum stm32_timers_dmas id,
+ u32 reg,
+ unsigned int num_reg,
+ unsigned int bursts,
+ unsigned long tmo_ms)
+{
+ return -ENODEV;
+}
+#endif
#endif
diff --git a/include/linux/mfd/syscon/exynos4-pmu.h b/include/linux/mfd/syscon/exynos4-pmu.h
deleted file mode 100644
index 278b1b1..0000000
--- a/include/linux/mfd/syscon/exynos4-pmu.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2015 Samsung Electronics Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _LINUX_MFD_SYSCON_PMU_EXYNOS4_H_
-#define _LINUX_MFD_SYSCON_PMU_EXYNOS4_H_
-
-/* Exynos4 PMU register definitions */
-
-/* MIPI_PHYn_CONTROL register offset: n = 0..1 */
-#define EXYNOS4_MIPI_PHY_CONTROL(n) (0x710 + (n) * 4)
-#define EXYNOS4_MIPI_PHY_ENABLE (1 << 0)
-#define EXYNOS4_MIPI_PHY_SRESETN (1 << 1)
-#define EXYNOS4_MIPI_PHY_MRESETN (1 << 2)
-#define EXYNOS4_MIPI_PHY_RESET_MASK (3 << 1)
-
-#endif /* _LINUX_MFD_SYSCON_PMU_EXYNOS4_H_ */
diff --git a/include/linux/mfd/syscon/exynos5-pmu.h b/include/linux/mfd/syscon/exynos5-pmu.h
deleted file mode 100644
index b4942a3..0000000
--- a/include/linux/mfd/syscon/exynos5-pmu.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Exynos5 SoC series Power Management Unit (PMU) register offsets
- * and bit definitions.
- *
- * Copyright (C) 2014 Samsung Electronics Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_
-#define _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_
-
-#define EXYNOS5_PHY_ENABLE BIT(0)
-#define EXYNOS5_MIPI_PHY_S_RESETN BIT(1)
-#define EXYNOS5_MIPI_PHY_M_RESETN BIT(2)
-
-#endif /* _LINUX_MFD_SYSCON_PMU_EXYNOS5_H_ */
diff --git a/include/linux/mfd/tps65218.h b/include/linux/mfd/tps65218.h
index f069c51..c204d9a 100644
--- a/include/linux/mfd/tps65218.h
+++ b/include/linux/mfd/tps65218.h
@@ -205,10 +205,10 @@ enum tps65218_regulator_id {
TPS65218_DCDC_4,
TPS65218_DCDC_5,
TPS65218_DCDC_6,
- /* LS's */
- TPS65218_LS_3,
/* LDOs */
TPS65218_LDO_1,
+ /* LS's */
+ TPS65218_LS_3,
};
#define TPS65218_MAX_REG_ID TPS65218_LDO_1
diff --git a/include/linux/mfd/tps68470.h b/include/linux/mfd/tps68470.h
index 44f9d9f..ffe8112 100644
--- a/include/linux/mfd/tps68470.h
+++ b/include/linux/mfd/tps68470.h
@@ -1,17 +1,6 @@
-/*
- * Copyright (c) 2017 Intel Corporation
- *
- * Functions to access TPS68470 power management chip.
- *
- * 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.
- *
- * This program is distributed "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2017 Intel Corporation */
+/* Functions to access TPS68470 power management chip. */
#ifndef __LINUX_MFD_TPS68470_H
#define __LINUX_MFD_TPS68470_H
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 0e49388..a0fbb9f 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -575,6 +575,11 @@ static inline void *kvmalloc_array(size_t n, size_t size, gfp_t flags)
return kvmalloc(bytes, flags);
}
+static inline void *kvcalloc(size_t n, size_t size, gfp_t flags)
+{
+ return kvmalloc_array(n, size, flags | __GFP_ZERO);
+}
+
extern void kvfree(const void *addr);
static inline atomic_t *compound_mapcount_ptr(struct page *page)
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index 2014bd1..96a71a6 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -501,6 +501,7 @@ enum dmi_field {
DMI_PRODUCT_VERSION,
DMI_PRODUCT_SERIAL,
DMI_PRODUCT_UUID,
+ DMI_PRODUCT_SKU,
DMI_PRODUCT_FAMILY,
DMI_BOARD_VENDOR,
DMI_BOARD_NAME,
diff --git a/include/linux/namei.h b/include/linux/namei.h
index a982bb7..a78606e 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -81,6 +81,7 @@ extern void done_path_create(struct path *, struct dentry *);
extern struct dentry *kern_path_locked(const char *, struct path *);
extern int kern_path_mountpoint(int, const char *, struct path *, unsigned int);
+extern struct dentry *try_lookup_one_len(const char *, struct dentry *, int);
extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
extern struct dentry *lookup_one_len_unlocked(const char *, struct dentry *, int);
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 04551af..dd2052f 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -345,7 +345,7 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
rcu_read_lock();
nat_hook = rcu_dereference(nf_nat_hook);
- if (nat_hook->decode_session)
+ if (nat_hook && nat_hook->decode_session)
nat_hook->decode_session(skb, fl);
rcu_read_unlock();
#endif
diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h
index bfb3531..8ce271e 100644
--- a/include/linux/netfilter/ipset/ip_set_timeout.h
+++ b/include/linux/netfilter/ipset/ip_set_timeout.h
@@ -23,6 +23,9 @@
/* Set is defined with timeout support: timeout value may be 0 */
#define IPSET_NO_TIMEOUT UINT_MAX
+/* Max timeout value, see msecs_to_jiffies() in jiffies.h */
+#define IPSET_MAX_TIMEOUT (UINT_MAX >> 1)/MSEC_PER_SEC
+
#define ip_set_adt_opt_timeout(opt, set) \
((opt)->ext.timeout != IPSET_NO_TIMEOUT ? (opt)->ext.timeout : (set)->timeout)
@@ -32,11 +35,10 @@ ip_set_timeout_uget(struct nlattr *tb)
unsigned int timeout = ip_set_get_h32(tb);
/* Normalize to fit into jiffies */
- if (timeout > UINT_MAX/MSEC_PER_SEC)
- timeout = UINT_MAX/MSEC_PER_SEC;
+ if (timeout > IPSET_MAX_TIMEOUT)
+ timeout = IPSET_MAX_TIMEOUT;
- /* Userspace supplied TIMEOUT parameter: adjust crazy size */
- return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;
+ return timeout;
}
static inline bool
@@ -65,8 +67,14 @@ ip_set_timeout_set(unsigned long *timeout, u32 value)
static inline u32
ip_set_timeout_get(const unsigned long *timeout)
{
- return *timeout == IPSET_ELEM_PERMANENT ? 0 :
- jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC;
+ u32 t;
+
+ if (*timeout == IPSET_ELEM_PERMANENT)
+ return 0;
+
+ t = jiffies_to_msecs(*timeout - jiffies)/MSEC_PER_SEC;
+ /* Zero value in userspace means no timeout */
+ return t == 0 ? 1 : t;
}
#endif /* __KERNEL__ */
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index 4e735be..74ae3e1 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -28,6 +28,7 @@ struct nfs41_impl_id;
struct nfs_client {
refcount_t cl_count;
atomic_t cl_mds_count;
+ seqcount_t cl_callback_count;
int cl_cons_state; /* current construction state (-ve: init error) */
#define NFS_CS_READY 0 /* ready to be used */
#define NFS_CS_INITING 1 /* busy initialising */
@@ -235,6 +236,7 @@ struct nfs_server {
#define NFS_CAP_ACLS (1U << 3)
#define NFS_CAP_ATOMIC_OPEN (1U << 4)
/* #define NFS_CAP_CHANGE_ATTR (1U << 5) */
+#define NFS_CAP_LGOPEN (1U << 5)
#define NFS_CAP_FILEID (1U << 6)
#define NFS_CAP_MODE (1U << 7)
#define NFS_CAP_NLINK (1U << 8)
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 34d2856..712eed1 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -259,6 +259,7 @@ struct nfs4_layoutget_args {
struct nfs4_layoutget_res {
struct nfs4_sequence_res seq_res;
+ int status;
__u32 return_on_close;
struct pnfs_layout_range range;
__u32 type;
@@ -270,6 +271,7 @@ struct nfs4_layoutget {
struct nfs4_layoutget_args args;
struct nfs4_layoutget_res res;
struct rpc_cred *cred;
+ unsigned callback_count;
gfp_t gfp_flags;
};
@@ -435,6 +437,7 @@ struct nfs_openargs {
enum createmode4 createmode;
const struct nfs4_label *label;
umode_t umask;
+ struct nfs4_layoutget_args *lg_args;
};
struct nfs_openres {
@@ -457,6 +460,7 @@ struct nfs_openres {
__u32 access_request;
__u32 access_supported;
__u32 access_result;
+ struct nfs4_layoutget_res *lg_res;
};
/*
@@ -1434,6 +1438,8 @@ enum {
NFS_IOHDR_EOF,
NFS_IOHDR_REDO,
NFS_IOHDR_STAT,
+ NFS_IOHDR_RESEND_PNFS,
+ NFS_IOHDR_RESEND_MDS,
};
struct nfs_io_completion;
@@ -1577,7 +1583,8 @@ struct nfs_rpc_ops {
struct dentry *(*try_mount) (int, const char *, struct nfs_mount_info *,
struct nfs_subversion *);
int (*getattr) (struct nfs_server *, struct nfs_fh *,
- struct nfs_fattr *, struct nfs4_label *);
+ struct nfs_fattr *, struct nfs4_label *,
+ struct inode *);
int (*setattr) (struct dentry *, struct nfs_fattr *,
struct iattr *);
int (*lookup) (struct inode *, const struct qstr *,
@@ -1591,7 +1598,7 @@ struct nfs_rpc_ops {
int (*create) (struct inode *, struct dentry *,
struct iattr *, int);
int (*remove) (struct inode *, struct dentry *);
- void (*unlink_setup) (struct rpc_message *, struct dentry *);
+ void (*unlink_setup) (struct rpc_message *, struct dentry *, struct inode *);
void (*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *);
int (*unlink_done) (struct rpc_task *, struct inode *);
void (*rename_setup) (struct rpc_message *msg,
@@ -1620,9 +1627,11 @@ struct nfs_rpc_ops {
struct nfs_pgio_header *);
void (*read_setup)(struct nfs_pgio_header *, struct rpc_message *);
int (*read_done)(struct rpc_task *, struct nfs_pgio_header *);
- void (*write_setup)(struct nfs_pgio_header *, struct rpc_message *);
+ void (*write_setup)(struct nfs_pgio_header *, struct rpc_message *,
+ struct rpc_clnt **);
int (*write_done)(struct rpc_task *, struct nfs_pgio_header *);
- void (*commit_setup) (struct nfs_commit_data *, struct rpc_message *);
+ void (*commit_setup) (struct nfs_commit_data *, struct rpc_message *,
+ struct rpc_clnt **);
void (*commit_rpc_prepare)(struct rpc_task *, struct nfs_commit_data *);
int (*commit_done) (struct rpc_task *, struct nfs_commit_data *);
int (*lock)(struct file *, int, struct file_lock *);
diff --git a/include/linux/i2c-gpio.h b/include/linux/platform_data/i2c-gpio.h
index 352c142..352c142 100644
--- a/include/linux/i2c-gpio.h
+++ b/include/linux/platform_data/i2c-gpio.h
diff --git a/include/linux/i2c-mux-gpio.h b/include/linux/platform_data/i2c-mux-gpio.h
index 4406108..4406108 100644
--- a/include/linux/i2c-mux-gpio.h
+++ b/include/linux/platform_data/i2c-mux-gpio.h
diff --git a/include/linux/i2c-ocores.h b/include/linux/platform_data/i2c-ocores.h
index 01edd96..01edd96 100644
--- a/include/linux/i2c-ocores.h
+++ b/include/linux/platform_data/i2c-ocores.h
diff --git a/include/linux/i2c-omap.h b/include/linux/platform_data/i2c-omap.h
index 3444265..3444265 100644
--- a/include/linux/i2c-omap.h
+++ b/include/linux/platform_data/i2c-omap.h
diff --git a/include/linux/i2c-pca-platform.h b/include/linux/platform_data/i2c-pca-platform.h
index c373294..c373294 100644
--- a/include/linux/i2c-pca-platform.h
+++ b/include/linux/platform_data/i2c-pca-platform.h
diff --git a/include/linux/i2c-xiic.h b/include/linux/platform_data/i2c-xiic.h
index 4f9f225..4f9f225 100644
--- a/include/linux/i2c-xiic.h
+++ b/include/linux/platform_data/i2c-xiic.h
diff --git a/include/linux/platform_data/media/ir-rx51.h b/include/linux/platform_data/media/ir-rx51.h
deleted file mode 100644
index 9d127aa..0000000
--- a/include/linux/platform_data/media/ir-rx51.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _IR_RX51_H
-#define _IR_RX51_H
-
-struct ir_rx51_platform_data {
- int(*set_max_mpu_wakeup_lat)(struct device *dev, long t);
-};
-
-#endif
diff --git a/include/linux/platform_data/mlxreg.h b/include/linux/platform_data/mlxreg.h
index 2744cff..19f5cb61 100644
--- a/include/linux/platform_data/mlxreg.h
+++ b/include/linux/platform_data/mlxreg.h
@@ -58,11 +58,10 @@ struct mlxreg_hotplug_device {
* struct mlxreg_core_data - attributes control data:
*
* @label: attribute label;
- * @label: attribute register offset;
* @reg: attribute register;
* @mask: attribute access mask;
- * @mode: access mode;
* @bit: attribute effective bit;
+ * @mode: access mode;
* @np - pointer to node platform associated with attribute;
* @hpdev - hotplug device data;
* @health_cntr: dynamic device health indication counter;
diff --git a/include/linux/platform_data/mtd-davinci.h b/include/linux/platform_data/mtd-davinci.h
index f1a2cf6..1bbfa27 100644
--- a/include/linux/platform_data/mtd-davinci.h
+++ b/include/linux/platform_data/mtd-davinci.h
@@ -56,6 +56,16 @@ struct davinci_nand_pdata { /* platform_data */
uint32_t mask_ale;
uint32_t mask_cle;
+ /*
+ * 0-indexed chip-select number of the asynchronous
+ * interface to which the NAND device has been connected.
+ *
+ * So, if you have NAND connected to CS3 of DA850, you
+ * will pass '1' here. Since the asynchronous interface
+ * on DA850 starts from CS2.
+ */
+ uint32_t core_chipsel;
+
/* for packages using two chipselects */
uint32_t mask_chipsel;
diff --git a/include/linux/platform_data/sc18is602.h b/include/linux/platform_data/sc18is602.h
index 997b066..18602ca 100644
--- a/include/linux/platform_data/sc18is602.h
+++ b/include/linux/platform_data/sc18is602.h
@@ -7,7 +7,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
- * For further information, see the Documentation/spi/sc18is602 file.
+ * For further information, see the Documentation/spi/spi-sc18is602 file.
*/
/**
diff --git a/include/linux/platform_data/shmob_drm.h b/include/linux/platform_data/shmob_drm.h
index 7c686d3..ee495d7 100644
--- a/include/linux/platform_data/shmob_drm.h
+++ b/include/linux/platform_data/shmob_drm.h
@@ -18,9 +18,6 @@
#include <drm/drm_mode.h>
-struct sh_mobile_meram_cfg;
-struct sh_mobile_meram_info;
-
enum shmob_drm_clk_source {
SHMOB_DRM_CLK_BUS,
SHMOB_DRM_CLK_PERIPHERAL,
@@ -93,7 +90,6 @@ struct shmob_drm_platform_data {
struct shmob_drm_interface_data iface;
struct shmob_drm_panel_data panel;
struct shmob_drm_backlight_data backlight;
- const struct sh_mobile_meram_cfg *meram;
};
#endif /* __SHMOB_DRM_H__ */
diff --git a/include/linux/platform_data/spi-imx.h b/include/linux/platform_data/spi-imx.h
index 6f012fe..328f670 100644
--- a/include/linux/platform_data/spi-imx.h
+++ b/include/linux/platform_data/spi-imx.h
@@ -5,24 +5,29 @@
/*
* struct spi_imx_master - device.platform_data for SPI controller devices.
- * @chipselect: Array of chipselects for this master. Numbers >= 0 mean gpio
- * pins, numbers < 0 mean internal CSPI chipselects according
- * to MXC_SPI_CS(). Normally you want to use gpio based chip
- * selects as the CSPI module tries to be intelligent about
- * when to assert the chipselect: The CSPI module deasserts the
- * chipselect once it runs out of input data. The other problem
- * is that it is not possible to mix between high active and low
- * active chipselects on one single bus using the internal
- * chipselects. Unfortunately Freescale decided to put some
+ * @chipselect: Array of chipselects for this master or NULL. Numbers >= 0
+ * mean GPIO pins, -ENOENT means internal CSPI chipselect
+ * matching the position in the array. E.g., if chipselect[1] =
+ * -ENOENT then a SPI slave using chip select 1 will use the
+ * native SS1 line of the CSPI. Omitting the array will use
+ * all native chip selects.
+
+ * Normally you want to use gpio based chip selects as the CSPI
+ * module tries to be intelligent about when to assert the
+ * chipselect: The CSPI module deasserts the chipselect once it
+ * runs out of input data. The other problem is that it is not
+ * possible to mix between high active and low active chipselects
+ * on one single bus using the internal chipselects.
+ * Unfortunately, on some SoCs, Freescale decided to put some
* chipselects on dedicated pins which are not usable as gpios,
* so we have to support the internal chipselects.
- * @num_chipselect: ARRAY_SIZE(chipselect)
+ *
+ * @num_chipselect: If @chipselect is specified, ARRAY_SIZE(chipselect),
+ * otherwise the number of native chip selects.
*/
struct spi_imx_master {
int *chipselect;
int num_chipselect;
};
-#define MXC_SPI_CS(no) ((no) - 32)
-
#endif /* __MACH_SPI_H_*/
diff --git a/include/linux/platform_data/ti-aemif.h b/include/linux/platform_data/ti-aemif.h
index ac72e11..e6407ba 100644
--- a/include/linux/platform_data/ti-aemif.h
+++ b/include/linux/platform_data/ti-aemif.h
@@ -16,8 +16,33 @@
#include <linux/of_platform.h>
+/**
+ * struct aemif_abus_data - Async bus configuration parameters.
+ *
+ * @cs - Chip-select number.
+ */
+struct aemif_abus_data {
+ u32 cs;
+};
+
+/**
+ * struct aemif_platform_data - Data to set up the TI aemif driver.
+ *
+ * @dev_lookup: of_dev_auxdata passed to of_platform_populate() for aemif
+ * subdevices.
+ * @cs_offset: Lowest allowed chip-select number.
+ * @abus_data: Array of async bus configuration entries.
+ * @num_abus_data: Number of abus entries.
+ * @sub_devices: Array of platform subdevices.
+ * @num_sub_devices: Number of subdevices.
+ */
struct aemif_platform_data {
struct of_dev_auxdata *dev_lookup;
+ u32 cs_offset;
+ struct aemif_abus_data *abus_data;
+ size_t num_abus_data;
+ struct platform_device *sub_devices;
+ size_t num_sub_devices;
};
#endif /* __TI_DAVINCI_AEMIF_DATA_H__ */
diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h
index 80ce28d..990aad4 100644
--- a/include/linux/platform_data/ti-sysc.h
+++ b/include/linux/platform_data/ti-sysc.h
@@ -45,6 +45,7 @@ struct sysc_regbits {
s8 emufree_shift;
};
+#define SYSC_QUIRK_RESOURCE_PROVIDER BIT(9)
#define SYSC_QUIRK_LEGACY_IDLE BIT(8)
#define SYSC_QUIRK_RESET_STATUS BIT(7)
#define SYSC_QUIRK_NO_IDLE_ON_INIT BIT(6)
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 42e0d64..9206a4f 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -237,6 +237,8 @@ unsigned int of_genpd_opp_to_performance_state(struct device *dev,
struct device_node *opp_node);
int genpd_dev_pm_attach(struct device *dev);
+struct device *genpd_dev_pm_attach_by_id(struct device *dev,
+ unsigned int index);
#else /* !CONFIG_PM_GENERIC_DOMAINS_OF */
static inline int of_genpd_add_provider_simple(struct device_node *np,
struct generic_pm_domain *genpd)
@@ -282,6 +284,12 @@ static inline int genpd_dev_pm_attach(struct device *dev)
return 0;
}
+static inline struct device *genpd_dev_pm_attach_by_id(struct device *dev,
+ unsigned int index)
+{
+ return NULL;
+}
+
static inline
struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
{
@@ -291,6 +299,8 @@ struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
#ifdef CONFIG_PM
int dev_pm_domain_attach(struct device *dev, bool power_on);
+struct device *dev_pm_domain_attach_by_id(struct device *dev,
+ unsigned int index);
void dev_pm_domain_detach(struct device *dev, bool power_off);
void dev_pm_domain_set(struct device *dev, struct dev_pm_domain *pd);
#else
@@ -298,6 +308,11 @@ static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
{
return 0;
}
+static inline struct device *dev_pm_domain_attach_by_id(struct device *dev,
+ unsigned int index)
+{
+ return NULL;
+}
static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
static inline void dev_pm_domain_set(struct device *dev,
struct dev_pm_domain *pd) {}
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index db5dbbf..f0fc470 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -56,7 +56,8 @@ extern void pm_runtime_update_max_time_suspended(struct device *dev,
s64 delta_ns);
extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable);
extern void pm_runtime_clean_up_links(struct device *dev);
-extern void pm_runtime_resume_suppliers(struct device *dev);
+extern void pm_runtime_get_suppliers(struct device *dev);
+extern void pm_runtime_put_suppliers(struct device *dev);
extern void pm_runtime_new_link(struct device *dev);
extern void pm_runtime_drop_link(struct device *dev);
@@ -172,7 +173,8 @@ static inline unsigned long pm_runtime_autosuspend_expiration(
static inline void pm_runtime_set_memalloc_noio(struct device *dev,
bool enable){}
static inline void pm_runtime_clean_up_links(struct device *dev) {}
-static inline void pm_runtime_resume_suppliers(struct device *dev) {}
+static inline void pm_runtime_get_suppliers(struct device *dev) {}
+static inline void pm_runtime_put_suppliers(struct device *dev) {}
static inline void pm_runtime_new_link(struct device *dev) {}
static inline void pm_runtime_drop_link(struct device *dev) {}
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index e518352..626fc65 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -14,6 +14,8 @@ struct seq_operations;
#ifdef CONFIG_PROC_FS
+typedef int (*proc_write_t)(struct file *, char *, size_t);
+
extern void proc_root_init(void);
extern void proc_flush_task(struct task_struct *);
@@ -61,6 +63,16 @@ struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
struct proc_dir_entry *parent,
int (*show)(struct seq_file *, void *), void *data);
+struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode,
+ struct proc_dir_entry *parent,
+ const struct seq_operations *ops,
+ proc_write_t write,
+ unsigned int state_size, void *data);
+struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mode,
+ struct proc_dir_entry *parent,
+ int (*show)(struct seq_file *, void *),
+ proc_write_t write,
+ void *data);
#else /* CONFIG_PROC_FS */
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 61f806a..a15bc4d 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -71,7 +71,7 @@ struct pstore_record {
struct pstore_info *psi;
enum pstore_type_id type;
u64 id;
- struct timespec time;
+ struct timespec64 time;
char *buf;
ssize_t size;
ssize_t ecc_notice_size;
diff --git a/include/linux/pwm_backlight.h b/include/linux/pwm_backlight.h
index e8afbd7..8ea265a 100644
--- a/include/linux/pwm_backlight.h
+++ b/include/linux/pwm_backlight.h
@@ -14,6 +14,8 @@ struct platform_pwm_backlight_data {
unsigned int lth_brightness;
unsigned int pwm_period_ns;
unsigned int *levels;
+ unsigned int post_pwm_on_delay;
+ unsigned int pwm_off_delay;
/* TODO remove once all users are switched to gpiod_* API */
int enable_gpio;
int (*init)(struct device *dev);
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
new file mode 100644
index 0000000..5d61449
--- /dev/null
+++ b/include/linux/qcom-geni-se.h
@@ -0,0 +1,425 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ */
+
+#ifndef _LINUX_QCOM_GENI_SE
+#define _LINUX_QCOM_GENI_SE
+
+/* Transfer mode supported by GENI Serial Engines */
+enum geni_se_xfer_mode {
+ GENI_SE_INVALID,
+ GENI_SE_FIFO,
+ GENI_SE_DMA,
+};
+
+/* Protocols supported by GENI Serial Engines */
+enum geni_se_protocol_type {
+ GENI_SE_NONE,
+ GENI_SE_SPI,
+ GENI_SE_UART,
+ GENI_SE_I2C,
+ GENI_SE_I3C,
+};
+
+struct geni_wrapper;
+struct clk;
+
+/**
+ * struct geni_se - GENI Serial Engine
+ * @base: Base Address of the Serial Engine's register block
+ * @dev: Pointer to the Serial Engine device
+ * @wrapper: Pointer to the parent QUP Wrapper core
+ * @clk: Handle to the core serial engine clock
+ * @num_clk_levels: Number of valid clock levels in clk_perf_tbl
+ * @clk_perf_tbl: Table of clock frequency input to serial engine clock
+ */
+struct geni_se {
+ void __iomem *base;
+ struct device *dev;
+ struct geni_wrapper *wrapper;
+ struct clk *clk;
+ unsigned int num_clk_levels;
+ unsigned long *clk_perf_tbl;
+};
+
+/* Common SE registers */
+#define GENI_FORCE_DEFAULT_REG 0x20
+#define SE_GENI_STATUS 0x40
+#define GENI_SER_M_CLK_CFG 0x48
+#define GENI_SER_S_CLK_CFG 0x4c
+#define GENI_FW_REVISION_RO 0x68
+#define SE_GENI_CLK_SEL 0x7c
+#define SE_GENI_DMA_MODE_EN 0x258
+#define SE_GENI_M_CMD0 0x600
+#define SE_GENI_M_CMD_CTRL_REG 0x604
+#define SE_GENI_M_IRQ_STATUS 0x610
+#define SE_GENI_M_IRQ_EN 0x614
+#define SE_GENI_M_IRQ_CLEAR 0x618
+#define SE_GENI_S_CMD0 0x630
+#define SE_GENI_S_CMD_CTRL_REG 0x634
+#define SE_GENI_S_IRQ_STATUS 0x640
+#define SE_GENI_S_IRQ_EN 0x644
+#define SE_GENI_S_IRQ_CLEAR 0x648
+#define SE_GENI_TX_FIFOn 0x700
+#define SE_GENI_RX_FIFOn 0x780
+#define SE_GENI_TX_FIFO_STATUS 0x800
+#define SE_GENI_RX_FIFO_STATUS 0x804
+#define SE_GENI_TX_WATERMARK_REG 0x80c
+#define SE_GENI_RX_WATERMARK_REG 0x810
+#define SE_GENI_RX_RFR_WATERMARK_REG 0x814
+#define SE_GENI_IOS 0x908
+#define SE_DMA_TX_IRQ_STAT 0xc40
+#define SE_DMA_TX_IRQ_CLR 0xc44
+#define SE_DMA_TX_FSM_RST 0xc58
+#define SE_DMA_RX_IRQ_STAT 0xd40
+#define SE_DMA_RX_IRQ_CLR 0xd44
+#define SE_DMA_RX_FSM_RST 0xd58
+#define SE_HW_PARAM_0 0xe24
+#define SE_HW_PARAM_1 0xe28
+
+/* GENI_FORCE_DEFAULT_REG fields */
+#define FORCE_DEFAULT BIT(0)
+
+/* GENI_STATUS fields */
+#define M_GENI_CMD_ACTIVE BIT(0)
+#define S_GENI_CMD_ACTIVE BIT(12)
+
+/* GENI_SER_M_CLK_CFG/GENI_SER_S_CLK_CFG */
+#define SER_CLK_EN BIT(0)
+#define CLK_DIV_MSK GENMASK(15, 4)
+#define CLK_DIV_SHFT 4
+
+/* GENI_FW_REVISION_RO fields */
+#define FW_REV_PROTOCOL_MSK GENMASK(15, 8)
+#define FW_REV_PROTOCOL_SHFT 8
+
+/* GENI_CLK_SEL fields */
+#define CLK_SEL_MSK GENMASK(2, 0)
+
+/* SE_GENI_DMA_MODE_EN */
+#define GENI_DMA_MODE_EN BIT(0)
+
+/* GENI_M_CMD0 fields */
+#define M_OPCODE_MSK GENMASK(31, 27)
+#define M_OPCODE_SHFT 27
+#define M_PARAMS_MSK GENMASK(26, 0)
+
+/* GENI_M_CMD_CTRL_REG */
+#define M_GENI_CMD_CANCEL BIT(2)
+#define M_GENI_CMD_ABORT BIT(1)
+#define M_GENI_DISABLE BIT(0)
+
+/* GENI_S_CMD0 fields */
+#define S_OPCODE_MSK GENMASK(31, 27)
+#define S_OPCODE_SHFT 27
+#define S_PARAMS_MSK GENMASK(26, 0)
+
+/* GENI_S_CMD_CTRL_REG */
+#define S_GENI_CMD_CANCEL BIT(2)
+#define S_GENI_CMD_ABORT BIT(1)
+#define S_GENI_DISABLE BIT(0)
+
+/* GENI_M_IRQ_EN fields */
+#define M_CMD_DONE_EN BIT(0)
+#define M_CMD_OVERRUN_EN BIT(1)
+#define M_ILLEGAL_CMD_EN BIT(2)
+#define M_CMD_FAILURE_EN BIT(3)
+#define M_CMD_CANCEL_EN BIT(4)
+#define M_CMD_ABORT_EN BIT(5)
+#define M_TIMESTAMP_EN BIT(6)
+#define M_RX_IRQ_EN BIT(7)
+#define M_GP_SYNC_IRQ_0_EN BIT(8)
+#define M_GP_IRQ_0_EN BIT(9)
+#define M_GP_IRQ_1_EN BIT(10)
+#define M_GP_IRQ_2_EN BIT(11)
+#define M_GP_IRQ_3_EN BIT(12)
+#define M_GP_IRQ_4_EN BIT(13)
+#define M_GP_IRQ_5_EN BIT(14)
+#define M_IO_DATA_DEASSERT_EN BIT(22)
+#define M_IO_DATA_ASSERT_EN BIT(23)
+#define M_RX_FIFO_RD_ERR_EN BIT(24)
+#define M_RX_FIFO_WR_ERR_EN BIT(25)
+#define M_RX_FIFO_WATERMARK_EN BIT(26)
+#define M_RX_FIFO_LAST_EN BIT(27)
+#define M_TX_FIFO_RD_ERR_EN BIT(28)
+#define M_TX_FIFO_WR_ERR_EN BIT(29)
+#define M_TX_FIFO_WATERMARK_EN BIT(30)
+#define M_SEC_IRQ_EN BIT(31)
+#define M_COMMON_GENI_M_IRQ_EN (GENMASK(6, 1) | \
+ M_IO_DATA_DEASSERT_EN | \
+ M_IO_DATA_ASSERT_EN | M_RX_FIFO_RD_ERR_EN | \
+ M_RX_FIFO_WR_ERR_EN | M_TX_FIFO_RD_ERR_EN | \
+ M_TX_FIFO_WR_ERR_EN)
+
+/* GENI_S_IRQ_EN fields */
+#define S_CMD_DONE_EN BIT(0)
+#define S_CMD_OVERRUN_EN BIT(1)
+#define S_ILLEGAL_CMD_EN BIT(2)
+#define S_CMD_FAILURE_EN BIT(3)
+#define S_CMD_CANCEL_EN BIT(4)
+#define S_CMD_ABORT_EN BIT(5)
+#define S_GP_SYNC_IRQ_0_EN BIT(8)
+#define S_GP_IRQ_0_EN BIT(9)
+#define S_GP_IRQ_1_EN BIT(10)
+#define S_GP_IRQ_2_EN BIT(11)
+#define S_GP_IRQ_3_EN BIT(12)
+#define S_GP_IRQ_4_EN BIT(13)
+#define S_GP_IRQ_5_EN BIT(14)
+#define S_IO_DATA_DEASSERT_EN BIT(22)
+#define S_IO_DATA_ASSERT_EN BIT(23)
+#define S_RX_FIFO_RD_ERR_EN BIT(24)
+#define S_RX_FIFO_WR_ERR_EN BIT(25)
+#define S_RX_FIFO_WATERMARK_EN BIT(26)
+#define S_RX_FIFO_LAST_EN BIT(27)
+#define S_COMMON_GENI_S_IRQ_EN (GENMASK(5, 1) | GENMASK(13, 9) | \
+ S_RX_FIFO_RD_ERR_EN | S_RX_FIFO_WR_ERR_EN)
+
+/* GENI_/TX/RX/RX_RFR/_WATERMARK_REG fields */
+#define WATERMARK_MSK GENMASK(5, 0)
+
+/* GENI_TX_FIFO_STATUS fields */
+#define TX_FIFO_WC GENMASK(27, 0)
+
+/* GENI_RX_FIFO_STATUS fields */
+#define RX_LAST BIT(31)
+#define RX_LAST_BYTE_VALID_MSK GENMASK(30, 28)
+#define RX_LAST_BYTE_VALID_SHFT 28
+#define RX_FIFO_WC_MSK GENMASK(24, 0)
+
+/* SE_GENI_IOS fields */
+#define IO2_DATA_IN BIT(1)
+#define RX_DATA_IN BIT(0)
+
+/* SE_DMA_TX_IRQ_STAT Register fields */
+#define TX_DMA_DONE BIT(0)
+#define TX_EOT BIT(1)
+#define TX_SBE BIT(2)
+#define TX_RESET_DONE BIT(3)
+
+/* SE_DMA_RX_IRQ_STAT Register fields */
+#define RX_DMA_DONE BIT(0)
+#define RX_EOT BIT(1)
+#define RX_SBE BIT(2)
+#define RX_RESET_DONE BIT(3)
+#define RX_FLUSH_DONE BIT(4)
+#define RX_GENI_GP_IRQ GENMASK(10, 5)
+#define RX_GENI_CANCEL_IRQ BIT(11)
+#define RX_GENI_GP_IRQ_EXT GENMASK(13, 12)
+
+/* SE_HW_PARAM_0 fields */
+#define TX_FIFO_WIDTH_MSK GENMASK(29, 24)
+#define TX_FIFO_WIDTH_SHFT 24
+#define TX_FIFO_DEPTH_MSK GENMASK(21, 16)
+#define TX_FIFO_DEPTH_SHFT 16
+
+/* SE_HW_PARAM_1 fields */
+#define RX_FIFO_WIDTH_MSK GENMASK(29, 24)
+#define RX_FIFO_WIDTH_SHFT 24
+#define RX_FIFO_DEPTH_MSK GENMASK(21, 16)
+#define RX_FIFO_DEPTH_SHFT 16
+
+#define HW_VER_MAJOR_MASK GENMASK(31, 28)
+#define HW_VER_MAJOR_SHFT 28
+#define HW_VER_MINOR_MASK GENMASK(27, 16)
+#define HW_VER_MINOR_SHFT 16
+#define HW_VER_STEP_MASK GENMASK(15, 0)
+
+#if IS_ENABLED(CONFIG_QCOM_GENI_SE)
+
+u32 geni_se_get_qup_hw_version(struct geni_se *se);
+
+#define geni_se_get_wrapper_version(se, major, minor, step) do { \
+ u32 ver; \
+\
+ ver = geni_se_get_qup_hw_version(se); \
+ major = (ver & HW_VER_MAJOR_MASK) >> HW_VER_MAJOR_SHFT; \
+ minor = (ver & HW_VER_MINOR_MASK) >> HW_VER_MINOR_SHFT; \
+ step = version & HW_VER_STEP_MASK; \
+} while (0)
+
+/**
+ * geni_se_read_proto() - Read the protocol configured for a serial engine
+ * @se: Pointer to the concerned serial engine.
+ *
+ * Return: Protocol value as configured in the serial engine.
+ */
+static inline u32 geni_se_read_proto(struct geni_se *se)
+{
+ u32 val;
+
+ val = readl_relaxed(se->base + GENI_FW_REVISION_RO);
+
+ return (val & FW_REV_PROTOCOL_MSK) >> FW_REV_PROTOCOL_SHFT;
+}
+
+/**
+ * geni_se_setup_m_cmd() - Setup the primary sequencer
+ * @se: Pointer to the concerned serial engine.
+ * @cmd: Command/Operation to setup in the primary sequencer.
+ * @params: Parameter for the sequencer command.
+ *
+ * This function is used to configure the primary sequencer with the
+ * command and its associated parameters.
+ */
+static inline void geni_se_setup_m_cmd(struct geni_se *se, u32 cmd, u32 params)
+{
+ u32 m_cmd;
+
+ m_cmd = (cmd << M_OPCODE_SHFT) | (params & M_PARAMS_MSK);
+ writel_relaxed(m_cmd, se->base + SE_GENI_M_CMD0);
+}
+
+/**
+ * geni_se_setup_s_cmd() - Setup the secondary sequencer
+ * @se: Pointer to the concerned serial engine.
+ * @cmd: Command/Operation to setup in the secondary sequencer.
+ * @params: Parameter for the sequencer command.
+ *
+ * This function is used to configure the secondary sequencer with the
+ * command and its associated parameters.
+ */
+static inline void geni_se_setup_s_cmd(struct geni_se *se, u32 cmd, u32 params)
+{
+ u32 s_cmd;
+
+ s_cmd = readl_relaxed(se->base + SE_GENI_S_CMD0);
+ s_cmd &= ~(S_OPCODE_MSK | S_PARAMS_MSK);
+ s_cmd |= (cmd << S_OPCODE_SHFT);
+ s_cmd |= (params & S_PARAMS_MSK);
+ writel_relaxed(s_cmd, se->base + SE_GENI_S_CMD0);
+}
+
+/**
+ * geni_se_cancel_m_cmd() - Cancel the command configured in the primary
+ * sequencer
+ * @se: Pointer to the concerned serial engine.
+ *
+ * This function is used to cancel the currently configured command in the
+ * primary sequencer.
+ */
+static inline void geni_se_cancel_m_cmd(struct geni_se *se)
+{
+ writel_relaxed(M_GENI_CMD_CANCEL, se->base + SE_GENI_M_CMD_CTRL_REG);
+}
+
+/**
+ * geni_se_cancel_s_cmd() - Cancel the command configured in the secondary
+ * sequencer
+ * @se: Pointer to the concerned serial engine.
+ *
+ * This function is used to cancel the currently configured command in the
+ * secondary sequencer.
+ */
+static inline void geni_se_cancel_s_cmd(struct geni_se *se)
+{
+ writel_relaxed(S_GENI_CMD_CANCEL, se->base + SE_GENI_S_CMD_CTRL_REG);
+}
+
+/**
+ * geni_se_abort_m_cmd() - Abort the command configured in the primary sequencer
+ * @se: Pointer to the concerned serial engine.
+ *
+ * This function is used to force abort the currently configured command in the
+ * primary sequencer.
+ */
+static inline void geni_se_abort_m_cmd(struct geni_se *se)
+{
+ writel_relaxed(M_GENI_CMD_ABORT, se->base + SE_GENI_M_CMD_CTRL_REG);
+}
+
+/**
+ * geni_se_abort_s_cmd() - Abort the command configured in the secondary
+ * sequencer
+ * @se: Pointer to the concerned serial engine.
+ *
+ * This function is used to force abort the currently configured command in the
+ * secondary sequencer.
+ */
+static inline void geni_se_abort_s_cmd(struct geni_se *se)
+{
+ writel_relaxed(S_GENI_CMD_ABORT, se->base + SE_GENI_S_CMD_CTRL_REG);
+}
+
+/**
+ * geni_se_get_tx_fifo_depth() - Get the TX fifo depth of the serial engine
+ * @se: Pointer to the concerned serial engine.
+ *
+ * This function is used to get the depth i.e. number of elements in the
+ * TX fifo of the serial engine.
+ *
+ * Return: TX fifo depth in units of FIFO words.
+ */
+static inline u32 geni_se_get_tx_fifo_depth(struct geni_se *se)
+{
+ u32 val;
+
+ val = readl_relaxed(se->base + SE_HW_PARAM_0);
+
+ return (val & TX_FIFO_DEPTH_MSK) >> TX_FIFO_DEPTH_SHFT;
+}
+
+/**
+ * geni_se_get_tx_fifo_width() - Get the TX fifo width of the serial engine
+ * @se: Pointer to the concerned serial engine.
+ *
+ * This function is used to get the width i.e. word size per element in the
+ * TX fifo of the serial engine.
+ *
+ * Return: TX fifo width in bits
+ */
+static inline u32 geni_se_get_tx_fifo_width(struct geni_se *se)
+{
+ u32 val;
+
+ val = readl_relaxed(se->base + SE_HW_PARAM_0);
+
+ return (val & TX_FIFO_WIDTH_MSK) >> TX_FIFO_WIDTH_SHFT;
+}
+
+/**
+ * geni_se_get_rx_fifo_depth() - Get the RX fifo depth of the serial engine
+ * @se: Pointer to the concerned serial engine.
+ *
+ * This function is used to get the depth i.e. number of elements in the
+ * RX fifo of the serial engine.
+ *
+ * Return: RX fifo depth in units of FIFO words
+ */
+static inline u32 geni_se_get_rx_fifo_depth(struct geni_se *se)
+{
+ u32 val;
+
+ val = readl_relaxed(se->base + SE_HW_PARAM_1);
+
+ return (val & RX_FIFO_DEPTH_MSK) >> RX_FIFO_DEPTH_SHFT;
+}
+
+void geni_se_init(struct geni_se *se, u32 rx_wm, u32 rx_rfr);
+
+void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode);
+
+void geni_se_config_packing(struct geni_se *se, int bpw, int pack_words,
+ bool msb_to_lsb, bool tx_cfg, bool rx_cfg);
+
+int geni_se_resources_off(struct geni_se *se);
+
+int geni_se_resources_on(struct geni_se *se);
+
+int geni_se_clk_tbl_get(struct geni_se *se, unsigned long **tbl);
+
+int geni_se_clk_freq_match(struct geni_se *se, unsigned long req_freq,
+ unsigned int *index, unsigned long *res_freq,
+ bool exact);
+
+int geni_se_tx_dma_prep(struct geni_se *se, void *buf, size_t len,
+ dma_addr_t *iova);
+
+int geni_se_rx_dma_prep(struct geni_se *se, void *buf, size_t len,
+ dma_addr_t *iova);
+
+void geni_se_tx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
+
+void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len);
+#endif
+#endif
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 127f534..36df6cc 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -404,6 +404,19 @@ static inline void list_splice_tail_init_rcu(struct list_head *list,
pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
/**
+ * list_for_each_entry_from_rcu - iterate over a list from current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_node within the struct.
+ *
+ * Iterate over the tail of a list starting from a given position,
+ * which must have been in the list when the RCU read lock was taken.
+ */
+#define list_for_each_entry_from_rcu(pos, head, member) \
+ for (; &(pos)->member != (head); \
+ pos = list_entry_rcu(pos->member.next, typeof(*(pos)), member))
+
+/**
* hlist_del_rcu - deletes entry from hash list without re-initialization
* @n: the element to delete from the hash list.
*
diff --git a/include/linux/rculist_nulls.h b/include/linux/rculist_nulls.h
index e4b257f..bc8206a 100644
--- a/include/linux/rculist_nulls.h
+++ b/include/linux/rculist_nulls.h
@@ -109,7 +109,7 @@ static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n,
*
* The barrier() is needed to make sure compiler doesn't cache first element [1],
* as this loop can be restarted [2]
- * [1] Documentation/atomic_ops.txt around line 114
+ * [1] Documentation/core-api/atomic_ops.rst around line 114
* [2] Documentation/RCU/rculist_nulls.txt around line 146
*/
#define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member) \
diff --git a/include/linux/refcount.h b/include/linux/refcount.h
index 4193c41..a685da2 100644
--- a/include/linux/refcount.h
+++ b/include/linux/refcount.h
@@ -98,5 +98,7 @@ extern __must_check bool refcount_dec_if_one(refcount_t *r);
extern __must_check bool refcount_dec_not_one(refcount_t *r);
extern __must_check bool refcount_dec_and_mutex_lock(refcount_t *r, struct mutex *lock);
extern __must_check bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock);
-
+extern __must_check bool refcount_dec_and_lock_irqsave(refcount_t *r,
+ spinlock_t *lock,
+ unsigned long *flags);
#endif /* _LINUX_REFCOUNT_H */
diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h
index ca07366..9fe156d 100644
--- a/include/linux/rpmsg.h
+++ b/include/linux/rpmsg.h
@@ -1,35 +1,10 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
/*
* Remote processor messaging
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2011 Google, Inc.
* All rights reserved.
- *
- * 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 Texas Instruments nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _LINUX_RPMSG_H
diff --git a/include/linux/rpmsg/qcom_glink.h b/include/linux/rpmsg/qcom_glink.h
index a622f02..96e26d9 100644
--- a/include/linux/rpmsg/qcom_glink.h
+++ b/include/linux/rpmsg/qcom_glink.h
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
#ifndef _LINUX_RPMSG_QCOM_GLINK_H
#define _LINUX_RPMSG_QCOM_GLINK_H
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 4c007f6..6268208 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -285,7 +285,7 @@ void rtc_nvmem_unregister(struct rtc_device *rtc);
static inline int rtc_nvmem_register(struct rtc_device *rtc,
struct nvmem_config *nvmem_config)
{
- return -ENODEV;
+ return 0;
}
static inline void rtc_nvmem_unregister(struct rtc_device *rtc) {}
#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 3aa4fcb..9256118 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -742,7 +742,7 @@ struct task_struct {
pid_t pid;
pid_t tgid;
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
/* Canary value for the -fstack-protector GCC feature: */
unsigned long stack_canary;
#endif
@@ -1130,7 +1130,7 @@ struct task_struct {
#ifdef CONFIG_KCOV
/* Coverage collection mode enabled for this task (0 if disabled): */
- enum kcov_mode kcov_mode;
+ unsigned int kcov_mode;
/* Size of the kcov_area: */
unsigned int kcov_size;
@@ -1639,6 +1639,12 @@ static inline void clear_tsk_thread_flag(struct task_struct *tsk, int flag)
clear_ti_thread_flag(task_thread_info(tsk), flag);
}
+static inline void update_tsk_thread_flag(struct task_struct *tsk, int flag,
+ bool value)
+{
+ update_ti_thread_flag(task_thread_info(tsk), flag, value);
+}
+
static inline int test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag)
{
return test_and_set_ti_thread_flag(task_thread_info(tsk), flag);
@@ -1793,20 +1799,22 @@ static inline void rseq_set_notify_resume(struct task_struct *t)
set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
}
-void __rseq_handle_notify_resume(struct pt_regs *regs);
+void __rseq_handle_notify_resume(struct ksignal *sig, struct pt_regs *regs);
-static inline void rseq_handle_notify_resume(struct pt_regs *regs)
+static inline void rseq_handle_notify_resume(struct ksignal *ksig,
+ struct pt_regs *regs)
{
if (current->rseq)
- __rseq_handle_notify_resume(regs);
+ __rseq_handle_notify_resume(ksig, regs);
}
-static inline void rseq_signal_deliver(struct pt_regs *regs)
+static inline void rseq_signal_deliver(struct ksignal *ksig,
+ struct pt_regs *regs)
{
preempt_disable();
__set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask);
preempt_enable();
- rseq_handle_notify_resume(regs);
+ rseq_handle_notify_resume(ksig, regs);
}
/* rseq_preempt() requires preemption to be disabled. */
@@ -1825,9 +1833,7 @@ static inline void rseq_migrate(struct task_struct *t)
/*
* If parent process has a registered restartable sequences area, the
- * child inherits. Only applies when forking a process, not a thread. In
- * case a parent fork() in the middle of a restartable sequence, set the
- * resume notifier to force the child to retry.
+ * child inherits. Only applies when forking a process, not a thread.
*/
static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
{
@@ -1841,7 +1847,6 @@ static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
t->rseq_len = current->rseq_len;
t->rseq_sig = current->rseq_sig;
t->rseq_event_mask = current->rseq_event_mask;
- rseq_preempt(t);
}
}
@@ -1858,10 +1863,12 @@ static inline void rseq_execve(struct task_struct *t)
static inline void rseq_set_notify_resume(struct task_struct *t)
{
}
-static inline void rseq_handle_notify_resume(struct pt_regs *regs)
+static inline void rseq_handle_notify_resume(struct ksignal *ksig,
+ struct pt_regs *regs)
{
}
-static inline void rseq_signal_deliver(struct pt_regs *regs)
+static inline void rseq_signal_deliver(struct ksignal *ksig,
+ struct pt_regs *regs)
{
}
static inline void rseq_preempt(struct task_struct *t)
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index b458c87..f4c9fc0 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -85,8 +85,8 @@ struct scmi_clk_ops {
* @level_set: sets the performance level of a domain
* @level_get: gets the performance level of a domain
* @device_domain_id: gets the scmi domain id for a given device
- * @get_transition_latency: gets the DVFS transition latency for a given device
- * @add_opps_to_device: adds all the OPPs for a given device
+ * @transition_latency_get: gets the DVFS transition latency for a given device
+ * @device_opps_add: adds all the OPPs for a given device
* @freq_set: sets the frequency for a given device using sustained frequency
* to sustained performance level mapping
* @freq_get: gets the frequency for a given device using sustained frequency
@@ -102,10 +102,10 @@ struct scmi_perf_ops {
int (*level_get)(const struct scmi_handle *handle, u32 domain,
u32 *level, bool poll);
int (*device_domain_id)(struct device *dev);
- int (*get_transition_latency)(const struct scmi_handle *handle,
+ int (*transition_latency_get)(const struct scmi_handle *handle,
struct device *dev);
- int (*add_opps_to_device)(const struct scmi_handle *handle,
- struct device *dev);
+ int (*device_opps_add)(const struct scmi_handle *handle,
+ struct device *dev);
int (*freq_set)(const struct scmi_handle *handle, u32 domain,
unsigned long rate, bool poll);
int (*freq_get)(const struct scmi_handle *handle, u32 domain,
@@ -189,6 +189,14 @@ struct scmi_sensor_ops {
* @perf_ops: pointer to set of performance protocol operations
* @clk_ops: pointer to set of clock protocol operations
* @sensor_ops: pointer to set of sensor protocol operations
+ * @perf_priv: pointer to private data structure specific to performance
+ * protocol(for internal use only)
+ * @clk_priv: pointer to private data structure specific to clock
+ * protocol(for internal use only)
+ * @power_priv: pointer to private data structure specific to power
+ * protocol(for internal use only)
+ * @sensor_priv: pointer to private data structure specific to sensors
+ * protocol(for internal use only)
*/
struct scmi_handle {
struct device *dev;
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 4d759e1..14e3fe4 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -600,6 +600,7 @@ struct memcg_cache_params {
struct memcg_cache_array __rcu *memcg_caches;
struct list_head __root_caches_node;
struct list_head children;
+ bool dying;
};
struct {
struct mem_cgroup *memcg;
diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h
index c1657ed..86e1b35 100644
--- a/include/linux/soc/qcom/smem.h
+++ b/include/linux/soc/qcom/smem.h
@@ -9,4 +9,6 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size);
int qcom_smem_get_free_space(unsigned host);
+phys_addr_t qcom_smem_virt_to_phys(void *p);
+
#endif
diff --git a/include/linux/soc/ti/ti_sci_protocol.h b/include/linux/soc/ti/ti_sci_protocol.h
index 0ccbc13..18435e5 100644
--- a/include/linux/soc/ti/ti_sci_protocol.h
+++ b/include/linux/soc/ti/ti_sci_protocol.h
@@ -1,17 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* Texas Instruments System Control Interface Protocol
*
* Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
* Nishanth Menon
- *
- * 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 "as is" WITHOUT ANY WARRANTY of any
- * kind, whether express or implied; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
#ifndef __TISCI_PROTOCOL_H
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 1e8a464..fd57888 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -427,6 +427,11 @@ extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
#define atomic_dec_and_lock(atomic, lock) \
__cond_lock(lock, _atomic_dec_and_lock(atomic, lock))
+extern int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock,
+ unsigned long *flags);
+#define atomic_dec_and_lock_irqsave(atomic, lock, flags) \
+ __cond_lock(lock, _atomic_dec_and_lock_irqsave(atomic, lock, &(flags)))
+
int alloc_bucket_spinlocks(spinlock_t **locks, unsigned int *lock_mask,
size_t max_size, unsigned int cpu_mult,
gfp_t gfp);
diff --git a/include/linux/stackprotector.h b/include/linux/stackprotector.h
index 03696c7..6b792d0 100644
--- a/include/linux/stackprotector.h
+++ b/include/linux/stackprotector.h
@@ -6,7 +6,7 @@
#include <linux/sched.h>
#include <linux/random.h>
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
# include <asm/stackprotector.h>
#else
static inline void boot_init_stack_canary(void)
diff --git a/include/linux/stat.h b/include/linux/stat.h
index 22484e4..765573d 100644
--- a/include/linux/stat.h
+++ b/include/linux/stat.h
@@ -41,10 +41,10 @@ struct kstat {
kuid_t uid;
kgid_t gid;
loff_t size;
- struct timespec atime;
- struct timespec mtime;
- struct timespec ctime;
- struct timespec btime; /* File creation time */
+ struct timespec64 atime;
+ struct timespec64 mtime;
+ struct timespec64 ctime;
+ struct timespec64 btime; /* File creation time */
u64 blocks;
};
diff --git a/include/linux/ste_modem_shm.h b/include/linux/ste_modem_shm.h
deleted file mode 100644
index 8444a4e..0000000
--- a/include/linux/ste_modem_shm.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson AB 2012
- * Author: Sjur Brendeland / sjur.brandeland@stericsson.com
- *
- * License terms: GNU General Public License (GPL) version 2
- */
-
-#ifndef __INC_MODEM_DEV_H
-#define __INC_MODEM_DEV_H
-#include <linux/types.h>
-#include <linux/platform_device.h>
-
-struct ste_modem_device;
-
-/**
- * struct ste_modem_dev_cb - Callbacks for modem initiated events.
- * @kick: Called when the modem kicks the host.
- *
- * This structure contains callbacks for actions triggered by the modem.
- */
-struct ste_modem_dev_cb {
- void (*kick)(struct ste_modem_device *mdev, int notify_id);
-};
-
-/**
- * struct ste_modem_dev_ops - Functions to control modem and modem interface.
- *
- * @power: Main power switch, used for cold-start or complete power off.
- * @kick: Kick the modem.
- * @kick_subscribe: Subscribe for notifications from the modem.
- * @setup: Provide callback functions to modem device.
- *
- * This structure contains functions used by the ste remoteproc driver
- * to manage the modem.
- */
-struct ste_modem_dev_ops {
- int (*power)(struct ste_modem_device *mdev, bool on);
- int (*kick)(struct ste_modem_device *mdev, int notify_id);
- int (*kick_subscribe)(struct ste_modem_device *mdev, int notify_id);
- int (*setup)(struct ste_modem_device *mdev,
- struct ste_modem_dev_cb *cfg);
-};
-
-/**
- * struct ste_modem_device - represent the STE modem device
- * @pdev: Reference to platform device
- * @ops: Operations used to manage the modem.
- * @drv_data: Driver private data.
- */
-struct ste_modem_device {
- struct platform_device pdev;
- struct ste_modem_dev_ops ops;
- void *drv_data;
-};
-
-#endif /*INC_MODEM_DEV_H*/
diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h
index 4397c52..d23c503 100644
--- a/include/linux/string_helpers.h
+++ b/include/linux/string_helpers.h
@@ -5,6 +5,7 @@
#include <linux/types.h>
struct file;
+struct task_struct;
/* Descriptions of the types of units to
* print in */
diff --git a/include/linux/sunrpc/rpc_rdma.h b/include/linux/sunrpc/rpc_rdma.h
index 8f144db..92d182f 100644
--- a/include/linux/sunrpc/rpc_rdma.h
+++ b/include/linux/sunrpc/rpc_rdma.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (c) 2015-2017 Oracle. All rights reserved.
* Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h
index 7337e12..fd78f78 100644
--- a/include/linux/sunrpc/svc_rdma.h
+++ b/include/linux/sunrpc/svc_rdma.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved.
*
@@ -70,37 +71,16 @@ extern atomic_t rdma_stat_rq_prod;
extern atomic_t rdma_stat_sq_poll;
extern atomic_t rdma_stat_sq_prod;
-/*
- * Contexts are built when an RDMA request is created and are a
- * record of the resources that can be recovered when the request
- * completes.
- */
-struct svc_rdma_op_ctxt {
- struct list_head list;
- struct xdr_buf arg;
- struct ib_cqe cqe;
- u32 byte_len;
- struct svcxprt_rdma *xprt;
- enum dma_data_direction direction;
- int count;
- unsigned int mapped_sges;
- int hdr_count;
- struct ib_send_wr send_wr;
- struct ib_sge sge[1 + RPCRDMA_MAX_INLINE_THRESH / PAGE_SIZE];
- struct page *pages[RPCSVC_MAXPAGES];
-};
-
struct svcxprt_rdma {
struct svc_xprt sc_xprt; /* SVC transport structure */
struct rdma_cm_id *sc_cm_id; /* RDMA connection id */
struct list_head sc_accept_q; /* Conn. waiting accept */
int sc_ord; /* RDMA read limit */
- int sc_max_sge;
+ int sc_max_send_sges;
bool sc_snd_w_inv; /* OK to use Send With Invalidate */
atomic_t sc_sq_avail; /* SQEs ready to be consumed */
unsigned int sc_sq_depth; /* Depth of SQ */
- unsigned int sc_rq_depth; /* Depth of RQ */
__be32 sc_fc_credits; /* Forward credits */
u32 sc_max_requests; /* Max requests */
u32 sc_max_bc_requests;/* Backward credits */
@@ -109,9 +89,8 @@ struct svcxprt_rdma {
struct ib_pd *sc_pd;
- spinlock_t sc_ctxt_lock;
- struct list_head sc_ctxts;
- int sc_ctxt_used;
+ spinlock_t sc_send_lock;
+ struct list_head sc_send_ctxts;
spinlock_t sc_rw_ctxt_lock;
struct list_head sc_rw_ctxts;
@@ -127,6 +106,9 @@ struct svcxprt_rdma {
unsigned long sc_flags;
struct list_head sc_read_complete_q;
struct work_struct sc_work;
+
+ spinlock_t sc_recv_lock;
+ struct list_head sc_recv_ctxts;
};
/* sc_flags */
#define RDMAXPRT_CONN_PENDING 3
@@ -141,12 +123,30 @@ struct svcxprt_rdma {
#define RPCSVC_MAXPAYLOAD_RDMA RPCSVC_MAXPAYLOAD
-/* Track DMA maps for this transport and context */
-static inline void svc_rdma_count_mappings(struct svcxprt_rdma *rdma,
- struct svc_rdma_op_ctxt *ctxt)
-{
- ctxt->mapped_sges++;
-}
+struct svc_rdma_recv_ctxt {
+ struct list_head rc_list;
+ struct ib_recv_wr rc_recv_wr;
+ struct ib_cqe rc_cqe;
+ struct ib_sge rc_recv_sge;
+ void *rc_recv_buf;
+ struct xdr_buf rc_arg;
+ bool rc_temp;
+ u32 rc_byte_len;
+ unsigned int rc_page_count;
+ unsigned int rc_hdr_count;
+ struct page *rc_pages[RPCSVC_MAXPAGES];
+};
+
+struct svc_rdma_send_ctxt {
+ struct list_head sc_list;
+ struct ib_send_wr sc_send_wr;
+ struct ib_cqe sc_cqe;
+ void *sc_xprt_buf;
+ int sc_page_count;
+ int sc_cur_sge_no;
+ struct page *sc_pages[RPCSVC_MAXPAGES];
+ struct ib_sge sc_sges[];
+};
/* svc_rdma_backchannel.c */
extern int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt,
@@ -154,13 +154,18 @@ extern int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt,
struct xdr_buf *rcvbuf);
/* svc_rdma_recvfrom.c */
+extern void svc_rdma_recv_ctxts_destroy(struct svcxprt_rdma *rdma);
+extern bool svc_rdma_post_recvs(struct svcxprt_rdma *rdma);
+extern void svc_rdma_recv_ctxt_put(struct svcxprt_rdma *rdma,
+ struct svc_rdma_recv_ctxt *ctxt);
+extern void svc_rdma_flush_recv_queues(struct svcxprt_rdma *rdma);
extern int svc_rdma_recvfrom(struct svc_rqst *);
/* svc_rdma_rw.c */
extern void svc_rdma_destroy_rw_ctxts(struct svcxprt_rdma *rdma);
extern int svc_rdma_recv_read_chunk(struct svcxprt_rdma *rdma,
struct svc_rqst *rqstp,
- struct svc_rdma_op_ctxt *head, __be32 *p);
+ struct svc_rdma_recv_ctxt *head, __be32 *p);
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,
@@ -168,24 +173,22 @@ extern int svc_rdma_send_reply_chunk(struct svcxprt_rdma *rdma,
struct xdr_buf *xdr);
/* svc_rdma_sendto.c */
-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 void svc_rdma_send_ctxts_destroy(struct svcxprt_rdma *rdma);
+extern struct svc_rdma_send_ctxt *
+ svc_rdma_send_ctxt_get(struct svcxprt_rdma *rdma);
+extern void svc_rdma_send_ctxt_put(struct svcxprt_rdma *rdma,
+ struct svc_rdma_send_ctxt *ctxt);
+extern int svc_rdma_send(struct svcxprt_rdma *rdma, struct ib_send_wr *wr);
+extern void svc_rdma_sync_reply_hdr(struct svcxprt_rdma *rdma,
+ struct svc_rdma_send_ctxt *ctxt,
+ unsigned int len);
+extern int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
+ struct svc_rdma_send_ctxt *ctxt,
+ struct xdr_buf *xdr, __be32 *wr_lst);
extern int svc_rdma_sendto(struct svc_rqst *);
/* svc_rdma_transport.c */
-extern void svc_rdma_wc_send(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 *);
-extern int svc_rdma_send(struct svcxprt_rdma *, struct ib_send_wr *);
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 void svc_sq_reap(struct svcxprt_rdma *);
extern void svc_rq_reap(struct svcxprt_rdma *);
extern void svc_rdma_prep_reply_hdr(struct svc_rqst *);
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
index 5fea0fb..336fd1a 100644
--- a/include/linux/sunrpc/xprt.h
+++ b/include/linux/sunrpc/xprt.h
@@ -84,7 +84,6 @@ struct rpc_rqst {
void (*rq_release_snd_buf)(struct rpc_rqst *); /* release rq_enc_pages */
struct list_head rq_list;
- void *rq_xprtdata; /* Per-xprt private data */
void *rq_buffer; /* Call XDR encode buffer */
size_t rq_callsize;
void *rq_rbuffer; /* Reply XDR decode buffer */
@@ -127,6 +126,8 @@ struct rpc_xprt_ops {
int (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
void (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task);
+ void (*free_slot)(struct rpc_xprt *xprt,
+ struct rpc_rqst *req);
void (*rpcbind)(struct rpc_task *task);
void (*set_port)(struct rpc_xprt *xprt, unsigned short port);
void (*connect)(struct rpc_xprt *xprt, struct rpc_task *task);
@@ -324,10 +325,13 @@ struct xprt_class {
struct rpc_xprt *xprt_create_transport(struct xprt_create *args);
void xprt_connect(struct rpc_task *task);
void xprt_reserve(struct rpc_task *task);
+void xprt_request_init(struct rpc_task *task);
void xprt_retry_reserve(struct rpc_task *task);
int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
+void xprt_free_slot(struct rpc_xprt *xprt,
+ struct rpc_rqst *req);
void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
bool xprt_prepare_transmit(struct rpc_task *task);
void xprt_transmit(struct rpc_task *task);
diff --git a/include/linux/sunrpc/xprtrdma.h b/include/linux/sunrpc/xprtrdma.h
index 5859563..86fc38f 100644
--- a/include/linux/sunrpc/xprtrdma.h
+++ b/include/linux/sunrpc/xprtrdma.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
*
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 7834be6..5f4705f 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -1,25 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
* thermal.h ($Revision: 0 $)
*
* Copyright (C) 2008 Intel Corp
* Copyright (C) 2008 Zhang Rui <rui.zhang@intel.com>
* Copyright (C) 2008 Sujith Thomas <sujith.thomas@intel.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.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- *
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
#ifndef __THERMAL_H__
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index cf2862b..8d8821b 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -60,6 +60,15 @@ static inline void clear_ti_thread_flag(struct thread_info *ti, int flag)
clear_bit(flag, (unsigned long *)&ti->flags);
}
+static inline void update_ti_thread_flag(struct thread_info *ti, int flag,
+ bool value)
+{
+ if (value)
+ set_ti_thread_flag(ti, flag);
+ else
+ clear_ti_thread_flag(ti, flag);
+}
+
static inline int test_and_set_ti_thread_flag(struct thread_info *ti, int flag)
{
return test_and_set_bit(flag, (unsigned long *)&ti->flags);
@@ -79,6 +88,8 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
set_ti_thread_flag(current_thread_info(), flag)
#define clear_thread_flag(flag) \
clear_ti_thread_flag(current_thread_info(), flag)
+#define update_thread_flag(flag, value) \
+ update_ti_thread_flag(current_thread_info(), flag, value)
#define test_and_set_thread_flag(flag) \
test_and_set_ti_thread_flag(current_thread_info(), flag)
#define test_and_clear_thread_flag(flag) \
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index c94f466d..19a690b 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -4,7 +4,7 @@
/*
* Kernel Tracepoint API.
*
- * See Documentation/trace/tracepoints.txt.
+ * See Documentation/trace/tracepoints.rst.
*
* Copyright (C) 2008-2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*
diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index f144216..9397628 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -58,7 +58,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
struct virtio_net_hdr *hdr,
bool little_endian,
- bool has_data_valid)
+ bool has_data_valid,
+ int vlan_hlen)
{
memset(hdr, 0, sizeof(*hdr)); /* no info leak */
@@ -83,12 +84,8 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
if (skb->ip_summed == CHECKSUM_PARTIAL) {
hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
- if (skb_vlan_tag_present(skb))
- hdr->csum_start = __cpu_to_virtio16(little_endian,
- skb_checksum_start_offset(skb) + VLAN_HLEN);
- else
- hdr->csum_start = __cpu_to_virtio16(little_endian,
- skb_checksum_start_offset(skb));
+ hdr->csum_start = __cpu_to_virtio16(little_endian,
+ skb_checksum_start_offset(skb) + vlan_hlen);
hdr->csum_offset = __cpu_to_virtio16(little_endian,
skb->csum_offset);
} else if (has_data_valid &&
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
index bbf3252..fab0213 100644
--- a/include/linux/virtio_ring.h
+++ b/include/linux/virtio_ring.h
@@ -35,7 +35,7 @@ static inline void virtio_rmb(bool weak_barriers)
if (weak_barriers)
virt_rmb();
else
- rmb();
+ dma_rmb();
}
static inline void virtio_wmb(bool weak_barriers)
@@ -43,7 +43,7 @@ static inline void virtio_wmb(bool weak_barriers)
if (weak_barriers)
virt_wmb();
else
- wmb();
+ dma_wmb();
}
static inline void virtio_store_mb(bool weak_barriers,
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 5cba71d..71b9043 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -170,6 +170,7 @@ struct fib6_info {
unused:3;
struct fib6_nh fib6_nh;
+ struct rcu_head rcu;
};
struct rt6_info {
@@ -273,7 +274,7 @@ static inline void ip6_rt_put(struct rt6_info *rt)
}
struct fib6_info *fib6_info_alloc(gfp_t gfp_flags);
-void fib6_info_destroy(struct fib6_info *f6i);
+void fib6_info_destroy_rcu(struct rcu_head *head);
static inline void fib6_info_hold(struct fib6_info *f6i)
{
@@ -283,7 +284,7 @@ static inline void fib6_info_hold(struct fib6_info *f6i)
static inline void fib6_info_release(struct fib6_info *f6i)
{
if (f6i && atomic_dec_and_test(&f6i->fib6_ref))
- fib6_info_destroy(f6i);
+ call_rcu(&f6i->rcu, fib6_info_destroy_rcu);
}
enum fib6_walk_state {
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 6d6e21d..a0bec23 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -631,6 +631,7 @@ struct ip_vs_service {
/* alternate persistence engine */
struct ip_vs_pe __rcu *pe;
+ int conntrack_afmask;
struct rcu_head rcu_head;
};
@@ -1611,6 +1612,35 @@ static inline bool ip_vs_conn_uses_conntrack(struct ip_vs_conn *cp,
return false;
}
+static inline int ip_vs_register_conntrack(struct ip_vs_service *svc)
+{
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ int afmask = (svc->af == AF_INET6) ? 2 : 1;
+ int ret = 0;
+
+ if (!(svc->conntrack_afmask & afmask)) {
+ ret = nf_ct_netns_get(svc->ipvs->net, svc->af);
+ if (ret >= 0)
+ svc->conntrack_afmask |= afmask;
+ }
+ return ret;
+#else
+ return 0;
+#endif
+}
+
+static inline void ip_vs_unregister_conntrack(struct ip_vs_service *svc)
+{
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
+ int afmask = (svc->af == AF_INET6) ? 2 : 1;
+
+ if (svc->conntrack_afmask & afmask) {
+ nf_ct_netns_put(svc->ipvs->net, svc->af);
+ svc->conntrack_afmask &= ~afmask;
+ }
+#endif
+}
+
static inline int
ip_vs_dest_conn_overhead(struct ip_vs_dest *dest)
{
diff --git a/include/net/netfilter/nf_conntrack_count.h b/include/net/netfilter/nf_conntrack_count.h
index 1910b65..3a188a0 100644
--- a/include/net/netfilter/nf_conntrack_count.h
+++ b/include/net/netfilter/nf_conntrack_count.h
@@ -20,7 +20,8 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
bool *addit);
bool nf_conncount_add(struct hlist_head *head,
- const struct nf_conntrack_tuple *tuple);
+ const struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_zone *zone);
void nf_conncount_cache_free(struct hlist_head *hhead);
diff --git a/include/net/netfilter/nft_dup.h b/include/net/netfilter/nft_dup.h
deleted file mode 100644
index 4d9d512..0000000
--- a/include/net/netfilter/nft_dup.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _NFT_DUP_H_
-#define _NFT_DUP_H_
-
-struct nft_dup_inet {
- enum nft_registers sreg_addr:8;
- enum nft_registers sreg_dev:8;
-};
-
-#endif /* _NFT_DUP_H_ */
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index ebf809e..dbe1b91 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1133,6 +1133,11 @@ struct sctp_input_cb {
};
#define SCTP_INPUT_CB(__skb) ((struct sctp_input_cb *)&((__skb)->cb[0]))
+struct sctp_output_cb {
+ struct sk_buff *last;
+};
+#define SCTP_OUTPUT_CB(__skb) ((struct sctp_output_cb *)&((__skb)->cb[0]))
+
static inline const struct sk_buff *sctp_gso_headskb(const struct sk_buff *skb)
{
const struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk;
diff --git a/include/net/tls.h b/include/net/tls.h
index 70c2737..7f84ea3 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -109,8 +109,7 @@ struct tls_sw_context_rx {
struct strparser strp;
void (*saved_data_ready)(struct sock *sk);
- unsigned int (*sk_poll)(struct file *file, struct socket *sock,
- struct poll_table_struct *wait);
+ __poll_t (*sk_poll_mask)(struct socket *sock, __poll_t events);
struct sk_buff *recv_pkt;
u8 control;
bool decrypted;
@@ -225,8 +224,7 @@ void tls_sw_free_resources_tx(struct sock *sk);
void tls_sw_free_resources_rx(struct sock *sk);
int tls_sw_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
int nonblock, int flags, int *addr_len);
-unsigned int tls_sw_poll(struct file *file, struct socket *sock,
- struct poll_table_struct *wait);
+__poll_t tls_sw_poll_mask(struct socket *sock, __poll_t events);
ssize_t tls_sw_splice_read(struct socket *sock, loff_t *ppos,
struct pipe_inode_info *pipe,
size_t len, unsigned int flags);
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h
index c4f5caa..f6a3543 100644
--- a/include/net/transp_v6.h
+++ b/include/net/transp_v6.h
@@ -45,8 +45,15 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg,
struct flowi6 *fl6, struct ipcm6_cookie *ipc6,
struct sockcm_cookie *sockc);
-void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
- __u16 srcp, __u16 destp, int bucket);
+void __ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
+ __u16 srcp, __u16 destp, int rqueue, int bucket);
+static inline void
+ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp, __u16 srcp,
+ __u16 destp, int bucket)
+{
+ __ip6_dgram_sock_seq_show(seq, sp, srcp, destp, sk_rmem_alloc_get(sp),
+ bucket);
+}
#define LOOPBACK4_IPV6 cpu_to_be32(0x7f000006)
diff --git a/include/net/udp.h b/include/net/udp.h
index 7ba0ed2..b1ea8b0 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -247,6 +247,11 @@ static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb,
return htons((((u64) hash * (max - min)) >> 32) + min);
}
+static inline int udp_rqueue_get(struct sock *sk)
+{
+ return sk_rmem_alloc_get(sk) - READ_ONCE(udp_sk(sk)->forward_deficit);
+}
+
/* net/ipv4/udp.c */
void udp_destruct_sock(struct sock *sk);
void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len);
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 2043e1a..6c00399 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -2093,10 +2093,7 @@ struct ib_flow_attr {
u32 flags;
u8 num_of_specs;
u8 port;
- /* Following are the optional layers according to user request
- * struct ib_flow_spec_xxx
- * struct ib_flow_spec_yyy
- */
+ union ib_flow_spec flows[];
};
struct ib_flow {
@@ -3394,11 +3391,14 @@ int ib_process_cq_direct(struct ib_cq *cq, int budget);
*
* Users can examine the cq structure to determine the actual CQ size.
*/
-struct ib_cq *ib_create_cq(struct ib_device *device,
- ib_comp_handler comp_handler,
- void (*event_handler)(struct ib_event *, void *),
- void *cq_context,
- const struct ib_cq_init_attr *cq_attr);
+struct ib_cq *__ib_create_cq(struct ib_device *device,
+ ib_comp_handler comp_handler,
+ void (*event_handler)(struct ib_event *, void *),
+ void *cq_context,
+ const struct ib_cq_init_attr *cq_attr,
+ const char *caller);
+#define ib_create_cq(device, cmp_hndlr, evt_hndlr, cq_ctxt, cq_attr) \
+ __ib_create_cq((device), (cmp_hndlr), (evt_hndlr), (cq_ctxt), (cq_attr), KBUILD_MODNAME)
/**
* ib_resize_cq - Modifies the capacity of the CQ.
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 7ae177c..4c36af6 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -15,7 +15,7 @@ struct scsi_cmnd;
struct scsi_lun;
struct scsi_sense_hdr;
-typedef unsigned int __bitwise blist_flags_t;
+typedef __u64 __bitwise blist_flags_t;
struct scsi_mode_data {
__u32 length;
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
index ea67c32..3fdb322 100644
--- a/include/scsi/scsi_devinfo.h
+++ b/include/scsi/scsi_devinfo.h
@@ -6,55 +6,80 @@
*/
/* Only scan LUN 0 */
-#define BLIST_NOLUN ((__force blist_flags_t)(1 << 0))
+#define BLIST_NOLUN ((__force blist_flags_t)(1ULL << 0))
/* Known to have LUNs, force scanning.
* DEPRECATED: Use max_luns=N */
-#define BLIST_FORCELUN ((__force blist_flags_t)(1 << 1))
+#define BLIST_FORCELUN ((__force blist_flags_t)(1ULL << 1))
/* Flag for broken handshaking */
-#define BLIST_BORKEN ((__force blist_flags_t)(1 << 2))
+#define BLIST_BORKEN ((__force blist_flags_t)(1ULL << 2))
/* unlock by special command */
-#define BLIST_KEY ((__force blist_flags_t)(1 << 3))
+#define BLIST_KEY ((__force blist_flags_t)(1ULL << 3))
/* Do not use LUNs in parallel */
-#define BLIST_SINGLELUN ((__force blist_flags_t)(1 << 4))
+#define BLIST_SINGLELUN ((__force blist_flags_t)(1ULL << 4))
/* Buggy Tagged Command Queuing */
-#define BLIST_NOTQ ((__force blist_flags_t)(1 << 5))
+#define BLIST_NOTQ ((__force blist_flags_t)(1ULL << 5))
/* Non consecutive LUN numbering */
-#define BLIST_SPARSELUN ((__force blist_flags_t)(1 << 6))
+#define BLIST_SPARSELUN ((__force blist_flags_t)(1ULL << 6))
/* Avoid LUNS >= 5 */
-#define BLIST_MAX5LUN ((__force blist_flags_t)(1 << 7))
+#define BLIST_MAX5LUN ((__force blist_flags_t)(1ULL << 7))
/* Treat as (removable) CD-ROM */
-#define BLIST_ISROM ((__force blist_flags_t)(1 << 8))
+#define BLIST_ISROM ((__force blist_flags_t)(1ULL << 8))
/* LUNs past 7 on a SCSI-2 device */
-#define BLIST_LARGELUN ((__force blist_flags_t)(1 << 9))
+#define BLIST_LARGELUN ((__force blist_flags_t)(1ULL << 9))
/* override additional length field */
-#define BLIST_INQUIRY_36 ((__force blist_flags_t)(1 << 10))
+#define BLIST_INQUIRY_36 ((__force blist_flags_t)(1ULL << 10))
+#define __BLIST_UNUSED_11 ((__force blist_flags_t)(1ULL << 11))
/* do not do automatic start on add */
-#define BLIST_NOSTARTONADD ((__force blist_flags_t)(1 << 12))
+#define BLIST_NOSTARTONADD ((__force blist_flags_t)(1ULL << 12))
+#define __BLIST_UNUSED_13 ((__force blist_flags_t)(1ULL << 13))
+#define __BLIST_UNUSED_14 ((__force blist_flags_t)(1ULL << 14))
+#define __BLIST_UNUSED_15 ((__force blist_flags_t)(1ULL << 15))
+#define __BLIST_UNUSED_16 ((__force blist_flags_t)(1ULL << 16))
/* try REPORT_LUNS even for SCSI-2 devs (if HBA supports more than 8 LUNs) */
-#define BLIST_REPORTLUN2 ((__force blist_flags_t)(1 << 17))
+#define BLIST_REPORTLUN2 ((__force blist_flags_t)(1ULL << 17))
/* don't try REPORT_LUNS scan (SCSI-3 devs) */
-#define BLIST_NOREPORTLUN ((__force blist_flags_t)(1 << 18))
+#define BLIST_NOREPORTLUN ((__force blist_flags_t)(1ULL << 18))
/* don't use PREVENT-ALLOW commands */
-#define BLIST_NOT_LOCKABLE ((__force blist_flags_t)(1 << 19))
+#define BLIST_NOT_LOCKABLE ((__force blist_flags_t)(1ULL << 19))
/* device is actually for RAID config */
-#define BLIST_NO_ULD_ATTACH ((__force blist_flags_t)(1 << 20))
+#define BLIST_NO_ULD_ATTACH ((__force blist_flags_t)(1ULL << 20))
/* select without ATN */
-#define BLIST_SELECT_NO_ATN ((__force blist_flags_t)(1 << 21))
+#define BLIST_SELECT_NO_ATN ((__force blist_flags_t)(1ULL << 21))
/* retry HARDWARE_ERROR */
-#define BLIST_RETRY_HWERROR ((__force blist_flags_t)(1 << 22))
+#define BLIST_RETRY_HWERROR ((__force blist_flags_t)(1ULL << 22))
/* maximum 512 sector cdb length */
-#define BLIST_MAX_512 ((__force blist_flags_t)(1 << 23))
+#define BLIST_MAX_512 ((__force blist_flags_t)(1ULL << 23))
+#define __BLIST_UNUSED_24 ((__force blist_flags_t)(1ULL << 24))
/* Disable T10 PI (DIF) */
-#define BLIST_NO_DIF ((__force blist_flags_t)(1 << 25))
+#define BLIST_NO_DIF ((__force blist_flags_t)(1ULL << 25))
/* Ignore SBC-3 VPD pages */
-#define BLIST_SKIP_VPD_PAGES ((__force blist_flags_t)(1 << 26))
+#define BLIST_SKIP_VPD_PAGES ((__force blist_flags_t)(1ULL << 26))
+#define __BLIST_UNUSED_27 ((__force blist_flags_t)(1ULL << 27))
/* Attempt to read VPD pages */
-#define BLIST_TRY_VPD_PAGES ((__force blist_flags_t)(1 << 28))
+#define BLIST_TRY_VPD_PAGES ((__force blist_flags_t)(1ULL << 28))
/* don't try to issue RSOC */
-#define BLIST_NO_RSOC ((__force blist_flags_t)(1 << 29))
+#define BLIST_NO_RSOC ((__force blist_flags_t)(1ULL << 29))
/* maximum 1024 sector cdb length */
-#define BLIST_MAX_1024 ((__force blist_flags_t)(1 << 30))
+#define BLIST_MAX_1024 ((__force blist_flags_t)(1ULL << 30))
/* Use UNMAP limit for WRITE SAME */
-#define BLIST_UNMAP_LIMIT_WS ((__force blist_flags_t)(1 << 31))
+#define BLIST_UNMAP_LIMIT_WS ((__force blist_flags_t)(1ULL << 31))
+/* Always retry ABORTED_COMMAND with Internal Target Failure */
+#define BLIST_RETRY_ITF ((__force blist_flags_t)(1ULL << 32))
+/* Always retry ABORTED_COMMAND with ASC 0xc1 */
+#define BLIST_RETRY_ASC_C1 ((__force blist_flags_t)(1ULL << 33))
+
+#define __BLIST_LAST_USED BLIST_RETRY_ASC_C1
+
+#define __BLIST_HIGH_UNUSED (~(__BLIST_LAST_USED | \
+ (__force blist_flags_t) \
+ ((__force __u64)__BLIST_LAST_USED - 1ULL)))
+#define __BLIST_UNUSED_MASK (__BLIST_UNUSED_11 | \
+ __BLIST_UNUSED_13 | \
+ __BLIST_UNUSED_14 | \
+ __BLIST_UNUSED_15 | \
+ __BLIST_UNUSED_16 | \
+ __BLIST_UNUSED_24 | \
+ __BLIST_UNUSED_27 | \
+ __BLIST_HIGH_UNUSED)
#endif
diff --git a/include/soc/qcom/cmd-db.h b/include/soc/qcom/cmd-db.h
new file mode 100644
index 0000000..578180c
--- /dev/null
+++ b/include/soc/qcom/cmd-db.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. */
+
+#ifndef __QCOM_COMMAND_DB_H__
+#define __QCOM_COMMAND_DB_H__
+
+
+enum cmd_db_hw_type {
+ CMD_DB_HW_INVALID = 0,
+ CMD_DB_HW_MIN = 3,
+ CMD_DB_HW_ARC = CMD_DB_HW_MIN,
+ CMD_DB_HW_VRM = 4,
+ CMD_DB_HW_BCM = 5,
+ CMD_DB_HW_MAX = CMD_DB_HW_BCM,
+ CMD_DB_HW_ALL = 0xff,
+};
+
+#if IS_ENABLED(CONFIG_QCOM_COMMAND_DB)
+u32 cmd_db_read_addr(const char *resource_id);
+
+int cmd_db_read_aux_data(const char *resource_id, u8 *data, size_t len);
+
+size_t cmd_db_read_aux_data_len(const char *resource_id);
+
+enum cmd_db_hw_type cmd_db_read_slave_id(const char *resource_id);
+
+int cmd_db_ready(void);
+#else
+static inline u32 cmd_db_read_addr(const char *resource_id)
+{ return 0; }
+
+static inline int cmd_db_read_aux_data(const char *resource_id, u8 *data,
+ size_t len)
+{ return -ENODEV; }
+
+static inline size_t cmd_db_read_aux_data_len(const char *resource_id)
+{ return -ENODEV; }
+
+static inline enum cmd_db_hw_type cmd_db_read_slave_id(const char *resource_id)
+{ return -ENODEV; }
+
+static inline int cmd_db_ready(void)
+{ return -ENODEV; }
+#endif /* CONFIG_QCOM_COMMAND_DB */
+#endif /* __QCOM_COMMAND_DB_H__ */
diff --git a/include/soc/tegra/cpuidle.h b/include/soc/tegra/cpuidle.h
index 1fae9c7..b6cf322 100644
--- a/include/soc/tegra/cpuidle.h
+++ b/include/soc/tegra/cpuidle.h
@@ -14,7 +14,7 @@
#ifndef __SOC_TEGRA_CPUIDLE_H__
#define __SOC_TEGRA_CPUIDLE_H__
-#if defined(CONFIG_ARM) && defined(CONFIG_CPU_IDLE)
+#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_TEGRA) && defined(CONFIG_CPU_IDLE)
void tegra_cpuidle_pcie_irqs_in_use(void);
#else
static inline void tegra_cpuidle_pcie_irqs_in_use(void)
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index 233bae9..b43f37f 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -9,6 +9,7 @@
#ifndef __SOC_TEGRA_MC_H__
#define __SOC_TEGRA_MC_H__
+#include <linux/reset-controller.h>
#include <linux/types.h>
struct clk;
@@ -95,6 +96,30 @@ static inline void tegra_smmu_remove(struct tegra_smmu *smmu)
}
#endif
+struct tegra_mc_reset {
+ const char *name;
+ unsigned long id;
+ unsigned int control;
+ unsigned int status;
+ unsigned int reset;
+ unsigned int bit;
+};
+
+struct tegra_mc_reset_ops {
+ int (*hotreset_assert)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+ int (*hotreset_deassert)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+ int (*block_dma)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+ bool (*dma_idling)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+ int (*unblock_dma)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+ int (*reset_status)(struct tegra_mc *mc,
+ const struct tegra_mc_reset *rst);
+};
+
struct tegra_mc_soc {
const struct tegra_mc_client *clients;
unsigned int num_clients;
@@ -108,12 +133,18 @@ struct tegra_mc_soc {
u8 client_id_mask;
const struct tegra_smmu_soc *smmu;
+
+ u32 intmask;
+
+ const struct tegra_mc_reset_ops *reset_ops;
+ const struct tegra_mc_reset *resets;
+ unsigned int num_resets;
};
struct tegra_mc {
struct device *dev;
struct tegra_smmu *smmu;
- void __iomem *regs;
+ void __iomem *regs, *regs2;
struct clk *clk;
int irq;
@@ -122,6 +153,10 @@ struct tegra_mc {
struct tegra_mc_timing *timings;
unsigned int num_timings;
+
+ struct reset_controller_dev reset;
+
+ spinlock_t lock;
};
void tegra_mc_write_emem_configuration(struct tegra_mc *mc, unsigned long rate);
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 9f9f590..922a39f 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -143,6 +143,7 @@ enum se_cmd_flags_table {
SCF_ACK_KREF = 0x00400000,
SCF_USE_CPUID = 0x00800000,
SCF_TASK_ATTR_SET = 0x01000000,
+ SCF_TREAT_READ_AS_NORMAL = 0x02000000,
};
/*
diff --git a/include/trace/events/rpcrdma.h b/include/trace/events/rpcrdma.h
index 50ed3f8..53df203 100644
--- a/include/trace/events/rpcrdma.h
+++ b/include/trace/events/rpcrdma.h
@@ -1,6 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Copyright (c) 2017 Oracle. All rights reserved.
+ * Copyright (c) 2017, 2018 Oracle. All rights reserved.
+ *
+ * Trace point definitions for the "rpcrdma" subsystem.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM rpcrdma
@@ -528,24 +530,54 @@ TRACE_EVENT(xprtrdma_post_send,
TRACE_EVENT(xprtrdma_post_recv,
TP_PROTO(
- const struct rpcrdma_rep *rep,
+ const struct ib_cqe *cqe
+ ),
+
+ TP_ARGS(cqe),
+
+ TP_STRUCT__entry(
+ __field(const void *, cqe)
+ ),
+
+ TP_fast_assign(
+ __entry->cqe = cqe;
+ ),
+
+ TP_printk("cqe=%p",
+ __entry->cqe
+ )
+);
+
+TRACE_EVENT(xprtrdma_post_recvs,
+ TP_PROTO(
+ const struct rpcrdma_xprt *r_xprt,
+ unsigned int count,
int status
),
- TP_ARGS(rep, status),
+ TP_ARGS(r_xprt, count, status),
TP_STRUCT__entry(
- __field(const void *, rep)
+ __field(const void *, r_xprt)
+ __field(unsigned int, count)
__field(int, status)
+ __field(int, posted)
+ __string(addr, rpcrdma_addrstr(r_xprt))
+ __string(port, rpcrdma_portstr(r_xprt))
),
TP_fast_assign(
- __entry->rep = rep;
+ __entry->r_xprt = r_xprt;
+ __entry->count = count;
__entry->status = status;
+ __entry->posted = r_xprt->rx_buf.rb_posted_receives;
+ __assign_str(addr, rpcrdma_addrstr(r_xprt));
+ __assign_str(port, rpcrdma_portstr(r_xprt));
),
- TP_printk("rep=%p status=%d",
- __entry->rep, __entry->status
+ TP_printk("peer=[%s]:%s r_xprt=%p: %u new recvs, %d active (rc %d)",
+ __get_str(addr), __get_str(port), __entry->r_xprt,
+ __entry->count, __entry->posted, __entry->status
)
);
@@ -584,28 +616,32 @@ TRACE_EVENT(xprtrdma_wc_send,
TRACE_EVENT(xprtrdma_wc_receive,
TP_PROTO(
- const struct rpcrdma_rep *rep,
const struct ib_wc *wc
),
- TP_ARGS(rep, wc),
+ TP_ARGS(wc),
TP_STRUCT__entry(
- __field(const void *, rep)
- __field(unsigned int, byte_len)
+ __field(const void *, cqe)
+ __field(u32, byte_len)
__field(unsigned int, status)
- __field(unsigned int, vendor_err)
+ __field(u32, vendor_err)
),
TP_fast_assign(
- __entry->rep = rep;
- __entry->byte_len = wc->byte_len;
+ __entry->cqe = wc->wr_cqe;
__entry->status = wc->status;
- __entry->vendor_err = __entry->status ? wc->vendor_err : 0;
+ if (wc->status) {
+ __entry->byte_len = 0;
+ __entry->vendor_err = wc->vendor_err;
+ } else {
+ __entry->byte_len = wc->byte_len;
+ __entry->vendor_err = 0;
+ }
),
- TP_printk("rep=%p, %u bytes: %s (%u/0x%x)",
- __entry->rep, __entry->byte_len,
+ TP_printk("cqe=%p %u bytes: %s (%u/0x%x)",
+ __entry->cqe, __entry->byte_len,
rdma_show_wc_status(__entry->status),
__entry->status, __entry->vendor_err
)
@@ -616,6 +652,7 @@ DEFINE_FRWR_DONE_EVENT(xprtrdma_wc_li);
DEFINE_FRWR_DONE_EVENT(xprtrdma_wc_li_wake);
DEFINE_MR_EVENT(xprtrdma_localinv);
+DEFINE_MR_EVENT(xprtrdma_dma_map);
DEFINE_MR_EVENT(xprtrdma_dma_unmap);
DEFINE_MR_EVENT(xprtrdma_remoteinv);
DEFINE_MR_EVENT(xprtrdma_recover_mr);
@@ -799,7 +836,6 @@ TRACE_EVENT(xprtrdma_allocate,
__field(unsigned int, task_id)
__field(unsigned int, client_id)
__field(const void *, req)
- __field(const void *, rep)
__field(size_t, callsize)
__field(size_t, rcvsize)
),
@@ -808,15 +844,13 @@ TRACE_EVENT(xprtrdma_allocate,
__entry->task_id = task->tk_pid;
__entry->client_id = task->tk_client->cl_clid;
__entry->req = req;
- __entry->rep = req ? req->rl_reply : NULL;
__entry->callsize = task->tk_rqstp->rq_callsize;
__entry->rcvsize = task->tk_rqstp->rq_rcvsize;
),
- TP_printk("task:%u@%u req=%p rep=%p (%zu, %zu)",
+ TP_printk("task:%u@%u req=%p (%zu, %zu)",
__entry->task_id, __entry->client_id,
- __entry->req, __entry->rep,
- __entry->callsize, __entry->rcvsize
+ __entry->req, __entry->callsize, __entry->rcvsize
)
);
@@ -848,8 +882,6 @@ TRACE_EVENT(xprtrdma_rpc_done,
)
);
-DEFINE_RXPRT_EVENT(xprtrdma_noreps);
-
/**
** Callback events
**/
@@ -885,6 +917,586 @@ TRACE_EVENT(xprtrdma_cb_setup,
DEFINE_CB_EVENT(xprtrdma_cb_call);
DEFINE_CB_EVENT(xprtrdma_cb_reply);
+/**
+ ** Server-side RPC/RDMA events
+ **/
+
+DECLARE_EVENT_CLASS(svcrdma_xprt_event,
+ TP_PROTO(
+ const struct svc_xprt *xprt
+ ),
+
+ TP_ARGS(xprt),
+
+ TP_STRUCT__entry(
+ __field(const void *, xprt)
+ __string(addr, xprt->xpt_remotebuf)
+ ),
+
+ TP_fast_assign(
+ __entry->xprt = xprt;
+ __assign_str(addr, xprt->xpt_remotebuf);
+ ),
+
+ TP_printk("xprt=%p addr=%s",
+ __entry->xprt, __get_str(addr)
+ )
+);
+
+#define DEFINE_XPRT_EVENT(name) \
+ DEFINE_EVENT(svcrdma_xprt_event, svcrdma_xprt_##name, \
+ TP_PROTO( \
+ const struct svc_xprt *xprt \
+ ), \
+ TP_ARGS(xprt))
+
+DEFINE_XPRT_EVENT(accept);
+DEFINE_XPRT_EVENT(fail);
+DEFINE_XPRT_EVENT(free);
+
+TRACE_DEFINE_ENUM(RDMA_MSG);
+TRACE_DEFINE_ENUM(RDMA_NOMSG);
+TRACE_DEFINE_ENUM(RDMA_MSGP);
+TRACE_DEFINE_ENUM(RDMA_DONE);
+TRACE_DEFINE_ENUM(RDMA_ERROR);
+
+#define show_rpcrdma_proc(x) \
+ __print_symbolic(x, \
+ { RDMA_MSG, "RDMA_MSG" }, \
+ { RDMA_NOMSG, "RDMA_NOMSG" }, \
+ { RDMA_MSGP, "RDMA_MSGP" }, \
+ { RDMA_DONE, "RDMA_DONE" }, \
+ { RDMA_ERROR, "RDMA_ERROR" })
+
+TRACE_EVENT(svcrdma_decode_rqst,
+ TP_PROTO(
+ __be32 *p,
+ unsigned int hdrlen
+ ),
+
+ TP_ARGS(p, hdrlen),
+
+ TP_STRUCT__entry(
+ __field(u32, xid)
+ __field(u32, vers)
+ __field(u32, proc)
+ __field(u32, credits)
+ __field(unsigned int, hdrlen)
+ ),
+
+ TP_fast_assign(
+ __entry->xid = be32_to_cpup(p++);
+ __entry->vers = be32_to_cpup(p++);
+ __entry->credits = be32_to_cpup(p++);
+ __entry->proc = be32_to_cpup(p);
+ __entry->hdrlen = hdrlen;
+ ),
+
+ TP_printk("xid=0x%08x vers=%u credits=%u proc=%s hdrlen=%u",
+ __entry->xid, __entry->vers, __entry->credits,
+ show_rpcrdma_proc(__entry->proc), __entry->hdrlen)
+);
+
+TRACE_EVENT(svcrdma_decode_short,
+ TP_PROTO(
+ unsigned int hdrlen
+ ),
+
+ TP_ARGS(hdrlen),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, hdrlen)
+ ),
+
+ TP_fast_assign(
+ __entry->hdrlen = hdrlen;
+ ),
+
+ TP_printk("hdrlen=%u", __entry->hdrlen)
+);
+
+DECLARE_EVENT_CLASS(svcrdma_badreq_event,
+ TP_PROTO(
+ __be32 *p
+ ),
+
+ TP_ARGS(p),
+
+ TP_STRUCT__entry(
+ __field(u32, xid)
+ __field(u32, vers)
+ __field(u32, proc)
+ __field(u32, credits)
+ ),
+
+ TP_fast_assign(
+ __entry->xid = be32_to_cpup(p++);
+ __entry->vers = be32_to_cpup(p++);
+ __entry->credits = be32_to_cpup(p++);
+ __entry->proc = be32_to_cpup(p);
+ ),
+
+ TP_printk("xid=0x%08x vers=%u credits=%u proc=%u",
+ __entry->xid, __entry->vers, __entry->credits, __entry->proc)
+);
+
+#define DEFINE_BADREQ_EVENT(name) \
+ DEFINE_EVENT(svcrdma_badreq_event, svcrdma_decode_##name,\
+ TP_PROTO( \
+ __be32 *p \
+ ), \
+ TP_ARGS(p))
+
+DEFINE_BADREQ_EVENT(badvers);
+DEFINE_BADREQ_EVENT(drop);
+DEFINE_BADREQ_EVENT(badproc);
+DEFINE_BADREQ_EVENT(parse);
+
+DECLARE_EVENT_CLASS(svcrdma_segment_event,
+ TP_PROTO(
+ u32 handle,
+ u32 length,
+ u64 offset
+ ),
+
+ TP_ARGS(handle, length, offset),
+
+ TP_STRUCT__entry(
+ __field(u32, handle)
+ __field(u32, length)
+ __field(u64, offset)
+ ),
+
+ TP_fast_assign(
+ __entry->handle = handle;
+ __entry->length = length;
+ __entry->offset = offset;
+ ),
+
+ TP_printk("%u@0x%016llx:0x%08x",
+ __entry->length, (unsigned long long)__entry->offset,
+ __entry->handle
+ )
+);
+
+#define DEFINE_SEGMENT_EVENT(name) \
+ DEFINE_EVENT(svcrdma_segment_event, svcrdma_encode_##name,\
+ TP_PROTO( \
+ u32 handle, \
+ u32 length, \
+ u64 offset \
+ ), \
+ TP_ARGS(handle, length, offset))
+
+DEFINE_SEGMENT_EVENT(rseg);
+DEFINE_SEGMENT_EVENT(wseg);
+
+DECLARE_EVENT_CLASS(svcrdma_chunk_event,
+ TP_PROTO(
+ u32 length
+ ),
+
+ TP_ARGS(length),
+
+ TP_STRUCT__entry(
+ __field(u32, length)
+ ),
+
+ TP_fast_assign(
+ __entry->length = length;
+ ),
+
+ TP_printk("length=%u",
+ __entry->length
+ )
+);
+
+#define DEFINE_CHUNK_EVENT(name) \
+ DEFINE_EVENT(svcrdma_chunk_event, svcrdma_encode_##name,\
+ TP_PROTO( \
+ u32 length \
+ ), \
+ TP_ARGS(length))
+
+DEFINE_CHUNK_EVENT(pzr);
+DEFINE_CHUNK_EVENT(write);
+DEFINE_CHUNK_EVENT(reply);
+
+TRACE_EVENT(svcrdma_encode_read,
+ TP_PROTO(
+ u32 length,
+ u32 position
+ ),
+
+ TP_ARGS(length, position),
+
+ TP_STRUCT__entry(
+ __field(u32, length)
+ __field(u32, position)
+ ),
+
+ TP_fast_assign(
+ __entry->length = length;
+ __entry->position = position;
+ ),
+
+ TP_printk("length=%u position=%u",
+ __entry->length, __entry->position
+ )
+);
+
+DECLARE_EVENT_CLASS(svcrdma_error_event,
+ TP_PROTO(
+ __be32 xid
+ ),
+
+ TP_ARGS(xid),
+
+ TP_STRUCT__entry(
+ __field(u32, xid)
+ ),
+
+ TP_fast_assign(
+ __entry->xid = be32_to_cpu(xid);
+ ),
+
+ TP_printk("xid=0x%08x",
+ __entry->xid
+ )
+);
+
+#define DEFINE_ERROR_EVENT(name) \
+ DEFINE_EVENT(svcrdma_error_event, svcrdma_err_##name, \
+ TP_PROTO( \
+ __be32 xid \
+ ), \
+ TP_ARGS(xid))
+
+DEFINE_ERROR_EVENT(vers);
+DEFINE_ERROR_EVENT(chunk);
+
+/**
+ ** Server-side RDMA API events
+ **/
+
+TRACE_EVENT(svcrdma_dma_map_page,
+ TP_PROTO(
+ const struct svcxprt_rdma *rdma,
+ const void *page
+ ),
+
+ TP_ARGS(rdma, page),
+
+ TP_STRUCT__entry(
+ __field(const void *, page);
+ __string(device, rdma->sc_cm_id->device->name)
+ __string(addr, rdma->sc_xprt.xpt_remotebuf)
+ ),
+
+ TP_fast_assign(
+ __entry->page = page;
+ __assign_str(device, rdma->sc_cm_id->device->name);
+ __assign_str(addr, rdma->sc_xprt.xpt_remotebuf);
+ ),
+
+ TP_printk("addr=%s device=%s page=%p",
+ __get_str(addr), __get_str(device), __entry->page
+ )
+);
+
+TRACE_EVENT(svcrdma_dma_map_rwctx,
+ TP_PROTO(
+ const struct svcxprt_rdma *rdma,
+ int status
+ ),
+
+ TP_ARGS(rdma, status),
+
+ TP_STRUCT__entry(
+ __field(int, status)
+ __string(device, rdma->sc_cm_id->device->name)
+ __string(addr, rdma->sc_xprt.xpt_remotebuf)
+ ),
+
+ TP_fast_assign(
+ __entry->status = status;
+ __assign_str(device, rdma->sc_cm_id->device->name);
+ __assign_str(addr, rdma->sc_xprt.xpt_remotebuf);
+ ),
+
+ TP_printk("addr=%s device=%s status=%d",
+ __get_str(addr), __get_str(device), __entry->status
+ )
+);
+
+TRACE_EVENT(svcrdma_send_failed,
+ TP_PROTO(
+ const struct svc_rqst *rqst,
+ int status
+ ),
+
+ TP_ARGS(rqst, status),
+
+ TP_STRUCT__entry(
+ __field(int, status)
+ __field(u32, xid)
+ __field(const void *, xprt)
+ __string(addr, rqst->rq_xprt->xpt_remotebuf)
+ ),
+
+ TP_fast_assign(
+ __entry->status = status;
+ __entry->xid = __be32_to_cpu(rqst->rq_xid);
+ __entry->xprt = rqst->rq_xprt;
+ __assign_str(addr, rqst->rq_xprt->xpt_remotebuf);
+ ),
+
+ TP_printk("xprt=%p addr=%s xid=0x%08x status=%d",
+ __entry->xprt, __get_str(addr),
+ __entry->xid, __entry->status
+ )
+);
+
+DECLARE_EVENT_CLASS(svcrdma_sendcomp_event,
+ TP_PROTO(
+ const struct ib_wc *wc
+ ),
+
+ TP_ARGS(wc),
+
+ TP_STRUCT__entry(
+ __field(const void *, cqe)
+ __field(unsigned int, status)
+ __field(unsigned int, vendor_err)
+ ),
+
+ TP_fast_assign(
+ __entry->cqe = wc->wr_cqe;
+ __entry->status = wc->status;
+ if (wc->status)
+ __entry->vendor_err = wc->vendor_err;
+ else
+ __entry->vendor_err = 0;
+ ),
+
+ TP_printk("cqe=%p status=%s (%u/0x%x)",
+ __entry->cqe, rdma_show_wc_status(__entry->status),
+ __entry->status, __entry->vendor_err
+ )
+);
+
+#define DEFINE_SENDCOMP_EVENT(name) \
+ DEFINE_EVENT(svcrdma_sendcomp_event, svcrdma_wc_##name, \
+ TP_PROTO( \
+ const struct ib_wc *wc \
+ ), \
+ TP_ARGS(wc))
+
+TRACE_EVENT(svcrdma_post_send,
+ TP_PROTO(
+ const struct ib_send_wr *wr,
+ int status
+ ),
+
+ TP_ARGS(wr, status),
+
+ TP_STRUCT__entry(
+ __field(const void *, cqe)
+ __field(unsigned int, num_sge)
+ __field(u32, inv_rkey)
+ __field(int, status)
+ ),
+
+ TP_fast_assign(
+ __entry->cqe = wr->wr_cqe;
+ __entry->num_sge = wr->num_sge;
+ __entry->inv_rkey = (wr->opcode == IB_WR_SEND_WITH_INV) ?
+ wr->ex.invalidate_rkey : 0;
+ __entry->status = status;
+ ),
+
+ TP_printk("cqe=%p num_sge=%u inv_rkey=0x%08x status=%d",
+ __entry->cqe, __entry->num_sge,
+ __entry->inv_rkey, __entry->status
+ )
+);
+
+DEFINE_SENDCOMP_EVENT(send);
+
+TRACE_EVENT(svcrdma_post_recv,
+ TP_PROTO(
+ const struct ib_recv_wr *wr,
+ int status
+ ),
+
+ TP_ARGS(wr, status),
+
+ TP_STRUCT__entry(
+ __field(const void *, cqe)
+ __field(int, status)
+ ),
+
+ TP_fast_assign(
+ __entry->cqe = wr->wr_cqe;
+ __entry->status = status;
+ ),
+
+ TP_printk("cqe=%p status=%d",
+ __entry->cqe, __entry->status
+ )
+);
+
+TRACE_EVENT(svcrdma_wc_receive,
+ TP_PROTO(
+ const struct ib_wc *wc
+ ),
+
+ TP_ARGS(wc),
+
+ TP_STRUCT__entry(
+ __field(const void *, cqe)
+ __field(u32, byte_len)
+ __field(unsigned int, status)
+ __field(u32, vendor_err)
+ ),
+
+ TP_fast_assign(
+ __entry->cqe = wc->wr_cqe;
+ __entry->status = wc->status;
+ if (wc->status) {
+ __entry->byte_len = 0;
+ __entry->vendor_err = wc->vendor_err;
+ } else {
+ __entry->byte_len = wc->byte_len;
+ __entry->vendor_err = 0;
+ }
+ ),
+
+ TP_printk("cqe=%p byte_len=%u status=%s (%u/0x%x)",
+ __entry->cqe, __entry->byte_len,
+ rdma_show_wc_status(__entry->status),
+ __entry->status, __entry->vendor_err
+ )
+);
+
+TRACE_EVENT(svcrdma_post_rw,
+ TP_PROTO(
+ const void *cqe,
+ int sqecount,
+ int status
+ ),
+
+ TP_ARGS(cqe, sqecount, status),
+
+ TP_STRUCT__entry(
+ __field(const void *, cqe)
+ __field(int, sqecount)
+ __field(int, status)
+ ),
+
+ TP_fast_assign(
+ __entry->cqe = cqe;
+ __entry->sqecount = sqecount;
+ __entry->status = status;
+ ),
+
+ TP_printk("cqe=%p sqecount=%d status=%d",
+ __entry->cqe, __entry->sqecount, __entry->status
+ )
+);
+
+DEFINE_SENDCOMP_EVENT(read);
+DEFINE_SENDCOMP_EVENT(write);
+
+TRACE_EVENT(svcrdma_cm_event,
+ TP_PROTO(
+ const struct rdma_cm_event *event,
+ const struct sockaddr *sap
+ ),
+
+ TP_ARGS(event, sap),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, event)
+ __field(int, status)
+ __array(__u8, addr, INET6_ADDRSTRLEN + 10)
+ ),
+
+ TP_fast_assign(
+ __entry->event = event->event;
+ __entry->status = event->status;
+ snprintf(__entry->addr, sizeof(__entry->addr) - 1,
+ "%pISpc", sap);
+ ),
+
+ TP_printk("addr=%s event=%s (%u/%d)",
+ __entry->addr,
+ rdma_show_cm_event(__entry->event),
+ __entry->event, __entry->status
+ )
+);
+
+TRACE_EVENT(svcrdma_qp_error,
+ TP_PROTO(
+ const struct ib_event *event,
+ const struct sockaddr *sap
+ ),
+
+ TP_ARGS(event, sap),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, event)
+ __string(device, event->device->name)
+ __array(__u8, addr, INET6_ADDRSTRLEN + 10)
+ ),
+
+ TP_fast_assign(
+ __entry->event = event->event;
+ __assign_str(device, event->device->name);
+ snprintf(__entry->addr, sizeof(__entry->addr) - 1,
+ "%pISpc", sap);
+ ),
+
+ TP_printk("addr=%s dev=%s event=%s (%u)",
+ __entry->addr, __get_str(device),
+ rdma_show_ib_event(__entry->event), __entry->event
+ )
+);
+
+DECLARE_EVENT_CLASS(svcrdma_sendqueue_event,
+ TP_PROTO(
+ const struct svcxprt_rdma *rdma
+ ),
+
+ TP_ARGS(rdma),
+
+ TP_STRUCT__entry(
+ __field(int, avail)
+ __field(int, depth)
+ __string(addr, rdma->sc_xprt.xpt_remotebuf)
+ ),
+
+ TP_fast_assign(
+ __entry->avail = atomic_read(&rdma->sc_sq_avail);
+ __entry->depth = rdma->sc_sq_depth;
+ __assign_str(addr, rdma->sc_xprt.xpt_remotebuf);
+ ),
+
+ TP_printk("addr=%s sc_sq_avail=%d/%d",
+ __get_str(addr), __entry->avail, __entry->depth
+ )
+);
+
+#define DEFINE_SQ_EVENT(name) \
+ DEFINE_EVENT(svcrdma_sendqueue_event, svcrdma_sq_##name,\
+ TP_PROTO( \
+ const struct svcxprt_rdma *rdma \
+ ), \
+ TP_ARGS(rdma))
+
+DEFINE_SQ_EVENT(full);
+DEFINE_SQ_EVENT(retry);
+
#endif /* _TRACE_RPCRDMA_H */
#include <trace/define_trace.h>
diff --git a/include/uapi/linux/aio_abi.h b/include/uapi/linux/aio_abi.h
index 7584616..d002213 100644
--- a/include/uapi/linux/aio_abi.h
+++ b/include/uapi/linux/aio_abi.h
@@ -109,7 +109,7 @@ struct iocb {
#undef IFLITTLE
struct __aio_sigset {
- sigset_t __user *sigmask;
+ const sigset_t __user *sigmask;
size_t sigsetsize;
};
diff --git a/include/uapi/linux/if_xdp.h b/include/uapi/linux/if_xdp.h
index 1fa0e97..caed8b1 100644
--- a/include/uapi/linux/if_xdp.h
+++ b/include/uapi/linux/if_xdp.h
@@ -63,8 +63,8 @@ struct xdp_statistics {
/* Pgoff for mmaping the rings */
#define XDP_PGOFF_RX_RING 0
#define XDP_PGOFF_TX_RING 0x80000000
-#define XDP_UMEM_PGOFF_FILL_RING 0x100000000
-#define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000
+#define XDP_UMEM_PGOFF_FILL_RING 0x100000000ULL
+#define XDP_UMEM_PGOFF_COMPLETION_RING 0x180000000ULL
/* Rx/Tx descriptor */
struct xdp_desc {
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index b02c41e..b6270a3 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -677,10 +677,10 @@ struct kvm_ioeventfd {
};
#define KVM_X86_DISABLE_EXITS_MWAIT (1 << 0)
-#define KVM_X86_DISABLE_EXITS_HTL (1 << 1)
+#define KVM_X86_DISABLE_EXITS_HLT (1 << 1)
#define KVM_X86_DISABLE_EXITS_PAUSE (1 << 2)
#define KVM_X86_DISABLE_VALID_EXITS (KVM_X86_DISABLE_EXITS_MWAIT | \
- KVM_X86_DISABLE_EXITS_HTL | \
+ KVM_X86_DISABLE_EXITS_HLT | \
KVM_X86_DISABLE_EXITS_PAUSE)
/* for KVM_ENABLE_CAP */
@@ -948,6 +948,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_S390_BPB 152
#define KVM_CAP_GET_MSR_FEATURES 153
#define KVM_CAP_HYPERV_EVENTFD 154
+#define KVM_CAP_HYPERV_TLBFLUSH 155
#ifdef KVM_CAP_IRQ_ROUTING
diff --git a/include/uapi/linux/nbd.h b/include/uapi/linux/nbd.h
index 85a3fb6..20d6cc9 100644
--- a/include/uapi/linux/nbd.h
+++ b/include/uapi/linux/nbd.h
@@ -53,6 +53,9 @@ enum {
/* These are client behavior specific flags. */
#define NBD_CFLAG_DESTROY_ON_DISCONNECT (1 << 0) /* delete the nbd device on
disconnect. */
+#define NBD_CFLAG_DISCONNECT_ON_CLOSE (1 << 1) /* disconnect the nbd device on
+ * close by last opener.
+ */
/* userspace doesn't need the nbd_device structure */
diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h b/include/uapi/linux/netfilter/nf_conntrack_common.h
index c712eb6..336014b 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -112,7 +112,7 @@ enum ip_conntrack_status {
IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING |
IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD),
- __IPS_MAX_BIT = 14,
+ __IPS_MAX_BIT = 15,
};
/* Connection tracking event types */
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index ae00a3c..89438e6 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -266,7 +266,7 @@ enum nft_rule_compat_attributes {
* @NFT_SET_INTERVAL: set contains intervals
* @NFT_SET_MAP: set is used as a dictionary
* @NFT_SET_TIMEOUT: set uses timeouts
- * @NFT_SET_EVAL: set contains expressions for evaluation
+ * @NFT_SET_EVAL: set can be updated from the evaluation path
* @NFT_SET_OBJECT: set contains stateful objects
*/
enum nft_set_flags {
@@ -1099,9 +1099,31 @@ enum nft_log_attributes {
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
/**
- * LOGLEVEL_AUDIT - a pseudo log level enabling audit logging
- */
-#define LOGLEVEL_AUDIT 8
+ * enum nft_log_level - nf_tables log levels
+ *
+ * @NFT_LOGLEVEL_EMERG: system is unusable
+ * @NFT_LOGLEVEL_ALERT: action must be taken immediately
+ * @NFT_LOGLEVEL_CRIT: critical conditions
+ * @NFT_LOGLEVEL_ERR: error conditions
+ * @NFT_LOGLEVEL_WARNING: warning conditions
+ * @NFT_LOGLEVEL_NOTICE: normal but significant condition
+ * @NFT_LOGLEVEL_INFO: informational
+ * @NFT_LOGLEVEL_DEBUG: debug-level messages
+ * @NFT_LOGLEVEL_AUDIT: enabling audit logging
+ */
+enum nft_log_level {
+ NFT_LOGLEVEL_EMERG,
+ NFT_LOGLEVEL_ALERT,
+ NFT_LOGLEVEL_CRIT,
+ NFT_LOGLEVEL_ERR,
+ NFT_LOGLEVEL_WARNING,
+ NFT_LOGLEVEL_NOTICE,
+ NFT_LOGLEVEL_INFO,
+ NFT_LOGLEVEL_DEBUG,
+ NFT_LOGLEVEL_AUDIT,
+ __NFT_LOGLEVEL_MAX
+};
+#define NFT_LOGLEVEL_MAX (__NFT_LOGLEVEL_MAX + 1)
/**
* enum nft_queue_attributes - nf_tables queue expression netlink attributes
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 28b3654..27e4e44 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -981,18 +981,18 @@
* only the %NL80211_ATTR_IE data is used and updated with this command.
*
* @NL80211_CMD_SET_PMK: For offloaded 4-Way handshake, set the PMK or PMK-R0
- * for the given authenticator address (specified with &NL80211_ATTR_MAC).
- * When &NL80211_ATTR_PMKR0_NAME is set, &NL80211_ATTR_PMK specifies the
+ * for the given authenticator address (specified with %NL80211_ATTR_MAC).
+ * When %NL80211_ATTR_PMKR0_NAME is set, %NL80211_ATTR_PMK specifies the
* PMK-R0, otherwise it specifies the PMK.
* @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously
* configured PMK for the authenticator address identified by
- * &NL80211_ATTR_MAC.
+ * %NL80211_ATTR_MAC.
* @NL80211_CMD_PORT_AUTHORIZED: An event that indicates that the 4 way
* handshake was completed successfully by the driver. The BSSID is
- * specified with &NL80211_ATTR_MAC. Drivers that support 4 way handshake
+ * specified with %NL80211_ATTR_MAC. Drivers that support 4 way handshake
* offload should send this event after indicating 802.11 association with
- * &NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed
- * &NL80211_CMD_DISCONNECT should be indicated instead.
+ * %NL80211_CMD_CONNECT or %NL80211_CMD_ROAM. If the 4 way handshake failed
+ * %NL80211_CMD_DISCONNECT should be indicated instead.
*
* @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request
* and RX notification. This command is used both as a request to transmit
@@ -1029,9 +1029,9 @@
* initiated the connection through the connect request.
*
* @NL80211_CMD_STA_OPMODE_CHANGED: An event that notify station's
- * ht opmode or vht opmode changes using any of &NL80211_ATTR_SMPS_MODE,
- * &NL80211_ATTR_CHANNEL_WIDTH,&NL80211_ATTR_NSS attributes with its
- * address(specified in &NL80211_ATTR_MAC).
+ * ht opmode or vht opmode changes using any of %NL80211_ATTR_SMPS_MODE,
+ * %NL80211_ATTR_CHANNEL_WIDTH,%NL80211_ATTR_NSS attributes with its
+ * address(specified in %NL80211_ATTR_MAC).
*
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
@@ -2218,7 +2218,7 @@ enum nl80211_commands {
* @NL80211_ATTR_EXTERNAL_AUTH_ACTION: Identify the requested external
* authentication operation (u32 attribute with an
* &enum nl80211_external_auth_action value). This is used with the
- * &NL80211_CMD_EXTERNAL_AUTH request event.
+ * %NL80211_CMD_EXTERNAL_AUTH request event.
* @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user
* space supports external authentication. This attribute shall be used
* only with %NL80211_CMD_CONNECT request. The driver may offload
@@ -3491,7 +3491,7 @@ enum nl80211_sched_scan_match_attr {
* @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated
* base on contiguous rules and wider channels will be allowed to cross
* multiple contiguous/overlapping frequency ranges.
- * @NL80211_RRF_IR_CONCURRENT: See &NL80211_FREQUENCY_ATTR_IR_CONCURRENT
+ * @NL80211_RRF_IR_CONCURRENT: See %NL80211_FREQUENCY_ATTR_IR_CONCURRENT
* @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation
* @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation
* @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed
@@ -5643,11 +5643,11 @@ enum nl80211_nan_func_attributes {
* @NL80211_NAN_SRF_INCLUDE: present if the include bit of the SRF set.
* This is a flag.
* @NL80211_NAN_SRF_BF: Bloom Filter. Present if and only if
- * &NL80211_NAN_SRF_MAC_ADDRS isn't present. This attribute is binary.
+ * %NL80211_NAN_SRF_MAC_ADDRS isn't present. This attribute is binary.
* @NL80211_NAN_SRF_BF_IDX: index of the Bloom Filter. Mandatory if
- * &NL80211_NAN_SRF_BF is present. This is a u8.
+ * %NL80211_NAN_SRF_BF is present. This is a u8.
* @NL80211_NAN_SRF_MAC_ADDRS: list of MAC addresses for the SRF. Present if
- * and only if &NL80211_NAN_SRF_BF isn't present. This is a nested
+ * and only if %NL80211_NAN_SRF_BF isn't present. This is a nested
* attribute. Each nested attribute is a MAC address.
* @NUM_NL80211_NAN_SRF_ATTR: internal
* @NL80211_NAN_SRF_ATTR_MAX: highest NAN SRF attribute
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index db9f15f..c0d7ea0 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -170,7 +170,7 @@ struct prctl_mm_map {
* asking selinux for a specific new context (e.g. with runcon) will result
* in execve returning -EPERM.
*
- * See Documentation/prctl/no_new_privs.txt for more details.
+ * See Documentation/userspace-api/no_new_privs.rst for more details.
*/
#define PR_SET_NO_NEW_PRIVS 38
#define PR_GET_NO_NEW_PRIVS 39
diff --git a/include/uapi/linux/rpmsg.h b/include/uapi/linux/rpmsg.h
index 225eb38..e14c6da 100644
--- a/include/uapi/linux/rpmsg.h
+++ b/include/uapi/linux/rpmsg.h
@@ -1,15 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Copyright (c) 2016, Linaro Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only 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 _UAPI_RPMSG_H_
diff --git a/include/uapi/linux/target_core_user.h b/include/uapi/linux/target_core_user.h
index 0be80f7..6e29934 100644
--- a/include/uapi/linux/target_core_user.h
+++ b/include/uapi/linux/target_core_user.h
@@ -9,21 +9,22 @@
#define TCMU_VERSION "2.0"
-/*
+/**
+ * DOC: Ring Design
* Ring Design
* -----------
*
* The mmaped area is divided into three parts:
- * 1) The mailbox (struct tcmu_mailbox, below)
- * 2) The command ring
- * 3) Everything beyond the command ring (data)
+ * 1) The mailbox (struct tcmu_mailbox, below);
+ * 2) The command ring;
+ * 3) Everything beyond the command ring (data).
*
* The mailbox tells userspace the offset of the command ring from the
* start of the shared memory region, and how big the command ring is.
*
* The kernel passes SCSI commands to userspace by putting a struct
* tcmu_cmd_entry in the ring, updating mailbox->cmd_head, and poking
- * userspace via uio's interrupt mechanism.
+ * userspace via UIO's interrupt mechanism.
*
* tcmu_cmd_entry contains a header. If the header type is PAD,
* userspace should skip hdr->length bytes (mod cmdr_size) to find the
diff --git a/include/uapi/linux/usb/audio.h b/include/uapi/linux/usb/audio.h
index 13d98e6..74e520f 100644
--- a/include/uapi/linux/usb/audio.h
+++ b/include/uapi/linux/usb/audio.h
@@ -230,6 +230,14 @@ struct uac1_output_terminal_descriptor {
#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306
#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307
+/* Terminals - 2.4 Bi-directional Terminal Types */
+#define UAC_BIDIR_TERMINAL_UNDEFINED 0x400
+#define UAC_BIDIR_TERMINAL_HANDSET 0x401
+#define UAC_BIDIR_TERMINAL_HEADSET 0x402
+#define UAC_BIDIR_TERMINAL_SPEAKER_PHONE 0x403
+#define UAC_BIDIR_TERMINAL_ECHO_SUPPRESSING 0x404
+#define UAC_BIDIR_TERMINAL_ECHO_CANCELING 0x405
+
/* Set bControlSize = 2 as default setting */
#define UAC_DT_FEATURE_UNIT_SIZE(ch) (7 + ((ch) + 1) * 2)
diff --git a/include/uapi/linux/virtio_config.h b/include/uapi/linux/virtio_config.h
index 308e209..449132c 100644
--- a/include/uapi/linux/virtio_config.h
+++ b/include/uapi/linux/virtio_config.h
@@ -45,11 +45,14 @@
/* We've given up on this device. */
#define VIRTIO_CONFIG_S_FAILED 0x80
-/* Some virtio feature bits (currently bits 28 through 32) are reserved for the
- * transport being used (eg. virtio_ring), the rest are per-device feature
- * bits. */
+/*
+ * Virtio feature bits VIRTIO_TRANSPORT_F_START through
+ * VIRTIO_TRANSPORT_F_END are reserved for the transport
+ * being used (e.g. virtio_ring, virtio_pci etc.), the
+ * rest are per-device feature bits.
+ */
#define VIRTIO_TRANSPORT_F_START 28
-#define VIRTIO_TRANSPORT_F_END 34
+#define VIRTIO_TRANSPORT_F_END 38
#ifndef VIRTIO_CONFIG_NO_LEGACY
/* Do we get callbacks when the ring is completely used, even if we've
@@ -71,4 +74,9 @@
* this is for compatibility with legacy systems.
*/
#define VIRTIO_F_IOMMU_PLATFORM 33
+
+/*
+ * Does the device support Single Root I/O Virtualization?
+ */
+#define VIRTIO_F_SR_IOV 37
#endif /* _UAPI_LINUX_VIRTIO_CONFIG_H */
diff --git a/include/video/auo_k190xfb.h b/include/video/auo_k190xfb.h
deleted file mode 100644
index ac329ee..0000000
--- a/include/video/auo_k190xfb.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Definitions for AUO-K190X framebuffer drivers
- *
- * Copyright (C) 2012 Heiko Stuebner <heiko@sntech.de>
- *
- * 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 _LINUX_VIDEO_AUO_K190XFB_H_
-#define _LINUX_VIDEO_AUO_K190XFB_H_
-
-/* Controller standby command needs a param */
-#define AUOK190X_QUIRK_STANDBYPARAM (1 << 0)
-
-/* Controller standby is completely broken */
-#define AUOK190X_QUIRK_STANDBYBROKEN (1 << 1)
-
-/*
- * Resolutions for the displays
- */
-#define AUOK190X_RESOLUTION_800_600 0
-#define AUOK190X_RESOLUTION_1024_768 1
-#define AUOK190X_RESOLUTION_600_800 4
-#define AUOK190X_RESOLUTION_768_1024 5
-
-/*
- * struct used by auok190x. board specific stuff comes from *board
- */
-struct auok190xfb_par {
- struct fb_info *info;
- struct auok190x_board *board;
-
- struct regulator *regulator;
-
- struct mutex io_lock;
- struct delayed_work work;
- wait_queue_head_t waitq;
- int resolution;
- int rotation;
- int consecutive_threshold;
- int update_cnt;
-
- /* panel and controller informations */
- int epd_type;
- int panel_size_int;
- int panel_size_float;
- int panel_model;
- int tcon_version;
- int lut_version;
-
- /* individual controller callbacks */
- void (*update_partial)(struct auok190xfb_par *par, u16 y1, u16 y2);
- void (*update_all)(struct auok190xfb_par *par);
- bool (*need_refresh)(struct auok190xfb_par *par);
- void (*init)(struct auok190xfb_par *par);
- void (*recover)(struct auok190xfb_par *par);
-
- int update_mode; /* mode to use for updates */
- int last_mode; /* update mode last used */
- int flash;
-
- /* power management */
- int autosuspend_delay;
- bool standby;
- bool manual_standby;
-};
-
-/**
- * Board specific platform-data
- * @init: initialize the controller interface
- * @cleanup: cleanup the controller interface
- * @wait_for_rdy: wait until the controller is not busy anymore
- * @set_ctl: change an interface control
- * @set_hdb: write a value to the data register
- * @get_hdb: read a value from the data register
- * @setup_irq: method to setup the irq handling on the busy gpio
- * @gpio_nsleep: sleep gpio
- * @gpio_nrst: reset gpio
- * @gpio_nbusy: busy gpio
- * @resolution: one of the AUOK190X_RESOLUTION constants
- * @rotation: rotation of the framebuffer
- * @quirks: controller quirks to honor
- * @fps: frames per second for defio
- */
-struct auok190x_board {
- int (*init)(struct auok190xfb_par *);
- void (*cleanup)(struct auok190xfb_par *);
- int (*wait_for_rdy)(struct auok190xfb_par *);
-
- void (*set_ctl)(struct auok190xfb_par *, unsigned char, u8);
- void (*set_hdb)(struct auok190xfb_par *, u16);
- u16 (*get_hdb)(struct auok190xfb_par *);
-
- int (*setup_irq)(struct fb_info *);
-
- int gpio_nsleep;
- int gpio_nrst;
- int gpio_nbusy;
-
- int resolution;
- int quirks;
- int fps;
-};
-
-#endif
diff --git a/include/video/sh_mobile_lcdc.h b/include/video/sh_mobile_lcdc.h
index f706b0f..84aa976 100644
--- a/include/video/sh_mobile_lcdc.h
+++ b/include/video/sh_mobile_lcdc.h
@@ -3,7 +3,6 @@
#define __ASM_SH_MOBILE_LCDC_H__
#include <linux/fb.h>
-#include <video/sh_mobile_meram.h>
/* Register definitions */
#define _LDDCKR 0x410
@@ -184,7 +183,6 @@ struct sh_mobile_lcdc_chan_cfg {
struct sh_mobile_lcdc_panel_cfg panel_cfg;
struct sh_mobile_lcdc_bl_info bl_info;
struct sh_mobile_lcdc_sys_bus_cfg sys_bus_cfg; /* only for SYSn I/F */
- const struct sh_mobile_meram_cfg *meram_cfg;
struct platform_device *tx_dev; /* HDMI/DSI transmitter device */
};
@@ -193,7 +191,6 @@ struct sh_mobile_lcdc_info {
int clock_source;
struct sh_mobile_lcdc_chan_cfg ch[2];
struct sh_mobile_lcdc_overlay_cfg overlays[4];
- struct sh_mobile_meram_info *meram_dev;
};
#endif /* __ASM_SH_MOBILE_LCDC_H__ */
diff --git a/include/video/sh_mobile_meram.h b/include/video/sh_mobile_meram.h
deleted file mode 100644
index f4efc21..0000000
--- a/include/video/sh_mobile_meram.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __VIDEO_SH_MOBILE_MERAM_H__
-#define __VIDEO_SH_MOBILE_MERAM_H__
-
-/* For sh_mobile_meram_info.addr_mode */
-enum {
- SH_MOBILE_MERAM_MODE0 = 0,
- SH_MOBILE_MERAM_MODE1
-};
-
-enum {
- SH_MOBILE_MERAM_PF_NV = 0,
- SH_MOBILE_MERAM_PF_RGB,
- SH_MOBILE_MERAM_PF_NV24
-};
-
-
-struct sh_mobile_meram_priv;
-
-/*
- * struct sh_mobile_meram_info - MERAM platform data
- * @reserved_icbs: Bitmask of reserved ICBs (for instance used through UIO)
- */
-struct sh_mobile_meram_info {
- int addr_mode;
- u32 reserved_icbs;
- struct sh_mobile_meram_priv *priv;
- struct platform_device *pdev;
-};
-
-/* icb config */
-struct sh_mobile_meram_icb_cfg {
- unsigned int meram_size; /* MERAM Buffer Size to use */
-};
-
-struct sh_mobile_meram_cfg {
- struct sh_mobile_meram_icb_cfg icb[2];
-};
-
-#if defined(CONFIG_FB_SH_MOBILE_MERAM) || \
- defined(CONFIG_FB_SH_MOBILE_MERAM_MODULE)
-unsigned long sh_mobile_meram_alloc(struct sh_mobile_meram_info *meram_dev,
- size_t size);
-void sh_mobile_meram_free(struct sh_mobile_meram_info *meram_dev,
- unsigned long mem, size_t size);
-void *sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
- const struct sh_mobile_meram_cfg *cfg,
- unsigned int xres, unsigned int yres,
- unsigned int pixelformat,
- unsigned int *pitch);
-void sh_mobile_meram_cache_free(struct sh_mobile_meram_info *dev, void *data);
-void sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
- unsigned long base_addr_y,
- unsigned long base_addr_c,
- unsigned long *icb_addr_y,
- unsigned long *icb_addr_c);
-#else
-static inline unsigned long
-sh_mobile_meram_alloc(struct sh_mobile_meram_info *meram_dev, size_t size)
-{
- return 0;
-}
-
-static inline void
-sh_mobile_meram_free(struct sh_mobile_meram_info *meram_dev,
- unsigned long mem, size_t size)
-{
-}
-
-static inline void *
-sh_mobile_meram_cache_alloc(struct sh_mobile_meram_info *dev,
- const struct sh_mobile_meram_cfg *cfg,
- unsigned int xres, unsigned int yres,
- unsigned int pixelformat,
- unsigned int *pitch)
-{
- return ERR_PTR(-ENODEV);
-}
-
-static inline void
-sh_mobile_meram_cache_free(struct sh_mobile_meram_info *dev, void *data)
-{
-}
-
-static inline void
-sh_mobile_meram_cache_update(struct sh_mobile_meram_info *dev, void *data,
- unsigned long base_addr_y,
- unsigned long base_addr_c,
- unsigned long *icb_addr_y,
- unsigned long *icb_addr_c)
-{
-}
-#endif
-
-#endif /* __VIDEO_SH_MOBILE_MERAM_H__ */
diff --git a/include/xen/interface/io/kbdif.h b/include/xen/interface/io/kbdif.h
index 2a9510a..e2340a4 100644
--- a/include/xen/interface/io/kbdif.h
+++ b/include/xen/interface/io/kbdif.h
@@ -317,7 +317,7 @@ struct xenkbd_position {
* Linux [2] and Windows [3] multi-touch support.
*
* [1] https://cgit.freedesktop.org/wayland/wayland/tree/protocol/wayland.xml
- * [2] https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt
+ * [2] https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.rst
* [3] https://msdn.microsoft.com/en-us/library/jj151564(v=vs.85).aspx
*
*
diff --git a/include/xen/xen.h b/include/xen/xen.h
index 9d4340c..1e1d9bd 100644
--- a/include/xen/xen.h
+++ b/include/xen/xen.h
@@ -25,12 +25,16 @@ extern bool xen_pvh;
#define xen_hvm_domain() (xen_domain_type == XEN_HVM_DOMAIN)
#define xen_pvh_domain() (xen_pvh)
+#include <linux/types.h>
+
+extern uint32_t xen_start_flags;
+
#ifdef CONFIG_XEN_DOM0
#include <xen/interface/xen.h>
#include <asm/xen/hypervisor.h>
#define xen_initial_domain() (xen_domain() && \
- xen_start_info && xen_start_info->flags & SIF_INITDOMAIN)
+ (xen_start_flags & SIF_INITDOMAIN))
#else /* !CONFIG_XEN_DOM0 */
#define xen_initial_domain() (0)
#endif /* CONFIG_XEN_DOM0 */
diff --git a/init/Kconfig b/init/Kconfig
index d2b8b2e..fde3d09 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -8,6 +8,21 @@ config DEFCONFIG_LIST
default ARCH_DEFCONFIG
default "arch/$(ARCH)/defconfig"
+config CC_IS_GCC
+ def_bool $(success,$(CC) --version | head -n 1 | grep -q gcc)
+
+config GCC_VERSION
+ int
+ default $(shell,$(srctree)/scripts/gcc-version.sh -p $(CC) | sed 's/^0*//') if CC_IS_GCC
+ default 0
+
+config CC_IS_CLANG
+ def_bool $(success,$(CC) --version | head -n 1 | grep -q clang)
+
+config CLANG_VERSION
+ int
+ default $(shell,$(srctree)/scripts/clang-version.sh $(CC))
+
config CONSTRUCTORS
bool
depends on !UML
@@ -1704,10 +1719,6 @@ source "arch/Kconfig"
endmenu # General setup
-config HAVE_GENERIC_DMA_COHERENT
- bool
- default n
-
config RT_MUTEXES
bool
diff --git a/ipc/sem.c b/ipc/sem.c
index cfd94d4..5af1943 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -85,6 +85,7 @@
#include <linux/nsproxy.h>
#include <linux/ipc_namespace.h>
#include <linux/sched/wake_q.h>
+#include <linux/nospec.h>
#include <linux/uaccess.h>
#include "util.h"
@@ -368,6 +369,7 @@ static inline int sem_lock(struct sem_array *sma, struct sembuf *sops,
int nsops)
{
struct sem *sem;
+ int idx;
if (nsops != 1) {
/* Complex operation - acquire a full lock */
@@ -385,7 +387,8 @@ static inline int sem_lock(struct sem_array *sma, struct sembuf *sops,
*
* Both facts are tracked by use_global_mode.
*/
- sem = &sma->sems[sops->sem_num];
+ idx = array_index_nospec(sops->sem_num, sma->sem_nsems);
+ sem = &sma->sems[idx];
/*
* Initial check for use_global_lock. Just an optimization,
@@ -638,7 +641,8 @@ static int perform_atomic_semop_slow(struct sem_array *sma, struct sem_queue *q)
un = q->undo;
for (sop = sops; sop < sops + nsops; sop++) {
- curr = &sma->sems[sop->sem_num];
+ int idx = array_index_nospec(sop->sem_num, sma->sem_nsems);
+ curr = &sma->sems[idx];
sem_op = sop->sem_op;
result = curr->semval;
@@ -718,7 +722,9 @@ static int perform_atomic_semop(struct sem_array *sma, struct sem_queue *q)
* until the operations can go through.
*/
for (sop = sops; sop < sops + nsops; sop++) {
- curr = &sma->sems[sop->sem_num];
+ int idx = array_index_nospec(sop->sem_num, sma->sem_nsems);
+
+ curr = &sma->sems[idx];
sem_op = sop->sem_op;
result = curr->semval;
@@ -1356,6 +1362,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
return -EIDRM;
}
+ semnum = array_index_nospec(semnum, sma->sem_nsems);
curr = &sma->sems[semnum];
ipc_assert_locked_object(&sma->sem_perm);
@@ -1509,6 +1516,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
err = -EIDRM;
goto out_unlock;
}
+
+ semnum = array_index_nospec(semnum, nsems);
curr = &sma->sems[semnum];
switch (cmd) {
@@ -1945,7 +1954,7 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
if (nsops > ns->sc_semopm)
return -E2BIG;
if (nsops > SEMOPM_FAST) {
- sops = kvmalloc(sizeof(*sops)*nsops, GFP_KERNEL);
+ sops = kvmalloc_array(nsops, sizeof(*sops), GFP_KERNEL);
if (sops == NULL)
return -ENOMEM;
}
@@ -2081,7 +2090,8 @@ static long do_semtimedop(int semid, struct sembuf __user *tsops,
*/
if (nsops == 1) {
struct sem *curr;
- curr = &sma->sems[sops->sem_num];
+ int idx = array_index_nospec(sops->sem_num, sma->sem_nsems);
+ curr = &sma->sems[idx];
if (alter) {
if (sma->complex_count) {
diff --git a/ipc/shm.c b/ipc/shm.c
index 29978ee..051a3e1 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -408,7 +408,7 @@ void exit_shm(struct task_struct *task)
up_write(&shm_ids(ns).rwsem);
}
-static int shm_fault(struct vm_fault *vmf)
+static vm_fault_t shm_fault(struct vm_fault *vmf)
{
struct file *file = vmf->vma->vm_file;
struct shm_file_data *sfd = shm_file_data(file);
diff --git a/kernel/Makefile b/kernel/Makefile
index d200162..04bc07c 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -41,6 +41,7 @@ obj-y += printk/
obj-y += irq/
obj-y += rcu/
obj-y += livepatch/
+obj-y += dma/
obj-$(CONFIG_CHECKPOINT_RESTORE) += kcmp.o
obj-$(CONFIG_FREEZER) += freezer.o
diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
index 52f368b..fba7804 100644
--- a/kernel/audit_fsnotify.c
+++ b/kernel/audit_fsnotify.c
@@ -109,7 +109,7 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pa
audit_update_mark(audit_mark, dentry->d_inode);
audit_mark->rule = krule;
- ret = fsnotify_add_mark(&audit_mark->mark, inode, NULL, true);
+ ret = fsnotify_add_inode_mark(&audit_mark->mark, inode, true);
if (ret < 0) {
fsnotify_put_mark(&audit_mark->mark);
audit_mark = ERR_PTR(ret);
@@ -165,12 +165,11 @@ static void audit_autoremove_mark_rule(struct audit_fsnotify_mark *audit_mark)
/* Update mark data in audit rules based on fsnotify events. */
static int audit_mark_handle_event(struct fsnotify_group *group,
struct inode *to_tell,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *dname, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
+ struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
struct audit_fsnotify_mark *audit_mark;
const struct inode *inode = NULL;
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 67e6956..c99ebaa 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -288,8 +288,8 @@ static void untag_chunk(struct node *p)
if (!new)
goto Fallback;
- if (fsnotify_add_mark_locked(&new->mark, entry->connector->inode,
- NULL, 1)) {
+ if (fsnotify_add_inode_mark_locked(&new->mark, entry->connector->inode,
+ 1)) {
fsnotify_put_mark(&new->mark);
goto Fallback;
}
@@ -354,7 +354,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree)
return -ENOMEM;
entry = &chunk->mark;
- if (fsnotify_add_mark(entry, inode, NULL, 0)) {
+ if (fsnotify_add_inode_mark(entry, inode, 0)) {
fsnotify_put_mark(entry);
return -ENOSPC;
}
@@ -434,8 +434,8 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
return -ENOENT;
}
- if (fsnotify_add_mark_locked(chunk_entry,
- old_entry->connector->inode, NULL, 1)) {
+ if (fsnotify_add_inode_mark_locked(chunk_entry,
+ old_entry->connector->inode, 1)) {
spin_unlock(&old_entry->lock);
mutex_unlock(&old_entry->group->mark_mutex);
fsnotify_put_mark(chunk_entry);
@@ -989,8 +989,6 @@ static void evict_chunk(struct audit_chunk *chunk)
static int audit_tree_handle_event(struct fsnotify_group *group,
struct inode *to_tell,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *file_name, u32 cookie,
struct fsnotify_iter_info *iter_info)
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index f1ba889..c17c0c2 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -160,7 +160,7 @@ static struct audit_parent *audit_init_parent(struct path *path)
fsnotify_init_mark(&parent->mark, audit_watch_group);
parent->mark.mask = AUDIT_FS_WATCH;
- ret = fsnotify_add_mark(&parent->mark, inode, NULL, 0);
+ ret = fsnotify_add_inode_mark(&parent->mark, inode, 0);
if (ret < 0) {
audit_free_parent(parent);
return ERR_PTR(ret);
@@ -472,12 +472,11 @@ void audit_remove_watch_rule(struct audit_krule *krule)
/* Update watch data in audit rules based on fsnotify events. */
static int audit_watch_handle_event(struct fsnotify_group *group,
struct inode *to_tell,
- struct fsnotify_mark *inode_mark,
- struct fsnotify_mark *vfsmount_mark,
u32 mask, const void *data, int data_type,
const unsigned char *dname, u32 cookie,
struct fsnotify_iter_info *iter_info)
{
+ struct fsnotify_mark *inode_mark = fsnotify_iter_inode_mark(iter_info);
const struct inode *inode;
struct audit_parent *parent;
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 8653ab0..2d49d18 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -608,7 +608,7 @@ static int btf_add_type(struct btf_verifier_env *env, struct btf_type *t)
new_size = min_t(u32, BTF_MAX_TYPE,
btf->types_size + expand_by);
- new_types = kvzalloc(new_size * sizeof(*new_types),
+ new_types = kvcalloc(new_size, sizeof(*new_types),
GFP_KERNEL | __GFP_NOWARN);
if (!new_types)
return -ENOMEM;
@@ -698,17 +698,17 @@ static int env_resolve_init(struct btf_verifier_env *env)
u8 *visit_states = NULL;
/* +1 for btf_void */
- resolved_sizes = kvzalloc((nr_types + 1) * sizeof(*resolved_sizes),
+ resolved_sizes = kvcalloc(nr_types + 1, sizeof(*resolved_sizes),
GFP_KERNEL | __GFP_NOWARN);
if (!resolved_sizes)
goto nomem;
- resolved_ids = kvzalloc((nr_types + 1) * sizeof(*resolved_ids),
+ resolved_ids = kvcalloc(nr_types + 1, sizeof(*resolved_ids),
GFP_KERNEL | __GFP_NOWARN);
if (!resolved_ids)
goto nomem;
- visit_states = kvzalloc((nr_types + 1) * sizeof(*visit_states),
+ visit_states = kvcalloc(nr_types + 1, sizeof(*visit_states),
GFP_KERNEL | __GFP_NOWARN);
if (!visit_states)
goto nomem;
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 9f14937..a9e6c04 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -350,6 +350,20 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
return prog_adj;
}
+void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp)
+{
+ int i;
+
+ for (i = 0; i < fp->aux->func_cnt; i++)
+ bpf_prog_kallsyms_del(fp->aux->func[i]);
+}
+
+void bpf_prog_kallsyms_del_all(struct bpf_prog *fp)
+{
+ bpf_prog_kallsyms_del_subprogs(fp);
+ bpf_prog_kallsyms_del(fp);
+}
+
#ifdef CONFIG_BPF_JIT
/* All BPF JIT sysctl knobs here. */
int bpf_jit_enable __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_ALWAYS_ON);
@@ -584,6 +598,8 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,
bpf_fill_ill_insns(hdr, size);
hdr->pages = size / PAGE_SIZE;
+ hdr->locked = 0;
+
hole = min_t(unsigned int, size - (proglen + sizeof(*hdr)),
PAGE_SIZE - sizeof(*hdr));
start = (get_random_int() % hole) & ~(alignment - 1);
@@ -1434,6 +1450,33 @@ static int bpf_check_tail_call(const struct bpf_prog *fp)
return 0;
}
+static int bpf_prog_check_pages_ro_locked(const struct bpf_prog *fp)
+{
+#ifdef CONFIG_ARCH_HAS_SET_MEMORY
+ int i, err;
+
+ for (i = 0; i < fp->aux->func_cnt; i++) {
+ err = bpf_prog_check_pages_ro_single(fp->aux->func[i]);
+ if (err)
+ return err;
+ }
+
+ return bpf_prog_check_pages_ro_single(fp);
+#endif
+ return 0;
+}
+
+static void bpf_prog_select_func(struct bpf_prog *fp)
+{
+#ifndef CONFIG_BPF_JIT_ALWAYS_ON
+ u32 stack_depth = max_t(u32, fp->aux->stack_depth, 1);
+
+ fp->bpf_func = interpreters[(round_up(stack_depth, 32) / 32) - 1];
+#else
+ fp->bpf_func = __bpf_prog_ret0_warn;
+#endif
+}
+
/**
* bpf_prog_select_runtime - select exec runtime for BPF program
* @fp: bpf_prog populated with internal BPF program
@@ -1444,13 +1487,13 @@ static int bpf_check_tail_call(const struct bpf_prog *fp)
*/
struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
{
-#ifndef CONFIG_BPF_JIT_ALWAYS_ON
- u32 stack_depth = max_t(u32, fp->aux->stack_depth, 1);
+ /* In case of BPF to BPF calls, verifier did all the prep
+ * work with regards to JITing, etc.
+ */
+ if (fp->bpf_func)
+ goto finalize;
- fp->bpf_func = interpreters[(round_up(stack_depth, 32) / 32) - 1];
-#else
- fp->bpf_func = __bpf_prog_ret0_warn;
-#endif
+ bpf_prog_select_func(fp);
/* eBPF JITs can rewrite the program in case constant
* blinding is active. However, in case of error during
@@ -1471,6 +1514,8 @@ struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
if (*err)
return fp;
}
+
+finalize:
bpf_prog_lock_ro(fp);
/* The tail call compatibility check can only be done at
@@ -1479,7 +1524,17 @@ struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
* all eBPF JITs might immediately support all features.
*/
*err = bpf_check_tail_call(fp);
-
+ if (*err)
+ return fp;
+
+ /* Checkpoint: at this point onwards any cBPF -> eBPF or
+ * native eBPF program is read-only. If we failed to change
+ * the page attributes (e.g. allocation failure from
+ * splitting large pages), then reject the whole program
+ * in order to guarantee not ending up with any W+X pages
+ * from BPF side in kernel.
+ */
+ *err = bpf_prog_check_pages_ro_locked(fp);
return fp;
}
EXPORT_SYMBOL_GPL(bpf_prog_select_runtime);
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
index a7cc7b3..642c97f 100644
--- a/kernel/bpf/devmap.c
+++ b/kernel/bpf/devmap.c
@@ -345,6 +345,20 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_buff *xdp,
return bq_enqueue(dst, xdpf, dev_rx);
}
+int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
+ struct bpf_prog *xdp_prog)
+{
+ int err;
+
+ err = __xdp_generic_ok_fwd_dev(skb, dst->dev);
+ if (unlikely(err))
+ return err;
+ skb->dev = dst->dev;
+ generic_xdp_tx(skb, xdp_prog);
+
+ return 0;
+}
+
static void *dev_map_lookup_elem(struct bpf_map *map, void *key)
{
struct bpf_dtab_netdev *obj = __dev_map_lookup_elem(map, *(u32 *)key);
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index ed13645..76efe9a 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -295,6 +295,15 @@ static const struct file_operations bpffs_map_fops = {
.release = bpffs_map_release,
};
+static int bpffs_obj_open(struct inode *inode, struct file *file)
+{
+ return -EIO;
+}
+
+static const struct file_operations bpffs_obj_fops = {
+ .open = bpffs_obj_open,
+};
+
static int bpf_mkobj_ops(struct dentry *dentry, umode_t mode, void *raw,
const struct inode_operations *iops,
const struct file_operations *fops)
@@ -314,7 +323,8 @@ static int bpf_mkobj_ops(struct dentry *dentry, umode_t mode, void *raw,
static int bpf_mkprog(struct dentry *dentry, umode_t mode, void *arg)
{
- return bpf_mkobj_ops(dentry, mode, arg, &bpf_prog_iops, NULL);
+ return bpf_mkobj_ops(dentry, mode, arg, &bpf_prog_iops,
+ &bpffs_obj_fops);
}
static int bpf_mkmap(struct dentry *dentry, umode_t mode, void *arg)
@@ -322,7 +332,7 @@ static int bpf_mkmap(struct dentry *dentry, umode_t mode, void *arg)
struct bpf_map *map = arg;
return bpf_mkobj_ops(dentry, mode, arg, &bpf_map_iops,
- map->btf ? &bpffs_map_fops : NULL);
+ map->btf ? &bpffs_map_fops : &bpffs_obj_fops);
}
static struct dentry *
diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index b4b5b81..1603492 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -623,8 +623,9 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key)
if (!key || key->prefixlen > trie->max_prefixlen)
goto find_leftmost;
- node_stack = kmalloc(trie->max_prefixlen * sizeof(struct lpm_trie_node *),
- GFP_ATOMIC | __GFP_NOWARN);
+ node_stack = kmalloc_array(trie->max_prefixlen,
+ sizeof(struct lpm_trie_node *),
+ GFP_ATOMIC | __GFP_NOWARN);
if (!node_stack)
return -ENOMEM;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 0fa2062..35dc466 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1034,14 +1034,9 @@ static void __bpf_prog_put_rcu(struct rcu_head *rcu)
static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock)
{
if (atomic_dec_and_test(&prog->aux->refcnt)) {
- int i;
-
/* bpf_prog_free_id() must be called first */
bpf_prog_free_id(prog, do_idr_lock);
-
- for (i = 0; i < prog->aux->func_cnt; i++)
- bpf_prog_kallsyms_del(prog->aux->func[i]);
- bpf_prog_kallsyms_del(prog);
+ bpf_prog_kallsyms_del_all(prog);
call_rcu(&prog->aux->rcu, __bpf_prog_put_rcu);
}
@@ -1358,9 +1353,7 @@ static int bpf_prog_load(union bpf_attr *attr)
if (err < 0)
goto free_used_maps;
- /* eBPF program is ready to be JITed */
- if (!prog->bpf_func)
- prog = bpf_prog_select_runtime(prog, &err);
+ prog = bpf_prog_select_runtime(prog, &err);
if (err < 0)
goto free_used_maps;
@@ -1384,6 +1377,7 @@ static int bpf_prog_load(union bpf_attr *attr)
return err;
free_used_maps:
+ bpf_prog_kallsyms_del_subprogs(prog);
free_used_maps(prog->aux);
free_prog:
bpf_prog_uncharge_memlock(prog);
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index d6403b5..9e2bf83 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1617,6 +1617,30 @@ static int get_callee_stack_depth(struct bpf_verifier_env *env,
}
#endif
+static int check_ctx_reg(struct bpf_verifier_env *env,
+ const struct bpf_reg_state *reg, int regno)
+{
+ /* Access to ctx or passing it to a helper is only allowed in
+ * its original, unmodified form.
+ */
+
+ if (reg->off) {
+ verbose(env, "dereference of modified ctx ptr R%d off=%d disallowed\n",
+ regno, reg->off);
+ return -EACCES;
+ }
+
+ if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
+ char tn_buf[48];
+
+ tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
+ verbose(env, "variable ctx access var_off=%s disallowed\n", tn_buf);
+ return -EACCES;
+ }
+
+ return 0;
+}
+
/* truncate register to smaller size (in bytes)
* must be called with size < BPF_REG_SIZE
*/
@@ -1686,24 +1710,11 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
verbose(env, "R%d leaks addr into ctx\n", value_regno);
return -EACCES;
}
- /* ctx accesses must be at a fixed offset, so that we can
- * determine what type of data were returned.
- */
- if (reg->off) {
- verbose(env,
- "dereference of modified ctx ptr R%d off=%d+%d, ctx+const is allowed, ctx+const+const is not\n",
- regno, reg->off, off - reg->off);
- return -EACCES;
- }
- if (!tnum_is_const(reg->var_off) || reg->var_off.value) {
- char tn_buf[48];
- tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
- verbose(env,
- "variable ctx access var_off=%s off=%d size=%d",
- tn_buf, off, size);
- return -EACCES;
- }
+ err = check_ctx_reg(env, reg, regno);
+ if (err < 0)
+ return err;
+
err = check_ctx_access(env, insn_idx, off, size, t, &reg_type);
if (!err && t == BPF_READ && value_regno >= 0) {
/* ctx access returns either a scalar, or a
@@ -1984,6 +1995,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 regno,
expected_type = PTR_TO_CTX;
if (type != expected_type)
goto err_type;
+ err = check_ctx_reg(env, reg, regno);
+ if (err < 0)
+ return err;
} else if (arg_type_is_mem_ptr(arg_type)) {
expected_type = PTR_TO_STACK;
/* One exception here. In case function allows for NULL to be
@@ -5192,7 +5206,8 @@ static int adjust_insn_aux_data(struct bpf_verifier_env *env, u32 prog_len,
if (cnt == 1)
return 0;
- new_data = vzalloc(sizeof(struct bpf_insn_aux_data) * prog_len);
+ new_data = vzalloc(array_size(prog_len,
+ sizeof(struct bpf_insn_aux_data)));
if (!new_data)
return -ENOMEM;
memcpy(new_data, old_data, sizeof(struct bpf_insn_aux_data) * off);
@@ -5433,7 +5448,7 @@ static int jit_subprogs(struct bpf_verifier_env *env)
insn->imm = 1;
}
- func = kzalloc(sizeof(prog) * env->subprog_cnt, GFP_KERNEL);
+ func = kcalloc(env->subprog_cnt, sizeof(prog), GFP_KERNEL);
if (!func)
return -ENOMEM;
@@ -5856,8 +5871,9 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
return -ENOMEM;
log = &env->log;
- env->insn_aux_data = vzalloc(sizeof(struct bpf_insn_aux_data) *
- (*prog)->len);
+ env->insn_aux_data =
+ vzalloc(array_size(sizeof(struct bpf_insn_aux_data),
+ (*prog)->len));
ret = -ENOMEM;
if (!env->insn_aux_data)
goto err_free_env;
diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c
index e06c97f..8b4f076 100644
--- a/kernel/cgroup/cgroup-v1.c
+++ b/kernel/cgroup/cgroup-v1.c
@@ -195,9 +195,9 @@ struct cgroup_pidlist {
static void *pidlist_allocate(int count)
{
if (PIDLIST_TOO_LARGE(count))
- return vmalloc(count * sizeof(pid_t));
+ return vmalloc(array_size(count, sizeof(pid_t)));
else
- return kmalloc(count * sizeof(pid_t), GFP_KERNEL);
+ return kmalloc_array(count, sizeof(pid_t), GFP_KERNEL);
}
static void pidlist_free(void *p)
diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c
index b42037e..266f10c 100644
--- a/kernel/cgroup/cpuset.c
+++ b/kernel/cgroup/cpuset.c
@@ -605,7 +605,7 @@ static inline int nr_cpusets(void)
* load balancing domains (sched domains) as specified by that partial
* partition.
*
- * See "What is sched_load_balance" in Documentation/cgroups/cpusets.txt
+ * See "What is sched_load_balance" in Documentation/cgroup-v1/cpusets.txt
* for a background explanation of this.
*
* Does not return errors, on the theory that the callers of this
@@ -683,7 +683,7 @@ static int generate_sched_domains(cpumask_var_t **domains,
goto done;
}
- csa = kmalloc(nr_cpusets() * sizeof(cp), GFP_KERNEL);
+ csa = kmalloc_array(nr_cpusets(), sizeof(cp), GFP_KERNEL);
if (!csa)
goto done;
csn = 0;
@@ -753,7 +753,8 @@ restart:
* The rest of the code, including the scheduler, can deal with
* dattr==NULL case. No need to abort if alloc fails.
*/
- dattr = kmalloc(ndoms * sizeof(struct sched_domain_attr), GFP_KERNEL);
+ dattr = kmalloc_array(ndoms, sizeof(struct sched_domain_attr),
+ GFP_KERNEL);
for (nslot = 0, i = 0; i < csn; i++) {
struct cpuset *a = csa[i];
diff --git a/kernel/configs/android-recommended.config b/kernel/configs/android-recommended.config
index 946fb92..81e9af7 100644
--- a/kernel/configs/android-recommended.config
+++ b/kernel/configs/android-recommended.config
@@ -12,7 +12,7 @@ CONFIG_BLK_DEV_DM=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_STACKPROTECTOR_STRONG=y
CONFIG_COMPACTION=y
CONFIG_CPU_SW_DOMAIN_PAN=y
CONFIG_DM_CRYPT=y
diff --git a/kernel/configs/tiny.config b/kernel/configs/tiny.config
index 9bfdffc..7fa0c4a 100644
--- a/kernel/configs/tiny.config
+++ b/kernel/configs/tiny.config
@@ -10,7 +10,3 @@ CONFIG_OPTIMIZE_INLINING=y
# CONFIG_SLAB is not set
# CONFIG_SLUB is not set
CONFIG_SLOB=y
-CONFIG_CC_STACKPROTECTOR_NONE=y
-# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
-# CONFIG_CC_STACKPROTECTOR_STRONG is not set
-# CONFIG_CC_STACKPROTECTOR_AUTO is not set
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index e405677..2ddfce8 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -691,7 +691,7 @@ static int kdb_defcmd2(const char *cmdstr, const char *argv0)
}
if (!s->usable)
return KDB_NOTIMP;
- s->command = kzalloc((s->count + 1) * sizeof(*(s->command)), GFP_KDB);
+ s->command = kcalloc(s->count + 1, sizeof(*(s->command)), GFP_KDB);
if (!s->command) {
kdb_printf("Could not allocate new kdb_defcmd table for %s\n",
cmdstr);
@@ -729,8 +729,8 @@ static int kdb_defcmd(int argc, const char **argv)
kdb_printf("Command only available during kdb_init()\n");
return KDB_NOTIMP;
}
- defcmd_set = kmalloc((defcmd_set_count + 1) * sizeof(*defcmd_set),
- GFP_KDB);
+ defcmd_set = kmalloc_array(defcmd_set_count + 1, sizeof(*defcmd_set),
+ GFP_KDB);
if (!defcmd_set)
goto fail_defcmd;
memcpy(defcmd_set, save_defcmd_set,
@@ -2706,8 +2706,11 @@ int kdb_register_flags(char *cmd,
}
if (i >= kdb_max_commands) {
- kdbtab_t *new = kmalloc((kdb_max_commands - KDB_BASE_CMD_MAX +
- kdb_command_extend) * sizeof(*new), GFP_KDB);
+ kdbtab_t *new = kmalloc_array(kdb_max_commands -
+ KDB_BASE_CMD_MAX +
+ kdb_command_extend,
+ sizeof(*new),
+ GFP_KDB);
if (!new) {
kdb_printf("Could not allocate new kdb_command "
"table\n");
diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig
new file mode 100644
index 0000000..9bd5430
--- /dev/null
+++ b/kernel/dma/Kconfig
@@ -0,0 +1,50 @@
+
+config HAS_DMA
+ bool
+ depends on !NO_DMA
+ default y
+
+config NEED_SG_DMA_LENGTH
+ bool
+
+config NEED_DMA_MAP_STATE
+ bool
+
+config ARCH_DMA_ADDR_T_64BIT
+ def_bool 64BIT || PHYS_ADDR_T_64BIT
+
+config HAVE_GENERIC_DMA_COHERENT
+ bool
+
+config ARCH_HAS_SYNC_DMA_FOR_DEVICE
+ bool
+
+config ARCH_HAS_SYNC_DMA_FOR_CPU
+ bool
+ select NEED_DMA_MAP_STATE
+
+config DMA_DIRECT_OPS
+ bool
+ depends on HAS_DMA
+
+config DMA_NONCOHERENT_OPS
+ bool
+ depends on HAS_DMA
+ select DMA_DIRECT_OPS
+
+config DMA_NONCOHERENT_MMAP
+ bool
+ depends on DMA_NONCOHERENT_OPS
+
+config DMA_NONCOHERENT_CACHE_SYNC
+ bool
+ depends on DMA_NONCOHERENT_OPS
+
+config DMA_VIRT_OPS
+ bool
+ depends on HAS_DMA
+
+config SWIOTLB
+ bool
+ select DMA_DIRECT_OPS
+ select NEED_DMA_MAP_STATE
diff --git a/kernel/dma/Makefile b/kernel/dma/Makefile
new file mode 100644
index 0000000..6de44e4
--- /dev/null
+++ b/kernel/dma/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_HAS_DMA) += mapping.o
+obj-$(CONFIG_DMA_CMA) += contiguous.o
+obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += coherent.o
+obj-$(CONFIG_DMA_DIRECT_OPS) += direct.o
+obj-$(CONFIG_DMA_NONCOHERENT_OPS) += noncoherent.o
+obj-$(CONFIG_DMA_VIRT_OPS) += virt.o
+obj-$(CONFIG_DMA_API_DEBUG) += debug.o
+obj-$(CONFIG_SWIOTLB) += swiotlb.o
+
diff --git a/drivers/base/dma-coherent.c b/kernel/dma/coherent.c
index 597d408..597d408 100644
--- a/drivers/base/dma-coherent.c
+++ b/kernel/dma/coherent.c
diff --git a/drivers/base/dma-contiguous.c b/kernel/dma/contiguous.c
index d987dcd..d987dcd 100644
--- a/drivers/base/dma-contiguous.c
+++ b/kernel/dma/contiguous.c
diff --git a/lib/dma-debug.c b/kernel/dma/debug.c
index c007d25..c007d25 100644
--- a/lib/dma-debug.c
+++ b/kernel/dma/debug.c
diff --git a/lib/dma-direct.c b/kernel/dma/direct.c
index 8be8106..8be8106 100644
--- a/lib/dma-direct.c
+++ b/kernel/dma/direct.c
diff --git a/drivers/base/dma-mapping.c b/kernel/dma/mapping.c
index f831a58..d2a92dd 100644
--- a/drivers/base/dma-mapping.c
+++ b/kernel/dma/mapping.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * drivers/base/dma-mapping.c - arch-independent dma-mapping routines
+ * arch-independent dma-mapping routines
*
* Copyright (c) 2006 SUSE Linux Products GmbH
* Copyright (c) 2006 Tejun Heo <teheo@suse.de>
diff --git a/lib/dma-noncoherent.c b/kernel/dma/noncoherent.c
index 79e9a75..79e9a75 100644
--- a/lib/dma-noncoherent.c
+++ b/kernel/dma/noncoherent.c
diff --git a/lib/swiotlb.c b/kernel/dma/swiotlb.c
index 04b68d9..04b68d9 100644
--- a/lib/swiotlb.c
+++ b/kernel/dma/swiotlb.c
diff --git a/lib/dma-virt.c b/kernel/dma/virt.c
index 8e61a02..631ddec 100644
--- a/lib/dma-virt.c
+++ b/kernel/dma/virt.c
@@ -1,7 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * lib/dma-virt.c
- *
* DMA operations that map to virtual addresses without flushing memory.
*/
#include <linux/export.h>
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index d11f60c..5d3cf40 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -614,7 +614,8 @@ int rb_alloc_aux(struct ring_buffer *rb, struct perf_event *event,
}
}
- rb->aux_pages = kzalloc_node(nr_pages * sizeof(void *), GFP_KERNEL, node);
+ rb->aux_pages = kcalloc_node(nr_pages, sizeof(void *), GFP_KERNEL,
+ node);
if (!rb->aux_pages)
return -ENOMEM;
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 1725b90..ccc579a 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -1184,7 +1184,8 @@ static struct xol_area *__create_xol_area(unsigned long vaddr)
if (unlikely(!area))
goto out;
- area->bitmap = kzalloc(BITS_TO_LONGS(UINSNS_PER_PAGE) * sizeof(long), GFP_KERNEL);
+ area->bitmap = kcalloc(BITS_TO_LONGS(UINSNS_PER_PAGE), sizeof(long),
+ GFP_KERNEL);
if (!area->bitmap)
goto free_area;
diff --git a/kernel/fail_function.c b/kernel/fail_function.c
index 1d5632d..5349c91 100644
--- a/kernel/fail_function.c
+++ b/kernel/fail_function.c
@@ -258,7 +258,7 @@ static ssize_t fei_write(struct file *file, const char __user *buffer,
/* cut off if it is too long */
if (count > KSYM_NAME_LEN)
count = KSYM_NAME_LEN;
- buf = kmalloc(sizeof(char) * (count + 1), GFP_KERNEL);
+ buf = kmalloc(count + 1, GFP_KERNEL);
if (!buf)
return -ENOMEM;
diff --git a/kernel/fork.c b/kernel/fork.c
index 08c6e5e..9440d61 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -440,6 +440,14 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
continue;
}
charge = 0;
+ /*
+ * Don't duplicate many vmas if we've been oom-killed (for
+ * example)
+ */
+ if (fatal_signal_pending(current)) {
+ retval = -EINTR;
+ goto out;
+ }
if (mpnt->vm_flags & VM_ACCOUNT) {
unsigned long len = vma_pages(mpnt);
@@ -811,7 +819,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
clear_tsk_need_resched(tsk);
set_task_stack_end_magic(tsk);
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
tsk->stack_canary = get_random_canary();
#endif
diff --git a/kernel/gcov/Kconfig b/kernel/gcov/Kconfig
index 1276aab..1e3823f 100644
--- a/kernel/gcov/Kconfig
+++ b/kernel/gcov/Kconfig
@@ -53,23 +53,16 @@ config GCOV_PROFILE_ALL
choice
prompt "Specify GCOV format"
depends on GCOV_KERNEL
- default GCOV_FORMAT_AUTODETECT
---help---
- The gcov format is usually determined by the GCC version, but there are
+ The gcov format is usually determined by the GCC version, and the
+ default is chosen according to your GCC version. However, there are
exceptions where format changes are integrated in lower-version GCCs.
- In such a case use this option to adjust the format used in the kernel
- accordingly.
-
- If unsure, choose "Autodetect".
-
-config GCOV_FORMAT_AUTODETECT
- bool "Autodetect"
- ---help---
- Select this option to use the format that corresponds to your GCC
- version.
+ In such a case, change this option to adjust the format used in the
+ kernel accordingly.
config GCOV_FORMAT_3_4
bool "GCC 3.4 format"
+ depends on CC_IS_GCC && GCC_VERSION < 40700
---help---
Select this option to use the format defined by GCC 3.4.
diff --git a/kernel/gcov/Makefile b/kernel/gcov/Makefile
index c6c50e5..ff06d64 100644
--- a/kernel/gcov/Makefile
+++ b/kernel/gcov/Makefile
@@ -4,5 +4,3 @@ ccflags-y := -DSRCTREE='"$(srctree)"' -DOBJTREE='"$(objtree)"'
obj-y := base.o fs.o
obj-$(CONFIG_GCOV_FORMAT_3_4) += gcc_3_4.o
obj-$(CONFIG_GCOV_FORMAT_4_7) += gcc_4_7.o
-obj-$(CONFIG_GCOV_FORMAT_AUTODETECT) += $(call cc-ifversion, -lt, 0407, \
- gcc_3_4.o, gcc_4_7.o)
diff --git a/kernel/irq/debugfs.c b/kernel/irq/debugfs.c
index 4dadeb3..6f63613 100644
--- a/kernel/irq/debugfs.c
+++ b/kernel/irq/debugfs.c
@@ -55,6 +55,7 @@ static const struct irq_bit_descr irqchip_flags[] = {
BIT_MASK_DESCR(IRQCHIP_SKIP_SET_WAKE),
BIT_MASK_DESCR(IRQCHIP_ONESHOT_SAFE),
BIT_MASK_DESCR(IRQCHIP_EOI_THREADED),
+ BIT_MASK_DESCR(IRQCHIP_SUPPORTS_LEVEL_MSI),
};
static void
diff --git a/kernel/kcov.c b/kernel/kcov.c
index 2c16f1a..3ebd09e 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -58,7 +58,7 @@ struct kcov {
static bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t)
{
- enum kcov_mode mode;
+ unsigned int mode;
/*
* We are interested in code coverage as a function of a syscall inputs,
@@ -241,7 +241,8 @@ static void kcov_put(struct kcov *kcov)
void kcov_task_init(struct task_struct *t)
{
- t->kcov_mode = KCOV_MODE_DISABLED;
+ WRITE_ONCE(t->kcov_mode, KCOV_MODE_DISABLED);
+ barrier();
t->kcov_size = 0;
t->kcov_area = NULL;
t->kcov = NULL;
@@ -323,6 +324,21 @@ static int kcov_close(struct inode *inode, struct file *filep)
return 0;
}
+/*
+ * Fault in a lazily-faulted vmalloc area before it can be used by
+ * __santizer_cov_trace_pc(), to avoid recursion issues if any code on the
+ * vmalloc fault handling path is instrumented.
+ */
+static void kcov_fault_in_area(struct kcov *kcov)
+{
+ unsigned long stride = PAGE_SIZE / sizeof(unsigned long);
+ unsigned long *area = kcov->area;
+ unsigned long offset;
+
+ for (offset = 0; offset < kcov->size; offset += stride)
+ READ_ONCE(area[offset]);
+}
+
static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd,
unsigned long arg)
{
@@ -371,6 +387,7 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd,
#endif
else
return -EINVAL;
+ kcov_fault_in_area(kcov);
/* Cache in task struct for performance. */
t->kcov_size = kcov->size;
t->kcov_area = kcov->area;
diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c
index 20fef1a..23a83a4 100644
--- a/kernel/kexec_core.c
+++ b/kernel/kexec_core.c
@@ -829,6 +829,8 @@ static int kimage_load_normal_segment(struct kimage *image,
else
buf += mchunk;
mbytes -= mchunk;
+
+ cond_resched();
}
out:
return result;
@@ -893,6 +895,8 @@ static int kimage_load_crash_segment(struct kimage *image,
else
buf += mchunk;
mbytes -= mchunk;
+
+ cond_resched();
}
out:
return result;
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 75d8e7c..c6a3b68 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -793,7 +793,7 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
* The section headers in kexec_purgatory are read-only. In order to
* have them modifiable make a temporary copy.
*/
- sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr));
+ sechdrs = vzalloc(array_size(sizeof(Elf_Shdr), pi->ehdr->e_shnum));
if (!sechdrs)
return -ENOMEM;
memcpy(sechdrs, (void *)pi->ehdr + pi->ehdr->e_shoff,
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index edcac5d..5fa4d31 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -1265,11 +1265,11 @@ unsigned long lockdep_count_forward_deps(struct lock_class *class)
this.parent = NULL;
this.class = class;
- local_irq_save(flags);
+ raw_local_irq_save(flags);
arch_spin_lock(&lockdep_lock);
ret = __lockdep_count_forward_deps(&this);
arch_spin_unlock(&lockdep_lock);
- local_irq_restore(flags);
+ raw_local_irq_restore(flags);
return ret;
}
@@ -1292,11 +1292,11 @@ unsigned long lockdep_count_backward_deps(struct lock_class *class)
this.parent = NULL;
this.class = class;
- local_irq_save(flags);
+ raw_local_irq_save(flags);
arch_spin_lock(&lockdep_lock);
ret = __lockdep_count_backward_deps(&this);
arch_spin_unlock(&lockdep_lock);
- local_irq_restore(flags);
+ raw_local_irq_restore(flags);
return ret;
}
@@ -4411,7 +4411,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
if (unlikely(!debug_locks))
return;
- local_irq_save(flags);
+ raw_local_irq_save(flags);
for (i = 0; i < curr->lockdep_depth; i++) {
hlock = curr->held_locks + i;
@@ -4422,7 +4422,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
print_freed_lock_bug(curr, mem_from, mem_from + mem_len, hlock);
break;
}
- local_irq_restore(flags);
+ raw_local_irq_restore(flags);
}
EXPORT_SYMBOL_GPL(debug_check_no_locks_freed);
diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
index 6850ffd..8402b33 100644
--- a/kernel/locking/locktorture.c
+++ b/kernel/locking/locktorture.c
@@ -913,7 +913,9 @@ static int __init lock_torture_init(void)
/* Initialize the statistics so that each run gets its own numbers. */
if (nwriters_stress) {
lock_is_write_held = 0;
- cxt.lwsa = kmalloc(sizeof(*cxt.lwsa) * cxt.nrealwriters_stress, GFP_KERNEL);
+ cxt.lwsa = kmalloc_array(cxt.nrealwriters_stress,
+ sizeof(*cxt.lwsa),
+ GFP_KERNEL);
if (cxt.lwsa == NULL) {
VERBOSE_TOROUT_STRING("cxt.lwsa: Out of memory");
firsterr = -ENOMEM;
@@ -942,7 +944,9 @@ static int __init lock_torture_init(void)
if (nreaders_stress) {
lock_is_read_held = 0;
- cxt.lrsa = kmalloc(sizeof(*cxt.lrsa) * cxt.nrealreaders_stress, GFP_KERNEL);
+ cxt.lrsa = kmalloc_array(cxt.nrealreaders_stress,
+ sizeof(*cxt.lrsa),
+ GFP_KERNEL);
if (cxt.lrsa == NULL) {
VERBOSE_TOROUT_STRING("cxt.lrsa: Out of memory");
firsterr = -ENOMEM;
@@ -985,7 +989,8 @@ static int __init lock_torture_init(void)
}
if (nwriters_stress) {
- writer_tasks = kzalloc(cxt.nrealwriters_stress * sizeof(writer_tasks[0]),
+ writer_tasks = kcalloc(cxt.nrealwriters_stress,
+ sizeof(writer_tasks[0]),
GFP_KERNEL);
if (writer_tasks == NULL) {
VERBOSE_TOROUT_ERRSTRING("writer_tasks: Out of memory");
@@ -995,7 +1000,8 @@ static int __init lock_torture_init(void)
}
if (cxt.cur_ops->readlock) {
- reader_tasks = kzalloc(cxt.nrealreaders_stress * sizeof(reader_tasks[0]),
+ reader_tasks = kcalloc(cxt.nrealreaders_stress,
+ sizeof(reader_tasks[0]),
GFP_KERNEL);
if (reader_tasks == NULL) {
VERBOSE_TOROUT_ERRSTRING("reader_tasks: Out of memory");
diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c
index bc1e507..776308d 100644
--- a/kernel/locking/rwsem.c
+++ b/kernel/locking/rwsem.c
@@ -181,6 +181,7 @@ void down_read_non_owner(struct rw_semaphore *sem)
might_sleep();
__down_read(sem);
+ rwsem_set_reader_owned(sem);
}
EXPORT_SYMBOL(down_read_non_owner);
diff --git a/kernel/module.c b/kernel/module.c
index 68469b3..f475f30 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -274,9 +274,7 @@ static void module_assert_mutex_or_preempt(void)
}
static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE);
-#ifndef CONFIG_MODULE_SIG_FORCE
module_param(sig_enforce, bool_enable_only, 0644);
-#endif /* !CONFIG_MODULE_SIG_FORCE */
/*
* Export sig_enforce kernel cmdline parameter to allow other subsystems rely
@@ -2785,7 +2783,7 @@ static int module_sig_check(struct load_info *info, int flags)
}
/* Not having a signature is only an error if we're strict. */
- if (err == -ENOKEY && !sig_enforce)
+ if (err == -ENOKEY && !is_module_sig_enforced())
err = 0;
return err;
diff --git a/kernel/panic.c b/kernel/panic.c
index 42e4874..8b2e002 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -623,7 +623,7 @@ static __init int register_warn_debugfs(void)
device_initcall(register_warn_debugfs);
#endif
-#ifdef CONFIG_CC_STACKPROTECTOR
+#ifdef CONFIG_STACKPROTECTOR
/*
* Called when gcc's -fstack-protector feature is used, and
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 705c236..d9706da 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -455,8 +455,9 @@ struct kobject *power_kobj;
* state - control system sleep states.
*
* show() returns available sleep state labels, which may be "mem", "standby",
- * "freeze" and "disk" (hibernation). See Documentation/power/states.txt for a
- * description of what they mean.
+ * "freeze" and "disk" (hibernation).
+ * See Documentation/admin-guide/pm/sleep-states.rst for a description of
+ * what they mean.
*
* store() accepts one of those strings, translates it into the proper
* enumerated value, and initiates a suspend transition.
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 1efcb5b..c2bcf97 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -698,7 +698,7 @@ static int save_image_lzo(struct swap_map_handle *handle,
goto out_clean;
}
- data = vmalloc(sizeof(*data) * nr_threads);
+ data = vmalloc(array_size(nr_threads, sizeof(*data)));
if (!data) {
pr_err("Failed to allocate LZO data\n");
ret = -ENOMEM;
@@ -1183,14 +1183,14 @@ static int load_image_lzo(struct swap_map_handle *handle,
nr_threads = num_online_cpus() - 1;
nr_threads = clamp_val(nr_threads, 1, LZO_THREADS);
- page = vmalloc(sizeof(*page) * LZO_MAX_RD_PAGES);
+ page = vmalloc(array_size(LZO_MAX_RD_PAGES, sizeof(*page)));
if (!page) {
pr_err("Failed to allocate LZO page\n");
ret = -ENOMEM;
goto out_clean;
}
- data = vmalloc(sizeof(*data) * nr_threads);
+ data = vmalloc(array_size(nr_threads, sizeof(*data)));
if (!data) {
pr_err("Failed to allocate LZO data\n");
ret = -ENOMEM;
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index e628fcf..42fcb7f 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -831,8 +831,9 @@ rcu_torture_cbflood(void *arg)
cbflood_intra_holdoff > 0 &&
cur_ops->call &&
cur_ops->cb_barrier) {
- rhp = vmalloc(sizeof(*rhp) *
- cbflood_n_burst * cbflood_n_per_burst);
+ rhp = vmalloc(array3_size(cbflood_n_burst,
+ cbflood_n_per_burst,
+ sizeof(*rhp)));
err = !rhp;
}
if (err) {
diff --git a/kernel/relay.c b/kernel/relay.c
index c955b10..04f2486 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -39,7 +39,7 @@ static void relay_file_mmap_close(struct vm_area_struct *vma)
/*
* fault() vm_op implementation for relay file mapping.
*/
-static int relay_buf_fault(struct vm_fault *vmf)
+static vm_fault_t relay_buf_fault(struct vm_fault *vmf)
{
struct page *page;
struct rchan_buf *buf = vmf->vma->vm_private_data;
@@ -169,7 +169,8 @@ static struct rchan_buf *relay_create_buf(struct rchan *chan)
buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL);
if (!buf)
return NULL;
- buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL);
+ buf->padding = kmalloc_array(chan->n_subbufs, sizeof(size_t *),
+ GFP_KERNEL);
if (!buf->padding)
goto free_buf;
diff --git a/kernel/rseq.c b/kernel/rseq.c
index ae306f9..22b6acf 100644
--- a/kernel/rseq.c
+++ b/kernel/rseq.c
@@ -251,10 +251,10 @@ static int rseq_ip_fixup(struct pt_regs *regs)
* respect to other threads scheduled on the same CPU, and with respect
* to signal handlers.
*/
-void __rseq_handle_notify_resume(struct pt_regs *regs)
+void __rseq_handle_notify_resume(struct ksignal *ksig, struct pt_regs *regs)
{
struct task_struct *t = current;
- int ret;
+ int ret, sig;
if (unlikely(t->flags & PF_EXITING))
return;
@@ -268,7 +268,8 @@ void __rseq_handle_notify_resume(struct pt_regs *regs)
return;
error:
- force_sig(SIGSEGV, t);
+ sig = ksig ? ksig->sig : 0;
+ force_sigsegv(sig, t);
}
#ifdef CONFIG_DEBUG_RSEQ
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index a98d54c..78d8fac 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -10,6 +10,8 @@
#include <linux/kthread.h>
#include <linux/nospec.h>
+#include <linux/kcov.h>
+
#include <asm/switch_to.h>
#include <asm/tlb.h>
@@ -2633,6 +2635,7 @@ static inline void
prepare_task_switch(struct rq *rq, struct task_struct *prev,
struct task_struct *next)
{
+ kcov_prepare_switch(prev);
sched_info_switch(rq, prev, next);
perf_event_task_sched_out(prev, next);
rseq_preempt(prev);
@@ -2702,6 +2705,7 @@ static struct rq *finish_task_switch(struct task_struct *prev)
finish_task(prev);
finish_lock_switch(rq);
finish_arch_post_lock_switch();
+ kcov_finish_switch(current);
fire_sched_in_preempt_notifiers(current);
/*
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e497c05..1866e64 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -10215,10 +10215,10 @@ int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
struct cfs_rq *cfs_rq;
int i;
- tg->cfs_rq = kzalloc(sizeof(cfs_rq) * nr_cpu_ids, GFP_KERNEL);
+ tg->cfs_rq = kcalloc(nr_cpu_ids, sizeof(cfs_rq), GFP_KERNEL);
if (!tg->cfs_rq)
goto err;
- tg->se = kzalloc(sizeof(se) * nr_cpu_ids, GFP_KERNEL);
+ tg->se = kcalloc(nr_cpu_ids, sizeof(se), GFP_KERNEL);
if (!tg->se)
goto err;
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index ef3c4e6..47556b0 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -183,10 +183,10 @@ int alloc_rt_sched_group(struct task_group *tg, struct task_group *parent)
struct sched_rt_entity *rt_se;
int i;
- tg->rt_rq = kzalloc(sizeof(rt_rq) * nr_cpu_ids, GFP_KERNEL);
+ tg->rt_rq = kcalloc(nr_cpu_ids, sizeof(rt_rq), GFP_KERNEL);
if (!tg->rt_rq)
goto err;
- tg->rt_se = kzalloc(sizeof(rt_se) * nr_cpu_ids, GFP_KERNEL);
+ tg->rt_se = kcalloc(nr_cpu_ids, sizeof(rt_se), GFP_KERNEL);
if (!tg->rt_se)
goto err;
diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c
index 61a1125..05a8314 100644
--- a/kernel/sched/topology.c
+++ b/kernel/sched/topology.c
@@ -1750,7 +1750,7 @@ cpumask_var_t *alloc_sched_domains(unsigned int ndoms)
int i;
cpumask_var_t *doms;
- doms = kmalloc(sizeof(*doms) * ndoms, GFP_KERNEL);
+ doms = kmalloc_array(ndoms, sizeof(*doms), GFP_KERNEL);
if (!doms)
return NULL;
for (i = 0; i < ndoms; i++) {
diff --git a/kernel/softirq.c b/kernel/softirq.c
index de2f57f..900dcfe 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -139,9 +139,13 @@ static void __local_bh_enable(unsigned int cnt)
{
lockdep_assert_irqs_disabled();
+ if (preempt_count() == cnt)
+ trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip());
+
if (softirq_count() == (cnt & SOFTIRQ_MASK))
trace_softirqs_on(_RET_IP_);
- preempt_count_sub(cnt);
+
+ __preempt_count_sub(cnt);
}
/*
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 6a78cf7..2d9837c 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -3047,7 +3047,8 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,
if (IS_ERR(kbuf))
return PTR_ERR(kbuf);
- tmp_bitmap = kzalloc(BITS_TO_LONGS(bitmap_len) * sizeof(unsigned long),
+ tmp_bitmap = kcalloc(BITS_TO_LONGS(bitmap_len),
+ sizeof(unsigned long),
GFP_KERNEL);
if (!tmp_bitmap) {
kfree(kbuf);
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 055a4a7..3e93c54 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -1659,7 +1659,7 @@ EXPORT_SYMBOL_GPL(hrtimer_init_sleeper);
int nanosleep_copyout(struct restart_block *restart, struct timespec64 *ts)
{
switch(restart->nanosleep.type) {
-#ifdef CONFIG_COMPAT
+#ifdef CONFIG_COMPAT_32BIT_TIME
case TT_COMPAT:
if (compat_put_timespec64(ts, restart->nanosleep.compat_rmtp))
return -EFAULT;
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 5a6251ac..9cdf54b 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -604,7 +604,6 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
/*
* Disarm any old timer after extracting its expiry time.
*/
- lockdep_assert_irqs_disabled();
ret = 0;
old_incr = timer->it.cpu.incr;
@@ -1049,7 +1048,6 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
/*
* Now re-arm for the new expiry time.
*/
- lockdep_assert_irqs_disabled();
arm_timer(timer);
unlock:
unlock_task_sighand(p, &flags);
diff --git a/kernel/time/time.c b/kernel/time/time.c
index 6fa9921..2b41e8e 100644
--- a/kernel/time/time.c
+++ b/kernel/time/time.c
@@ -28,6 +28,7 @@
*/
#include <linux/export.h>
+#include <linux/kernel.h>
#include <linux/timex.h>
#include <linux/capability.h>
#include <linux/timekeeper_internal.h>
@@ -314,9 +315,10 @@ unsigned int jiffies_to_msecs(const unsigned long j)
return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC);
#else
# if BITS_PER_LONG == 32
- return (HZ_TO_MSEC_MUL32 * j) >> HZ_TO_MSEC_SHR32;
+ return (HZ_TO_MSEC_MUL32 * j + (1ULL << HZ_TO_MSEC_SHR32) - 1) >>
+ HZ_TO_MSEC_SHR32;
# else
- return (j * HZ_TO_MSEC_NUM) / HZ_TO_MSEC_DEN;
+ return DIV_ROUND_UP(j * HZ_TO_MSEC_NUM, HZ_TO_MSEC_DEN);
# endif
#endif
}
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index dd6c0a2..dcc0166 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -12,22 +12,22 @@ config NOP_TRACER
config HAVE_FTRACE_NMI_ENTER
bool
help
- See Documentation/trace/ftrace-design.txt
+ See Documentation/trace/ftrace-design.rst
config HAVE_FUNCTION_TRACER
bool
help
- See Documentation/trace/ftrace-design.txt
+ See Documentation/trace/ftrace-design.rst
config HAVE_FUNCTION_GRAPH_TRACER
bool
help
- See Documentation/trace/ftrace-design.txt
+ See Documentation/trace/ftrace-design.rst
config HAVE_DYNAMIC_FTRACE
bool
help
- See Documentation/trace/ftrace-design.txt
+ See Documentation/trace/ftrace-design.rst
config HAVE_DYNAMIC_FTRACE_WITH_REGS
bool
@@ -35,12 +35,12 @@ config HAVE_DYNAMIC_FTRACE_WITH_REGS
config HAVE_FTRACE_MCOUNT_RECORD
bool
help
- See Documentation/trace/ftrace-design.txt
+ See Documentation/trace/ftrace-design.rst
config HAVE_SYSCALL_TRACEPOINTS
bool
help
- See Documentation/trace/ftrace-design.txt
+ See Documentation/trace/ftrace-design.rst
config HAVE_FENTRY
bool
@@ -448,7 +448,7 @@ config KPROBE_EVENTS
help
This allows the user to add tracing events (similar to tracepoints)
on the fly via the ftrace interface. See
- Documentation/trace/kprobetrace.txt for more details.
+ Documentation/trace/kprobetrace.rst for more details.
Those events can be inserted wherever kprobes can probe, and record
various register and memory values.
@@ -575,7 +575,7 @@ config MMIOTRACE
implementation and works via page faults. Tracing is disabled by
default and can be enabled at run-time.
- See Documentation/trace/mmiotrace.txt.
+ See Documentation/trace/mmiotrace.rst.
If you are not helping to develop drivers, say N.
config TRACING_MAP
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 8d83bcf..efed9c1 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -728,7 +728,7 @@ static int ftrace_profile_init_cpu(int cpu)
*/
size = FTRACE_PROFILE_HASH_SIZE;
- stat->hash = kzalloc(sizeof(struct hlist_head) * size, GFP_KERNEL);
+ stat->hash = kcalloc(size, sizeof(struct hlist_head), GFP_KERNEL);
if (!stat->hash)
return -ENOMEM;
@@ -6830,9 +6830,10 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
struct task_struct *g, *t;
for (i = 0; i < FTRACE_RETSTACK_ALLOC_SIZE; i++) {
- ret_stack_list[i] = kmalloc(FTRACE_RETFUNC_DEPTH
- * sizeof(struct ftrace_ret_stack),
- GFP_KERNEL);
+ ret_stack_list[i] =
+ kmalloc_array(FTRACE_RETFUNC_DEPTH,
+ sizeof(struct ftrace_ret_stack),
+ GFP_KERNEL);
if (!ret_stack_list[i]) {
start = 0;
end = i;
@@ -6904,9 +6905,9 @@ static int start_graph_tracing(void)
struct ftrace_ret_stack **ret_stack_list;
int ret, cpu;
- ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE *
- sizeof(struct ftrace_ret_stack *),
- GFP_KERNEL);
+ ret_stack_list = kmalloc_array(FTRACE_RETSTACK_ALLOC_SIZE,
+ sizeof(struct ftrace_ret_stack *),
+ GFP_KERNEL);
if (!ret_stack_list)
return -ENOMEM;
@@ -7088,9 +7089,10 @@ void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
ret_stack = per_cpu(idle_ret_stack, cpu);
if (!ret_stack) {
- ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
- * sizeof(struct ftrace_ret_stack),
- GFP_KERNEL);
+ ret_stack =
+ kmalloc_array(FTRACE_RETFUNC_DEPTH,
+ sizeof(struct ftrace_ret_stack),
+ GFP_KERNEL);
if (!ret_stack)
return;
per_cpu(idle_ret_stack, cpu) = ret_stack;
@@ -7109,9 +7111,9 @@ void ftrace_graph_init_task(struct task_struct *t)
if (ftrace_graph_active) {
struct ftrace_ret_stack *ret_stack;
- ret_stack = kmalloc(FTRACE_RETFUNC_DEPTH
- * sizeof(struct ftrace_ret_stack),
- GFP_KERNEL);
+ ret_stack = kmalloc_array(FTRACE_RETFUNC_DEPTH,
+ sizeof(struct ftrace_ret_stack),
+ GFP_KERNEL);
if (!ret_stack)
return;
graph_init_task(t, ret_stack);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 108ce3e..a0079b4 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1360,8 +1360,6 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
void
update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
{
- struct ring_buffer *buf;
-
if (tr->stop_count)
return;
@@ -1375,9 +1373,7 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
arch_spin_lock(&tr->max_lock);
- buf = tr->trace_buffer.buffer;
- tr->trace_buffer.buffer = tr->max_buffer.buffer;
- tr->max_buffer.buffer = buf;
+ swap(tr->trace_buffer.buffer, tr->max_buffer.buffer);
__update_max_tr(tr, tsk, cpu);
arch_spin_unlock(&tr->max_lock);
@@ -1751,12 +1747,13 @@ static inline void set_cmdline(int idx, const char *cmdline)
static int allocate_cmdlines_buffer(unsigned int val,
struct saved_cmdlines_buffer *s)
{
- s->map_cmdline_to_pid = kmalloc(val * sizeof(*s->map_cmdline_to_pid),
- GFP_KERNEL);
+ s->map_cmdline_to_pid = kmalloc_array(val,
+ sizeof(*s->map_cmdline_to_pid),
+ GFP_KERNEL);
if (!s->map_cmdline_to_pid)
return -ENOMEM;
- s->saved_cmdlines = kmalloc(val * TASK_COMM_LEN, GFP_KERNEL);
+ s->saved_cmdlines = kmalloc_array(TASK_COMM_LEN, val, GFP_KERNEL);
if (!s->saved_cmdlines) {
kfree(s->map_cmdline_to_pid);
return -ENOMEM;
@@ -4360,7 +4357,8 @@ int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled)
if (mask == TRACE_ITER_RECORD_TGID) {
if (!tgid_map)
- tgid_map = kzalloc((PID_MAX_DEFAULT + 1) * sizeof(*tgid_map),
+ tgid_map = kcalloc(PID_MAX_DEFAULT + 1,
+ sizeof(*tgid_map),
GFP_KERNEL);
if (!tgid_map) {
tr->trace_flags &= ~TRACE_ITER_RECORD_TGID;
@@ -5063,7 +5061,7 @@ trace_insert_eval_map_file(struct module *mod, struct trace_eval_map **start,
* where the head holds the module and length of array, and the
* tail holds a pointer to the next list.
*/
- map_array = kmalloc(sizeof(*map_array) * (len + 2), GFP_KERNEL);
+ map_array = kmalloc_array(len + 2, sizeof(*map_array), GFP_KERNEL);
if (!map_array) {
pr_warn("Unable to allocate trace eval mapping\n");
return;
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 0171407..0dceb77 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -78,7 +78,8 @@ static const char * ops[] = { OPS };
C(TOO_MANY_PREDS, "Too many terms in predicate expression"), \
C(INVALID_FILTER, "Meaningless filter expression"), \
C(IP_FIELD_ONLY, "Only 'ip' field is supported for function trace"), \
- C(INVALID_VALUE, "Invalid value (did you forget quotes)?"),
+ C(INVALID_VALUE, "Invalid value (did you forget quotes)?"), \
+ C(NO_FILTER, "No filter found"),
#undef C
#define C(a, b) FILT_ERR_##a
@@ -436,15 +437,15 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
nr_preds += 2; /* For TRUE and FALSE */
- op_stack = kmalloc(sizeof(*op_stack) * nr_parens, GFP_KERNEL);
+ op_stack = kmalloc_array(nr_parens, sizeof(*op_stack), GFP_KERNEL);
if (!op_stack)
return ERR_PTR(-ENOMEM);
- prog_stack = kmalloc(sizeof(*prog_stack) * nr_preds, GFP_KERNEL);
+ prog_stack = kmalloc_array(nr_preds, sizeof(*prog_stack), GFP_KERNEL);
if (!prog_stack) {
parse_error(pe, -ENOMEM, 0);
goto out_free;
}
- inverts = kmalloc(sizeof(*inverts) * nr_preds, GFP_KERNEL);
+ inverts = kmalloc_array(nr_preds, sizeof(*inverts), GFP_KERNEL);
if (!inverts) {
parse_error(pe, -ENOMEM, 0);
goto out_free;
@@ -550,6 +551,13 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
goto out_free;
}
+ if (!N) {
+ /* No program? */
+ ret = -EINVAL;
+ parse_error(pe, FILT_ERR_NO_FILTER, ptr - str);
+ goto out_free;
+ }
+
prog[N].pred = NULL; /* #13 */
prog[N].target = 1; /* TRUE */
prog[N+1].pred = NULL;
diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c
index 5cadb1b..752d804 100644
--- a/kernel/trace/tracing_map.c
+++ b/kernel/trace/tracing_map.c
@@ -1075,7 +1075,7 @@ int tracing_map_sort_entries(struct tracing_map *map,
struct tracing_map_sort_entry *sort_entry, **entries;
int i, n_entries, ret;
- entries = vmalloc(map->max_elts * sizeof(sort_entry));
+ entries = vmalloc(array_size(sizeof(sort_entry), map->max_elts));
if (!entries)
return -ENOMEM;
diff --git a/kernel/umh.c b/kernel/umh.c
index 30db93f..c449858 100644
--- a/kernel/umh.c
+++ b/kernel/umh.c
@@ -99,6 +99,7 @@ static int call_usermodehelper_exec_async(void *data)
commit_creds(new);
+ sub_info->pid = task_pid_nr(current);
if (sub_info->file)
retval = do_execve_file(sub_info->file,
sub_info->argv, sub_info->envp);
@@ -191,8 +192,6 @@ static void call_usermodehelper_exec_work(struct work_struct *work)
if (pid < 0) {
sub_info->retval = pid;
umh_complete(sub_info);
- } else {
- sub_info->pid = pid;
}
}
}
diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c
index 492c255..c3d7583 100644
--- a/kernel/user_namespace.c
+++ b/kernel/user_namespace.c
@@ -764,8 +764,9 @@ static int insert_extent(struct uid_gid_map *map, struct uid_gid_extent *extent)
struct uid_gid_extent *forward;
/* Allocate memory for 340 mappings. */
- forward = kmalloc(sizeof(struct uid_gid_extent) *
- UID_GID_MAP_MAX_EXTENTS, GFP_KERNEL);
+ forward = kmalloc_array(UID_GID_MAP_MAX_EXTENTS,
+ sizeof(struct uid_gid_extent),
+ GFP_KERNEL);
if (!forward)
return -ENOMEM;
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 9f9983b..78b1920 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -4362,6 +4362,7 @@ void set_worker_desc(const char *fmt, ...)
va_end(args);
}
}
+EXPORT_SYMBOL_GPL(set_worker_desc);
/**
* print_worker_info - print out worker information and description
@@ -5637,7 +5638,7 @@ static void __init wq_numa_init(void)
* available. Build one from cpu_to_node() which should have been
* fully initialized by now.
*/
- tbl = kzalloc(nr_node_ids * sizeof(tbl[0]), GFP_KERNEL);
+ tbl = kcalloc(nr_node_ids, sizeof(tbl[0]), GFP_KERNEL);
BUG_ON(!tbl);
for_each_node(node)
diff --git a/lib/Kconfig b/lib/Kconfig
index abc111e..706836e 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -405,7 +405,7 @@ config ASSOCIATIVE_ARRAY
See:
- Documentation/assoc_array.txt
+ Documentation/core-api/assoc_array.rst
for more information.
@@ -420,60 +420,15 @@ config HAS_IOPORT_MAP
depends on HAS_IOMEM && !NO_IOPORT_MAP
default y
-config HAS_DMA
- bool
- depends on !NO_DMA
- default y
+source "kernel/dma/Kconfig"
config SGL_ALLOC
bool
default n
-config NEED_SG_DMA_LENGTH
- bool
-
-config NEED_DMA_MAP_STATE
- bool
-
-config ARCH_DMA_ADDR_T_64BIT
- def_bool 64BIT || PHYS_ADDR_T_64BIT
-
config IOMMU_HELPER
bool
-config ARCH_HAS_SYNC_DMA_FOR_DEVICE
- bool
-
-config ARCH_HAS_SYNC_DMA_FOR_CPU
- bool
- select NEED_DMA_MAP_STATE
-
-config DMA_DIRECT_OPS
- bool
- depends on HAS_DMA
-
-config DMA_NONCOHERENT_OPS
- bool
- depends on HAS_DMA
- select DMA_DIRECT_OPS
-
-config DMA_NONCOHERENT_MMAP
- bool
- depends on DMA_NONCOHERENT_OPS
-
-config DMA_NONCOHERENT_CACHE_SYNC
- bool
- depends on DMA_NONCOHERENT_OPS
-
-config DMA_VIRT_OPS
- bool
- depends on HAS_DMA
-
-config SWIOTLB
- bool
- select DMA_DIRECT_OPS
- select NEED_DMA_MAP_STATE
-
config CHECK_SIGNATURE
bool
@@ -642,20 +597,20 @@ config STRING_SELFTEST
endmenu
-config GENERIC_ASHLDI3
+config GENERIC_LIB_ASHLDI3
bool
-config GENERIC_ASHRDI3
+config GENERIC_LIB_ASHRDI3
bool
-config GENERIC_LSHRDI3
+config GENERIC_LIB_LSHRDI3
bool
-config GENERIC_MULDI3
+config GENERIC_LIB_MULDI3
bool
-config GENERIC_CMPDI2
+config GENERIC_LIB_CMPDI2
bool
-config GENERIC_UCMPDI2
+config GENERIC_LIB_UCMPDI2
bool
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index eb885942..8838d11 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -736,12 +736,15 @@ config ARCH_HAS_KCOV
only for x86_64. KCOV requires testing on other archs, and most likely
disabling of instrumentation for some early boot code.
+config CC_HAS_SANCOV_TRACE_PC
+ def_bool $(cc-option,-fsanitize-coverage=trace-pc)
+
config KCOV
bool "Code coverage for fuzzing"
depends on ARCH_HAS_KCOV
+ depends on CC_HAS_SANCOV_TRACE_PC || GCC_PLUGINS
select DEBUG_FS
- select GCC_PLUGINS if !COMPILE_TEST
- select GCC_PLUGIN_SANCOV if !COMPILE_TEST
+ select GCC_PLUGIN_SANCOV if !CC_HAS_SANCOV_TRACE_PC
help
KCOV exposes kernel code coverage information in a form suitable
for coverage-guided fuzzing (randomized testing).
@@ -755,7 +758,7 @@ config KCOV
config KCOV_ENABLE_COMPARISONS
bool "Enable comparison operands collection by KCOV"
depends on KCOV
- default n
+ depends on $(cc-option,-fsanitize-coverage=trace-cmp)
help
KCOV also exposes operands of every comparison in the instrumented
code along with operand sizes and PCs of the comparison instructions.
@@ -765,7 +768,7 @@ config KCOV_ENABLE_COMPARISONS
config KCOV_INSTRUMENT_ALL
bool "Instrument all code by default"
depends on KCOV
- default y if KCOV
+ default y
help
If you are doing generic system call fuzzing (like e.g. syzkaller),
then you will want to instrument the whole kernel and you should
@@ -1503,6 +1506,10 @@ config NETDEV_NOTIFIER_ERROR_INJECT
If unsure, say N.
+config FUNCTION_ERROR_INJECTION
+ def_bool y
+ depends on HAVE_FUNCTION_ERROR_INJECTION && KPROBES
+
config FAULT_INJECTION
bool "Fault-injection framework"
depends on DEBUG_KERNEL
@@ -1510,10 +1517,6 @@ config FAULT_INJECTION
Provide fault-injection framework.
For more details, see Documentation/fault-injection/.
-config FUNCTION_ERROR_INJECTION
- def_bool y
- depends on HAVE_FUNCTION_ERROR_INJECTION && KPROBES
-
config FAILSLAB
bool "Fault-injection capability for kmalloc"
depends on FAULT_INJECTION
@@ -1544,16 +1547,6 @@ config FAIL_IO_TIMEOUT
Only works with drivers that use the generic timeout handling,
for others it wont do anything.
-config FAIL_MMC_REQUEST
- bool "Fault-injection capability for MMC IO"
- depends on FAULT_INJECTION_DEBUG_FS && MMC
- help
- Provide fault-injection capability for MMC IO.
- This will make the mmc core return data errors. This is
- useful to test the error handling in the mmc block device
- and to test how the mmc host driver handles retries from
- the block device.
-
config FAIL_FUTEX
bool "Fault-injection capability for futexes"
select DEBUG_FS
@@ -1561,6 +1554,12 @@ config FAIL_FUTEX
help
Provide fault-injection capability for futexes.
+config FAULT_INJECTION_DEBUG_FS
+ bool "Debugfs entries for fault-injection capabilities"
+ depends on FAULT_INJECTION && SYSFS && DEBUG_FS
+ help
+ Enable configuration of fault-injection capabilities via debugfs.
+
config FAIL_FUNCTION
bool "Fault-injection capability for functions"
depends on FAULT_INJECTION_DEBUG_FS && FUNCTION_ERROR_INJECTION
@@ -1571,11 +1570,15 @@ config FAIL_FUNCTION
an error value and have to handle it. This is useful to test the
error handling in various subsystems.
-config FAULT_INJECTION_DEBUG_FS
- bool "Debugfs entries for fault-injection capabilities"
- depends on FAULT_INJECTION && SYSFS && DEBUG_FS
+config FAIL_MMC_REQUEST
+ bool "Fault-injection capability for MMC IO"
+ depends on FAULT_INJECTION_DEBUG_FS && MMC
help
- Enable configuration of fault-injection capabilities via debugfs.
+ Provide fault-injection capability for MMC IO.
+ This will make the mmc core return data errors. This is
+ useful to test the error handling in the mmc block device
+ and to test how the mmc host driver handles retries from
+ the block device.
config FAULT_INJECTION_STACKTRACE_FILTER
bool "stacktrace filter for fault-injection capabilities"
diff --git a/lib/Makefile b/lib/Makefile
index 84c6dcb..90dc552 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -23,15 +23,12 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \
sha1.o chacha20.o irq_regs.o argv_split.o \
flex_proportions.o ratelimit.o show_mem.o \
is_single_threaded.o plist.o decompress.o kobject_uevent.o \
- earlycpio.o seq_buf.o siphash.o \
+ earlycpio.o seq_buf.o siphash.o dec_and_lock.o \
nmi_backtrace.o nodemask.o win_minmax.o
lib-$(CONFIG_PRINTK) += dump_stack.o
lib-$(CONFIG_MMU) += ioremap.o
lib-$(CONFIG_SMP) += cpumask.o
-lib-$(CONFIG_DMA_DIRECT_OPS) += dma-direct.o
-lib-$(CONFIG_DMA_NONCOHERENT_OPS) += dma-noncoherent.o
-lib-$(CONFIG_DMA_VIRT_OPS) += dma-virt.o
lib-y += kobject.o klist.o
obj-y += lockref.o
@@ -98,10 +95,6 @@ obj-$(CONFIG_DEBUG_PREEMPT) += smp_processor_id.o
obj-$(CONFIG_DEBUG_LIST) += list_debug.o
obj-$(CONFIG_DEBUG_OBJECTS) += debugobjects.o
-ifneq ($(CONFIG_HAVE_DEC_LOCK),y)
- lib-y += dec_and_lock.o
-endif
-
obj-$(CONFIG_BITREVERSE) += bitrev.o
obj-$(CONFIG_RATIONAL) += rational.o
obj-$(CONFIG_CRC_CCITT) += crc-ccitt.o
@@ -148,7 +141,6 @@ obj-$(CONFIG_SMP) += percpu_counter.o
obj-$(CONFIG_AUDIT_GENERIC) += audit.o
obj-$(CONFIG_AUDIT_COMPAT_GENERIC) += compat_audit.o
-obj-$(CONFIG_SWIOTLB) += swiotlb.o
obj-$(CONFIG_IOMMU_HELPER) += iommu-helper.o
obj-$(CONFIG_FAULT_INJECTION) += fault-inject.o
obj-$(CONFIG_NOTIFIER_ERROR_INJECTION) += notifier-error-inject.o
@@ -169,8 +161,6 @@ obj-$(CONFIG_NLATTR) += nlattr.o
obj-$(CONFIG_LRU_CACHE) += lru_cache.o
-obj-$(CONFIG_DMA_API_DEBUG) += dma-debug.o
-
obj-$(CONFIG_GENERIC_CSUM) += checksum.o
obj-$(CONFIG_GENERIC_ATOMIC64) += atomic64.o
@@ -261,9 +251,9 @@ obj-$(CONFIG_SBITMAP) += sbitmap.o
obj-$(CONFIG_PARMAN) += parman.o
# GCC library routines
-obj-$(CONFIG_GENERIC_ASHLDI3) += ashldi3.o
-obj-$(CONFIG_GENERIC_ASHRDI3) += ashrdi3.o
-obj-$(CONFIG_GENERIC_LSHRDI3) += lshrdi3.o
-obj-$(CONFIG_GENERIC_MULDI3) += muldi3.o
-obj-$(CONFIG_GENERIC_CMPDI2) += cmpdi2.o
-obj-$(CONFIG_GENERIC_UCMPDI2) += ucmpdi2.o
+obj-$(CONFIG_GENERIC_LIB_ASHLDI3) += ashldi3.o
+obj-$(CONFIG_GENERIC_LIB_ASHRDI3) += ashrdi3.o
+obj-$(CONFIG_GENERIC_LIB_LSHRDI3) += lshrdi3.o
+obj-$(CONFIG_GENERIC_LIB_MULDI3) += muldi3.o
+obj-$(CONFIG_GENERIC_LIB_CMPDI2) += cmpdi2.o
+obj-$(CONFIG_GENERIC_LIB_UCMPDI2) += ucmpdi2.o
diff --git a/lib/argv_split.c b/lib/argv_split.c
index 5c35752..1a19a0a 100644
--- a/lib/argv_split.c
+++ b/lib/argv_split.c
@@ -69,7 +69,7 @@ char **argv_split(gfp_t gfp, const char *str, int *argcp)
return NULL;
argc = count_argc(argv_str);
- argv = kmalloc(sizeof(*argv) * (argc + 2), gfp);
+ argv = kmalloc_array(argc + 2, sizeof(*argv), gfp);
if (!argv) {
kfree(argv_str);
return NULL;
diff --git a/lib/dec_and_lock.c b/lib/dec_and_lock.c
index 347fa7a..9555b68 100644
--- a/lib/dec_and_lock.c
+++ b/lib/dec_and_lock.c
@@ -33,3 +33,19 @@ int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
}
EXPORT_SYMBOL(_atomic_dec_and_lock);
+
+int _atomic_dec_and_lock_irqsave(atomic_t *atomic, spinlock_t *lock,
+ unsigned long *flags)
+{
+ /* Subtract 1 from counter unless that drops it to 0 (ie. it was 1) */
+ if (atomic_add_unless(atomic, -1, 1))
+ return 0;
+
+ /* Otherwise do it the slow way */
+ spin_lock_irqsave(lock, *flags);
+ if (atomic_dec_and_test(atomic))
+ return 1;
+ spin_unlock_irqrestore(lock, *flags);
+ return 0;
+}
+EXPORT_SYMBOL(_atomic_dec_and_lock_irqsave);
diff --git a/lib/interval_tree_test.c b/lib/interval_tree_test.c
index 835242e..75509a1 100644
--- a/lib/interval_tree_test.c
+++ b/lib/interval_tree_test.c
@@ -64,11 +64,12 @@ static int interval_tree_test_init(void)
unsigned long results;
cycles_t time1, time2, time;
- nodes = kmalloc(nnodes * sizeof(struct interval_tree_node), GFP_KERNEL);
+ nodes = kmalloc_array(nnodes, sizeof(struct interval_tree_node),
+ GFP_KERNEL);
if (!nodes)
return -ENOMEM;
- queries = kmalloc(nsearches * sizeof(int), GFP_KERNEL);
+ queries = kmalloc_array(nsearches, sizeof(int), GFP_KERNEL);
if (!queries) {
kfree(nodes);
return -ENOMEM;
diff --git a/lib/kfifo.c b/lib/kfifo.c
index b0f757b..015656a 100644
--- a/lib/kfifo.c
+++ b/lib/kfifo.c
@@ -54,7 +54,7 @@ int __kfifo_alloc(struct __kfifo *fifo, unsigned int size,
return -EINVAL;
}
- fifo->data = kmalloc(size * esize, gfp_mask);
+ fifo->data = kmalloc_array(esize, size, gfp_mask);
if (!fifo->data) {
fifo->mask = 0;
diff --git a/lib/lru_cache.c b/lib/lru_cache.c
index 28ba40b..2b10a40 100644
--- a/lib/lru_cache.c
+++ b/lib/lru_cache.c
@@ -119,7 +119,7 @@ struct lru_cache *lc_create(const char *name, struct kmem_cache *cache,
slot = kcalloc(e_count, sizeof(struct hlist_head), GFP_KERNEL);
if (!slot)
goto out_fail;
- element = kzalloc(e_count * sizeof(struct lc_element *), GFP_KERNEL);
+ element = kcalloc(e_count, sizeof(struct lc_element *), GFP_KERNEL);
if (!element)
goto out_fail;
diff --git a/lib/mpi/mpiutil.c b/lib/mpi/mpiutil.c
index 314f4df..20ed0f7 100644
--- a/lib/mpi/mpiutil.c
+++ b/lib/mpi/mpiutil.c
@@ -91,14 +91,14 @@ int mpi_resize(MPI a, unsigned nlimbs)
return 0; /* no need to do it */
if (a->d) {
- p = kmalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL);
+ p = kmalloc_array(nlimbs, sizeof(mpi_limb_t), GFP_KERNEL);
if (!p)
return -ENOMEM;
memcpy(p, a->d, a->alloced * sizeof(mpi_limb_t));
kzfree(a->d);
a->d = p;
} else {
- a->d = kzalloc(nlimbs * sizeof(mpi_limb_t), GFP_KERNEL);
+ a->d = kcalloc(nlimbs, sizeof(mpi_limb_t), GFP_KERNEL);
if (!a->d)
return -ENOMEM;
}
diff --git a/lib/rbtree_test.c b/lib/rbtree_test.c
index 7d36c1e..b7055b2 100644
--- a/lib/rbtree_test.c
+++ b/lib/rbtree_test.c
@@ -247,7 +247,7 @@ static int __init rbtree_test_init(void)
cycles_t time1, time2, time;
struct rb_node *node;
- nodes = kmalloc(nnodes * sizeof(*nodes), GFP_KERNEL);
+ nodes = kmalloc_array(nnodes, sizeof(*nodes), GFP_KERNEL);
if (!nodes)
return -ENOMEM;
diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c
index dfcf542..d8bb1a1 100644
--- a/lib/reed_solomon/reed_solomon.c
+++ b/lib/reed_solomon/reed_solomon.c
@@ -88,15 +88,15 @@ static struct rs_codec *codec_init(int symsize, int gfpoly, int (*gffunc)(int),
rs->gffunc = gffunc;
/* Allocate the arrays */
- rs->alpha_to = kmalloc(sizeof(uint16_t) * (rs->nn + 1), gfp);
+ rs->alpha_to = kmalloc_array(rs->nn + 1, sizeof(uint16_t), gfp);
if (rs->alpha_to == NULL)
goto err;
- rs->index_of = kmalloc(sizeof(uint16_t) * (rs->nn + 1), gfp);
+ rs->index_of = kmalloc_array(rs->nn + 1, sizeof(uint16_t), gfp);
if (rs->index_of == NULL)
goto err;
- rs->genpoly = kmalloc(sizeof(uint16_t) * (rs->nroots + 1), gfp);
+ rs->genpoly = kmalloc_array(rs->nroots + 1, sizeof(uint16_t), gfp);
if(rs->genpoly == NULL)
goto err;
diff --git a/lib/refcount.c b/lib/refcount.c
index 0eb4835..d3b81ce 100644
--- a/lib/refcount.c
+++ b/lib/refcount.c
@@ -350,3 +350,31 @@ bool refcount_dec_and_lock(refcount_t *r, spinlock_t *lock)
}
EXPORT_SYMBOL(refcount_dec_and_lock);
+/**
+ * refcount_dec_and_lock_irqsave - return holding spinlock with disabled
+ * interrupts if able to decrement refcount to 0
+ * @r: the refcount
+ * @lock: the spinlock to be locked
+ * @flags: saved IRQ-flags if the is acquired
+ *
+ * Same as refcount_dec_and_lock() above except that the spinlock is acquired
+ * with disabled interupts.
+ *
+ * Return: true and hold spinlock if able to decrement refcount to 0, false
+ * otherwise
+ */
+bool refcount_dec_and_lock_irqsave(refcount_t *r, spinlock_t *lock,
+ unsigned long *flags)
+{
+ if (refcount_dec_not_one(r))
+ return false;
+
+ spin_lock_irqsave(lock, *flags);
+ if (!refcount_dec_and_test(r)) {
+ spin_unlock_irqrestore(lock, *flags);
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(refcount_dec_and_lock_irqsave);
diff --git a/lib/sbitmap.c b/lib/sbitmap.c
index 6fdc626..fdd1b8a 100644
--- a/lib/sbitmap.c
+++ b/lib/sbitmap.c
@@ -52,7 +52,7 @@ int sbitmap_init_node(struct sbitmap *sb, unsigned int depth, int shift,
return 0;
}
- sb->map = kzalloc_node(sb->map_nr * sizeof(*sb->map), flags, node);
+ sb->map = kcalloc_node(sb->map_nr, sizeof(*sb->map), flags, node);
if (!sb->map)
return -ENOMEM;
diff --git a/lib/scatterlist.c b/lib/scatterlist.c
index 06dad7a..1642fd5 100644
--- a/lib/scatterlist.c
+++ b/lib/scatterlist.c
@@ -170,7 +170,8 @@ static struct scatterlist *sg_kmalloc(unsigned int nents, gfp_t gfp_mask)
kmemleak_alloc(ptr, PAGE_SIZE, 1, gfp_mask);
return ptr;
} else
- return kmalloc(nents * sizeof(struct scatterlist), gfp_mask);
+ return kmalloc_array(nents, sizeof(struct scatterlist),
+ gfp_mask);
}
static void sg_kfree(struct scatterlist *sg, unsigned int nents)
diff --git a/lib/test_firmware.c b/lib/test_firmware.c
index cee000a..b984806 100644
--- a/lib/test_firmware.c
+++ b/lib/test_firmware.c
@@ -618,8 +618,9 @@ static ssize_t trigger_batched_requests_store(struct device *dev,
mutex_lock(&test_fw_mutex);
- test_fw_config->reqs = vzalloc(sizeof(struct test_batched_req) *
- test_fw_config->num_requests * 2);
+ test_fw_config->reqs =
+ vzalloc(array3_size(sizeof(struct test_batched_req),
+ test_fw_config->num_requests, 2));
if (!test_fw_config->reqs) {
rc = -ENOMEM;
goto out_unlock;
@@ -720,8 +721,9 @@ ssize_t trigger_batched_requests_async_store(struct device *dev,
mutex_lock(&test_fw_mutex);
- test_fw_config->reqs = vzalloc(sizeof(struct test_batched_req) *
- test_fw_config->num_requests * 2);
+ test_fw_config->reqs =
+ vzalloc(array3_size(sizeof(struct test_batched_req),
+ test_fw_config->num_requests, 2));
if (!test_fw_config->reqs) {
rc = -ENOMEM;
goto out;
diff --git a/lib/test_kmod.c b/lib/test_kmod.c
index 0e5b7a6..e3ddd83 100644
--- a/lib/test_kmod.c
+++ b/lib/test_kmod.c
@@ -779,8 +779,9 @@ static int kmod_config_sync_info(struct kmod_test_device *test_dev)
struct test_config *config = &test_dev->config;
free_test_dev_info(test_dev);
- test_dev->info = vzalloc(config->num_threads *
- sizeof(struct kmod_test_device_info));
+ test_dev->info =
+ vzalloc(array_size(sizeof(struct kmod_test_device_info),
+ config->num_threads));
if (!test_dev->info)
return -ENOMEM;
diff --git a/lib/test_overflow.c b/lib/test_overflow.c
index aecbbb2..2278fe0 100644
--- a/lib/test_overflow.c
+++ b/lib/test_overflow.c
@@ -367,7 +367,7 @@ static int __init test_overflow_allocation(void)
/* Create dummy device for devm_kmalloc()-family tests. */
dev = root_device_register(device_name);
- if (!dev) {
+ if (IS_ERR(dev)) {
pr_warn("Cannot register test device\n");
return 1;
}
diff --git a/lib/test_printf.c b/lib/test_printf.c
index cea592f..b2aa8f5 100644
--- a/lib/test_printf.c
+++ b/lib/test_printf.c
@@ -260,6 +260,13 @@ plain(void)
{
int err;
+ /*
+ * Make sure crng is ready. Otherwise we get "(ptrval)" instead
+ * of a hashed address when printing '%p' in plain_hash() and
+ * plain_format().
+ */
+ wait_for_random_bytes();
+
err = plain_hash();
if (err) {
pr_warn("plain 'p' does not appear to be hashed\n");
diff --git a/lib/test_rhashtable.c b/lib/test_rhashtable.c
index f4000c1..fb69681 100644
--- a/lib/test_rhashtable.c
+++ b/lib/test_rhashtable.c
@@ -285,12 +285,14 @@ static int __init test_rhltable(unsigned int entries)
if (entries == 0)
entries = 1;
- rhl_test_objects = vzalloc(sizeof(*rhl_test_objects) * entries);
+ rhl_test_objects = vzalloc(array_size(entries,
+ sizeof(*rhl_test_objects)));
if (!rhl_test_objects)
return -ENOMEM;
ret = -ENOMEM;
- obj_in_table = vzalloc(BITS_TO_LONGS(entries) * sizeof(unsigned long));
+ obj_in_table = vzalloc(array_size(sizeof(unsigned long),
+ BITS_TO_LONGS(entries)));
if (!obj_in_table)
goto out_free;
@@ -706,7 +708,8 @@ static int __init test_rht_init(void)
test_rht_params.max_size = max_size ? : roundup_pow_of_two(entries);
test_rht_params.nelem_hint = size;
- objs = vzalloc((test_rht_params.max_size + 1) * sizeof(struct test_obj));
+ objs = vzalloc(array_size(sizeof(struct test_obj),
+ test_rht_params.max_size + 1));
if (!objs)
return -ENOMEM;
@@ -753,10 +756,10 @@ static int __init test_rht_init(void)
pr_info("Testing concurrent rhashtable access from %d threads\n",
tcount);
sema_init(&prestart_sem, 1 - tcount);
- tdata = vzalloc(tcount * sizeof(struct thread_data));
+ tdata = vzalloc(array_size(tcount, sizeof(struct thread_data)));
if (!tdata)
return -ENOMEM;
- objs = vzalloc(tcount * entries * sizeof(struct test_obj));
+ objs = vzalloc(array3_size(sizeof(struct test_obj), tcount, entries));
if (!objs) {
vfree(tdata);
return -ENOMEM;
diff --git a/lib/ucmpdi2.c b/lib/ucmpdi2.c
index 25ca2d4..5979981 100644
--- a/lib/ucmpdi2.c
+++ b/lib/ucmpdi2.c
@@ -17,7 +17,7 @@
#include <linux/module.h>
#include <linux/libgcc.h>
-word_type __ucmpdi2(unsigned long long a, unsigned long long b)
+word_type notrace __ucmpdi2(unsigned long long a, unsigned long long b)
{
const DWunion au = {.ll = a};
const DWunion bu = {.ll = b};
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 347cc83..2e5d3df 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -359,15 +359,8 @@ static void wb_shutdown(struct bdi_writeback *wb)
spin_lock_bh(&wb->work_lock);
if (!test_and_clear_bit(WB_registered, &wb->state)) {
spin_unlock_bh(&wb->work_lock);
- /*
- * Wait for wb shutdown to finish if someone else is just
- * running wb_shutdown(). Otherwise we could proceed to wb /
- * bdi destruction before wb_shutdown() is finished.
- */
- wait_on_bit(&wb->state, WB_shutting_down, TASK_UNINTERRUPTIBLE);
return;
}
- set_bit(WB_shutting_down, &wb->state);
spin_unlock_bh(&wb->work_lock);
cgwb_remove_from_bdi_list(wb);
@@ -379,12 +372,6 @@ static void wb_shutdown(struct bdi_writeback *wb)
mod_delayed_work(bdi_wq, &wb->dwork, 0);
flush_delayed_work(&wb->dwork);
WARN_ON(!list_empty(&wb->work_list));
- /*
- * Make sure bit gets cleared after shutdown is finished. Matches with
- * the barrier provided by test_and_clear_bit() above.
- */
- smp_wmb();
- clear_and_wake_up_bit(WB_shutting_down, &wb->state);
}
static void wb_exit(struct bdi_writeback *wb)
@@ -508,10 +495,12 @@ static void cgwb_release_workfn(struct work_struct *work)
struct bdi_writeback *wb = container_of(work, struct bdi_writeback,
release_work);
+ mutex_lock(&wb->bdi->cgwb_release_mutex);
wb_shutdown(wb);
css_put(wb->memcg_css);
css_put(wb->blkcg_css);
+ mutex_unlock(&wb->bdi->cgwb_release_mutex);
fprop_local_destroy_percpu(&wb->memcg_completions);
percpu_ref_exit(&wb->refcnt);
@@ -697,6 +686,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
INIT_RADIX_TREE(&bdi->cgwb_tree, GFP_ATOMIC);
bdi->cgwb_congested_tree = RB_ROOT;
+ mutex_init(&bdi->cgwb_release_mutex);
ret = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
if (!ret) {
@@ -717,7 +707,10 @@ static void cgwb_bdi_unregister(struct backing_dev_info *bdi)
spin_lock_irq(&cgwb_lock);
radix_tree_for_each_slot(slot, &bdi->cgwb_tree, &iter, 0)
cgwb_kill(*slot);
+ spin_unlock_irq(&cgwb_lock);
+ mutex_lock(&bdi->cgwb_release_mutex);
+ spin_lock_irq(&cgwb_lock);
while (!list_empty(&bdi->wb_list)) {
wb = list_first_entry(&bdi->wb_list, struct bdi_writeback,
bdi_node);
@@ -726,6 +719,7 @@ static void cgwb_bdi_unregister(struct backing_dev_info *bdi)
spin_lock_irq(&cgwb_lock);
}
spin_unlock_irq(&cgwb_lock);
+ mutex_unlock(&bdi->cgwb_release_mutex);
}
/**
diff --git a/mm/cleancache.c b/mm/cleancache.c
index 126548b..2bf12da 100644
--- a/mm/cleancache.c
+++ b/mm/cleancache.c
@@ -307,12 +307,10 @@ static int __init init_cleancache(void)
struct dentry *root = debugfs_create_dir("cleancache", NULL);
if (root == NULL)
return -ENXIO;
- debugfs_create_u64("succ_gets", S_IRUGO, root, &cleancache_succ_gets);
- debugfs_create_u64("failed_gets", S_IRUGO,
- root, &cleancache_failed_gets);
- debugfs_create_u64("puts", S_IRUGO, root, &cleancache_puts);
- debugfs_create_u64("invalidates", S_IRUGO,
- root, &cleancache_invalidates);
+ debugfs_create_u64("succ_gets", 0444, root, &cleancache_succ_gets);
+ debugfs_create_u64("failed_gets", 0444, root, &cleancache_failed_gets);
+ debugfs_create_u64("puts", 0444, root, &cleancache_puts);
+ debugfs_create_u64("invalidates", 0444, root, &cleancache_invalidates);
#endif
return 0;
}
diff --git a/mm/cma_debug.c b/mm/cma_debug.c
index 275df8b..f234672 100644
--- a/mm/cma_debug.c
+++ b/mm/cma_debug.c
@@ -172,23 +172,18 @@ static void cma_debugfs_add_one(struct cma *cma, int idx)
tmp = debugfs_create_dir(name, cma_debugfs_root);
- debugfs_create_file("alloc", S_IWUSR, tmp, cma,
- &cma_alloc_fops);
-
- debugfs_create_file("free", S_IWUSR, tmp, cma,
- &cma_free_fops);
-
- debugfs_create_file("base_pfn", S_IRUGO, tmp,
- &cma->base_pfn, &cma_debugfs_fops);
- debugfs_create_file("count", S_IRUGO, tmp,
- &cma->count, &cma_debugfs_fops);
- debugfs_create_file("order_per_bit", S_IRUGO, tmp,
- &cma->order_per_bit, &cma_debugfs_fops);
- debugfs_create_file("used", S_IRUGO, tmp, cma, &cma_used_fops);
- debugfs_create_file("maxchunk", S_IRUGO, tmp, cma, &cma_maxchunk_fops);
+ debugfs_create_file("alloc", 0200, tmp, cma, &cma_alloc_fops);
+ debugfs_create_file("free", 0200, tmp, cma, &cma_free_fops);
+ debugfs_create_file("base_pfn", 0444, tmp,
+ &cma->base_pfn, &cma_debugfs_fops);
+ debugfs_create_file("count", 0444, tmp, &cma->count, &cma_debugfs_fops);
+ debugfs_create_file("order_per_bit", 0444, tmp,
+ &cma->order_per_bit, &cma_debugfs_fops);
+ debugfs_create_file("used", 0444, tmp, cma, &cma_used_fops);
+ debugfs_create_file("maxchunk", 0444, tmp, cma, &cma_maxchunk_fops);
u32s = DIV_ROUND_UP(cma_bitmap_maxno(cma), BITS_PER_BYTE * sizeof(u32));
- debugfs_create_u32_array("bitmap", S_IRUGO, tmp, (u32*)cma->bitmap, u32s);
+ debugfs_create_u32_array("bitmap", 0444, tmp, (u32 *)cma->bitmap, u32s);
}
static int __init cma_debugfs_init(void)
diff --git a/mm/compaction.c b/mm/compaction.c
index 29bd1df..faca45e 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -1899,7 +1899,7 @@ static ssize_t sysfs_compact_node(struct device *dev,
return count;
}
-static DEVICE_ATTR(compact, S_IWUSR, NULL, sysfs_compact_node);
+static DEVICE_ATTR(compact, 0200, NULL, sysfs_compact_node);
int compaction_register_node(struct node *node)
{
diff --git a/mm/dmapool.c b/mm/dmapool.c
index 4d90a64..6d4b97e 100644
--- a/mm/dmapool.c
+++ b/mm/dmapool.c
@@ -105,7 +105,7 @@ show_pools(struct device *dev, struct device_attribute *attr, char *buf)
return PAGE_SIZE - size;
}
-static DEVICE_ATTR(pools, S_IRUGO, show_pools, NULL);
+static DEVICE_ATTR(pools, 0444, show_pools, NULL);
/**
* dma_pool_create - Creates a pool of consistent memory blocks, for dma.
diff --git a/mm/failslab.c b/mm/failslab.c
index 1f2f248..b135ebb 100644
--- a/mm/failslab.c
+++ b/mm/failslab.c
@@ -42,7 +42,7 @@ __setup("failslab=", setup_failslab);
static int __init failslab_debugfs_init(void)
{
struct dentry *dir;
- umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+ umode_t mode = S_IFREG | 0600;
dir = fault_create_debugfs_attr("failslab", NULL, &failslab.attr);
if (IS_ERR(dir))
diff --git a/mm/frontswap.c b/mm/frontswap.c
index 4f5476a..157e5bf 100644
--- a/mm/frontswap.c
+++ b/mm/frontswap.c
@@ -486,12 +486,11 @@ static int __init init_frontswap(void)
struct dentry *root = debugfs_create_dir("frontswap", NULL);
if (root == NULL)
return -ENXIO;
- debugfs_create_u64("loads", S_IRUGO, root, &frontswap_loads);
- debugfs_create_u64("succ_stores", S_IRUGO, root, &frontswap_succ_stores);
- debugfs_create_u64("failed_stores", S_IRUGO, root,
- &frontswap_failed_stores);
- debugfs_create_u64("invalidates", S_IRUGO,
- root, &frontswap_invalidates);
+ debugfs_create_u64("loads", 0444, root, &frontswap_loads);
+ debugfs_create_u64("succ_stores", 0444, root, &frontswap_succ_stores);
+ debugfs_create_u64("failed_stores", 0444, root,
+ &frontswap_failed_stores);
+ debugfs_create_u64("invalidates", 0444, root, &frontswap_invalidates);
#endif
return 0;
}
diff --git a/mm/gup_benchmark.c b/mm/gup_benchmark.c
index 0f44759..6a47370 100644
--- a/mm/gup_benchmark.c
+++ b/mm/gup_benchmark.c
@@ -23,7 +23,7 @@ static int __gup_benchmark_ioctl(unsigned int cmd,
struct page **pages;
nr_pages = gup->size / PAGE_SIZE;
- pages = kvzalloc(sizeof(void *) * nr_pages, GFP_KERNEL);
+ pages = kvcalloc(nr_pages, sizeof(void *), GFP_KERNEL);
if (!pages)
return -ENOMEM;
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index ba8fdc0..1cd7c1a 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1131,8 +1131,8 @@ static int do_huge_pmd_wp_page_fallback(struct vm_fault *vmf, pmd_t orig_pmd,
unsigned long mmun_start; /* For mmu_notifiers */
unsigned long mmun_end; /* For mmu_notifiers */
- pages = kmalloc(sizeof(struct page *) * HPAGE_PMD_NR,
- GFP_KERNEL);
+ pages = kmalloc_array(HPAGE_PMD_NR, sizeof(struct page *),
+ GFP_KERNEL);
if (unlikely(!pages)) {
ret |= VM_FAULT_OOM;
goto out;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 696beff..3612fbb 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -2798,7 +2798,8 @@ static int __init hugetlb_init(void)
num_fault_mutexes = 1;
#endif
hugetlb_fault_mutex_table =
- kmalloc(sizeof(struct mutex) * num_fault_mutexes, GFP_KERNEL);
+ kmalloc_array(num_fault_mutexes, sizeof(struct mutex),
+ GFP_KERNEL);
BUG_ON(!hugetlb_fault_mutex_table);
for (i = 0; i < num_fault_mutexes; i++)
diff --git a/mm/ksm.c b/mm/ksm.c
index e2d2886..a6d43cf 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -216,6 +216,8 @@ struct rmap_item {
#define SEQNR_MASK 0x0ff /* low bits of unstable tree seqnr */
#define UNSTABLE_FLAG 0x100 /* is a node of the unstable tree */
#define STABLE_FLAG 0x200 /* is listed from the stable tree */
+#define KSM_FLAG_MASK (SEQNR_MASK|UNSTABLE_FLAG|STABLE_FLAG)
+ /* to mask all the flags */
/* The stable and unstable tree heads */
static struct rb_root one_stable_tree[1] = { RB_ROOT };
@@ -2598,10 +2600,15 @@ again:
anon_vma_lock_read(anon_vma);
anon_vma_interval_tree_foreach(vmac, &anon_vma->rb_root,
0, ULONG_MAX) {
+ unsigned long addr;
+
cond_resched();
vma = vmac->vma;
- if (rmap_item->address < vma->vm_start ||
- rmap_item->address >= vma->vm_end)
+
+ /* Ignore the stable/unstable/sqnr flags */
+ addr = rmap_item->address & ~KSM_FLAG_MASK;
+
+ if (addr < vma->vm_start || addr >= vma->vm_end)
continue;
/*
* Initially we examine only the vma which covers this
@@ -2615,8 +2622,7 @@ again:
if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg))
continue;
- if (!rwc->rmap_one(page, vma,
- rmap_item->address, rwc->arg)) {
+ if (!rwc->rmap_one(page, vma, addr, rwc->arg)) {
anon_vma_unlock_read(anon_vma);
return;
}
diff --git a/mm/memblock.c b/mm/memblock.c
index 93ad42bc..03d48d8 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -1808,10 +1808,13 @@ static int __init memblock_init_debugfs(void)
struct dentry *root = debugfs_create_dir("memblock", NULL);
if (!root)
return -ENXIO;
- debugfs_create_file("memory", S_IRUGO, root, &memblock.memory, &memblock_debug_fops);
- debugfs_create_file("reserved", S_IRUGO, root, &memblock.reserved, &memblock_debug_fops);
+ debugfs_create_file("memory", 0444, root,
+ &memblock.memory, &memblock_debug_fops);
+ debugfs_create_file("reserved", 0444, root,
+ &memblock.reserved, &memblock_debug_fops);
#ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
- debugfs_create_file("physmem", S_IRUGO, root, &memblock.physmem, &memblock_debug_fops);
+ debugfs_create_file("physmem", 0444, root,
+ &memblock.physmem, &memblock_debug_fops);
#endif
return 0;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index c1e64d6..e6f0d5e 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3550,7 +3550,8 @@ static int mem_cgroup_oom_control_read(struct seq_file *sf, void *v)
seq_printf(sf, "oom_kill_disable %d\n", memcg->oom_kill_disable);
seq_printf(sf, "under_oom %d\n", (bool)memcg->under_oom);
- seq_printf(sf, "oom_kill %lu\n", memcg_sum_events(memcg, OOM_KILL));
+ seq_printf(sf, "oom_kill %lu\n",
+ atomic_long_read(&memcg->memory_events[MEMCG_OOM_KILL]));
return 0;
}
@@ -5239,7 +5240,8 @@ static int memory_events_show(struct seq_file *m, void *v)
atomic_long_read(&memcg->memory_events[MEMCG_MAX]));
seq_printf(m, "oom %lu\n",
atomic_long_read(&memcg->memory_events[MEMCG_OOM]));
- seq_printf(m, "oom_kill %lu\n", memcg_sum_events(memcg, OOM_KILL));
+ seq_printf(m, "oom_kill %lu\n",
+ atomic_long_read(&memcg->memory_events[MEMCG_OOM_KILL]));
return 0;
}
@@ -5480,6 +5482,10 @@ enum mem_cgroup_protection mem_cgroup_protected(struct mem_cgroup *root,
elow = memcg->memory.low;
parent = parent_mem_cgroup(memcg);
+ /* No parent means a non-hierarchical mode on v1 memcg */
+ if (!parent)
+ return MEMCG_PROT_NONE;
+
if (parent == root)
goto exit;
diff --git a/mm/mremap.c b/mm/mremap.c
index 049470a..5c2e185 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -191,8 +191,6 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
drop_rmap_locks(vma);
}
-#define LATENCY_LIMIT (64 * PAGE_SIZE)
-
unsigned long move_page_tables(struct vm_area_struct *vma,
unsigned long old_addr, struct vm_area_struct *new_vma,
unsigned long new_addr, unsigned long len,
@@ -247,8 +245,6 @@ unsigned long move_page_tables(struct vm_area_struct *vma,
next = (new_addr + PMD_SIZE) & PMD_MASK;
if (extent > next - new_addr)
extent = next - new_addr;
- if (extent > LATENCY_LIMIT)
- extent = LATENCY_LIMIT;
move_ptes(vma, old_pmd, old_addr, old_addr + extent, new_vma,
new_pmd, new_addr, need_rmap_locks, &need_flush);
}
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 6694348..84081e7 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -913,7 +913,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
/* Raise event before sending signal: task reaper must see this */
count_vm_event(OOM_KILL);
- count_memcg_event_mm(mm, OOM_KILL);
+ memcg_memory_event_mm(mm, MEMCG_OOM_KILL);
/*
* We should send SIGKILL before granting access to memory reserves
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 07b3c23..1521100 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3061,7 +3061,7 @@ static bool should_fail_alloc_page(gfp_t gfp_mask, unsigned int order)
static int __init fail_page_alloc_debugfs(void)
{
- umode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
+ umode_t mode = S_IFREG | 0600;
struct dentry *dir;
dir = fault_create_debugfs_attr("fail_page_alloc", NULL,
diff --git a/mm/page_idle.c b/mm/page_idle.c
index e412a63..6302bc6 100644
--- a/mm/page_idle.c
+++ b/mm/page_idle.c
@@ -201,7 +201,7 @@ static ssize_t page_idle_bitmap_write(struct file *file, struct kobject *kobj,
}
static struct bin_attribute page_idle_bitmap_attr =
- __BIN_ATTR(bitmap, S_IRUSR | S_IWUSR,
+ __BIN_ATTR(bitmap, 0600,
page_idle_bitmap_read, page_idle_bitmap_write, 0);
static struct bin_attribute *page_idle_bin_attrs[] = {
diff --git a/mm/page_owner.c b/mm/page_owner.c
index 75d21a2..d80adfe 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -631,8 +631,8 @@ static int __init pageowner_init(void)
return 0;
}
- dentry = debugfs_create_file("page_owner", S_IRUSR, NULL,
- NULL, &proc_page_owner_operations);
+ dentry = debugfs_create_file("page_owner", 0400, NULL,
+ NULL, &proc_page_owner_operations);
return PTR_ERR_OR_ZERO(dentry);
}
diff --git a/mm/percpu-stats.c b/mm/percpu-stats.c
index 063ff60..b5fdd43 100644
--- a/mm/percpu-stats.c
+++ b/mm/percpu-stats.c
@@ -144,7 +144,7 @@ alloc_buffer:
spin_unlock_irq(&pcpu_lock);
/* there can be at most this many free and allocated fragments */
- buffer = vmalloc((2 * max_nr_alloc + 1) * sizeof(int));
+ buffer = vmalloc(array_size(sizeof(int), (2 * max_nr_alloc + 1)));
if (!buffer)
return -ENOMEM;
diff --git a/mm/shmem.c b/mm/shmem.c
index e9a7ac7..2cab844 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3013,7 +3013,8 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
if (len > PAGE_SIZE)
return -ENAMETOOLONG;
- inode = shmem_get_inode(dir->i_sb, dir, S_IFLNK|S_IRWXUGO, 0, VM_NORESERVE);
+ inode = shmem_get_inode(dir->i_sb, dir, S_IFLNK | 0777, 0,
+ VM_NORESERVE);
if (!inode)
return -ENOSPC;
@@ -3445,7 +3446,7 @@ static int shmem_show_options(struct seq_file *seq, struct dentry *root)
sbinfo->max_blocks << (PAGE_SHIFT - 10));
if (sbinfo->max_inodes != shmem_default_max_inodes())
seq_printf(seq, ",nr_inodes=%lu", sbinfo->max_inodes);
- if (sbinfo->mode != (S_IRWXUGO | S_ISVTX))
+ if (sbinfo->mode != (0777 | S_ISVTX))
seq_printf(seq, ",mode=%03ho", sbinfo->mode);
if (!uid_eq(sbinfo->uid, GLOBAL_ROOT_UID))
seq_printf(seq, ",uid=%u",
@@ -3486,7 +3487,7 @@ int shmem_fill_super(struct super_block *sb, void *data, int silent)
if (!sbinfo)
return -ENOMEM;
- sbinfo->mode = S_IRWXUGO | S_ISVTX;
+ sbinfo->mode = 0777 | S_ISVTX;
sbinfo->uid = current_fsuid();
sbinfo->gid = current_fsgid();
sb->s_fs_info = sbinfo;
@@ -3929,7 +3930,7 @@ static struct file *__shmem_file_setup(struct vfsmount *mnt, const char *name, l
d_set_d_op(path.dentry, &anon_ops);
res = ERR_PTR(-ENOSPC);
- inode = shmem_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0, flags);
+ inode = shmem_get_inode(sb, NULL, S_IFREG | 0777, 0, flags);
if (!inode)
goto put_memory;
diff --git a/mm/slab.c b/mm/slab.c
index 36688f6..aa76a70 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -4338,7 +4338,8 @@ static int leaks_show(struct seq_file *m, void *p)
if (x[0] == x[1]) {
/* Increase the buffer size */
mutex_unlock(&slab_mutex);
- m->private = kzalloc(x[0] * 4 * sizeof(unsigned long), GFP_KERNEL);
+ m->private = kcalloc(x[0] * 4, sizeof(unsigned long),
+ GFP_KERNEL);
if (!m->private) {
/* Too bad, we are really out */
m->private = x;
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 98dcdc3..890b1f0 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -136,6 +136,7 @@ void slab_init_memcg_params(struct kmem_cache *s)
s->memcg_params.root_cache = NULL;
RCU_INIT_POINTER(s->memcg_params.memcg_caches, NULL);
INIT_LIST_HEAD(&s->memcg_params.children);
+ s->memcg_params.dying = false;
}
static int init_memcg_params(struct kmem_cache *s,
@@ -608,7 +609,7 @@ void memcg_create_kmem_cache(struct mem_cgroup *memcg,
* The memory cgroup could have been offlined while the cache
* creation work was pending.
*/
- if (memcg->kmem_state != KMEM_ONLINE)
+ if (memcg->kmem_state != KMEM_ONLINE || root_cache->memcg_params.dying)
goto out_unlock;
idx = memcg_cache_id(memcg);
@@ -712,6 +713,9 @@ void slab_deactivate_memcg_cache_rcu_sched(struct kmem_cache *s,
WARN_ON_ONCE(s->memcg_params.deact_fn))
return;
+ if (s->memcg_params.root_cache->memcg_params.dying)
+ return;
+
/* pin memcg so that @s doesn't get destroyed in the middle */
css_get(&s->memcg_params.memcg->css);
@@ -823,11 +827,36 @@ static int shutdown_memcg_caches(struct kmem_cache *s)
return -EBUSY;
return 0;
}
+
+static void flush_memcg_workqueue(struct kmem_cache *s)
+{
+ mutex_lock(&slab_mutex);
+ s->memcg_params.dying = true;
+ mutex_unlock(&slab_mutex);
+
+ /*
+ * SLUB deactivates the kmem_caches through call_rcu_sched. Make
+ * sure all registered rcu callbacks have been invoked.
+ */
+ if (IS_ENABLED(CONFIG_SLUB))
+ rcu_barrier_sched();
+
+ /*
+ * SLAB and SLUB create memcg kmem_caches through workqueue and SLUB
+ * deactivates the memcg kmem_caches through workqueue. Make sure all
+ * previous workitems on workqueue are processed.
+ */
+ flush_workqueue(memcg_kmem_cache_wq);
+}
#else
static inline int shutdown_memcg_caches(struct kmem_cache *s)
{
return 0;
}
+
+static inline void flush_memcg_workqueue(struct kmem_cache *s)
+{
+}
#endif /* CONFIG_MEMCG && !CONFIG_SLOB */
void slab_kmem_cache_release(struct kmem_cache *s)
@@ -845,6 +874,8 @@ void kmem_cache_destroy(struct kmem_cache *s)
if (unlikely(!s))
return;
+ flush_memcg_workqueue(s);
+
get_online_cpus();
get_online_mems();
@@ -1212,9 +1243,9 @@ void cache_random_seq_destroy(struct kmem_cache *cachep)
#if defined(CONFIG_SLAB) || defined(CONFIG_SLUB_DEBUG)
#ifdef CONFIG_SLAB
-#define SLABINFO_RIGHTS (S_IWUSR | S_IRUSR)
+#define SLABINFO_RIGHTS (0600)
#else
-#define SLABINFO_RIGHTS S_IRUSR
+#define SLABINFO_RIGHTS (0400)
#endif
static void print_slabinfo_header(struct seq_file *m)
diff --git a/mm/slub.c b/mm/slub.c
index 1550547..a3b8467 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3623,8 +3623,9 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page,
#ifdef CONFIG_SLUB_DEBUG
void *addr = page_address(page);
void *p;
- unsigned long *map = kzalloc(BITS_TO_LONGS(page->objects) *
- sizeof(long), GFP_ATOMIC);
+ unsigned long *map = kcalloc(BITS_TO_LONGS(page->objects),
+ sizeof(long),
+ GFP_ATOMIC);
if (!map)
return;
slab_err(s, page, text, s->name);
@@ -4412,8 +4413,9 @@ static long validate_slab_cache(struct kmem_cache *s)
{
int node;
unsigned long count = 0;
- unsigned long *map = kmalloc(BITS_TO_LONGS(oo_objects(s->max)) *
- sizeof(unsigned long), GFP_KERNEL);
+ unsigned long *map = kmalloc_array(BITS_TO_LONGS(oo_objects(s->max)),
+ sizeof(unsigned long),
+ GFP_KERNEL);
struct kmem_cache_node *n;
if (!map)
@@ -4573,8 +4575,9 @@ static int list_locations(struct kmem_cache *s, char *buf,
unsigned long i;
struct loc_track t = { 0, 0, NULL };
int node;
- unsigned long *map = kmalloc(BITS_TO_LONGS(oo_objects(s->max)) *
- sizeof(unsigned long), GFP_KERNEL);
+ unsigned long *map = kmalloc_array(BITS_TO_LONGS(oo_objects(s->max)),
+ sizeof(unsigned long),
+ GFP_KERNEL);
struct kmem_cache_node *n;
if (!map || !alloc_loc_track(&t, PAGE_SIZE / sizeof(struct location),
@@ -4750,7 +4753,7 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
int x;
unsigned long *nodes;
- nodes = kzalloc(sizeof(unsigned long) * nr_node_ids, GFP_KERNEL);
+ nodes = kcalloc(nr_node_ids, sizeof(unsigned long), GFP_KERNEL);
if (!nodes)
return -ENOMEM;
@@ -5293,7 +5296,7 @@ static int show_stat(struct kmem_cache *s, char *buf, enum stat_item si)
unsigned long sum = 0;
int cpu;
int len;
- int *data = kmalloc(nr_cpu_ids * sizeof(int), GFP_KERNEL);
+ int *data = kmalloc_array(nr_cpu_ids, sizeof(int), GFP_KERNEL);
if (!data)
return -ENOMEM;
diff --git a/mm/swap_slots.c b/mm/swap_slots.c
index f51ac05..a791411 100644
--- a/mm/swap_slots.c
+++ b/mm/swap_slots.c
@@ -122,12 +122,12 @@ static int alloc_swap_slot_cache(unsigned int cpu)
* as kvzalloc could trigger reclaim and get_swap_page,
* which can lock swap_slots_cache_mutex.
*/
- slots = kvzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE,
+ slots = kvcalloc(SWAP_SLOTS_CACHE_SIZE, sizeof(swp_entry_t),
GFP_KERNEL);
if (!slots)
return -ENOMEM;
- slots_ret = kvzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE,
+ slots_ret = kvcalloc(SWAP_SLOTS_CACHE_SIZE, sizeof(swp_entry_t),
GFP_KERNEL);
if (!slots_ret) {
kvfree(slots);
diff --git a/mm/swap_state.c b/mm/swap_state.c
index ab8e59c..ecee9c6 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -620,7 +620,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 = kvzalloc(sizeof(struct address_space) * nr, GFP_KERNEL);
+ spaces = kvcalloc(nr, sizeof(struct address_space), GFP_KERNEL);
if (!spaces)
return -ENOMEM;
for (i = 0; i < nr; i++) {
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 78a015f..2cc2972 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -100,7 +100,7 @@ atomic_t nr_rotate_swap = ATOMIC_INIT(0);
static inline unsigned char swap_count(unsigned char ent)
{
- return ent & ~SWAP_HAS_CACHE; /* may include SWAP_HAS_CONT flag */
+ return ent & ~SWAP_HAS_CACHE; /* may include COUNT_CONTINUED flag */
}
/* returns 1 if swap entry is freed */
@@ -3196,7 +3196,7 @@ 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 = kvzalloc(nr_cluster * sizeof(*cluster_info),
+ cluster_info = kvcalloc(nr_cluster, sizeof(*cluster_info),
GFP_KERNEL);
if (!cluster_info) {
error = -ENOMEM;
@@ -3233,7 +3233,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 = kvzalloc(BITS_TO_LONGS(maxpages) * sizeof(long),
+ frontswap_map = kvcalloc(BITS_TO_LONGS(maxpages),
+ sizeof(long),
GFP_KERNEL);
if (p->bdev &&(swap_flags & SWAP_FLAG_DISCARD) && swap_discardable(p)) {
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 89efac3..cfea25b 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2741,11 +2741,11 @@ static const struct seq_operations vmalloc_op = {
static int __init proc_vmalloc_init(void)
{
if (IS_ENABLED(CONFIG_NUMA))
- proc_create_seq_private("vmallocinfo", S_IRUSR, NULL,
+ proc_create_seq_private("vmallocinfo", 0400, NULL,
&vmalloc_op,
nr_node_ids * sizeof(unsigned int), NULL);
else
- proc_create_seq("vmallocinfo", S_IRUSR, NULL, &vmalloc_op);
+ proc_create_seq("vmallocinfo", 0400, NULL, &vmalloc_op);
return 0;
}
module_init(proc_vmalloc_init);
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 61cb05d..8d87e97 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -661,8 +661,9 @@ static void zs_pool_stat_create(struct zs_pool *pool, const char *name)
}
pool->stat_dentry = entry;
- entry = debugfs_create_file("classes", S_IFREG | S_IRUGO,
- pool->stat_dentry, pool, &zs_stats_size_fops);
+ entry = debugfs_create_file("classes", S_IFREG | 0444,
+ pool->stat_dentry, pool,
+ &zs_stats_size_fops);
if (!entry) {
pr_warn("%s: debugfs file entry <%s> creation failed\n",
name, "classes");
diff --git a/mm/zswap.c b/mm/zswap.c
index 61a5c41..7d34e69 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -1256,26 +1256,26 @@ static int __init zswap_debugfs_init(void)
if (!zswap_debugfs_root)
return -ENOMEM;
- debugfs_create_u64("pool_limit_hit", S_IRUGO,
- zswap_debugfs_root, &zswap_pool_limit_hit);
- debugfs_create_u64("reject_reclaim_fail", S_IRUGO,
- zswap_debugfs_root, &zswap_reject_reclaim_fail);
- debugfs_create_u64("reject_alloc_fail", S_IRUGO,
- zswap_debugfs_root, &zswap_reject_alloc_fail);
- debugfs_create_u64("reject_kmemcache_fail", S_IRUGO,
- zswap_debugfs_root, &zswap_reject_kmemcache_fail);
- debugfs_create_u64("reject_compress_poor", S_IRUGO,
- zswap_debugfs_root, &zswap_reject_compress_poor);
- debugfs_create_u64("written_back_pages", S_IRUGO,
- zswap_debugfs_root, &zswap_written_back_pages);
- debugfs_create_u64("duplicate_entry", S_IRUGO,
- zswap_debugfs_root, &zswap_duplicate_entry);
- debugfs_create_u64("pool_total_size", S_IRUGO,
- zswap_debugfs_root, &zswap_pool_total_size);
- debugfs_create_atomic_t("stored_pages", S_IRUGO,
- zswap_debugfs_root, &zswap_stored_pages);
+ debugfs_create_u64("pool_limit_hit", 0444,
+ zswap_debugfs_root, &zswap_pool_limit_hit);
+ debugfs_create_u64("reject_reclaim_fail", 0444,
+ zswap_debugfs_root, &zswap_reject_reclaim_fail);
+ debugfs_create_u64("reject_alloc_fail", 0444,
+ zswap_debugfs_root, &zswap_reject_alloc_fail);
+ debugfs_create_u64("reject_kmemcache_fail", 0444,
+ zswap_debugfs_root, &zswap_reject_kmemcache_fail);
+ debugfs_create_u64("reject_compress_poor", 0444,
+ zswap_debugfs_root, &zswap_reject_compress_poor);
+ debugfs_create_u64("written_back_pages", 0444,
+ zswap_debugfs_root, &zswap_written_back_pages);
+ debugfs_create_u64("duplicate_entry", 0444,
+ zswap_debugfs_root, &zswap_duplicate_entry);
+ debugfs_create_u64("pool_total_size", 0444,
+ zswap_debugfs_root, &zswap_pool_total_size);
+ debugfs_create_atomic_t("stored_pages", 0444,
+ zswap_debugfs_root, &zswap_stored_pages);
debugfs_create_atomic_t("same_filled_pages", 0444,
- zswap_debugfs_root, &zswap_same_filled_pages);
+ zswap_debugfs_root, &zswap_same_filled_pages);
return 0;
}
diff --git a/net/9p/protocol.c b/net/9p/protocol.c
index 16e1068..931ea00 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -242,8 +242,9 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
"w", nwname);
if (!errcode) {
*wnames =
- kmalloc(sizeof(char *) * *nwname,
- GFP_NOFS);
+ kmalloc_array(*nwname,
+ sizeof(char *),
+ GFP_NOFS);
if (!*wnames)
errcode = -ENOMEM;
}
@@ -285,9 +286,9 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
p9pdu_readf(pdu, proto_version, "w", nwqid);
if (!errcode) {
*wqids =
- kmalloc(*nwqid *
- sizeof(struct p9_qid),
- GFP_NOFS);
+ kmalloc_array(*nwqid,
+ sizeof(struct p9_qid),
+ GFP_NOFS);
if (*wqids == NULL)
errcode = -ENOMEM;
}
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 4d03722..05006cb 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -360,7 +360,8 @@ static int p9_get_mapped_pages(struct virtio_chan *chan,
nr_pages = DIV_ROUND_UP((unsigned long)p + len, PAGE_SIZE) -
(unsigned long)p / PAGE_SIZE;
- *pages = kmalloc(sizeof(struct page *) * nr_pages, GFP_NOFS);
+ *pages = kmalloc_array(nr_pages, sizeof(struct page *),
+ GFP_NOFS);
if (!*pages)
return -ENOMEM;
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index 36b3ada..10462de 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -252,8 +252,7 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
- refcount_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
- ATM_SKB(skb)->atm_options = atmvcc->atm_options;
+ atm_account_tx(atmvcc, skb);
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
diff --git a/net/atm/clip.c b/net/atm/clip.c
index 66caa48..d795b9c 100644
--- a/net/atm/clip.c
+++ b/net/atm/clip.c
@@ -381,8 +381,7 @@ static netdev_tx_t clip_start_xmit(struct sk_buff *skb,
memcpy(here, llc_oui, sizeof(llc_oui));
((__be16 *) here)[3] = skb->protocol;
}
- refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
- ATM_SKB(skb)->atm_options = vcc->atm_options;
+ atm_account_tx(vcc, skb);
entry->vccs->last_use = jiffies;
pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, vcc, vcc->dev);
old = xchg(&entry->vccs->xoff, 1); /* assume XOFF ... */
diff --git a/net/atm/common.c b/net/atm/common.c
index 1f2af59..ff5748b 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -630,10 +630,9 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
goto out;
}
pr_debug("%d += %d\n", sk_wmem_alloc_get(sk), skb->truesize);
- refcount_add(skb->truesize, &sk->sk_wmem_alloc);
+ atm_account_tx(vcc, skb);
skb->dev = NULL; /* for paths shared with net_device interfaces */
- ATM_SKB(skb)->atm_options = vcc->atm_options;
if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) {
kfree_skb(skb);
error = -EFAULT;
diff --git a/net/atm/lec.c b/net/atm/lec.c
index 5a95fcf..d7f5cf5 100644
--- a/net/atm/lec.c
+++ b/net/atm/lec.c
@@ -182,9 +182,8 @@ lec_send(struct atm_vcc *vcc, struct sk_buff *skb)
struct net_device *dev = skb->dev;
ATM_SKB(skb)->vcc = vcc;
- ATM_SKB(skb)->atm_options = vcc->atm_options;
+ atm_account_tx(vcc, skb);
- refcount_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
if (vcc->send(vcc, skb) < 0) {
dev->stats.tx_dropped++;
return;
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 31e0dcb..24b53c4 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -472,7 +472,7 @@ static const uint8_t *copy_macs(struct mpoa_client *mpc,
if (mpc->number_of_mps_macs != 0)
kfree(mpc->mps_macs);
mpc->number_of_mps_macs = 0;
- mpc->mps_macs = kmalloc(num_macs * ETH_ALEN, GFP_KERNEL);
+ mpc->mps_macs = kmalloc_array(ETH_ALEN, num_macs, GFP_KERNEL);
if (mpc->mps_macs == NULL) {
pr_info("(%s) out of mem\n", mpc->dev->name);
return NULL;
@@ -555,8 +555,7 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
sizeof(struct llc_snap_hdr));
}
- refcount_add(skb->truesize, &sk_atm(entry->shortcut)->sk_wmem_alloc);
- ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
+ atm_account_tx(entry->shortcut, skb);
entry->shortcut->send(entry->shortcut, skb);
entry->packets_fwded++;
mpc->in_ops->put(entry);
diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 21d9d34..af8c4b3 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -350,8 +350,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb)
return 1;
}
- refcount_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
- ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
+ atm_account_tx(vcc, skb);
pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n",
skb, ATM_SKB(skb)->vcc, ATM_SKB(skb)->vcc->dev);
ret = ATM_SKB(skb)->vcc->send(ATM_SKB(skb)->vcc, skb)
diff --git a/net/atm/raw.c b/net/atm/raw.c
index ee10e8d..b3ba44a 100644
--- a/net/atm/raw.c
+++ b/net/atm/raw.c
@@ -35,8 +35,8 @@ static void atm_pop_raw(struct atm_vcc *vcc, struct sk_buff *skb)
struct sock *sk = sk_atm(vcc);
pr_debug("(%d) %d -= %d\n",
- vcc->vci, sk_wmem_alloc_get(sk), skb->truesize);
- WARN_ON(refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc));
+ vcc->vci, sk_wmem_alloc_get(sk), ATM_SKB(skb)->acct_truesize);
+ WARN_ON(refcount_sub_and_test(ATM_SKB(skb)->acct_truesize, &sk->sk_wmem_alloc));
dev_kfree_skb_any(skb);
sk->sk_write_space(sk);
}
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 1dec337..ee8ef12 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -1281,7 +1281,7 @@ int hci_inquiry(void __user *arg)
/* cache_dump can't sleep. Therefore we allocate temp buffer and then
* copy it to the user space.
*/
- buf = kmalloc(sizeof(struct inquiry_info) * max_rsp, GFP_KERNEL);
+ buf = kmalloc_array(max_rsp, sizeof(struct inquiry_info), GFP_KERNEL);
if (!buf) {
err = -ENOMEM;
goto done;
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 9b7907e..d17a473 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -331,7 +331,7 @@ static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size)
*/
alloc_size = roundup_pow_of_two(size);
- seq_list->list = kmalloc(sizeof(u16) * alloc_size, GFP_KERNEL);
+ seq_list->list = kmalloc_array(alloc_size, sizeof(u16), GFP_KERNEL);
if (!seq_list->list)
return -ENOMEM;
diff --git a/net/bpfilter/.gitignore b/net/bpfilter/.gitignore
new file mode 100644
index 0000000..e97084e
--- /dev/null
+++ b/net/bpfilter/.gitignore
@@ -0,0 +1 @@
+bpfilter_umh
diff --git a/net/bpfilter/Makefile b/net/bpfilter/Makefile
index aafa720..dd86b02 100644
--- a/net/bpfilter/Makefile
+++ b/net/bpfilter/Makefile
@@ -21,8 +21,10 @@ endif
# which bpfilter_kern.c passes further into umh blob loader at run-time
quiet_cmd_copy_umh = GEN $@
cmd_copy_umh = echo ':' > $(obj)/.bpfilter_umh.o.cmd; \
- $(OBJCOPY) -I binary -O $(CONFIG_OUTPUT_FORMAT) \
- -B `$(OBJDUMP) -f $<|grep architecture|cut -d, -f1|cut -d' ' -f2` \
+ $(OBJCOPY) -I binary \
+ `LC_ALL=C objdump -f net/bpfilter/bpfilter_umh \
+ |awk -F' |,' '/file format/{print "-O",$$NF} \
+ /^architecture:/{print "-B",$$2}'` \
--rename-section .data=.init.rodata $< $@
$(obj)/bpfilter_umh.o: $(obj)/bpfilter_umh
diff --git a/net/bpfilter/bpfilter_kern.c b/net/bpfilter/bpfilter_kern.c
index b13d058..0952257 100644
--- a/net/bpfilter/bpfilter_kern.c
+++ b/net/bpfilter/bpfilter_kern.c
@@ -24,17 +24,19 @@ static void shutdown_umh(struct umh_info *info)
{
struct task_struct *tsk;
+ if (!info->pid)
+ return;
tsk = pid_task(find_vpid(info->pid), PIDTYPE_PID);
if (tsk)
force_sig(SIGKILL, tsk);
fput(info->pipe_to_umh);
fput(info->pipe_from_umh);
+ info->pid = 0;
}
static void __stop_umh(void)
{
- if (IS_ENABLED(CONFIG_INET) &&
- bpfilter_process_sockopt) {
+ if (IS_ENABLED(CONFIG_INET)) {
bpfilter_process_sockopt = NULL;
shutdown_umh(&info);
}
@@ -55,7 +57,7 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
struct mbox_reply reply;
loff_t pos;
ssize_t n;
- int ret;
+ int ret = -EFAULT;
req.is_set = is_set;
req.pid = current->pid;
@@ -63,6 +65,8 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
req.addr = (long)optval;
req.len = optlen;
mutex_lock(&bpfilter_lock);
+ if (!info.pid)
+ goto out;
n = __kernel_write(info.pipe_to_umh, &req, sizeof(req), &pos);
if (n != sizeof(req)) {
pr_err("write fail %zd\n", n);
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index b19e310..502f663 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -135,9 +135,11 @@ struct net_device *br_fdb_find_port(const struct net_device *br_dev,
return NULL;
br = netdev_priv(br_dev);
- f = br_fdb_find(br, addr, vid);
+ rcu_read_lock();
+ f = br_fdb_find_rcu(br, addr, vid);
if (f && f->dst)
dev = f->dst->dev;
+ rcu_read_unlock();
return dev;
}
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index cb47295..920665d 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -333,7 +333,7 @@ static int br_mdb_rehash(struct net_bridge_mdb_htable __rcu **mdbp, int max,
mdb->max = max;
mdb->old = old;
- mdb->mhash = kzalloc(max * sizeof(*mdb->mhash), GFP_ATOMIC);
+ mdb->mhash = kcalloc(max, sizeof(*mdb->mhash), GFP_ATOMIC);
if (!mdb->mhash) {
kfree(mdb);
return -ENOMEM;
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 28f68a2..4918287 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -411,6 +411,12 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par,
watcher = xt_request_find_target(NFPROTO_BRIDGE, w->u.name, 0);
if (IS_ERR(watcher))
return PTR_ERR(watcher);
+
+ if (watcher->family != NFPROTO_BRIDGE) {
+ module_put(watcher->me);
+ return -ENOENT;
+ }
+
w->u.watcher = watcher;
par->target = watcher;
@@ -709,6 +715,8 @@ ebt_check_entry(struct ebt_entry *e, struct net *net,
}
i = 0;
+ memset(&mtpar, 0, sizeof(mtpar));
+ memset(&tgpar, 0, sizeof(tgpar));
mtpar.net = tgpar.net = net;
mtpar.table = tgpar.table = name;
mtpar.entryinfo = tgpar.entryinfo = e;
@@ -730,6 +738,13 @@ ebt_check_entry(struct ebt_entry *e, struct net *net,
goto cleanup_watchers;
}
+ /* Reject UNSPEC, xtables verdicts/return values are incompatible */
+ if (target->family != NFPROTO_BRIDGE) {
+ module_put(target->me);
+ ret = -ENOENT;
+ goto cleanup_watchers;
+ }
+
t->u.target = target;
if (t->u.target == &ebt_standard_target) {
if (gap < sizeof(struct ebt_standard_target)) {
@@ -903,12 +918,13 @@ static int translate_table(struct net *net, const char *name,
* if an error occurs
*/
newinfo->chainstack =
- vmalloc(nr_cpu_ids * sizeof(*(newinfo->chainstack)));
+ vmalloc(array_size(nr_cpu_ids,
+ sizeof(*(newinfo->chainstack))));
if (!newinfo->chainstack)
return -ENOMEM;
for_each_possible_cpu(i) {
newinfo->chainstack[i] =
- vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0])));
+ vmalloc(array_size(udc_cnt, sizeof(*(newinfo->chainstack[0]))));
if (!newinfo->chainstack[i]) {
while (i)
vfree(newinfo->chainstack[--i]);
@@ -918,7 +934,7 @@ static int translate_table(struct net *net, const char *name,
}
}
- cl_s = vmalloc(udc_cnt * sizeof(*cl_s));
+ cl_s = vmalloc(array_size(udc_cnt, sizeof(*cl_s)));
if (!cl_s)
return -ENOMEM;
i = 0; /* the i'th udc */
@@ -1293,7 +1309,7 @@ static int do_update_counters(struct net *net, const char *name,
if (num_counters == 0)
return -EINVAL;
- tmp = vmalloc(num_counters * sizeof(*tmp));
+ tmp = vmalloc(array_size(num_counters, sizeof(*tmp)));
if (!tmp)
return -ENOMEM;
@@ -1434,7 +1450,7 @@ static int copy_counters_to_user(struct ebt_table *t,
return -EINVAL;
}
- counterstmp = vmalloc(nentries * sizeof(*counterstmp));
+ counterstmp = vmalloc(array_size(nentries, sizeof(*counterstmp)));
if (!counterstmp)
return -ENOMEM;
@@ -1605,16 +1621,16 @@ struct compat_ebt_entry_mwt {
compat_uptr_t ptr;
} u;
compat_uint_t match_size;
- compat_uint_t data[0];
+ compat_uint_t data[0] __attribute__ ((aligned (__alignof__(struct compat_ebt_replace))));
};
/* account for possible padding between match_size and ->data */
static int ebt_compat_entry_padsize(void)
{
- BUILD_BUG_ON(XT_ALIGN(sizeof(struct ebt_entry_match)) <
- COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt)));
- return (int) XT_ALIGN(sizeof(struct ebt_entry_match)) -
- COMPAT_XT_ALIGN(sizeof(struct compat_ebt_entry_mwt));
+ BUILD_BUG_ON(sizeof(struct ebt_entry_match) <
+ sizeof(struct compat_ebt_entry_mwt));
+ return (int) sizeof(struct ebt_entry_match) -
+ sizeof(struct compat_ebt_entry_mwt);
}
static int ebt_compat_match_offset(const struct xt_match *match,
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c
index eaf05de..6de9812 100644
--- a/net/bridge/netfilter/nft_reject_bridge.c
+++ b/net/bridge/netfilter/nft_reject_bridge.c
@@ -261,7 +261,7 @@ static void nft_reject_br_send_v6_unreach(struct net *net,
if (!reject6_br_csum_ok(oldskb, hook))
return;
- nskb = alloc_skb(sizeof(struct iphdr) + sizeof(struct icmp6hdr) +
+ nskb = alloc_skb(sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr) +
LL_MAX_HEADER + len, GFP_ATOMIC);
if (!nskb)
return;
diff --git a/net/can/bcm.c b/net/can/bcm.c
index 97fedff..9393f25 100644
--- a/net/can/bcm.c
+++ b/net/can/bcm.c
@@ -923,8 +923,9 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
/* create array for CAN frames and copy the data */
if (msg_head->nframes > 1) {
- op->frames = kmalloc(msg_head->nframes * op->cfsiz,
- GFP_KERNEL);
+ op->frames = kmalloc_array(msg_head->nframes,
+ op->cfsiz,
+ GFP_KERNEL);
if (!op->frames) {
kfree(op);
return -ENOMEM;
@@ -1095,15 +1096,17 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
if (msg_head->nframes > 1) {
/* create array for CAN frames and copy the data */
- op->frames = kmalloc(msg_head->nframes * op->cfsiz,
- GFP_KERNEL);
+ op->frames = kmalloc_array(msg_head->nframes,
+ op->cfsiz,
+ GFP_KERNEL);
if (!op->frames) {
kfree(op);
return -ENOMEM;
}
/* create and init array for received CAN frames */
- op->last_frames = kzalloc(msg_head->nframes * op->cfsiz,
+ op->last_frames = kcalloc(msg_head->nframes,
+ op->cfsiz,
GFP_KERNEL);
if (!op->last_frames) {
kfree(op->frames);
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c
index 3b3d33e..c6413c3 100644
--- a/net/ceph/messenger.c
+++ b/net/ceph/messenger.c
@@ -168,12 +168,6 @@ static char tag_keepalive2 = CEPH_MSGR_TAG_KEEPALIVE2;
static struct lock_class_key socket_class;
#endif
-/*
- * When skipping (ignoring) a block of input we read it into a "skip
- * buffer," which is this many bytes in size.
- */
-#define SKIP_BUF_SIZE 1024
-
static void queue_con(struct ceph_connection *con);
static void cancel_con(struct ceph_connection *con);
static void ceph_con_workfn(struct work_struct *);
@@ -520,12 +514,18 @@ static int ceph_tcp_connect(struct ceph_connection *con)
return 0;
}
+/*
+ * If @buf is NULL, discard up to @len bytes.
+ */
static int ceph_tcp_recvmsg(struct socket *sock, void *buf, size_t len)
{
struct kvec iov = {buf, len};
struct msghdr msg = { .msg_flags = MSG_DONTWAIT | MSG_NOSIGNAL };
int r;
+ if (!buf)
+ msg.msg_flags |= MSG_TRUNC;
+
iov_iter_kvec(&msg.msg_iter, READ | ITER_KVEC, &iov, 1, len);
r = sock_recvmsg(sock, &msg, msg.msg_flags);
if (r == -EAGAIN)
@@ -2575,9 +2575,6 @@ static int try_write(struct ceph_connection *con)
con->state != CON_STATE_OPEN)
return 0;
-more:
- dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes);
-
/* open the socket first? */
if (con->state == CON_STATE_PREOPEN) {
BUG_ON(con->sock);
@@ -2598,7 +2595,8 @@ more:
}
}
-more_kvec:
+more:
+ dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes);
BUG_ON(!con->sock);
/* kvec data queued? */
@@ -2623,7 +2621,7 @@ more_kvec:
ret = write_partial_message_data(con);
if (ret == 1)
- goto more_kvec; /* we need to send the footer, too! */
+ goto more; /* we need to send the footer, too! */
if (ret == 0)
goto out;
if (ret < 0) {
@@ -2659,8 +2657,6 @@ out:
return ret;
}
-
-
/*
* Read what we can from the socket.
*/
@@ -2721,16 +2717,11 @@ more:
if (con->in_base_pos < 0) {
/*
* skipping + discarding content.
- *
- * FIXME: there must be a better way to do this!
*/
- static char buf[SKIP_BUF_SIZE];
- int skip = min((int) sizeof (buf), -con->in_base_pos);
-
- dout("skipping %d / %d bytes\n", skip, -con->in_base_pos);
- ret = ceph_tcp_recvmsg(con->sock, buf, skip);
+ ret = ceph_tcp_recvmsg(con->sock, NULL, -con->in_base_pos);
if (ret <= 0)
goto out;
+ dout("skipped %d / %d bytes\n", ret, -con->in_base_pos);
con->in_base_pos += ret;
if (con->in_base_pos)
goto more;
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 69a2581..a00c74f 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -766,7 +766,7 @@ void osd_req_op_extent_dup_last(struct ceph_osd_request *osd_req,
}
EXPORT_SYMBOL(osd_req_op_extent_dup_last);
-void osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
+int osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
u16 opcode, const char *class, const char *method)
{
struct ceph_osd_req_op *op = _osd_req_op_init(osd_req, which,
@@ -778,7 +778,9 @@ void osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
BUG_ON(opcode != CEPH_OSD_OP_CALL);
pagelist = kmalloc(sizeof (*pagelist), GFP_NOFS);
- BUG_ON(!pagelist);
+ if (!pagelist)
+ return -ENOMEM;
+
ceph_pagelist_init(pagelist);
op->cls.class_name = class;
@@ -798,6 +800,7 @@ void osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
osd_req_op_cls_request_info_pagelist(osd_req, which, pagelist);
op->indata_len = payload_len;
+ return 0;
}
EXPORT_SYMBOL(osd_req_op_cls_init);
@@ -1026,7 +1029,6 @@ 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);
@@ -1054,6 +1056,38 @@ EXPORT_SYMBOL(ceph_osdc_new_request);
DEFINE_RB_FUNCS(request, struct ceph_osd_request, r_tid, r_node)
DEFINE_RB_FUNCS(request_mc, struct ceph_osd_request, r_tid, r_mc_node)
+/*
+ * Call @fn on each OSD request as long as @fn returns 0.
+ */
+static void for_each_request(struct ceph_osd_client *osdc,
+ int (*fn)(struct ceph_osd_request *req, void *arg),
+ void *arg)
+{
+ struct rb_node *n, *p;
+
+ for (n = rb_first(&osdc->osds); n; n = rb_next(n)) {
+ struct ceph_osd *osd = rb_entry(n, struct ceph_osd, o_node);
+
+ for (p = rb_first(&osd->o_requests); p; ) {
+ struct ceph_osd_request *req =
+ rb_entry(p, struct ceph_osd_request, r_node);
+
+ p = rb_next(p);
+ if (fn(req, arg))
+ return;
+ }
+ }
+
+ for (p = rb_first(&osdc->homeless_osd.o_requests); p; ) {
+ struct ceph_osd_request *req =
+ rb_entry(p, struct ceph_osd_request, r_node);
+
+ p = rb_next(p);
+ if (fn(req, arg))
+ return;
+ }
+}
+
static bool osd_homeless(struct ceph_osd *osd)
{
return osd->o_osd == CEPH_HOMELESS_OSD;
@@ -1395,7 +1429,6 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
bool recovery_deletes = ceph_osdmap_flag(osdc,
CEPH_OSDMAP_RECOVERY_DELETES);
enum calc_target_result ct_res;
- int ret;
t->epoch = osdc->osdmap->epoch;
pi = ceph_pg_pool_by_id(osdc->osdmap, t->base_oloc.pool);
@@ -1431,14 +1464,7 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc,
}
}
- ret = __ceph_object_locator_to_pg(pi, &t->target_oid, &t->target_oloc,
- &pgid);
- if (ret) {
- WARN_ON(ret != -ENOENT);
- t->osd = CEPH_HOMELESS_OSD;
- ct_res = CALC_TARGET_POOL_DNE;
- goto out;
- }
+ __ceph_object_locator_to_pg(pi, &t->target_oid, &t->target_oloc, &pgid);
last_pgid.pool = pgid.pool;
last_pgid.seed = ceph_stable_mod(pgid.seed, t->pg_num, t->pg_num_mask);
@@ -2161,9 +2187,9 @@ static void __submit_request(struct ceph_osd_request *req, bool wrlocked)
struct ceph_osd_client *osdc = req->r_osdc;
struct ceph_osd *osd;
enum calc_target_result ct_res;
+ int err = 0;
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);
@@ -2179,7 +2205,10 @@ again:
goto promote;
}
- if (osdc->osdmap->epoch < osdc->epoch_barrier) {
+ if (osdc->abort_err) {
+ dout("req %p abort_err %d\n", req, osdc->abort_err);
+ err = osdc->abort_err;
+ } else 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;
@@ -2200,11 +2229,13 @@ again:
(ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
pool_full(osdc, req->r_t.base_oloc.pool))) {
dout("req %p full/pool_full\n", req);
- 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;
+ if (osdc->abort_on_full) {
+ err = -ENOSPC;
+ } else {
+ pr_warn_ratelimited("FULL or reached pool quota\n");
+ req->r_t.paused = true;
+ maybe_request_map(osdc);
+ }
} else if (!osd_homeless(osd)) {
need_send = true;
} else {
@@ -2221,11 +2252,11 @@ again:
link_request(osd, req);
if (need_send)
send_request(req);
- else if (need_abort)
- complete_request(req, -ENOSPC);
+ else if (err)
+ complete_request(req, err);
mutex_unlock(&osd->lock);
- if (ct_res == CALC_TARGET_POOL_DNE)
+ if (!err && ct_res == CALC_TARGET_POOL_DNE)
send_map_check(req);
if (promoted)
@@ -2281,11 +2312,21 @@ static void finish_request(struct ceph_osd_request *req)
static void __complete_request(struct ceph_osd_request *req)
{
- if (req->r_callback) {
- dout("%s req %p tid %llu cb %pf result %d\n", __func__, req,
- req->r_tid, req->r_callback, req->r_result);
+ dout("%s req %p tid %llu cb %pf result %d\n", __func__, req,
+ req->r_tid, req->r_callback, req->r_result);
+
+ if (req->r_callback)
req->r_callback(req);
- }
+ complete_all(&req->r_completion);
+ ceph_osdc_put_request(req);
+}
+
+static void complete_request_workfn(struct work_struct *work)
+{
+ struct ceph_osd_request *req =
+ container_of(work, struct ceph_osd_request, r_complete_work);
+
+ __complete_request(req);
}
/*
@@ -2297,9 +2338,9 @@ static void complete_request(struct ceph_osd_request *req, int err)
req->r_result = err;
finish_request(req);
- __complete_request(req);
- complete_all(&req->r_completion);
- ceph_osdc_put_request(req);
+
+ INIT_WORK(&req->r_complete_work, complete_request_workfn);
+ queue_work(req->r_osdc->completion_wq, &req->r_complete_work);
}
static void cancel_map_check(struct ceph_osd_request *req)
@@ -2336,6 +2377,28 @@ static void abort_request(struct ceph_osd_request *req, int err)
complete_request(req, err);
}
+static int abort_fn(struct ceph_osd_request *req, void *arg)
+{
+ int err = *(int *)arg;
+
+ abort_request(req, err);
+ return 0; /* continue iteration */
+}
+
+/*
+ * Abort all in-flight requests with @err and arrange for all future
+ * requests to be failed immediately.
+ */
+void ceph_osdc_abort_requests(struct ceph_osd_client *osdc, int err)
+{
+ dout("%s osdc %p err %d\n", __func__, osdc, err);
+ down_write(&osdc->lock);
+ for_each_request(osdc, abort_fn, &err);
+ osdc->abort_err = err;
+ up_write(&osdc->lock);
+}
+EXPORT_SYMBOL(ceph_osdc_abort_requests);
+
static void update_epoch_barrier(struct ceph_osd_client *osdc, u32 eb)
{
if (likely(eb > osdc->epoch_barrier)) {
@@ -2363,6 +2426,30 @@ void ceph_osdc_update_epoch_barrier(struct ceph_osd_client *osdc, u32 eb)
EXPORT_SYMBOL(ceph_osdc_update_epoch_barrier);
/*
+ * We can end up releasing caps as a result of abort_request().
+ * In that case, we probably want to ensure that the cap release message
+ * has an updated epoch barrier in it, so set the epoch barrier prior to
+ * aborting the first request.
+ */
+static int abort_on_full_fn(struct ceph_osd_request *req, void *arg)
+{
+ struct ceph_osd_client *osdc = req->r_osdc;
+ bool *victims = arg;
+
+ if ((req->r_flags & CEPH_OSD_FLAG_WRITE) &&
+ (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
+ pool_full(osdc, req->r_t.base_oloc.pool))) {
+ if (!*victims) {
+ update_epoch_barrier(osdc, osdc->osdmap->epoch);
+ *victims = true;
+ }
+ abort_request(req, -ENOSPC);
+ }
+
+ return 0; /* continue iteration */
+}
+
+/*
* 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
@@ -2370,61 +2457,11 @@ EXPORT_SYMBOL(ceph_osdc_update_epoch_barrier);
*/
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);
+ if (osdc->abort_on_full &&
+ (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) || have_pool_full(osdc)))
+ for_each_request(osdc, abort_on_full_fn, &victims);
}
static void check_pool_dne(struct ceph_osd_request *req)
@@ -3541,8 +3578,6 @@ static void handle_reply(struct ceph_osd *osd, struct ceph_msg *msg)
up_read(&osdc->lock);
__complete_request(req);
- complete_all(&req->r_completion);
- ceph_osdc_put_request(req);
return;
fail_request:
@@ -4927,7 +4962,10 @@ int ceph_osdc_call(struct ceph_osd_client *osdc,
if (ret)
goto out_put_req;
- osd_req_op_cls_init(req, 0, CEPH_OSD_OP_CALL, class, method);
+ ret = osd_req_op_cls_init(req, 0, CEPH_OSD_OP_CALL, class, method);
+ if (ret)
+ goto out_put_req;
+
if (req_page)
osd_req_op_cls_request_data_pages(req, 0, &req_page, req_len,
0, false, false);
@@ -4996,6 +5034,10 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client)
if (!osdc->notify_wq)
goto out_msgpool_reply;
+ osdc->completion_wq = create_singlethread_workqueue("ceph-completion");
+ if (!osdc->completion_wq)
+ goto out_notify_wq;
+
schedule_delayed_work(&osdc->timeout_work,
osdc->client->options->osd_keepalive_timeout);
schedule_delayed_work(&osdc->osds_timeout_work,
@@ -5003,6 +5045,8 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client)
return 0;
+out_notify_wq:
+ destroy_workqueue(osdc->notify_wq);
out_msgpool_reply:
ceph_msgpool_destroy(&osdc->msgpool_op_reply);
out_msgpool:
@@ -5017,7 +5061,7 @@ out:
void ceph_osdc_stop(struct ceph_osd_client *osdc)
{
- flush_workqueue(osdc->notify_wq);
+ destroy_workqueue(osdc->completion_wq);
destroy_workqueue(osdc->notify_wq);
cancel_delayed_work_sync(&osdc->timeout_work);
cancel_delayed_work_sync(&osdc->osds_timeout_work);
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c
index 9645ffd..98c0ff3 100644
--- a/net/ceph/osdmap.c
+++ b/net/ceph/osdmap.c
@@ -1299,8 +1299,9 @@ static int set_primary_affinity(struct ceph_osdmap *map, int osd, u32 aff)
if (!map->osd_primary_affinity) {
int i;
- map->osd_primary_affinity = kmalloc(map->max_osd*sizeof(u32),
- GFP_NOFS);
+ map->osd_primary_affinity = kmalloc_array(map->max_osd,
+ sizeof(u32),
+ GFP_NOFS);
if (!map->osd_primary_affinity)
return -ENOMEM;
@@ -2145,10 +2146,10 @@ bool ceph_osds_changed(const struct ceph_osds *old_acting,
* Should only be called with target_oid and target_oloc (as opposed to
* base_oid and base_oloc), since tiering isn't taken into account.
*/
-int __ceph_object_locator_to_pg(struct ceph_pg_pool_info *pi,
- const struct ceph_object_id *oid,
- const struct ceph_object_locator *oloc,
- struct ceph_pg *raw_pgid)
+void __ceph_object_locator_to_pg(struct ceph_pg_pool_info *pi,
+ const struct ceph_object_id *oid,
+ const struct ceph_object_locator *oloc,
+ struct ceph_pg *raw_pgid)
{
WARN_ON(pi->id != oloc->pool);
@@ -2164,11 +2165,8 @@ int __ceph_object_locator_to_pg(struct ceph_pg_pool_info *pi,
int nsl = oloc->pool_ns->len;
size_t total = nsl + 1 + oid->name_len;
- if (total > sizeof(stack_buf)) {
- buf = kmalloc(total, GFP_NOIO);
- if (!buf)
- return -ENOMEM;
- }
+ if (total > sizeof(stack_buf))
+ buf = kmalloc(total, GFP_NOIO | __GFP_NOFAIL);
memcpy(buf, oloc->pool_ns->str, nsl);
buf[nsl] = '\037';
memcpy(buf + nsl + 1, oid->name, oid->name_len);
@@ -2180,7 +2178,6 @@ int __ceph_object_locator_to_pg(struct ceph_pg_pool_info *pi,
oid->name, nsl, oloc->pool_ns->str,
raw_pgid->pool, raw_pgid->seed);
}
- return 0;
}
int ceph_object_locator_to_pg(struct ceph_osdmap *osdmap,
@@ -2194,7 +2191,8 @@ int ceph_object_locator_to_pg(struct ceph_osdmap *osdmap,
if (!pi)
return -ENOENT;
- return __ceph_object_locator_to_pg(pi, oid, oloc, raw_pgid);
+ __ceph_object_locator_to_pg(pi, oid, oloc, raw_pgid);
+ return 0;
}
EXPORT_SYMBOL(ceph_object_locator_to_pg);
diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c
index a3d0adc..e560d39 100644
--- a/net/ceph/pagevec.c
+++ b/net/ceph/pagevec.c
@@ -20,7 +20,7 @@ struct page **ceph_get_direct_page_vector(const void __user *data,
int got = 0;
int rc = 0;
- pages = kmalloc(sizeof(*pages) * num_pages, GFP_NOFS);
+ pages = kmalloc_array(num_pages, sizeof(*pages), GFP_NOFS);
if (!pages)
return ERR_PTR(-ENOMEM);
@@ -74,7 +74,7 @@ struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags)
struct page **pages;
int i;
- pages = kmalloc(sizeof(*pages) * num_pages, flags);
+ pages = kmalloc_array(num_pages, sizeof(*pages), flags);
if (!pages)
return ERR_PTR(-ENOMEM);
for (i = 0; i < num_pages; i++) {
diff --git a/net/core/dev.c b/net/core/dev.c
index 6e18242..a5aa1c7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -8643,7 +8643,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
/* We get here if we can't use the current device name */
if (!pat)
goto out;
- if (dev_get_valid_name(net, dev, pat) < 0)
+ err = dev_get_valid_name(net, dev, pat);
+ if (err < 0)
goto out;
}
@@ -8655,7 +8656,6 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
dev_close(dev);
/* And unlink it from device chain */
- err = -ENODEV;
unlist_netdevice(dev);
synchronize_net();
@@ -8823,7 +8823,7 @@ static struct hlist_head * __net_init netdev_create_hash(void)
int i;
struct hlist_head *hash;
- hash = kmalloc(sizeof(*hash) * NETDEV_HASHENTRIES, GFP_KERNEL);
+ hash = kmalloc_array(NETDEV_HASHENTRIES, sizeof(*hash), GFP_KERNEL);
if (hash != NULL)
for (i = 0; i < NETDEV_HASHENTRIES; i++)
INIT_HLIST_HEAD(&hash[i]);
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index c15075d..e677a20 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -911,7 +911,7 @@ static noinline_for_stack int ethtool_get_sset_info(struct net_device *dev,
memset(&info, 0, sizeof(info));
info.cmd = ETHTOOL_GSSET_INFO;
- info_buf = kzalloc(n_bits * sizeof(u32), GFP_USER);
+ info_buf = kcalloc(n_bits, sizeof(u32), GFP_USER);
if (!info_buf)
return -ENOMEM;
@@ -1017,7 +1017,7 @@ static noinline_for_stack int ethtool_get_rxnfc(struct net_device *dev,
if (info.cmd == ETHTOOL_GRXCLSRLALL) {
if (info.rule_cnt > 0) {
if (info.rule_cnt <= KMALLOC_MAX_SIZE / sizeof(u32))
- rule_buf = kzalloc(info.rule_cnt * sizeof(u32),
+ rule_buf = kcalloc(info.rule_cnt, sizeof(u32),
GFP_USER);
if (!rule_buf)
return -ENOMEM;
@@ -1816,7 +1816,7 @@ static int ethtool_self_test(struct net_device *dev, char __user *useraddr)
return -EFAULT;
test.len = test_len;
- data = kmalloc(test_len * sizeof(u64), GFP_USER);
+ data = kmalloc_array(test_len, sizeof(u64), GFP_USER);
if (!data)
return -ENOMEM;
@@ -1852,7 +1852,7 @@ static int ethtool_get_strings(struct net_device *dev, void __user *useraddr)
WARN_ON_ONCE(!ret);
gstrings.len = ret;
- data = vzalloc(gstrings.len * ETH_GSTRING_LEN);
+ data = vzalloc(array_size(gstrings.len, ETH_GSTRING_LEN));
if (gstrings.len && !data)
return -ENOMEM;
@@ -1952,7 +1952,7 @@ static int ethtool_get_stats(struct net_device *dev, void __user *useraddr)
return -EFAULT;
stats.n_stats = n_stats;
- data = vzalloc(n_stats * sizeof(u64));
+ data = vzalloc(array_size(n_stats, sizeof(u64)));
if (n_stats && !data)
return -ENOMEM;
@@ -1996,7 +1996,7 @@ static int ethtool_get_phy_stats(struct net_device *dev, void __user *useraddr)
return -EFAULT;
stats.n_stats = n_stats;
- data = vzalloc(n_stats * sizeof(u64));
+ data = vzalloc(array_size(n_stats, sizeof(u64)));
if (n_stats && !data)
return -ENOMEM;
diff --git a/net/core/filter.c b/net/core/filter.c
index 3d9ba7e..e7f12e9 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3214,20 +3214,6 @@ err:
}
EXPORT_SYMBOL_GPL(xdp_do_redirect);
-static int __xdp_generic_ok_fwd_dev(struct sk_buff *skb, struct net_device *fwd)
-{
- unsigned int len;
-
- if (unlikely(!(fwd->flags & IFF_UP)))
- return -ENETDOWN;
-
- len = fwd->mtu + fwd->hard_header_len + VLAN_HLEN;
- if (skb->len > len)
- return -EMSGSIZE;
-
- return 0;
-}
-
static int xdp_do_generic_redirect_map(struct net_device *dev,
struct sk_buff *skb,
struct xdp_buff *xdp,
@@ -3256,10 +3242,11 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
}
if (map->map_type == BPF_MAP_TYPE_DEVMAP) {
- if (unlikely((err = __xdp_generic_ok_fwd_dev(skb, fwd))))
+ struct bpf_dtab_netdev *dst = fwd;
+
+ err = dev_map_generic_redirect(dst, skb, xdp_prog);
+ if (unlikely(err))
goto err;
- skb->dev = fwd;
- generic_xdp_tx(skb, xdp_prog);
} else if (map->map_type == BPF_MAP_TYPE_XSKMAP) {
struct xdp_sock *xs = fwd;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index a7a9c3d..8e3fda9 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -119,13 +119,14 @@ unsigned long neigh_rand_reach_time(unsigned long base)
EXPORT_SYMBOL(neigh_rand_reach_time);
-static bool neigh_del(struct neighbour *n, __u8 state,
+static bool neigh_del(struct neighbour *n, __u8 state, __u8 flags,
struct neighbour __rcu **np, struct neigh_table *tbl)
{
bool retval = false;
write_lock(&n->lock);
- if (refcount_read(&n->refcnt) == 1 && !(n->nud_state & state)) {
+ if (refcount_read(&n->refcnt) == 1 && !(n->nud_state & state) &&
+ !(n->flags & flags)) {
struct neighbour *neigh;
neigh = rcu_dereference_protected(n->next,
@@ -157,7 +158,7 @@ bool neigh_remove_one(struct neighbour *ndel, struct neigh_table *tbl)
while ((n = rcu_dereference_protected(*np,
lockdep_is_held(&tbl->lock)))) {
if (n == ndel)
- return neigh_del(n, 0, np, tbl);
+ return neigh_del(n, 0, 0, np, tbl);
np = &n->next;
}
return false;
@@ -185,7 +186,8 @@ static int neigh_forced_gc(struct neigh_table *tbl)
* - nobody refers to it.
* - it is not permanent
*/
- if (neigh_del(n, NUD_PERMANENT, np, tbl)) {
+ if (neigh_del(n, NUD_PERMANENT, NTF_EXT_LEARNED, np,
+ tbl)) {
shrunk = 1;
continue;
}
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 7e4ede3..49368e2 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3603,7 +3603,8 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)
return -ENOMEM;
strcpy(pkt_dev->odevname, ifname);
- pkt_dev->flows = vzalloc_node(MAX_CFLOWS * sizeof(struct flow_state),
+ pkt_dev->flows = vzalloc_node(array_size(MAX_CFLOWS,
+ sizeof(struct flow_state)),
node);
if (pkt_dev->flows == NULL) {
kfree(pkt_dev);
diff --git a/net/core/sock.c b/net/core/sock.c
index f333d75..bcc4182 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -728,22 +728,9 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
sock_valbool_flag(sk, SOCK_DBG, valbool);
break;
case SO_REUSEADDR:
- val = (valbool ? SK_CAN_REUSE : SK_NO_REUSE);
- if ((sk->sk_family == PF_INET || sk->sk_family == PF_INET6) &&
- inet_sk(sk)->inet_num &&
- (sk->sk_reuse != val)) {
- ret = (sk->sk_state == TCP_ESTABLISHED) ? -EISCONN : -EUCLEAN;
- break;
- }
- sk->sk_reuse = val;
+ sk->sk_reuse = (valbool ? SK_CAN_REUSE : SK_NO_REUSE);
break;
case SO_REUSEPORT:
- if ((sk->sk_family == PF_INET || sk->sk_family == PF_INET6) &&
- inet_sk(sk)->inet_num &&
- (sk->sk_reuseport != valbool)) {
- ret = (sk->sk_state == TCP_ESTABLISHED) ? -EISCONN : -EUCLEAN;
- break;
- }
sk->sk_reuseport = valbool;
break;
case SO_TYPE:
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index d2f4e0c..2589a6b 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -984,7 +984,8 @@ static int dcbnl_build_peer_app(struct net_device *netdev, struct sk_buff* skb,
*/
err = ops->peer_getappinfo(netdev, &info, &app_count);
if (!err && app_count) {
- table = kmalloc(sizeof(struct dcb_app) * app_count, GFP_KERNEL);
+ table = kmalloc_array(app_count, sizeof(struct dcb_app),
+ GFP_KERNEL);
if (!table)
return -ENOMEM;
diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c
index 385f153..2b75df4 100644
--- a/net/dccp/ccids/ccid2.c
+++ b/net/dccp/ccids/ccid2.c
@@ -46,7 +46,8 @@ static int ccid2_hc_tx_alloc_seq(struct ccid2_hc_tx_sock *hc)
return -ENOMEM;
/* allocate buffer and initialize linked list */
- seqp = kmalloc(CCID2_SEQBUF_LEN * sizeof(struct ccid2_seq), gfp_any());
+ seqp = kmalloc_array(CCID2_SEQBUF_LEN, sizeof(struct ccid2_seq),
+ gfp_any());
if (seqp == NULL)
return -ENOMEM;
diff --git a/net/dsa/tag_trailer.c b/net/dsa/tag_trailer.c
index 7d20e1f..56197f0 100644
--- a/net/dsa/tag_trailer.c
+++ b/net/dsa/tag_trailer.c
@@ -75,7 +75,8 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
if (!skb->dev)
return NULL;
- pskb_trim_rcsum(skb, skb->len - 4);
+ if (pskb_trim_rcsum(skb, skb->len - 4))
+ return NULL;
return skb;
}
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index dc2960b..b231e40 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -38,7 +38,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
{
void *hdr;
int i, pages = 0;
- uint32_t *buf = kzalloc(32 * sizeof(uint32_t), GFP_KERNEL);
+ uint32_t *buf = kcalloc(32, sizeof(uint32_t), GFP_KERNEL);
pr_debug("%s\n", __func__);
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 63aa39b..b218336 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -567,7 +567,7 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
struct nlattr *mx;
int len = 0;
- mx = kzalloc(3 * nla_total_size(4), GFP_KERNEL);
+ mx = kcalloc(3, nla_total_size(4), GFP_KERNEL);
if (!mx)
return -ENOMEM;
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 31ff46d..3647167 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -243,9 +243,9 @@ static inline int compute_score(struct sock *sk, struct net *net,
bool dev_match = (sk->sk_bound_dev_if == dif ||
sk->sk_bound_dev_if == sdif);
- if (exact_dif && !dev_match)
+ if (!dev_match)
return -1;
- if (sk->sk_bound_dev_if && dev_match)
+ if (sk->sk_bound_dev_if)
score += 4;
}
if (sk->sk_incoming_cpu == raw_smp_processor_id())
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index af5a830..b3308e9 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1145,7 +1145,8 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
cork->fragsize = ip_sk_use_pmtu(sk) ?
dst_mtu(&rt->dst) : rt->dst.dev->mtu;
- cork->gso_size = sk->sk_type == SOCK_DGRAM ? ipc->gso_size : 0;
+ cork->gso_size = sk->sk_type == SOCK_DGRAM &&
+ sk->sk_protocol == IPPROTO_UDP ? ipc->gso_size : 0;
cork->dst = &rt->dst;
cork->length = 0;
cork->ttl = ipc->ttl;
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 38d906b..c4f5602 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -261,8 +261,8 @@ static struct net_device *__ip_tunnel_create(struct net *net,
} else {
if (strlen(ops->kind) > (IFNAMSIZ - 3))
goto failed;
- strlcpy(name, ops->kind, IFNAMSIZ);
- strncat(name, "%d", 2);
+ strcpy(name, ops->kind);
+ strcat(name, "%d");
}
ASSERT_RTNL();
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 38ab97b..ca0dad9 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -531,6 +531,7 @@ find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
return -ENOMEM;
j = 0;
+ memset(&mtpar, 0, sizeof(mtpar));
mtpar.net = net;
mtpar.table = name;
mtpar.entryinfo = &e->ip;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index bf4e4ad..1df6e97 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -649,7 +649,7 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
hash = rcu_dereference(nh->nh_exceptions);
if (!hash) {
- hash = kzalloc(FNHE_HASH_SIZE * sizeof(*hash), GFP_ATOMIC);
+ hash = kcalloc(FNHE_HASH_SIZE, sizeof(*hash), GFP_ATOMIC);
if (!hash)
goto out_unlock;
rcu_assign_pointer(nh->nh_exceptions, hash);
@@ -3146,7 +3146,8 @@ int __init ip_rt_init(void)
{
int cpu;
- ip_idents = kmalloc(IP_IDENTS_SZ * sizeof(*ip_idents), GFP_KERNEL);
+ ip_idents = kmalloc_array(IP_IDENTS_SZ, sizeof(*ip_idents),
+ GFP_KERNEL);
if (!ip_idents)
panic("IP: failed to allocate ip_idents\n");
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 2741953..141acd9 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1694,6 +1694,13 @@ EXPORT_SYMBOL(tcp_peek_len);
/* Make sure sk_rcvbuf is big enough to satisfy SO_RCVLOWAT hint */
int tcp_set_rcvlowat(struct sock *sk, int val)
{
+ int cap;
+
+ if (sk->sk_userlocks & SOCK_RCVBUF_LOCK)
+ cap = sk->sk_rcvbuf >> 1;
+ else
+ cap = sock_net(sk)->ipv4.sysctl_tcp_rmem[2] >> 1;
+ val = min(val, cap);
sk->sk_rcvlowat = val ? : 1;
/* Check if we need to signal EPOLLIN right now */
@@ -1702,12 +1709,7 @@ int tcp_set_rcvlowat(struct sock *sk, int val)
if (sk->sk_userlocks & SOCK_RCVBUF_LOCK)
return 0;
- /* val comes from user space and might be close to INT_MAX */
val <<= 1;
- if (val < 0)
- val = INT_MAX;
-
- val = min(val, sock_net(sk)->ipv4.sysctl_tcp_rmem[2]);
if (val > sk->sk_rcvbuf) {
sk->sk_rcvbuf = val;
tcp_sk(sk)->window_clamp = tcp_win_from_space(sk, val);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index fed3f1c..bea17f1 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1730,6 +1730,10 @@ process:
reqsk_put(req);
goto discard_it;
}
+ if (tcp_checksum_complete(skb)) {
+ reqsk_put(req);
+ goto csum_error;
+ }
if (unlikely(sk->sk_state != TCP_LISTEN)) {
inet_csk_reqsk_queue_drop_and_put(sk, req);
goto lookup;
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 4d58e2c..8cc7c348 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -268,8 +268,6 @@ found:
goto out_check_final;
}
- p = *head;
- th2 = tcp_hdr(p);
tcp_flag_word(th2) |= flags & (TCP_FLAG_FIN | TCP_FLAG_PSH);
out_check_final:
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 3365362..9bb27df 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2772,7 +2772,7 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f,
" %02X %08X:%08X %02X:%08lX %08X %5u %8d %lu %d %pK %d",
bucket, src, srcp, dest, destp, sp->sk_state,
sk_wmem_alloc_get(sp),
- sk_rmem_alloc_get(sp),
+ udp_rqueue_get(sp),
0, 0L, 0,
from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)),
0, sock_i_ino(sp),
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index d0390d8..d9ad986c 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -163,7 +163,7 @@ static int udp_diag_dump_one(struct sk_buff *in_skb, const struct nlmsghdr *nlh,
static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
void *info)
{
- r->idiag_rqueue = sk_rmem_alloc_get(sk);
+ r->idiag_rqueue = udp_rqueue_get(sk);
r->idiag_wqueue = sk_wmem_alloc_get(sk);
}
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 89019bf..c134286 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1324,6 +1324,7 @@ retry:
}
}
+ memset(&cfg, 0, sizeof(cfg));
cfg.valid_lft = min_t(__u32, ifp->valid_lft,
idev->cnf.temp_valid_lft + age);
cfg.preferred_lft = cnf_temp_preferred_lft + age - idev->desync_factor;
@@ -1357,7 +1358,6 @@ retry:
cfg.pfx = &addr;
cfg.scope = ipv6_addr_scope(cfg.pfx);
- cfg.rt_priority = 0;
ift = ipv6_add_addr(idev, &cfg, block, NULL);
if (IS_ERR(ift)) {
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index a02ad10..2ee08b6 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -1019,8 +1019,8 @@ exit_f:
}
EXPORT_SYMBOL_GPL(ip6_datagram_send_ctl);
-void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
- __u16 srcp, __u16 destp, int bucket)
+void __ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
+ __u16 srcp, __u16 destp, int rqueue, int bucket)
{
const struct in6_addr *dest, *src;
@@ -1036,7 +1036,7 @@ void ip6_dgram_sock_seq_show(struct seq_file *seq, struct sock *sp,
dest->s6_addr32[2], dest->s6_addr32[3], destp,
sp->sk_state,
sk_wmem_alloc_get(sp),
- sk_rmem_alloc_get(sp),
+ rqueue,
0, 0L, 0,
from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)),
0,
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index d8c4b63..be491bf 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -956,7 +956,7 @@ static int __net_init icmpv6_sk_init(struct net *net)
int err, i, j;
net->ipv6.icmp_sk =
- kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);
+ kcalloc(nr_cpu_ids, sizeof(struct sock *), GFP_KERNEL);
if (!net->ipv6.icmp_sk)
return -ENOMEM;
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 44c39c5..10ae135 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -42,7 +42,8 @@ static int alloc_ila_locks(struct ila_net *ilan)
size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU);
if (sizeof(spinlock_t) != 0) {
- ilan->locks = kvmalloc(size * sizeof(spinlock_t), GFP_KERNEL);
+ ilan->locks = kvmalloc_array(size, sizeof(spinlock_t),
+ GFP_KERNEL);
if (!ilan->locks)
return -ENOMEM;
for (i = 0; i < size; i++)
diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c
index 2febe26..595ad40 100644
--- a/net/ipv6/inet6_hashtables.c
+++ b/net/ipv6/inet6_hashtables.c
@@ -113,9 +113,9 @@ static inline int compute_score(struct sock *sk, struct net *net,
bool dev_match = (sk->sk_bound_dev_if == dif ||
sk->sk_bound_dev_if == sdif);
- if (exact_dif && !dev_match)
+ if (!dev_match)
return -1;
- if (sk->sk_bound_dev_if && dev_match)
+ if (sk->sk_bound_dev_if)
score++;
}
if (sk->sk_incoming_cpu == raw_smp_processor_id())
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 7aa4c41..1fb2f31 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -167,8 +167,9 @@ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags)
return f6i;
}
-void fib6_info_destroy(struct fib6_info *f6i)
+void fib6_info_destroy_rcu(struct rcu_head *head)
{
+ struct fib6_info *f6i = container_of(head, struct fib6_info, rcu);
struct rt6_exception_bucket *bucket;
struct dst_metrics *m;
@@ -206,7 +207,7 @@ void fib6_info_destroy(struct fib6_info *f6i)
kfree(f6i);
}
-EXPORT_SYMBOL_GPL(fib6_info_destroy);
+EXPORT_SYMBOL_GPL(fib6_info_destroy_rcu);
static struct fib6_node *node_alloc(struct net *net)
{
@@ -934,6 +935,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
{
struct fib6_info *leaf = rcu_dereference_protected(fn->leaf,
lockdep_is_held(&rt->fib6_table->tb6_lock));
+ enum fib_event_type event = FIB_EVENT_ENTRY_ADD;
struct fib6_info *iter = NULL, *match = NULL;
struct fib6_info __rcu **ins;
int replace = (info->nlh &&
@@ -1013,6 +1015,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
"Can not append to a REJECT route");
return -EINVAL;
}
+ event = FIB_EVENT_ENTRY_APPEND;
rt->fib6_nsiblings = match->fib6_nsiblings;
list_add_tail(&rt->fib6_siblings, &match->fib6_siblings);
match->fib6_nsiblings++;
@@ -1034,15 +1037,12 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
* insert node
*/
if (!replace) {
- enum fib_event_type event;
-
if (!add)
pr_warn("NLM_F_CREATE should be set when creating new route\n");
add:
nlflags |= NLM_F_CREATE;
- event = append ? FIB_EVENT_ENTRY_APPEND : FIB_EVENT_ENTRY_ADD;
err = call_fib6_entry_notifiers(info->nl_net, event, rt,
extack);
if (err)
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 021e5ae..a14fb4f 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1219,7 +1219,8 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
if (mtu < IPV6_MIN_MTU)
return -EINVAL;
cork->base.fragsize = mtu;
- cork->base.gso_size = sk->sk_type == SOCK_DGRAM ? ipc6->gso_size : 0;
+ cork->base.gso_size = sk->sk_type == SOCK_DGRAM &&
+ sk->sk_protocol == IPPROTO_UDP ? ipc6->gso_size : 0;
if (dst_allfrag(xfrm_dst_path(&rt->dst)))
cork->base.flags |= IPCORK_ALLFRAG;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 0758b5b..7eab959 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -550,6 +550,7 @@ find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
return -ENOMEM;
j = 0;
+ memset(&mtpar, 0, sizeof(mtpar));
mtpar.net = net;
mtpar.table = name;
mtpar.entryinfo = &e->ipv6;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index fb95698..86a0e43 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2307,9 +2307,6 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
const struct in6_addr *daddr, *saddr;
struct rt6_info *rt6 = (struct rt6_info *)dst;
- if (rt6->rt6i_flags & RTF_LOCAL)
- return;
-
if (dst_metric_locked(dst, RTAX_MTU))
return;
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index b620d9b..7efa9fd 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1479,6 +1479,10 @@ process:
reqsk_put(req);
goto discard_it;
}
+ if (tcp_checksum_complete(skb)) {
+ reqsk_put(req);
+ goto csum_error;
+ }
if (unlikely(sk->sk_state != TCP_LISTEN)) {
inet_csk_reqsk_queue_drop_and_put(sk, req);
goto lookup;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 164afd3..e6645ca 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1523,7 +1523,8 @@ int udp6_seq_show(struct seq_file *seq, void *v)
struct inet_sock *inet = inet_sk(v);
__u16 srcp = ntohs(inet->inet_sport);
__u16 destp = ntohs(inet->inet_dport);
- ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket);
+ __ip6_dgram_sock_seq_show(seq, v, srcp, destp,
+ udp_rqueue_get(v), bucket);
}
return 0;
}
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 6616c9f..5b99008 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -553,6 +553,12 @@ static int l2tp_nl_cmd_session_create(struct sk_buff *skb, struct genl_info *inf
goto out_tunnel;
}
+ /* L2TPv2 only accepts PPP pseudo-wires */
+ if (tunnel->version == 2 && cfg.pw_type != L2TP_PWTYPE_PPP) {
+ ret = -EPROTONOSUPPORT;
+ goto out_tunnel;
+ }
+
if (tunnel->version > 2) {
if (info->attrs[L2TP_ATTR_DATA_SEQ])
cfg.data_seq = nla_get_u8(info->attrs[L2TP_ATTR_DATA_SEQ]);
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index b56cb1d..5518838 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -612,6 +612,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
u32 session_id, peer_session_id;
bool drop_refcnt = false;
bool drop_tunnel = false;
+ bool new_session = false;
+ bool new_tunnel = false;
int ver = 2;
int fd;
@@ -701,6 +703,15 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
.encap = L2TP_ENCAPTYPE_UDP,
.debug = 0,
};
+
+ /* Prevent l2tp_tunnel_register() from trying to set up
+ * a kernel socket.
+ */
+ if (fd < 0) {
+ error = -EBADF;
+ goto end;
+ }
+
error = l2tp_tunnel_create(sock_net(sk), fd, ver, tunnel_id, peer_tunnel_id, &tcfg, &tunnel);
if (error < 0)
goto end;
@@ -713,6 +724,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
goto end;
}
drop_tunnel = true;
+ new_tunnel = true;
}
} else {
/* Error if we can't find the tunnel */
@@ -734,6 +746,12 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
session = l2tp_session_get(sock_net(sk), tunnel, session_id);
if (session) {
drop_refcnt = true;
+
+ if (session->pwtype != L2TP_PWTYPE_PPP) {
+ error = -EPROTOTYPE;
+ goto end;
+ }
+
ps = l2tp_session_priv(session);
/* Using a pre-existing session is fine as long as it hasn't
@@ -751,6 +769,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
/* Default MTU must allow space for UDP/L2TP/PPP headers */
cfg.mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD;
cfg.mru = cfg.mtu;
+ cfg.pw_type = L2TP_PWTYPE_PPP;
session = l2tp_session_create(sizeof(struct pppol2tp_session),
tunnel, session_id,
@@ -772,6 +791,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
goto end;
}
drop_refcnt = true;
+ new_session = true;
}
/* Special case: if source & dest session_id == 0x0000, this
@@ -818,6 +838,12 @@ out_no_ppp:
session->name);
end:
+ if (error) {
+ if (new_session)
+ l2tp_session_delete(session);
+ if (new_tunnel)
+ l2tp_tunnel_delete(tunnel);
+ }
if (drop_refcnt)
l2tp_session_dec_refcount(session);
if (drop_tunnel)
@@ -1175,7 +1201,7 @@ static int pppol2tp_tunnel_ioctl(struct l2tp_tunnel *tunnel,
l2tp_session_get(sock_net(sk), tunnel,
stats.session_id);
- if (session) {
+ if (session && session->pwtype == L2TP_PWTYPE_PPP) {
err = pppol2tp_session_ioctl(session, cmd,
arg);
l2tp_session_dec_refcount(session);
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 89178b4..d9558ff 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -1186,7 +1186,7 @@ static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local,
lockdep_assert_held(&local->mtx);
lockdep_assert_held(&local->chanctx_mtx);
- vif_chsw = kzalloc(sizeof(vif_chsw[0]) * n_vifs, GFP_KERNEL);
+ vif_chsw = kcalloc(n_vifs, sizeof(vif_chsw[0]), GFP_KERNEL);
if (!vif_chsw)
return -ENOMEM;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 4d2e797..fb73451 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -772,7 +772,7 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
if (have_mfp)
n_suites += 4;
- suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL);
+ suites = kmalloc_array(n_suites, sizeof(u32), GFP_KERNEL);
if (!suites)
return -ENOMEM;
@@ -1098,6 +1098,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
ieee80211_led_init(local);
+ result = ieee80211_txq_setup_flows(local);
+ if (result)
+ goto fail_flows;
+
rtnl_lock();
result = ieee80211_init_rate_ctrl_alg(local,
@@ -1120,10 +1124,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
rtnl_unlock();
- result = ieee80211_txq_setup_flows(local);
- if (result)
- goto fail_flows;
-
#ifdef CONFIG_INET
local->ifa_notifier.notifier_call = ieee80211_ifa_changed;
result = register_inetaddr_notifier(&local->ifa_notifier);
@@ -1149,8 +1149,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
#if defined(CONFIG_INET) || defined(CONFIG_IPV6)
fail_ifa:
#endif
- ieee80211_txq_teardown_flows(local);
- fail_flows:
rtnl_lock();
rate_control_deinitialize(local);
ieee80211_remove_interfaces(local);
@@ -1158,6 +1156,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
rtnl_unlock();
ieee80211_led_exit(local);
ieee80211_wep_free(local);
+ ieee80211_txq_teardown_flows(local);
+ fail_flows:
destroy_workqueue(local->workqueue);
fail_workqueue:
wiphy_unregister(local->hw.wiphy);
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 8221bc5..76048b5 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -592,11 +592,11 @@ minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
max_rates = sband->n_bitrates;
}
- mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp);
+ mi->r = kcalloc(max_rates, sizeof(struct minstrel_rate), gfp);
if (!mi->r)
goto error;
- mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp);
+ mi->sample_table = kmalloc_array(max_rates, SAMPLE_COLUMNS, gfp);
if (!mi->sample_table)
goto error1;
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index fb586b6..67ebdea 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -1313,11 +1313,11 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
if (!msp)
return NULL;
- msp->ratelist = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp);
+ msp->ratelist = kcalloc(max_rates, sizeof(struct minstrel_rate), gfp);
if (!msp->ratelist)
goto error;
- msp->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp);
+ msp->sample_table = kmalloc_array(max_rates, SAMPLE_COLUMNS, gfp);
if (!msp->sample_table)
goto error1;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index a3b1bcc..2e917a6 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -1157,7 +1157,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
}
}
- ie = kzalloc(num_bands * iebufsz, GFP_KERNEL);
+ ie = kcalloc(iebufsz, num_bands, GFP_KERNEL);
if (!ie) {
ret = -ENOMEM;
goto out;
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 2d82c88..5e2e511 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1803,8 +1803,9 @@ static int ieee80211_reconfig_nan(struct ieee80211_sub_if_data *sdata)
if (WARN_ON(res))
return res;
- funcs = kzalloc((sdata->local->hw.max_nan_de_entries + 1) *
- sizeof(*funcs), GFP_KERNEL);
+ funcs = kcalloc(sdata->local->hw.max_nan_de_entries + 1,
+ sizeof(*funcs),
+ GFP_KERNEL);
if (!funcs)
return -ENOMEM;
diff --git a/net/ncsi/ncsi-aen.c b/net/ncsi/ncsi-aen.c
index e7b05de..25e483e 100644
--- a/net/ncsi/ncsi-aen.c
+++ b/net/ncsi/ncsi-aen.c
@@ -73,8 +73,8 @@ static int ncsi_aen_handler_lsc(struct ncsi_dev_priv *ndp,
ncm->data[2] = data;
ncm->data[4] = ntohl(lsc->oem_status);
- netdev_info(ndp->ndev.dev, "NCSI: LSC AEN - channel %u state %s\n",
- nc->id, data & 0x1 ? "up" : "down");
+ netdev_dbg(ndp->ndev.dev, "NCSI: LSC AEN - channel %u state %s\n",
+ nc->id, data & 0x1 ? "up" : "down");
chained = !list_empty(&nc->link);
state = nc->state;
@@ -148,9 +148,9 @@ static int ncsi_aen_handler_hncdsc(struct ncsi_dev_priv *ndp,
hncdsc = (struct ncsi_aen_hncdsc_pkt *)h;
ncm->data[3] = ntohl(hncdsc->status);
spin_unlock_irqrestore(&nc->lock, flags);
- netdev_printk(KERN_DEBUG, ndp->ndev.dev,
- "NCSI: host driver %srunning on channel %u\n",
- ncm->data[3] & 0x1 ? "" : "not ", nc->id);
+ netdev_dbg(ndp->ndev.dev,
+ "NCSI: host driver %srunning on channel %u\n",
+ ncm->data[3] & 0x1 ? "" : "not ", nc->id);
return 0;
}
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 5561e22..0912847 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -788,8 +788,8 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
}
break;
case ncsi_dev_state_config_done:
- netdev_printk(KERN_DEBUG, ndp->ndev.dev,
- "NCSI: channel %u config done\n", nc->id);
+ netdev_dbg(ndp->ndev.dev, "NCSI: channel %u config done\n",
+ nc->id);
spin_lock_irqsave(&nc->lock, flags);
if (nc->reconfigure_needed) {
/* This channel's configuration has been updated
@@ -804,8 +804,7 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
list_add_tail_rcu(&nc->link, &ndp->channel_queue);
spin_unlock_irqrestore(&ndp->lock, flags);
- netdev_printk(KERN_DEBUG, dev,
- "Dirty NCSI channel state reset\n");
+ netdev_dbg(dev, "Dirty NCSI channel state reset\n");
ncsi_process_next_channel(ndp);
break;
}
@@ -816,9 +815,9 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
} else {
hot_nc = NULL;
nc->state = NCSI_CHANNEL_INACTIVE;
- netdev_warn(ndp->ndev.dev,
- "NCSI: channel %u link down after config\n",
- nc->id);
+ netdev_dbg(ndp->ndev.dev,
+ "NCSI: channel %u link down after config\n",
+ nc->id);
}
spin_unlock_irqrestore(&nc->lock, flags);
@@ -908,9 +907,9 @@ static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
}
ncm = &found->modes[NCSI_MODE_LINK];
- netdev_printk(KERN_DEBUG, ndp->ndev.dev,
- "NCSI: Channel %u added to queue (link %s)\n",
- found->id, ncm->data[2] & 0x1 ? "up" : "down");
+ netdev_dbg(ndp->ndev.dev,
+ "NCSI: Channel %u added to queue (link %s)\n",
+ found->id, ncm->data[2] & 0x1 ? "up" : "down");
out:
spin_lock_irqsave(&ndp->lock, flags);
@@ -1199,14 +1198,14 @@ int ncsi_process_next_channel(struct ncsi_dev_priv *ndp)
switch (old_state) {
case NCSI_CHANNEL_INACTIVE:
ndp->ndev.state = ncsi_dev_state_config;
- netdev_info(ndp->ndev.dev, "NCSI: configuring channel %u\n",
- nc->id);
+ netdev_dbg(ndp->ndev.dev, "NCSI: configuring channel %u\n",
+ nc->id);
ncsi_configure_channel(ndp);
break;
case NCSI_CHANNEL_ACTIVE:
ndp->ndev.state = ncsi_dev_state_suspend;
- netdev_info(ndp->ndev.dev, "NCSI: suspending channel %u\n",
- nc->id);
+ netdev_dbg(ndp->ndev.dev, "NCSI: suspending channel %u\n",
+ nc->id);
ncsi_suspend_channel(ndp);
break;
default:
@@ -1226,8 +1225,6 @@ out:
return ncsi_choose_active_channel(ndp);
}
- netdev_printk(KERN_DEBUG, ndp->ndev.dev,
- "NCSI: No more channels to process\n");
ncsi_report_link(ndp, false);
return -ENODEV;
}
@@ -1318,9 +1315,9 @@ static int ncsi_kick_channels(struct ncsi_dev_priv *ndp)
if ((ndp->ndev.state & 0xff00) ==
ncsi_dev_state_config ||
!list_empty(&nc->link)) {
- netdev_printk(KERN_DEBUG, nd->dev,
- "NCSI: channel %p marked dirty\n",
- nc);
+ netdev_dbg(nd->dev,
+ "NCSI: channel %p marked dirty\n",
+ nc);
nc->reconfigure_needed = true;
}
spin_unlock_irqrestore(&nc->lock, flags);
@@ -1338,8 +1335,7 @@ static int ncsi_kick_channels(struct ncsi_dev_priv *ndp)
list_add_tail_rcu(&nc->link, &ndp->channel_queue);
spin_unlock_irqrestore(&ndp->lock, flags);
- netdev_printk(KERN_DEBUG, nd->dev,
- "NCSI: kicked channel %p\n", nc);
+ netdev_dbg(nd->dev, "NCSI: kicked channel %p\n", nc);
n++;
}
}
@@ -1370,8 +1366,8 @@ int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
list_for_each_entry_rcu(vlan, &ndp->vlan_vids, list) {
n_vids++;
if (vlan->vid == vid) {
- netdev_printk(KERN_DEBUG, dev,
- "NCSI: vid %u already registered\n", vid);
+ netdev_dbg(dev, "NCSI: vid %u already registered\n",
+ vid);
return 0;
}
}
@@ -1390,7 +1386,7 @@ int ncsi_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
vlan->vid = vid;
list_add_rcu(&vlan->list, &ndp->vlan_vids);
- netdev_printk(KERN_DEBUG, dev, "NCSI: Added new vid %u\n", vid);
+ netdev_dbg(dev, "NCSI: Added new vid %u\n", vid);
found = ncsi_kick_channels(ndp) != 0;
@@ -1419,8 +1415,7 @@ int ncsi_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
/* Remove the VLAN id from our internal list */
list_for_each_entry_safe(vlan, tmp, &ndp->vlan_vids, list)
if (vlan->vid == vid) {
- netdev_printk(KERN_DEBUG, dev,
- "NCSI: vid %u found, removing\n", vid);
+ netdev_dbg(dev, "NCSI: vid %u found, removing\n", vid);
list_del_rcu(&vlan->list);
found = true;
kfree(vlan);
@@ -1547,7 +1542,7 @@ void ncsi_stop_dev(struct ncsi_dev *nd)
}
}
- netdev_printk(KERN_DEBUG, ndp->ndev.dev, "NCSI: Stopping device\n");
+ netdev_dbg(ndp->ndev.dev, "NCSI: Stopping device\n");
ncsi_report_link(ndp, true);
}
EXPORT_SYMBOL_GPL(ncsi_stop_dev);
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
index bbad940..8a33dac 100644
--- a/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/net/netfilter/ipset/ip_set_hash_gen.h
@@ -1234,7 +1234,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
pr_debug("Create set %s with family %s\n",
set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6");
-#ifndef IP_SET_PROTO_UNDEF
+#ifdef IP_SET_PROTO_UNDEF
+ if (set->family != NFPROTO_UNSPEC)
+ return -IPSET_ERR_INVALID_FAMILY;
+#else
if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
return -IPSET_ERR_INVALID_FAMILY;
#endif
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 61c3a38..99e0aa3 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -1380,7 +1380,8 @@ int __init ip_vs_conn_init(void)
/*
* Allocate the connection hash table and initialize its list heads
*/
- ip_vs_conn_tab = vmalloc(ip_vs_conn_tab_size * sizeof(*ip_vs_conn_tab));
+ ip_vs_conn_tab = vmalloc(array_size(ip_vs_conn_tab_size,
+ sizeof(*ip_vs_conn_tab)));
if (!ip_vs_conn_tab)
return -ENOMEM;
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 0c03c0e..dd21782 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -839,6 +839,9 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
* For now only for NAT!
*/
ip_vs_rs_hash(ipvs, dest);
+ /* FTP-NAT requires conntrack for mangling */
+ if (svc->port == FTPPORT)
+ ip_vs_register_conntrack(svc);
}
atomic_set(&dest->conn_flags, conn_flags);
@@ -1462,6 +1465,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)
*/
static void ip_vs_unlink_service(struct ip_vs_service *svc, bool cleanup)
{
+ ip_vs_unregister_conntrack(svc);
/* Hold svc to avoid double release from dest_trash */
atomic_inc(&svc->refcnt);
/*
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index ba0a0fd..473cce2 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -168,7 +168,7 @@ static inline bool crosses_local_route_boundary(int skb_af, struct sk_buff *skb,
bool new_rt_is_local)
{
bool rt_mode_allow_local = !!(rt_mode & IP_VS_RT_MODE_LOCAL);
- bool rt_mode_allow_non_local = !!(rt_mode & IP_VS_RT_MODE_LOCAL);
+ bool rt_mode_allow_non_local = !!(rt_mode & IP_VS_RT_MODE_NON_LOCAL);
bool rt_mode_allow_redirect = !!(rt_mode & IP_VS_RT_MODE_RDR);
bool source_is_loopback;
bool old_rt_is_local;
diff --git a/net/netfilter/nf_conncount.c b/net/netfilter/nf_conncount.c
index 3b5059a..d838360 100644
--- a/net/netfilter/nf_conncount.c
+++ b/net/netfilter/nf_conncount.c
@@ -46,6 +46,7 @@
struct nf_conncount_tuple {
struct hlist_node node;
struct nf_conntrack_tuple tuple;
+ struct nf_conntrack_zone zone;
};
struct nf_conncount_rb {
@@ -80,7 +81,8 @@ static int key_diff(const u32 *a, const u32 *b, unsigned int klen)
}
bool nf_conncount_add(struct hlist_head *head,
- const struct nf_conntrack_tuple *tuple)
+ const struct nf_conntrack_tuple *tuple,
+ const struct nf_conntrack_zone *zone)
{
struct nf_conncount_tuple *conn;
@@ -88,6 +90,7 @@ bool nf_conncount_add(struct hlist_head *head,
if (conn == NULL)
return false;
conn->tuple = *tuple;
+ conn->zone = *zone;
hlist_add_head(&conn->node, head);
return true;
}
@@ -108,7 +111,7 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
/* check the saved connections */
hlist_for_each_entry_safe(conn, n, head, node) {
- found = nf_conntrack_find_get(net, zone, &conn->tuple);
+ found = nf_conntrack_find_get(net, &conn->zone, &conn->tuple);
if (found == NULL) {
hlist_del(&conn->node);
kmem_cache_free(conncount_conn_cachep, conn);
@@ -117,7 +120,8 @@ unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head,
found_ct = nf_ct_tuplehash_to_ctrack(found);
- if (tuple && nf_ct_tuple_equal(&conn->tuple, tuple)) {
+ if (tuple && nf_ct_tuple_equal(&conn->tuple, tuple) &&
+ nf_ct_zone_equal(found_ct, zone, zone->dir)) {
/*
* Just to be sure we have it only once in the list.
* We should not see tuples twice unless someone hooks
@@ -196,7 +200,7 @@ count_tree(struct net *net, struct rb_root *root,
if (!addit)
return count;
- if (!nf_conncount_add(&rbconn->hhead, tuple))
+ if (!nf_conncount_add(&rbconn->hhead, tuple, zone))
return 0; /* hotdrop */
return count + 1;
@@ -238,6 +242,7 @@ count_tree(struct net *net, struct rb_root *root,
}
conn->tuple = *tuple;
+ conn->zone = *zone;
memcpy(rbconn->key, key, sizeof(u32) * keylen);
INIT_HLIST_HEAD(&rbconn->hhead);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 39327a4..20a2e37 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -1446,7 +1446,8 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct,
}
nfnl_lock(NFNL_SUBSYS_CTNETLINK);
rcu_read_lock();
- if (nat_hook->parse_nat_setup)
+ nat_hook = rcu_dereference(nf_nat_hook);
+ if (nat_hook)
return -EAGAIN;
#endif
return -EOPNOTSUPP;
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index afdeca5..d88841fb 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -402,7 +402,8 @@ int nf_ct_l4proto_register_one(const struct nf_conntrack_l4proto *l4proto)
struct nf_conntrack_l4proto __rcu **proto_array;
int i;
- proto_array = kmalloc(MAX_NF_CT_PROTO *
+ proto_array =
+ kmalloc_array(MAX_NF_CT_PROTO,
sizeof(struct nf_conntrack_l4proto *),
GFP_KERNEL);
if (proto_array == NULL) {
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index b7df32a..46f9df9 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -691,8 +691,9 @@ int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto)
mutex_lock(&nf_nat_proto_mutex);
if (nf_nat_l4protos[l3proto] == NULL) {
- l4protos = kmalloc(IPPROTO_MAX * sizeof(struct nf_nat_l4proto *),
- GFP_KERNEL);
+ l4protos = kmalloc_array(IPPROTO_MAX,
+ sizeof(struct nf_nat_l4proto *),
+ GFP_KERNEL);
if (l4protos == NULL) {
ret = -ENOMEM;
goto out;
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index ca4c4d9..896d4a3 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2890,12 +2890,13 @@ static struct nft_set *nft_set_lookup_byid(const struct net *net,
u32 id = ntohl(nla_get_be32(nla));
list_for_each_entry(trans, &net->nft.commit_list, list) {
- struct nft_set *set = nft_trans_set(trans);
+ if (trans->msg_type == NFT_MSG_NEWSET) {
+ struct nft_set *set = nft_trans_set(trans);
- if (trans->msg_type == NFT_MSG_NEWSET &&
- id == nft_trans_set_id(trans) &&
- nft_active_genmask(set, genmask))
- return set;
+ if (id == nft_trans_set_id(trans) &&
+ nft_active_genmask(set, genmask))
+ return set;
+ }
}
return ERR_PTR(-ENOENT);
}
@@ -5303,7 +5304,7 @@ static int nf_tables_flowtable_parse_hook(const struct nft_ctx *ctx,
if (err < 0)
return err;
- ops = kzalloc(sizeof(struct nf_hook_ops) * n, GFP_KERNEL);
+ ops = kcalloc(n, sizeof(struct nf_hook_ops), GFP_KERNEL);
if (!ops)
return -ENOMEM;
@@ -5836,18 +5837,23 @@ static int nf_tables_flowtable_event(struct notifier_block *this,
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
struct nft_flowtable *flowtable;
struct nft_table *table;
+ struct net *net;
if (event != NETDEV_UNREGISTER)
return 0;
+ net = maybe_get_net(dev_net(dev));
+ if (!net)
+ return 0;
+
nfnl_lock(NFNL_SUBSYS_NFTABLES);
- list_for_each_entry(table, &dev_net(dev)->nft.tables, list) {
+ list_for_each_entry(table, &net->nft.tables, list) {
list_for_each_entry(flowtable, &table->flowtables, list) {
nft_flowtable_event(event, dev, flowtable);
}
}
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
-
+ put_net(net);
return NOTIFY_DONE;
}
@@ -6438,7 +6444,7 @@ static void nf_tables_abort_release(struct nft_trans *trans)
kfree(trans);
}
-static int nf_tables_abort(struct net *net, struct sk_buff *skb)
+static int __nf_tables_abort(struct net *net)
{
struct nft_trans *trans, *next;
struct nft_trans_elem *te;
@@ -6554,6 +6560,11 @@ static void nf_tables_cleanup(struct net *net)
nft_validate_state_update(net, NFT_VALIDATE_SKIP);
}
+static int nf_tables_abort(struct net *net, struct sk_buff *skb)
+{
+ return __nf_tables_abort(net);
+}
+
static bool nf_tables_valid_genid(struct net *net, u32 genid)
{
return net->nft.base_seq == genid;
@@ -7148,9 +7159,12 @@ static int __net_init nf_tables_init_net(struct net *net)
static void __net_exit nf_tables_exit_net(struct net *net)
{
+ nfnl_lock(NFNL_SUBSYS_NFTABLES);
+ if (!list_empty(&net->nft.commit_list))
+ __nf_tables_abort(net);
__nft_release_tables(net);
+ nfnl_unlock(NFNL_SUBSYS_NFTABLES);
WARN_ON_ONCE(!list_empty(&net->nft.tables));
- WARN_ON_ONCE(!list_empty(&net->nft.commit_list));
}
static struct pernet_operations nf_tables_net_ops = {
@@ -7164,8 +7178,8 @@ static int __init nf_tables_module_init(void)
nft_chain_filter_init();
- info = kmalloc(sizeof(struct nft_expr_info) * NFT_RULE_MAXEXPRS,
- GFP_KERNEL);
+ info = kmalloc_array(NFT_RULE_MAXEXPRS, sizeof(struct nft_expr_info),
+ GFP_KERNEL);
if (info == NULL) {
err = -ENOMEM;
goto err1;
@@ -7192,13 +7206,13 @@ err1:
static void __exit nf_tables_module_exit(void)
{
- unregister_pernet_subsys(&nf_tables_net_ops);
nfnetlink_subsys_unregister(&nf_tables_subsys);
unregister_netdevice_notifier(&nf_tables_flowtable_notifier);
+ nft_chain_filter_fini();
+ unregister_pernet_subsys(&nf_tables_net_ops);
rcu_barrier();
nf_tables_core_module_exit();
kfree(info);
- nft_chain_filter_fini();
}
module_init(nf_tables_module_init);
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index deff10a..8de912c 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -183,7 +183,8 @@ next_rule:
switch (regs.verdict.code) {
case NFT_JUMP:
- BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE);
+ if (WARN_ON_ONCE(stackptr >= NFT_JUMP_STACK_SIZE))
+ return NF_DROP;
jumpstack[stackptr].chain = chain;
jumpstack[stackptr].rules = rules + 1;
stackptr++;
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index 4d0da70..e1b6be2 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -429,7 +429,7 @@ replay:
*/
if (err == -EAGAIN) {
status |= NFNL_BATCH_REPLAY;
- goto next;
+ goto done;
}
}
ack:
@@ -456,7 +456,7 @@ ack:
if (err)
status |= NFNL_BATCH_FAILURE;
}
-next:
+
msglen = NLMSG_ALIGN(nlh->nlmsg_len);
if (msglen > skb->len)
msglen = skb->len;
@@ -464,7 +464,11 @@ next:
}
done:
if (status & NFNL_BATCH_REPLAY) {
- ss->abort(net, oskb);
+ const struct nfnetlink_subsystem *ss2;
+
+ ss2 = nfnl_dereference_protected(subsys_id);
+ if (ss2 == ss)
+ ss->abort(net, oskb);
nfnl_err_reset(&err_list);
nfnl_unlock(subsys_id);
kfree_skb(skb);
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c
index cb5b5f2..e5d27b2 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -190,8 +190,9 @@ nfnl_cthelper_parse_expect_policy(struct nf_conntrack_helper *helper,
if (class_max > NF_CT_MAX_EXPECT_CLASSES)
return -EOVERFLOW;
- expect_policy = kzalloc(sizeof(struct nf_conntrack_expect_policy) *
- class_max, GFP_KERNEL);
+ expect_policy = kcalloc(class_max,
+ sizeof(struct nf_conntrack_expect_policy),
+ GFP_KERNEL);
if (expect_policy == NULL)
return -ENOMEM;
diff --git a/net/netfilter/nft_chain_filter.c b/net/netfilter/nft_chain_filter.c
index 84c9024..d21834b 100644
--- a/net/netfilter/nft_chain_filter.c
+++ b/net/netfilter/nft_chain_filter.c
@@ -318,6 +318,10 @@ static int nf_tables_netdev_event(struct notifier_block *this,
event != NETDEV_CHANGENAME)
return NOTIFY_DONE;
+ ctx.net = maybe_get_net(ctx.net);
+ if (!ctx.net)
+ return NOTIFY_DONE;
+
nfnl_lock(NFNL_SUBSYS_NFTABLES);
list_for_each_entry(table, &ctx.net->nft.tables, list) {
if (table->family != NFPROTO_NETDEV)
@@ -334,6 +338,7 @@ static int nf_tables_netdev_event(struct notifier_block *this,
}
}
nfnl_unlock(NFNL_SUBSYS_NFTABLES);
+ put_net(ctx.net);
return NOTIFY_DONE;
}
diff --git a/net/netfilter/nft_connlimit.c b/net/netfilter/nft_connlimit.c
index 50c068d..a832c59 100644
--- a/net/netfilter/nft_connlimit.c
+++ b/net/netfilter/nft_connlimit.c
@@ -52,7 +52,7 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv,
if (!addit)
goto out;
- if (!nf_conncount_add(&priv->hhead, tuple_ptr)) {
+ if (!nf_conncount_add(&priv->hhead, tuple_ptr, zone)) {
regs->verdict.code = NF_DROP;
spin_unlock_bh(&priv->lock);
return;
diff --git a/net/netfilter/nft_dynset.c b/net/netfilter/nft_dynset.c
index 4d49529..27d7e459 100644
--- a/net/netfilter/nft_dynset.c
+++ b/net/netfilter/nft_dynset.c
@@ -203,9 +203,7 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
goto err1;
set->ops->gc_init(set);
}
-
- } else if (set->flags & NFT_SET_EVAL)
- return -EINVAL;
+ }
nft_set_ext_prepare(&priv->tmpl);
nft_set_ext_add_length(&priv->tmpl, NFT_SET_EXT_KEY, set->klen);
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
index 7eef1cf..655187b 100644
--- a/net/netfilter/nft_log.c
+++ b/net/netfilter/nft_log.c
@@ -111,7 +111,7 @@ static void nft_log_eval(const struct nft_expr *expr,
const struct nft_log *priv = nft_expr_priv(expr);
if (priv->loginfo.type == NF_LOG_TYPE_LOG &&
- priv->loginfo.u.log.level == LOGLEVEL_AUDIT) {
+ priv->loginfo.u.log.level == NFT_LOGLEVEL_AUDIT) {
nft_log_eval_audit(pkt);
return;
}
@@ -166,9 +166,9 @@ static int nft_log_init(const struct nft_ctx *ctx,
li->u.log.level =
ntohl(nla_get_be32(tb[NFTA_LOG_LEVEL]));
} else {
- li->u.log.level = LOGLEVEL_WARNING;
+ li->u.log.level = NFT_LOGLEVEL_WARNING;
}
- if (li->u.log.level > LOGLEVEL_AUDIT) {
+ if (li->u.log.level > NFT_LOGLEVEL_AUDIT) {
err = -EINVAL;
goto err1;
}
@@ -196,7 +196,7 @@ static int nft_log_init(const struct nft_ctx *ctx,
break;
}
- if (li->u.log.level == LOGLEVEL_AUDIT)
+ if (li->u.log.level == NFT_LOGLEVEL_AUDIT)
return 0;
err = nf_logger_find_get(ctx->family, li->type);
@@ -220,7 +220,7 @@ static void nft_log_destroy(const struct nft_ctx *ctx,
if (priv->prefix != nft_log_null_prefix)
kfree(priv->prefix);
- if (li->u.log.level == LOGLEVEL_AUDIT)
+ if (li->u.log.level == NFT_LOGLEVEL_AUDIT)
return;
nf_logger_put(ctx->family, li->type);
diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c
index d260ce2..7f3a9a2 100644
--- a/net/netfilter/nft_set_rbtree.c
+++ b/net/netfilter/nft_set_rbtree.c
@@ -66,7 +66,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
parent = rcu_dereference_raw(parent->rb_left);
if (interval &&
nft_rbtree_equal(set, this, interval) &&
- nft_rbtree_interval_end(this) &&
+ nft_rbtree_interval_end(rbe) &&
!nft_rbtree_interval_end(interval))
continue;
interval = rbe;
diff --git a/net/netfilter/nft_socket.c b/net/netfilter/nft_socket.c
index f28a0b9..74e1b3b 100644
--- a/net/netfilter/nft_socket.c
+++ b/net/netfilter/nft_socket.c
@@ -142,3 +142,4 @@ module_exit(nft_socket_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Máté Eckl");
MODULE_DESCRIPTION("nf_tables socket match module");
+MODULE_ALIAS_NFT_EXPR("socket");
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index df9ab71..d0d8397 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1904,7 +1904,7 @@ static int __init xt_init(void)
seqcount_init(&per_cpu(xt_recseq, i));
}
- xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL);
+ xt = kmalloc_array(NFPROTO_NUMPROTO, sizeof(struct xt_af), GFP_KERNEL);
if (!xt)
return -ENOMEM;
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 8790190..03b9a50 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -245,12 +245,22 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
}
if (info->helper[0]) {
+ if (strnlen(info->helper, sizeof(info->helper)) == sizeof(info->helper)) {
+ ret = -ENAMETOOLONG;
+ goto err3;
+ }
+
ret = xt_ct_set_helper(ct, info->helper, par);
if (ret < 0)
goto err3;
}
if (info->timeout[0]) {
+ if (strnlen(info->timeout, sizeof(info->timeout)) == sizeof(info->timeout)) {
+ ret = -ENAMETOOLONG;
+ goto err4;
+ }
+
ret = xt_ct_set_timeout(ct, par, info->timeout);
if (ret < 0)
goto err4;
diff --git a/net/netfilter/xt_connmark.c b/net/netfilter/xt_connmark.c
index 94df000..29c38aa 100644
--- a/net/netfilter/xt_connmark.c
+++ b/net/netfilter/xt_connmark.c
@@ -211,7 +211,7 @@ static int __init connmark_mt_init(void)
static void __exit connmark_mt_exit(void)
{
xt_unregister_match(&connmark_mt_reg);
- xt_unregister_target(connmark_tg_reg);
+ xt_unregister_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
}
module_init(connmark_mt_init);
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index 6f4c521..bf2890b 100644
--- a/net/netfilter/xt_set.c
+++ b/net/netfilter/xt_set.c
@@ -372,8 +372,8 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
/* Normalize to fit into jiffies */
if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
- add_opt.ext.timeout > UINT_MAX / MSEC_PER_SEC)
- add_opt.ext.timeout = UINT_MAX / MSEC_PER_SEC;
+ add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
+ add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_add(info->add_set.index, skb, par, &add_opt);
if (info->del_set.index != IPSET_INVALID_ID)
@@ -407,8 +407,8 @@ set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
/* Normalize to fit into jiffies */
if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
- add_opt.ext.timeout > UINT_MAX / MSEC_PER_SEC)
- add_opt.ext.timeout = UINT_MAX / MSEC_PER_SEC;
+ add_opt.ext.timeout > IPSET_MAX_TIMEOUT)
+ add_opt.ext.timeout = IPSET_MAX_TIMEOUT;
if (info->add_set.index != IPSET_INVALID_ID)
ip_set_add(info->add_set.index, skb, par, &add_opt);
if (info->del_set.index != IPSET_INVALID_ID)
@@ -470,7 +470,7 @@ set_target_v3_checkentry(const struct xt_tgchk_param *par)
}
if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
(info->flags & IPSET_FLAG_MAP_SKBQUEUE)) &&
- !(par->hook_mask & (1 << NF_INET_FORWARD |
+ (par->hook_mask & ~(1 << NF_INET_FORWARD |
1 << NF_INET_LOCAL_OUT |
1 << NF_INET_POST_ROUTING))) {
pr_info_ratelimited("mapping of prio or/and queue is allowed only from OUTPUT/FORWARD/POSTROUTING chains\n");
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index b9ce82c..25eeb6d 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -352,8 +352,9 @@ int genl_register_family(struct genl_family *family)
}
if (family->maxattr && !family->parallel_ops) {
- family->attrbuf = kmalloc((family->maxattr+1) *
- sizeof(struct nlattr *), GFP_KERNEL);
+ family->attrbuf = kmalloc_array(family->maxattr + 1,
+ sizeof(struct nlattr *),
+ GFP_KERNEL);
if (family->attrbuf == NULL) {
err = -ENOMEM;
goto errout_locked;
@@ -566,8 +567,9 @@ static int genl_family_rcv_msg(const struct genl_family *family,
return -EOPNOTSUPP;
if (family->maxattr && family->parallel_ops) {
- attrbuf = kmalloc((family->maxattr+1) *
- sizeof(struct nlattr *), GFP_KERNEL);
+ attrbuf = kmalloc_array(family->maxattr + 1,
+ sizeof(struct nlattr *),
+ GFP_KERNEL);
if (attrbuf == NULL)
return -ENOMEM;
} else
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index b97eb76..93fbcaf 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -1395,7 +1395,7 @@ static int __init nr_proto_init(void)
return -1;
}
- dev_nr = kzalloc(nr_ndevs * sizeof(struct net_device *), GFP_KERNEL);
+ dev_nr = kcalloc(nr_ndevs, sizeof(struct net_device *), GFP_KERNEL);
if (dev_nr == NULL) {
printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device array\n");
return -1;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index a61818e..0f5ce77 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1578,8 +1578,9 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
goto err_destroy_table;
}
- dp->ports = kmalloc(DP_VPORT_HASH_BUCKETS * sizeof(struct hlist_head),
- GFP_KERNEL);
+ dp->ports = kmalloc_array(DP_VPORT_HASH_BUCKETS,
+ sizeof(struct hlist_head),
+ GFP_KERNEL);
if (!dp->ports) {
err = -ENOMEM;
goto err_destroy_percpu;
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c
index f81c1d0..19f6765 100644
--- a/net/openvswitch/vport.c
+++ b/net/openvswitch/vport.c
@@ -47,7 +47,7 @@ static struct hlist_head *dev_table;
*/
int ovs_vport_init(void)
{
- dev_table = kzalloc(VPORT_HASH_BUCKETS * sizeof(struct hlist_head),
+ dev_table = kcalloc(VPORT_HASH_BUCKETS, sizeof(struct hlist_head),
GFP_KERNEL);
if (!dev_table)
return -ENOMEM;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 54ce66f..5080974 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2005,7 +2005,7 @@ static int packet_rcv_vnet(struct msghdr *msg, const struct sk_buff *skb,
return -EINVAL;
*len -= sizeof(vnet_hdr);
- if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true))
+ if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le(), true, 0))
return -EINVAL;
return memcpy_to_msg(msg, (void *)&vnet_hdr, sizeof(vnet_hdr));
@@ -2272,7 +2272,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
if (do_vnet) {
if (virtio_net_hdr_from_skb(skb, h.raw + macoff -
sizeof(struct virtio_net_hdr),
- vio_le(), true)) {
+ vio_le(), true, 0)) {
spin_lock(&sk->sk_receive_queue.lock);
goto drop_n_account;
}
@@ -4161,7 +4161,7 @@ static char *alloc_one_pg_vec_page(unsigned long order)
return buffer;
/* __get_free_pages failed, fall back to vmalloc */
- buffer = vzalloc((1 << order) * PAGE_SIZE);
+ buffer = vzalloc(array_size((1 << order), PAGE_SIZE));
if (buffer)
return buffer;
diff --git a/net/rds/ib.c b/net/rds/ib.c
index 02deee2..b6ad38e 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -163,7 +163,8 @@ static void rds_ib_add_one(struct ib_device *device)
rds_ibdev->max_initiator_depth = device->attrs.max_qp_init_rd_atom;
rds_ibdev->max_responder_resources = device->attrs.max_qp_rd_atom;
- rds_ibdev->vector_load = kzalloc(sizeof(int) * device->num_comp_vectors,
+ rds_ibdev->vector_load = kcalloc(device->num_comp_vectors,
+ sizeof(int),
GFP_KERNEL);
if (!rds_ibdev->vector_load) {
pr_err("RDS/IB: %s failed to allocate vector memory\n",
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c
index 13b38ad..f1684ae 100644
--- a/net/rds/ib_cm.c
+++ b/net/rds/ib_cm.c
@@ -526,7 +526,8 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
goto recv_hdrs_dma_out;
}
- ic->i_sends = vzalloc_node(ic->i_send_ring.w_nr * sizeof(struct rds_ib_send_work),
+ ic->i_sends = vzalloc_node(array_size(sizeof(struct rds_ib_send_work),
+ ic->i_send_ring.w_nr),
ibdev_to_node(dev));
if (!ic->i_sends) {
ret = -ENOMEM;
@@ -534,7 +535,8 @@ static int rds_ib_setup_qp(struct rds_connection *conn)
goto ack_dma_out;
}
- ic->i_recvs = vzalloc_node(ic->i_recv_ring.w_nr * sizeof(struct rds_ib_recv_work),
+ ic->i_recvs = vzalloc_node(array_size(sizeof(struct rds_ib_recv_work),
+ ic->i_recv_ring.w_nr),
ibdev_to_node(dev));
if (!ic->i_recvs) {
ret = -ENOMEM;
diff --git a/net/rds/info.c b/net/rds/info.c
index 140a44a5f..e367a97 100644
--- a/net/rds/info.c
+++ b/net/rds/info.c
@@ -188,7 +188,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,
nr_pages = (PAGE_ALIGN(start + len) - (start & PAGE_MASK))
>> PAGE_SHIFT;
- pages = kmalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+ pages = kmalloc_array(nr_pages, sizeof(struct page *), GFP_KERNEL);
if (!pages) {
ret = -ENOMEM;
goto out;
diff --git a/net/rds/loop.c b/net/rds/loop.c
index f2bf78d..dac6218 100644
--- a/net/rds/loop.c
+++ b/net/rds/loop.c
@@ -193,4 +193,5 @@ struct rds_transport rds_loop_transport = {
.inc_copy_to_user = rds_message_inc_copy_to_user,
.inc_free = rds_loop_inc_free,
.t_name = "loopback",
+ .t_type = RDS_TRANS_LOOP,
};
diff --git a/net/rds/rds.h b/net/rds/rds.h
index b04c333..f2272fb 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -479,6 +479,11 @@ struct rds_notifier {
int n_status;
};
+/* Available as part of RDS core, so doesn't need to participate
+ * in get_preferred transport etc
+ */
+#define RDS_TRANS_LOOP 3
+
/**
* struct rds_transport - transport specific behavioural hooks
*
diff --git a/net/rds/recv.c b/net/rds/recv.c
index dc67458..192ac6f 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -103,6 +103,11 @@ static void rds_recv_rcvbuf_delta(struct rds_sock *rs, struct sock *sk,
rds_stats_add(s_recv_bytes_added_to_socket, delta);
else
rds_stats_add(s_recv_bytes_removed_from_socket, -delta);
+
+ /* loop transport doesn't send/recv congestion updates */
+ if (rs->rs_transport->t_type == RDS_TRANS_LOOP)
+ return;
+
now_congested = rs->rs_rcv_bytes > rds_sk_rcvbuf(rs);
rdsdebug("rs %p (%pI4:%u) recv bytes %d buf %d "
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 5b73fea..ebe42e7 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1514,7 +1514,8 @@ static int __init rose_proto_init(void)
rose_callsign = null_ax25_address;
- dev_rose = kzalloc(rose_ndevs * sizeof(struct net_device *), GFP_KERNEL);
+ dev_rose = kcalloc(rose_ndevs, sizeof(struct net_device *),
+ GFP_KERNEL);
if (dev_rose == NULL) {
printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate device structure\n");
rc = -ENOMEM;
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index 6c0ae27..278ac08 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -432,7 +432,7 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
sg = _sg;
if (unlikely(nsg > 4)) {
- sg = kmalloc(sizeof(*sg) * nsg, GFP_NOIO);
+ sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO);
if (!sg)
goto nomem;
}
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index 8527cfd..20d7d36 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -415,7 +415,8 @@ static void tcf_ife_cleanup(struct tc_action *a)
spin_unlock_bh(&ife->tcf_lock);
p = rcu_dereference_protected(ife->params, 1);
- kfree_rcu(p, rcu);
+ if (p)
+ kfree_rcu(p, rcu);
}
/* under ife->tcf_lock for existing action */
@@ -516,8 +517,6 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
saddr = nla_data(tb[TCA_IFE_SMAC]);
}
- ife->tcf_action = parm->action;
-
if (parm->flags & IFE_ENCODE) {
if (daddr)
ether_addr_copy(p->eth_dst, daddr);
@@ -543,10 +542,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
NULL, NULL);
if (err) {
metadata_parse_err:
- if (exists)
- tcf_idr_release(*a, bind);
if (ret == ACT_P_CREATED)
- _tcf_ife_cleanup(*a);
+ tcf_idr_release(*a, bind);
if (exists)
spin_unlock_bh(&ife->tcf_lock);
@@ -567,7 +564,7 @@ metadata_parse_err:
err = use_all_metadata(ife);
if (err) {
if (ret == ACT_P_CREATED)
- _tcf_ife_cleanup(*a);
+ tcf_idr_release(*a, bind);
if (exists)
spin_unlock_bh(&ife->tcf_lock);
@@ -576,6 +573,7 @@ metadata_parse_err:
}
}
+ ife->tcf_action = parm->action;
if (exists)
spin_unlock_bh(&ife->tcf_lock);
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index 9618b4a8..98c4afe 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -53,22 +53,22 @@ static void tcf_simp_release(struct tc_action *a)
kfree(d->tcfd_defdata);
}
-static int alloc_defdata(struct tcf_defact *d, char *defdata)
+static int alloc_defdata(struct tcf_defact *d, const struct nlattr *defdata)
{
d->tcfd_defdata = kzalloc(SIMP_MAX_DATA, GFP_KERNEL);
if (unlikely(!d->tcfd_defdata))
return -ENOMEM;
- strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
+ nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
return 0;
}
-static void reset_policy(struct tcf_defact *d, char *defdata,
+static void reset_policy(struct tcf_defact *d, const struct nlattr *defdata,
struct tc_defact *p)
{
spin_lock_bh(&d->tcf_lock);
d->tcf_action = p->action;
memset(d->tcfd_defdata, 0, SIMP_MAX_DATA);
- strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
+ nla_strlcpy(d->tcfd_defdata, defdata, SIMP_MAX_DATA);
spin_unlock_bh(&d->tcf_lock);
}
@@ -87,7 +87,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
struct tcf_defact *d;
bool exists = false;
int ret = 0, err;
- char *defdata;
if (nla == NULL)
return -EINVAL;
@@ -110,8 +109,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
return -EINVAL;
}
- defdata = nla_data(tb[TCA_DEF_DATA]);
-
if (!exists) {
ret = tcf_idr_create(tn, parm->index, est, a,
&act_simp_ops, bind, false);
@@ -119,7 +116,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
return ret;
d = to_defact(*a);
- ret = alloc_defdata(d, defdata);
+ ret = alloc_defdata(d, tb[TCA_DEF_DATA]);
if (ret < 0) {
tcf_idr_release(*a, bind);
return ret;
@@ -133,7 +130,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla,
if (!ovr)
return -EEXIST;
- reset_policy(d, defdata, parm);
+ reset_policy(d, tb[TCA_DEF_DATA], parm);
}
if (ret == ACT_P_CREATED)
diff --git a/net/sched/sch_blackhole.c b/net/sched/sch_blackhole.c
index c98a61e..9c4c2bb 100644
--- a/net/sched/sch_blackhole.c
+++ b/net/sched/sch_blackhole.c
@@ -21,7 +21,7 @@ static int blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
qdisc_drop(skb, sch, to_free);
- return NET_XMIT_SUCCESS;
+ return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
}
static struct sk_buff *blackhole_dequeue(struct Qdisc *sch)
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index 22fa13c..cd2e0e3 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -489,11 +489,12 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
return err;
if (!q->flows) {
- q->flows = kvzalloc(q->flows_cnt *
- sizeof(struct fq_codel_flow), GFP_KERNEL);
+ q->flows = kvcalloc(q->flows_cnt,
+ sizeof(struct fq_codel_flow),
+ GFP_KERNEL);
if (!q->flows)
return -ENOMEM;
- q->backlogs = kvzalloc(q->flows_cnt * sizeof(u32), GFP_KERNEL);
+ q->backlogs = kvcalloc(q->flows_cnt, sizeof(u32), GFP_KERNEL);
if (!q->backlogs)
return -ENOMEM;
for (i = 0; i < q->flows_cnt; i++) {
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c
index bce2632..c3a8388 100644
--- a/net/sched/sch_hhf.c
+++ b/net/sched/sch_hhf.c
@@ -599,8 +599,8 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt,
if (!q->hh_flows) {
/* Initialize heavy-hitter flow table. */
- q->hh_flows = kvzalloc(HH_FLOWS_CNT *
- sizeof(struct list_head), GFP_KERNEL);
+ q->hh_flows = kvcalloc(HH_FLOWS_CNT, sizeof(struct list_head),
+ GFP_KERNEL);
if (!q->hh_flows)
return -ENOMEM;
for (i = 0; i < HH_FLOWS_CNT; i++)
@@ -614,8 +614,9 @@ 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] = kvzalloc(HHF_ARRAYS_LEN *
- sizeof(u32), GFP_KERNEL);
+ q->hhf_arrays[i] = kvcalloc(HHF_ARRAYS_LEN,
+ sizeof(u32),
+ GFP_KERNEL);
if (!q->hhf_arrays[i]) {
/* Note: hhf_destroy() will be called
* by our caller.
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index e64630c..5b53761 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -482,8 +482,9 @@ int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp)
return 0;
/* Allocated the array of pointers to transorms */
- ep->auth_hmacs = kzalloc(sizeof(struct crypto_shash *) *
- SCTP_AUTH_NUM_HMACS, gfp);
+ ep->auth_hmacs = kcalloc(SCTP_AUTH_NUM_HMACS,
+ sizeof(struct crypto_shash *),
+ gfp);
if (!ep->auth_hmacs)
return -ENOMEM;
diff --git a/net/sctp/output.c b/net/sctp/output.c
index e672dee..7f849b0 100644
--- a/net/sctp/output.c
+++ b/net/sctp/output.c
@@ -409,6 +409,21 @@ static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk)
refcount_inc(&sk->sk_wmem_alloc);
}
+static void sctp_packet_gso_append(struct sk_buff *head, struct sk_buff *skb)
+{
+ if (SCTP_OUTPUT_CB(head)->last == head)
+ skb_shinfo(head)->frag_list = skb;
+ else
+ SCTP_OUTPUT_CB(head)->last->next = skb;
+ SCTP_OUTPUT_CB(head)->last = skb;
+
+ head->truesize += skb->truesize;
+ head->data_len += skb->len;
+ head->len += skb->len;
+
+ __skb_header_release(skb);
+}
+
static int sctp_packet_pack(struct sctp_packet *packet,
struct sk_buff *head, int gso, gfp_t gfp)
{
@@ -422,7 +437,7 @@ static int sctp_packet_pack(struct sctp_packet *packet,
if (gso) {
skb_shinfo(head)->gso_type = sk->sk_gso_type;
- NAPI_GRO_CB(head)->last = head;
+ SCTP_OUTPUT_CB(head)->last = head;
} else {
nskb = head;
pkt_size = packet->size;
@@ -503,15 +518,8 @@ merge:
&packet->chunk_list);
}
- if (gso) {
- if (skb_gro_receive(&head, nskb)) {
- kfree_skb(nskb);
- return 0;
- }
- if (WARN_ON_ONCE(skb_shinfo(head)->gso_segs >=
- sk->sk_gso_max_segs))
- return 0;
- }
+ if (gso)
+ sctp_packet_gso_append(head, nskb);
pkt_count++;
} while (!list_empty(&packet->chunk_list));
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 11d9337..5dffbc4 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -1438,7 +1438,7 @@ static __init int sctp_init(void)
/* Allocate and initialize the endpoint hash table. */
sctp_ep_hashsize = 64;
sctp_ep_hashtable =
- kmalloc(64 * sizeof(struct sctp_hashbucket), GFP_KERNEL);
+ kmalloc_array(64, sizeof(struct sctp_hashbucket), GFP_KERNEL);
if (!sctp_ep_hashtable) {
pr_err("Failed endpoint_hash alloc\n");
status = -ENOMEM;
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 973b447..da7f02e 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -1273,8 +1273,7 @@ static __poll_t smc_accept_poll(struct sock *parent)
return mask;
}
-static __poll_t smc_poll(struct file *file, struct socket *sock,
- poll_table *wait)
+static __poll_t smc_poll_mask(struct socket *sock, __poll_t events)
{
struct sock *sk = sock->sk;
__poll_t mask = 0;
@@ -1290,7 +1289,7 @@ static __poll_t smc_poll(struct file *file, struct socket *sock,
if ((sk->sk_state == SMC_INIT) || smc->use_fallback) {
/* delegate to CLC child sock */
release_sock(sk);
- mask = smc->clcsock->ops->poll(file, smc->clcsock, wait);
+ mask = smc->clcsock->ops->poll_mask(smc->clcsock, events);
lock_sock(sk);
sk->sk_err = smc->clcsock->sk->sk_err;
if (sk->sk_err) {
@@ -1308,11 +1307,6 @@ static __poll_t smc_poll(struct file *file, struct socket *sock,
}
}
} else {
- if (sk->sk_state != SMC_CLOSED) {
- release_sock(sk);
- sock_poll_wait(file, sk_sleep(sk), wait);
- lock_sock(sk);
- }
if (sk->sk_err)
mask |= EPOLLERR;
if ((sk->sk_shutdown == SHUTDOWN_MASK) ||
@@ -1625,7 +1619,7 @@ static const struct proto_ops smc_sock_ops = {
.socketpair = sock_no_socketpair,
.accept = smc_accept,
.getname = smc_getname,
- .poll = smc_poll,
+ .poll_mask = smc_poll_mask,
.ioctl = smc_ioctl,
.listen = smc_listen,
.shutdown = smc_shutdown,
diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c
index cc7c1bb..dbd2605 100644
--- a/net/smc/smc_wr.c
+++ b/net/smc/smc_wr.c
@@ -584,9 +584,9 @@ int smc_wr_alloc_link_mem(struct smc_link *link)
GFP_KERNEL);
if (!link->wr_rx_sges)
goto no_mem_wr_tx_sges;
- link->wr_tx_mask = kzalloc(
- BITS_TO_LONGS(SMC_WR_BUF_CNT) * sizeof(*link->wr_tx_mask),
- GFP_KERNEL);
+ link->wr_tx_mask = kcalloc(BITS_TO_LONGS(SMC_WR_BUF_CNT),
+ sizeof(*link->wr_tx_mask),
+ GFP_KERNEL);
if (!link->wr_tx_mask)
goto no_mem_wr_rx_sges;
link->wr_tx_pends = kcalloc(SMC_WR_BUF_CNT,
diff --git a/net/socket.c b/net/socket.c
index af57d85..8a10901 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -541,7 +541,10 @@ static int sockfs_setattr(struct dentry *dentry, struct iattr *iattr)
if (!err && (iattr->ia_valid & ATTR_UID)) {
struct socket *sock = SOCKET_I(d_inode(dentry));
- sock->sk->sk_uid = iattr->ia_uid;
+ if (sock->sk)
+ sock->sk->sk_uid = iattr->ia_uid;
+ else
+ err = -ENOENT;
}
return err;
@@ -590,12 +593,16 @@ EXPORT_SYMBOL(sock_alloc);
* an inode not a file.
*/
-void sock_release(struct socket *sock)
+static void __sock_release(struct socket *sock, struct inode *inode)
{
if (sock->ops) {
struct module *owner = sock->ops->owner;
+ if (inode)
+ inode_lock(inode);
sock->ops->release(sock);
+ if (inode)
+ inode_unlock(inode);
sock->ops = NULL;
module_put(owner);
}
@@ -609,6 +616,11 @@ void sock_release(struct socket *sock)
}
sock->file = NULL;
}
+
+void sock_release(struct socket *sock)
+{
+ __sock_release(sock, NULL);
+}
EXPORT_SYMBOL(sock_release);
void __sock_tx_timestamp(__u16 tsflags, __u8 *tx_flags)
@@ -1171,7 +1183,7 @@ static int sock_mmap(struct file *file, struct vm_area_struct *vma)
static int sock_close(struct inode *inode, struct file *filp)
{
- sock_release(SOCKET_I(inode));
+ __sock_release(SOCKET_I(inode), inode);
return 0;
}
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 9463af4..be8f103 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -1753,7 +1753,8 @@ alloc_enc_pages(struct rpc_rqst *rqstp)
last = (snd_buf->page_base + snd_buf->page_len - 1) >> PAGE_SHIFT;
rqstp->rq_enc_pages_num = last - first + 1 + 1;
rqstp->rq_enc_pages
- = kmalloc(rqstp->rq_enc_pages_num * sizeof(struct page *),
+ = kmalloc_array(rqstp->rq_enc_pages_num,
+ sizeof(struct page *),
GFP_NOFS);
if (!rqstp->rq_enc_pages)
goto out;
diff --git a/net/sunrpc/auth_gss/gss_rpc_upcall.c b/net/sunrpc/auth_gss/gss_rpc_upcall.c
index 46b295e..1c7c49d 100644
--- a/net/sunrpc/auth_gss/gss_rpc_upcall.c
+++ b/net/sunrpc/auth_gss/gss_rpc_upcall.c
@@ -224,7 +224,7 @@ static void gssp_free_receive_pages(struct gssx_arg_accept_sec_context *arg)
static int gssp_alloc_receive_pages(struct gssx_arg_accept_sec_context *arg)
{
arg->npages = DIV_ROUND_UP(NGROUPS_MAX * 4, PAGE_SIZE);
- arg->pages = kzalloc(arg->npages * sizeof(struct page *), GFP_KERNEL);
+ arg->pages = kcalloc(arg->npages, sizeof(struct page *), GFP_KERNEL);
/*
* XXX: actual pages are allocated by xdr layer in
* xdr_partial_copy_from_skb.
@@ -298,9 +298,11 @@ int gssp_accept_sec_context_upcall(struct net *net,
if (res.context_handle) {
data->out_handle = rctxh.exported_context_token;
data->mech_oid.len = rctxh.mech.len;
- if (rctxh.mech.data)
+ if (rctxh.mech.data) {
memcpy(data->mech_oid.data, rctxh.mech.data,
data->mech_oid.len);
+ kfree(rctxh.mech.data);
+ }
client_name = rctxh.src_name.display_name;
}
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index cdda474..109fbe5 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -1683,7 +1683,7 @@ struct cache_detail *cache_create_net(const struct cache_detail *tmpl, struct ne
if (cd == NULL)
return ERR_PTR(-ENOMEM);
- cd->hash_table = kzalloc(cd->hash_size * sizeof(struct hlist_head),
+ cd->hash_table = kcalloc(cd->hash_size, sizeof(struct hlist_head),
GFP_KERNEL);
if (cd->hash_table == NULL) {
kfree(cd);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index c2266f3..d839c33 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1546,6 +1546,7 @@ call_reserveresult(struct rpc_task *task)
task->tk_status = 0;
if (status >= 0) {
if (task->tk_rqstp) {
+ xprt_request_init(task);
task->tk_action = call_refresh;
return;
}
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 70f0050..3fabf9f6 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -66,7 +66,7 @@
* Local functions
*/
static void xprt_init(struct rpc_xprt *xprt, struct net *net);
-static void xprt_request_init(struct rpc_task *, struct rpc_xprt *);
+static __be32 xprt_alloc_xid(struct rpc_xprt *xprt);
static void xprt_connect_status(struct rpc_task *task);
static int __xprt_get_cong(struct rpc_xprt *, struct rpc_task *);
static void __xprt_put_cong(struct rpc_xprt *, struct rpc_rqst *);
@@ -1163,10 +1163,10 @@ void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
out_init_req:
xprt->stat.max_slots = max_t(unsigned int, xprt->stat.max_slots,
xprt->num_reqs);
+ spin_unlock(&xprt->reserve_lock);
+
task->tk_status = 0;
task->tk_rqstp = req;
- xprt_request_init(task, xprt);
- spin_unlock(&xprt->reserve_lock);
}
EXPORT_SYMBOL_GPL(xprt_alloc_slot);
@@ -1184,7 +1184,7 @@ void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
}
EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot);
-static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
+void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
{
spin_lock(&xprt->reserve_lock);
if (!xprt_dynamic_free_slot(xprt, req)) {
@@ -1194,6 +1194,7 @@ static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
xprt_wake_up_backlog(xprt);
spin_unlock(&xprt->reserve_lock);
}
+EXPORT_SYMBOL_GPL(xprt_free_slot);
static void xprt_free_all_slots(struct rpc_xprt *xprt)
{
@@ -1295,7 +1296,12 @@ void xprt_retry_reserve(struct rpc_task *task)
static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt)
{
- return (__force __be32)xprt->xid++;
+ __be32 xid;
+
+ spin_lock(&xprt->reserve_lock);
+ xid = (__force __be32)xprt->xid++;
+ spin_unlock(&xprt->reserve_lock);
+ return xid;
}
static inline void xprt_init_xid(struct rpc_xprt *xprt)
@@ -1303,8 +1309,9 @@ static inline void xprt_init_xid(struct rpc_xprt *xprt)
xprt->xid = prandom_u32();
}
-static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
+void xprt_request_init(struct rpc_task *task)
{
+ struct rpc_xprt *xprt = task->tk_xprt;
struct rpc_rqst *req = task->tk_rqstp;
INIT_LIST_HEAD(&req->rq_list);
@@ -1312,7 +1319,7 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt)
req->rq_task = task;
req->rq_xprt = xprt;
req->rq_buffer = NULL;
- req->rq_xid = xprt_alloc_xid(xprt);
+ req->rq_xid = xprt_alloc_xid(xprt);
req->rq_connect_cookie = xprt->connect_cookie - 1;
req->rq_bytes_sent = 0;
req->rq_snd_buf.len = 0;
@@ -1373,7 +1380,7 @@ void xprt_release(struct rpc_task *task)
dprintk("RPC: %5u release request %p\n", task->tk_pid, req);
if (likely(!bc_prealloc(req)))
- xprt_free_slot(xprt, req);
+ xprt->ops->free_slot(xprt, req);
else
xprt_free_bc_request(req);
}
diff --git a/net/sunrpc/xprtrdma/backchannel.c b/net/sunrpc/xprtrdma/backchannel.c
index 47ebac9..90adeff 100644
--- a/net/sunrpc/xprtrdma/backchannel.c
+++ b/net/sunrpc/xprtrdma/backchannel.c
@@ -9,8 +9,10 @@
#include <linux/sunrpc/xprt.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/svc_xprt.h>
+#include <linux/sunrpc/svc_rdma.h>
#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_TRANS
@@ -29,29 +31,41 @@ static void rpcrdma_bc_free_rqst(struct rpcrdma_xprt *r_xprt,
spin_unlock(&buf->rb_reqslock);
rpcrdma_destroy_req(req);
-
- kfree(rqst);
}
-static int rpcrdma_bc_setup_rqst(struct rpcrdma_xprt *r_xprt,
- struct rpc_rqst *rqst)
+static int rpcrdma_bc_setup_reqs(struct rpcrdma_xprt *r_xprt,
+ unsigned int count)
{
- struct rpcrdma_regbuf *rb;
- struct rpcrdma_req *req;
- size_t size;
+ struct rpc_xprt *xprt = &r_xprt->rx_xprt;
+ struct rpc_rqst *rqst;
+ unsigned int i;
+
+ for (i = 0; i < (count << 1); i++) {
+ struct rpcrdma_regbuf *rb;
+ struct rpcrdma_req *req;
+ size_t size;
+
+ req = rpcrdma_create_req(r_xprt);
+ if (IS_ERR(req))
+ return PTR_ERR(req);
+ rqst = &req->rl_slot;
+
+ rqst->rq_xprt = xprt;
+ INIT_LIST_HEAD(&rqst->rq_list);
+ INIT_LIST_HEAD(&rqst->rq_bc_list);
+ __set_bit(RPC_BC_PA_IN_USE, &rqst->rq_bc_pa_state);
+ spin_lock_bh(&xprt->bc_pa_lock);
+ list_add(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);
+ spin_unlock_bh(&xprt->bc_pa_lock);
- req = rpcrdma_create_req(r_xprt);
- if (IS_ERR(req))
- return PTR_ERR(req);
-
- size = r_xprt->rx_data.inline_rsize;
- rb = rpcrdma_alloc_regbuf(size, DMA_TO_DEVICE, GFP_KERNEL);
- if (IS_ERR(rb))
- goto out_fail;
- req->rl_sendbuf = rb;
- xdr_buf_init(&rqst->rq_snd_buf, rb->rg_base,
- min_t(size_t, size, PAGE_SIZE));
- rpcrdma_set_xprtdata(rqst, req);
+ size = r_xprt->rx_data.inline_rsize;
+ rb = rpcrdma_alloc_regbuf(size, DMA_TO_DEVICE, GFP_KERNEL);
+ if (IS_ERR(rb))
+ goto out_fail;
+ req->rl_sendbuf = rb;
+ xdr_buf_init(&rqst->rq_snd_buf, rb->rg_base,
+ min_t(size_t, size, PAGE_SIZE));
+ }
return 0;
out_fail:
@@ -59,23 +73,6 @@ out_fail:
return -ENOMEM;
}
-/* Allocate and add receive buffers to the rpcrdma_buffer's
- * existing list of rep's. These are released when the
- * transport is destroyed.
- */
-static int rpcrdma_bc_setup_reps(struct rpcrdma_xprt *r_xprt,
- unsigned int count)
-{
- int rc = 0;
-
- while (count--) {
- rc = rpcrdma_create_rep(r_xprt);
- if (rc)
- break;
- }
- return rc;
-}
-
/**
* xprt_rdma_bc_setup - Pre-allocate resources for handling backchannel requests
* @xprt: transport associated with these backchannel resources
@@ -86,9 +83,6 @@ static int rpcrdma_bc_setup_reps(struct rpcrdma_xprt *r_xprt,
int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs)
{
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
- struct rpcrdma_buffer *buffer = &r_xprt->rx_buf;
- struct rpc_rqst *rqst;
- unsigned int i;
int rc;
/* The backchannel reply path returns each rpc_rqst to the
@@ -103,35 +97,11 @@ int xprt_rdma_bc_setup(struct rpc_xprt *xprt, unsigned int reqs)
if (reqs > RPCRDMA_BACKWARD_WRS >> 1)
goto out_err;
- for (i = 0; i < (reqs << 1); i++) {
- rqst = kzalloc(sizeof(*rqst), GFP_KERNEL);
- if (!rqst)
- goto out_free;
-
- dprintk("RPC: %s: new rqst %p\n", __func__, rqst);
-
- rqst->rq_xprt = &r_xprt->rx_xprt;
- INIT_LIST_HEAD(&rqst->rq_list);
- INIT_LIST_HEAD(&rqst->rq_bc_list);
- __set_bit(RPC_BC_PA_IN_USE, &rqst->rq_bc_pa_state);
-
- if (rpcrdma_bc_setup_rqst(r_xprt, rqst))
- goto out_free;
-
- spin_lock_bh(&xprt->bc_pa_lock);
- list_add(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);
- spin_unlock_bh(&xprt->bc_pa_lock);
- }
-
- rc = rpcrdma_bc_setup_reps(r_xprt, reqs);
+ rc = rpcrdma_bc_setup_reqs(r_xprt, reqs);
if (rc)
goto out_free;
- rc = rpcrdma_ep_post_extra_recv(r_xprt, reqs);
- if (rc)
- goto out_free;
-
- buffer->rb_bc_srv_max_requests = reqs;
+ r_xprt->rx_buf.rb_bc_srv_max_requests = reqs;
request_module("svcrdma");
trace_xprtrdma_cb_setup(r_xprt, reqs);
return 0;
@@ -235,6 +205,7 @@ int xprt_rdma_bc_send_reply(struct rpc_rqst *rqst)
if (rc < 0)
goto failed_marshal;
+ rpcrdma_post_recvs(r_xprt, true);
if (rpcrdma_ep_post(&r_xprt->rx_ia, &r_xprt->rx_ep, req))
goto drop_connection;
return 0;
@@ -275,10 +246,14 @@ void xprt_rdma_bc_destroy(struct rpc_xprt *xprt, unsigned int reqs)
*/
void xprt_rdma_bc_free_rqst(struct rpc_rqst *rqst)
{
+ struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
struct rpc_xprt *xprt = rqst->rq_xprt;
dprintk("RPC: %s: freeing rqst %p (req %p)\n",
- __func__, rqst, rpcr_to_rdmar(rqst));
+ __func__, rqst, req);
+
+ rpcrdma_recv_buffer_put(req->rl_reply);
+ req->rl_reply = NULL;
spin_lock_bh(&xprt->bc_pa_lock);
list_add_tail(&rqst->rq_bc_pa_list, &xprt->bc_pa_list);
diff --git a/net/sunrpc/xprtrdma/fmr_ops.c b/net/sunrpc/xprtrdma/fmr_ops.c
index f2f6395..17fb1e0 100644
--- a/net/sunrpc/xprtrdma/fmr_ops.c
+++ b/net/sunrpc/xprtrdma/fmr_ops.c
@@ -20,7 +20,10 @@
* verb (fmr_op_unmap).
*/
+#include <linux/sunrpc/svc_rdma.h>
+
#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_TRANS
@@ -156,10 +159,32 @@ out_release:
fmr_op_release_mr(mr);
}
+/* On success, sets:
+ * ep->rep_attr.cap.max_send_wr
+ * ep->rep_attr.cap.max_recv_wr
+ * cdata->max_requests
+ * ia->ri_max_segs
+ */
static int
fmr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
struct rpcrdma_create_data_internal *cdata)
{
+ int max_qp_wr;
+
+ max_qp_wr = ia->ri_device->attrs.max_qp_wr;
+ max_qp_wr -= RPCRDMA_BACKWARD_WRS;
+ max_qp_wr -= 1;
+ if (max_qp_wr < RPCRDMA_MIN_SLOT_TABLE)
+ return -ENOMEM;
+ if (cdata->max_requests > max_qp_wr)
+ cdata->max_requests = max_qp_wr;
+ ep->rep_attr.cap.max_send_wr = cdata->max_requests;
+ ep->rep_attr.cap.max_send_wr += RPCRDMA_BACKWARD_WRS;
+ ep->rep_attr.cap.max_send_wr += 1; /* for ib_drain_sq */
+ ep->rep_attr.cap.max_recv_wr = cdata->max_requests;
+ ep->rep_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS;
+ ep->rep_attr.cap.max_recv_wr += 1; /* for ib_drain_rq */
+
ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS /
RPCRDMA_MAX_FMR_SGES);
return 0;
@@ -219,6 +244,7 @@ fmr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
mr->mr_sg, i, mr->mr_dir);
if (!mr->mr_nents)
goto out_dmamap_err;
+ trace_xprtrdma_dma_map(mr);
for (i = 0, dma_pages = mr->fmr.fm_physaddrs; i < mr->mr_nents; i++)
dma_pages[i] = sg_dma_address(&mr->mr_sg[i]);
diff --git a/net/sunrpc/xprtrdma/frwr_ops.c b/net/sunrpc/xprtrdma/frwr_ops.c
index c59c5c7..c040de1 100644
--- a/net/sunrpc/xprtrdma/frwr_ops.c
+++ b/net/sunrpc/xprtrdma/frwr_ops.c
@@ -71,8 +71,10 @@
*/
#include <linux/sunrpc/rpc_rdma.h>
+#include <linux/sunrpc/svc_rdma.h>
#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_TRANS
@@ -202,12 +204,22 @@ out_release:
frwr_op_release_mr(mr);
}
+/* On success, sets:
+ * ep->rep_attr.cap.max_send_wr
+ * ep->rep_attr.cap.max_recv_wr
+ * cdata->max_requests
+ * ia->ri_max_segs
+ *
+ * And these FRWR-related fields:
+ * ia->ri_max_frwr_depth
+ * ia->ri_mrtype
+ */
static int
frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
struct rpcrdma_create_data_internal *cdata)
{
struct ib_device_attr *attrs = &ia->ri_device->attrs;
- int depth, delta;
+ int max_qp_wr, depth, delta;
ia->ri_mrtype = IB_MR_TYPE_MEM_REG;
if (attrs->device_cap_flags & IB_DEVICE_SG_GAPS_REG)
@@ -241,14 +253,26 @@ frwr_op_open(struct rpcrdma_ia *ia, struct rpcrdma_ep *ep,
} while (delta > 0);
}
- ep->rep_attr.cap.max_send_wr *= depth;
- if (ep->rep_attr.cap.max_send_wr > attrs->max_qp_wr) {
- cdata->max_requests = attrs->max_qp_wr / depth;
+ max_qp_wr = ia->ri_device->attrs.max_qp_wr;
+ max_qp_wr -= RPCRDMA_BACKWARD_WRS;
+ max_qp_wr -= 1;
+ if (max_qp_wr < RPCRDMA_MIN_SLOT_TABLE)
+ return -ENOMEM;
+ if (cdata->max_requests > max_qp_wr)
+ cdata->max_requests = max_qp_wr;
+ ep->rep_attr.cap.max_send_wr = cdata->max_requests * depth;
+ if (ep->rep_attr.cap.max_send_wr > max_qp_wr) {
+ cdata->max_requests = max_qp_wr / depth;
if (!cdata->max_requests)
return -EINVAL;
ep->rep_attr.cap.max_send_wr = cdata->max_requests *
depth;
}
+ ep->rep_attr.cap.max_send_wr += RPCRDMA_BACKWARD_WRS;
+ ep->rep_attr.cap.max_send_wr += 1; /* for ib_drain_sq */
+ ep->rep_attr.cap.max_recv_wr = cdata->max_requests;
+ ep->rep_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS;
+ ep->rep_attr.cap.max_recv_wr += 1; /* for ib_drain_rq */
ia->ri_max_segs = max_t(unsigned int, 1, RPCRDMA_MAX_DATA_SEGS /
ia->ri_max_frwr_depth);
@@ -393,6 +417,7 @@ frwr_op_map(struct rpcrdma_xprt *r_xprt, struct rpcrdma_mr_seg *seg,
mr->mr_nents = ib_dma_map_sg(ia->ri_device, mr->mr_sg, i, mr->mr_dir);
if (!mr->mr_nents)
goto out_dmamap_err;
+ trace_xprtrdma_dma_map(mr);
ibmr = frwr->fr_mr;
n = ib_map_mr_sg(ibmr, mr->mr_sg, mr->mr_nents, NULL, PAGE_SIZE);
diff --git a/net/sunrpc/xprtrdma/module.c b/net/sunrpc/xprtrdma/module.c
index a762d19..620327c 100644
--- a/net/sunrpc/xprtrdma/module.c
+++ b/net/sunrpc/xprtrdma/module.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (c) 2015, 2017 Oracle. All rights reserved.
*/
@@ -13,9 +14,11 @@
#include <asm/swab.h>
-#define CREATE_TRACE_POINTS
#include "xprt_rdma.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/rpcrdma.h>
+
MODULE_AUTHOR("Open Grid Computing and Network Appliance, Inc.");
MODULE_DESCRIPTION("RPC/RDMA Transport");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index e8adad3..c8ae983 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (c) 2014-2017 Oracle. All rights reserved.
* Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@ -46,22 +47,17 @@
* to the Linux RPC framework lives.
*/
-#include "xprt_rdma.h"
-
#include <linux/highmem.h>
+#include <linux/sunrpc/svc_rdma.h>
+
+#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
+
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_TRANS
#endif
-static const char transfertypes[][12] = {
- "inline", /* no chunks */
- "read list", /* some argument via rdma read */
- "*read list", /* entire request via rdma read */
- "write list", /* some result via rdma write */
- "reply chunk" /* entire reply via rdma write */
-};
-
/* Returns size of largest RPC-over-RDMA header in a Call message
*
* The largest Call header contains a full-size Read list and a
@@ -230,7 +226,7 @@ rpcrdma_convert_iovs(struct rpcrdma_xprt *r_xprt, struct xdr_buf *xdrbuf,
*/
*ppages = alloc_page(GFP_ATOMIC);
if (!*ppages)
- return -EAGAIN;
+ return -ENOBUFS;
}
seg->mr_page = *ppages;
seg->mr_offset = (char *)page_base;
@@ -365,7 +361,7 @@ rpcrdma_encode_read_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
seg = r_xprt->rx_ia.ri_ops->ro_map(r_xprt, seg, nsegs,
false, &mr);
if (IS_ERR(seg))
- goto out_maperr;
+ return PTR_ERR(seg);
rpcrdma_mr_push(mr, &req->rl_registered);
if (encode_read_segment(xdr, mr, pos) < 0)
@@ -377,11 +373,6 @@ rpcrdma_encode_read_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
} while (nsegs);
return 0;
-
-out_maperr:
- if (PTR_ERR(seg) == -EAGAIN)
- xprt_wait_for_buffer_space(rqst->rq_task, NULL);
- return PTR_ERR(seg);
}
/* Register and XDR encode the Write list. Supports encoding a list
@@ -428,7 +419,7 @@ rpcrdma_encode_write_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
seg = r_xprt->rx_ia.ri_ops->ro_map(r_xprt, seg, nsegs,
true, &mr);
if (IS_ERR(seg))
- goto out_maperr;
+ return PTR_ERR(seg);
rpcrdma_mr_push(mr, &req->rl_registered);
if (encode_rdma_segment(xdr, mr) < 0)
@@ -445,11 +436,6 @@ rpcrdma_encode_write_list(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
*segcount = cpu_to_be32(nchunks);
return 0;
-
-out_maperr:
- if (PTR_ERR(seg) == -EAGAIN)
- xprt_wait_for_buffer_space(rqst->rq_task, NULL);
- return PTR_ERR(seg);
}
/* Register and XDR encode the Reply chunk. Supports encoding an array
@@ -491,7 +477,7 @@ rpcrdma_encode_reply_chunk(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
seg = r_xprt->rx_ia.ri_ops->ro_map(r_xprt, seg, nsegs,
true, &mr);
if (IS_ERR(seg))
- goto out_maperr;
+ return PTR_ERR(seg);
rpcrdma_mr_push(mr, &req->rl_registered);
if (encode_rdma_segment(xdr, mr) < 0)
@@ -508,11 +494,6 @@ rpcrdma_encode_reply_chunk(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
*segcount = cpu_to_be32(nchunks);
return 0;
-
-out_maperr:
- if (PTR_ERR(seg) == -EAGAIN)
- xprt_wait_for_buffer_space(rqst->rq_task, NULL);
- return PTR_ERR(seg);
}
/**
@@ -709,7 +690,7 @@ rpcrdma_prepare_send_sges(struct rpcrdma_xprt *r_xprt,
{
req->rl_sendctx = rpcrdma_sendctx_get_locked(&r_xprt->rx_buf);
if (!req->rl_sendctx)
- return -ENOBUFS;
+ return -EAGAIN;
req->rl_sendctx->sc_wr.num_sge = 0;
req->rl_sendctx->sc_unmap_count = 0;
req->rl_sendctx->sc_req = req;
@@ -883,7 +864,15 @@ rpcrdma_marshal_req(struct rpcrdma_xprt *r_xprt, struct rpc_rqst *rqst)
return 0;
out_err:
- r_xprt->rx_stats.failed_marshal_count++;
+ switch (ret) {
+ case -EAGAIN:
+ xprt_wait_for_buffer_space(rqst->rq_task, NULL);
+ break;
+ case -ENOBUFS:
+ break;
+ default:
+ r_xprt->rx_stats.failed_marshal_count++;
+ }
return ret;
}
@@ -1026,8 +1015,6 @@ rpcrdma_is_bcall(struct rpcrdma_xprt *r_xprt, struct rpcrdma_rep *rep)
out_short:
pr_warn("RPC/RDMA short backward direction call\n");
- if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, rep))
- xprt_disconnect_done(&r_xprt->rx_xprt);
return true;
}
#else /* CONFIG_SUNRPC_BACKCHANNEL */
@@ -1333,13 +1320,14 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
u32 credits;
__be32 *p;
+ --buf->rb_posted_receives;
+
if (rep->rr_hdrbuf.head[0].iov_len == 0)
goto out_badstatus;
+ /* Fixed transport header fields */
xdr_init_decode(&rep->rr_stream, &rep->rr_hdrbuf,
rep->rr_hdrbuf.head[0].iov_base);
-
- /* Fixed transport header fields */
p = xdr_inline_decode(&rep->rr_stream, 4 * sizeof(*p));
if (unlikely(!p))
goto out_shortreply;
@@ -1378,17 +1366,10 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *rep)
trace_xprtrdma_reply(rqst->rq_task, rep, req, credits);
+ rpcrdma_post_recvs(r_xprt, false);
queue_work(rpcrdma_receive_wq, &rep->rr_work);
return;
-out_badstatus:
- rpcrdma_recv_buffer_put(rep);
- if (r_xprt->rx_ep.rep_connected == 1) {
- r_xprt->rx_ep.rep_connected = -EIO;
- rpcrdma_conn_func(&r_xprt->rx_ep);
- }
- return;
-
out_badversion:
trace_xprtrdma_reply_vers(rep);
goto repost;
@@ -1408,7 +1389,7 @@ out_shortreply:
* receive buffer before returning.
*/
repost:
- r_xprt->rx_stats.bad_reply_count++;
- if (rpcrdma_ep_post_recv(&r_xprt->rx_ia, rep))
- rpcrdma_recv_buffer_put(rep);
+ rpcrdma_post_recvs(r_xprt, false);
+out_badstatus:
+ rpcrdma_recv_buffer_put(rep);
}
diff --git a/net/sunrpc/xprtrdma/svc_rdma.c b/net/sunrpc/xprtrdma/svc_rdma.c
index dd8a431..357ba90 100644
--- a/net/sunrpc/xprtrdma/svc_rdma.c
+++ b/net/sunrpc/xprtrdma/svc_rdma.c
@@ -1,4 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
+ * Copyright (c) 2015-2018 Oracle. All rights reserved.
* Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved.
*
* This software is available to you under a choice of one of two
@@ -46,7 +48,6 @@
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/sched.h>
#include <linux/sunrpc/svc_rdma.h>
-#include "xprt_rdma.h"
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c
index a73632c..a681800 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c
@@ -1,13 +1,16 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (c) 2015 Oracle. All rights reserved.
+ * Copyright (c) 2015-2018 Oracle. All rights reserved.
*
* Support for backward direction RPCs on RPC/RDMA (server-side).
*/
#include <linux/module.h>
+
#include <linux/sunrpc/svc_rdma.h>
+
#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
@@ -112,39 +115,21 @@ out_notfound:
* the adapter has a small maximum SQ depth.
*/
static int svc_rdma_bc_sendto(struct svcxprt_rdma *rdma,
- struct rpc_rqst *rqst)
+ struct rpc_rqst *rqst,
+ struct svc_rdma_send_ctxt *ctxt)
{
- struct svc_rdma_op_ctxt *ctxt;
int 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);
+ ret = svc_rdma_map_reply_msg(rdma, ctxt, &rqst->rq_snd_buf, NULL);
if (ret < 0)
- goto out_err;
+ return -EIO;
/* Bump page refcnt so Send completion doesn't release
* the rq_buffer before all retransmits are complete.
*/
get_page(virt_to_page(rqst->rq_buffer));
- ret = svc_rdma_post_send_wr(rdma, ctxt, 1, 0);
- if (ret)
- goto out_unmap;
-
-out_err:
- 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;
+ ctxt->sc_send_wr.opcode = IB_WR_SEND;
+ return svc_rdma_send(rdma, &ctxt->sc_send_wr);
}
/* Server-side transport endpoint wants a whole page for its send
@@ -191,13 +176,15 @@ rpcrdma_bc_send_request(struct svcxprt_rdma *rdma, struct rpc_rqst *rqst)
{
struct rpc_xprt *xprt = rqst->rq_xprt;
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
+ struct svc_rdma_send_ctxt *ctxt;
__be32 *p;
int rc;
- /* Space in the send buffer for an RPC/RDMA header is reserved
- * via xprt->tsh_size.
- */
- p = rqst->rq_buffer;
+ ctxt = svc_rdma_send_ctxt_get(rdma);
+ if (!ctxt)
+ goto drop_connection;
+
+ p = ctxt->sc_xprt_buf;
*p++ = rqst->rq_xid;
*p++ = rpcrdma_version;
*p++ = cpu_to_be32(r_xprt->rx_buf.rb_bc_max_requests);
@@ -205,14 +192,17 @@ rpcrdma_bc_send_request(struct svcxprt_rdma *rdma, struct rpc_rqst *rqst)
*p++ = xdr_zero;
*p++ = xdr_zero;
*p = xdr_zero;
+ svc_rdma_sync_reply_hdr(rdma, ctxt, RPCRDMA_HDRLEN_MIN);
#ifdef SVCRDMA_BACKCHANNEL_DEBUG
pr_info("%s: %*ph\n", __func__, 64, rqst->rq_buffer);
#endif
- rc = svc_rdma_bc_sendto(rdma, rqst);
- if (rc)
+ rc = svc_rdma_bc_sendto(rdma, rqst, ctxt);
+ if (rc) {
+ svc_rdma_send_ctxt_put(rdma, ctxt);
goto drop_connection;
+ }
return rc;
drop_connection:
@@ -273,6 +263,7 @@ static const struct rpc_xprt_ops xprt_rdma_bc_procs = {
.reserve_xprt = xprt_reserve_xprt_cong,
.release_xprt = xprt_release_xprt_cong,
.alloc_slot = xprt_alloc_slot,
+ .free_slot = xprt_free_slot,
.release_request = xprt_release_rqst_cong,
.buf_alloc = xprt_rdma_bc_allocate,
.buf_free = xprt_rdma_bc_free,
@@ -320,7 +311,7 @@ xprt_setup_rdma_bc(struct xprt_create *args)
xprt->idle_timeout = RPCRDMA_IDLE_DISC_TO;
xprt->prot = XPRT_TRANSPORT_BC_RDMA;
- xprt->tsh_size = RPCRDMA_HDRLEN_MIN / sizeof(__be32);
+ xprt->tsh_size = 0;
xprt->ops = &xprt_rdma_bc_procs;
memcpy(&xprt->addr, args->dstaddr, args->addrlen);
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 3d45015..841fca1 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (c) 2016, 2017 Oracle. All rights reserved.
+ * Copyright (c) 2016-2018 Oracle. All rights reserved.
* Copyright (c) 2014 Open Grid Computing, Inc. All rights reserved.
* Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved.
*
@@ -60,7 +61,7 @@
* svc_rdma_recvfrom must post RDMA Reads to pull the RPC Call's
* data payload from the client. svc_rdma_recvfrom sets up the
* RDMA Reads using pages in svc_rqst::rq_pages, which are
- * transferred to an svc_rdma_op_ctxt for the duration of the
+ * transferred to an svc_rdma_recv_ctxt for the duration of the
* I/O. svc_rdma_recvfrom then returns zero, since the RPC message
* is still not yet ready.
*
@@ -69,18 +70,18 @@
* svc_rdma_recvfrom again. This second call may use a different
* svc_rqst than the first one, thus any information that needs
* to be preserved across these two calls is kept in an
- * svc_rdma_op_ctxt.
+ * svc_rdma_recv_ctxt.
*
* The second call to svc_rdma_recvfrom performs final assembly
* of the RPC Call message, using the RDMA Read sink pages kept in
- * the svc_rdma_op_ctxt. The xdr_buf is copied from the
- * svc_rdma_op_ctxt to the second svc_rqst. The second call returns
+ * the svc_rdma_recv_ctxt. The xdr_buf is copied from the
+ * svc_rdma_recv_ctxt to the second svc_rqst. The second call returns
* the length of the completed RPC Call message.
*
* Page Management
*
* Pages under I/O must be transferred from the first svc_rqst to an
- * svc_rdma_op_ctxt before the first svc_rdma_recvfrom call returns.
+ * svc_rdma_recv_ctxt before the first svc_rdma_recvfrom call returns.
*
* The first svc_rqst supplies pages for RDMA Reads. These are moved
* from rqstp::rq_pages into ctxt::pages. The consumed elements of
@@ -88,78 +89,286 @@
* svc_rdma_recvfrom call returns.
*
* During the second svc_rdma_recvfrom call, RDMA Read sink pages
- * are transferred from the svc_rdma_op_ctxt to the second svc_rqst
+ * are transferred from the svc_rdma_recv_ctxt to the second svc_rqst
* (see rdma_read_complete() below).
*/
+#include <linux/spinlock.h>
#include <asm/unaligned.h>
#include <rdma/ib_verbs.h>
#include <rdma/rdma_cm.h>
-#include <linux/spinlock.h>
-
#include <linux/sunrpc/xdr.h>
#include <linux/sunrpc/debug.h>
#include <linux/sunrpc/rpc_rdma.h>
#include <linux/sunrpc/svc_rdma.h>
+#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
+
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
-/*
- * Replace the pages in the rq_argpages array with the pages from the SGE in
- * the RDMA_RECV completion. The SGL should contain full pages up until the
- * last one.
+static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc);
+
+static inline struct svc_rdma_recv_ctxt *
+svc_rdma_next_recv_ctxt(struct list_head *list)
+{
+ return list_first_entry_or_null(list, struct svc_rdma_recv_ctxt,
+ rc_list);
+}
+
+static struct svc_rdma_recv_ctxt *
+svc_rdma_recv_ctxt_alloc(struct svcxprt_rdma *rdma)
+{
+ struct svc_rdma_recv_ctxt *ctxt;
+ dma_addr_t addr;
+ void *buffer;
+
+ ctxt = kmalloc(sizeof(*ctxt), GFP_KERNEL);
+ if (!ctxt)
+ goto fail0;
+ buffer = kmalloc(rdma->sc_max_req_size, GFP_KERNEL);
+ if (!buffer)
+ goto fail1;
+ addr = ib_dma_map_single(rdma->sc_pd->device, buffer,
+ rdma->sc_max_req_size, DMA_FROM_DEVICE);
+ if (ib_dma_mapping_error(rdma->sc_pd->device, addr))
+ goto fail2;
+
+ ctxt->rc_recv_wr.next = NULL;
+ ctxt->rc_recv_wr.wr_cqe = &ctxt->rc_cqe;
+ ctxt->rc_recv_wr.sg_list = &ctxt->rc_recv_sge;
+ ctxt->rc_recv_wr.num_sge = 1;
+ ctxt->rc_cqe.done = svc_rdma_wc_receive;
+ ctxt->rc_recv_sge.addr = addr;
+ ctxt->rc_recv_sge.length = rdma->sc_max_req_size;
+ ctxt->rc_recv_sge.lkey = rdma->sc_pd->local_dma_lkey;
+ ctxt->rc_recv_buf = buffer;
+ ctxt->rc_temp = false;
+ return ctxt;
+
+fail2:
+ kfree(buffer);
+fail1:
+ kfree(ctxt);
+fail0:
+ return NULL;
+}
+
+static void svc_rdma_recv_ctxt_destroy(struct svcxprt_rdma *rdma,
+ struct svc_rdma_recv_ctxt *ctxt)
+{
+ ib_dma_unmap_single(rdma->sc_pd->device, ctxt->rc_recv_sge.addr,
+ ctxt->rc_recv_sge.length, DMA_FROM_DEVICE);
+ kfree(ctxt->rc_recv_buf);
+ kfree(ctxt);
+}
+
+/**
+ * svc_rdma_recv_ctxts_destroy - Release all recv_ctxt's for an xprt
+ * @rdma: svcxprt_rdma being torn down
+ *
*/
-static void svc_rdma_build_arg_xdr(struct svc_rqst *rqstp,
- struct svc_rdma_op_ctxt *ctxt)
+void svc_rdma_recv_ctxts_destroy(struct svcxprt_rdma *rdma)
{
- struct page *page;
- int sge_no;
- u32 len;
+ struct svc_rdma_recv_ctxt *ctxt;
- /* The reply path assumes the Call's transport header resides
- * in rqstp->rq_pages[0].
- */
- page = ctxt->pages[0];
- put_page(rqstp->rq_pages[0]);
- rqstp->rq_pages[0] = page;
-
- /* Set up the XDR head */
- rqstp->rq_arg.head[0].iov_base = page_address(page);
- rqstp->rq_arg.head[0].iov_len =
- min_t(size_t, ctxt->byte_len, ctxt->sge[0].length);
- rqstp->rq_arg.len = ctxt->byte_len;
- rqstp->rq_arg.buflen = ctxt->byte_len;
-
- /* Compute bytes past head in the SGL */
- len = ctxt->byte_len - rqstp->rq_arg.head[0].iov_len;
-
- /* If data remains, store it in the pagelist */
- rqstp->rq_arg.page_len = len;
- rqstp->rq_arg.page_base = 0;
-
- sge_no = 1;
- while (len && sge_no < ctxt->count) {
- page = ctxt->pages[sge_no];
- put_page(rqstp->rq_pages[sge_no]);
- rqstp->rq_pages[sge_no] = page;
- len -= min_t(u32, len, ctxt->sge[sge_no].length);
- sge_no++;
+ while ((ctxt = svc_rdma_next_recv_ctxt(&rdma->sc_recv_ctxts))) {
+ list_del(&ctxt->rc_list);
+ svc_rdma_recv_ctxt_destroy(rdma, ctxt);
}
- rqstp->rq_respages = &rqstp->rq_pages[sge_no];
- rqstp->rq_next_page = rqstp->rq_respages + 1;
+}
+
+static struct svc_rdma_recv_ctxt *
+svc_rdma_recv_ctxt_get(struct svcxprt_rdma *rdma)
+{
+ struct svc_rdma_recv_ctxt *ctxt;
+
+ spin_lock(&rdma->sc_recv_lock);
+ ctxt = svc_rdma_next_recv_ctxt(&rdma->sc_recv_ctxts);
+ if (!ctxt)
+ goto out_empty;
+ list_del(&ctxt->rc_list);
+ spin_unlock(&rdma->sc_recv_lock);
+
+out:
+ ctxt->rc_page_count = 0;
+ return ctxt;
+
+out_empty:
+ spin_unlock(&rdma->sc_recv_lock);
+
+ ctxt = svc_rdma_recv_ctxt_alloc(rdma);
+ if (!ctxt)
+ return NULL;
+ goto out;
+}
+
+/**
+ * svc_rdma_recv_ctxt_put - Return recv_ctxt to free list
+ * @rdma: controlling svcxprt_rdma
+ * @ctxt: object to return to the free list
+ *
+ */
+void svc_rdma_recv_ctxt_put(struct svcxprt_rdma *rdma,
+ struct svc_rdma_recv_ctxt *ctxt)
+{
+ unsigned int i;
+
+ for (i = 0; i < ctxt->rc_page_count; i++)
+ put_page(ctxt->rc_pages[i]);
+
+ if (!ctxt->rc_temp) {
+ spin_lock(&rdma->sc_recv_lock);
+ list_add(&ctxt->rc_list, &rdma->sc_recv_ctxts);
+ spin_unlock(&rdma->sc_recv_lock);
+ } else
+ svc_rdma_recv_ctxt_destroy(rdma, ctxt);
+}
+
+static int __svc_rdma_post_recv(struct svcxprt_rdma *rdma,
+ struct svc_rdma_recv_ctxt *ctxt)
+{
+ struct ib_recv_wr *bad_recv_wr;
+ int ret;
+
+ svc_xprt_get(&rdma->sc_xprt);
+ ret = ib_post_recv(rdma->sc_qp, &ctxt->rc_recv_wr, &bad_recv_wr);
+ trace_svcrdma_post_recv(&ctxt->rc_recv_wr, ret);
+ if (ret)
+ goto err_post;
+ return 0;
+
+err_post:
+ svc_rdma_recv_ctxt_put(rdma, ctxt);
+ svc_xprt_put(&rdma->sc_xprt);
+ return ret;
+}
- /* If not all pages were used from the SGL, free the remaining ones */
- len = sge_no;
- while (sge_no < ctxt->count) {
- page = ctxt->pages[sge_no++];
- put_page(page);
+static int svc_rdma_post_recv(struct svcxprt_rdma *rdma)
+{
+ struct svc_rdma_recv_ctxt *ctxt;
+
+ ctxt = svc_rdma_recv_ctxt_get(rdma);
+ if (!ctxt)
+ return -ENOMEM;
+ return __svc_rdma_post_recv(rdma, ctxt);
+}
+
+/**
+ * svc_rdma_post_recvs - Post initial set of Recv WRs
+ * @rdma: fresh svcxprt_rdma
+ *
+ * Returns true if successful, otherwise false.
+ */
+bool svc_rdma_post_recvs(struct svcxprt_rdma *rdma)
+{
+ struct svc_rdma_recv_ctxt *ctxt;
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < rdma->sc_max_requests; i++) {
+ ctxt = svc_rdma_recv_ctxt_get(rdma);
+ if (!ctxt)
+ return false;
+ ctxt->rc_temp = true;
+ ret = __svc_rdma_post_recv(rdma, ctxt);
+ if (ret) {
+ pr_err("svcrdma: failure posting recv buffers: %d\n",
+ ret);
+ return false;
+ }
}
- ctxt->count = len;
+ return true;
+}
- /* Set up tail */
- rqstp->rq_arg.tail[0].iov_base = NULL;
- rqstp->rq_arg.tail[0].iov_len = 0;
+/**
+ * svc_rdma_wc_receive - Invoked by RDMA provider for each polled Receive WC
+ * @cq: Completion Queue context
+ * @wc: Work Completion object
+ *
+ * NB: The svc_xprt/svcxprt_rdma is pinned whenever it's possible that
+ * the Receive completion handler could be running.
+ */
+static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct svcxprt_rdma *rdma = cq->cq_context;
+ struct ib_cqe *cqe = wc->wr_cqe;
+ struct svc_rdma_recv_ctxt *ctxt;
+
+ trace_svcrdma_wc_receive(wc);
+
+ /* WARNING: Only wc->wr_cqe and wc->status are reliable */
+ ctxt = container_of(cqe, struct svc_rdma_recv_ctxt, rc_cqe);
+
+ if (wc->status != IB_WC_SUCCESS)
+ goto flushed;
+
+ if (svc_rdma_post_recv(rdma))
+ goto post_err;
+
+ /* All wc fields are now known to be valid */
+ ctxt->rc_byte_len = wc->byte_len;
+ ib_dma_sync_single_for_cpu(rdma->sc_pd->device,
+ ctxt->rc_recv_sge.addr,
+ wc->byte_len, DMA_FROM_DEVICE);
+
+ spin_lock(&rdma->sc_rq_dto_lock);
+ list_add_tail(&ctxt->rc_list, &rdma->sc_rq_dto_q);
+ spin_unlock(&rdma->sc_rq_dto_lock);
+ set_bit(XPT_DATA, &rdma->sc_xprt.xpt_flags);
+ if (!test_bit(RDMAXPRT_CONN_PENDING, &rdma->sc_flags))
+ svc_xprt_enqueue(&rdma->sc_xprt);
+ goto out;
+
+flushed:
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ pr_err("svcrdma: Recv: %s (%u/0x%x)\n",
+ ib_wc_status_msg(wc->status),
+ wc->status, wc->vendor_err);
+post_err:
+ svc_rdma_recv_ctxt_put(rdma, ctxt);
+ set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
+ svc_xprt_enqueue(&rdma->sc_xprt);
+out:
+ svc_xprt_put(&rdma->sc_xprt);
+}
+
+/**
+ * svc_rdma_flush_recv_queues - Drain pending Receive work
+ * @rdma: svcxprt_rdma being shut down
+ *
+ */
+void svc_rdma_flush_recv_queues(struct svcxprt_rdma *rdma)
+{
+ struct svc_rdma_recv_ctxt *ctxt;
+
+ while ((ctxt = svc_rdma_next_recv_ctxt(&rdma->sc_read_complete_q))) {
+ list_del(&ctxt->rc_list);
+ svc_rdma_recv_ctxt_put(rdma, ctxt);
+ }
+ while ((ctxt = svc_rdma_next_recv_ctxt(&rdma->sc_rq_dto_q))) {
+ list_del(&ctxt->rc_list);
+ svc_rdma_recv_ctxt_put(rdma, ctxt);
+ }
+}
+
+static void svc_rdma_build_arg_xdr(struct svc_rqst *rqstp,
+ struct svc_rdma_recv_ctxt *ctxt)
+{
+ struct xdr_buf *arg = &rqstp->rq_arg;
+
+ arg->head[0].iov_base = ctxt->rc_recv_buf;
+ arg->head[0].iov_len = ctxt->rc_byte_len;
+ arg->tail[0].iov_base = NULL;
+ arg->tail[0].iov_len = 0;
+ arg->page_len = 0;
+ arg->page_base = 0;
+ arg->buflen = ctxt->rc_byte_len;
+ arg->len = ctxt->rc_byte_len;
+
+ rqstp->rq_respages = &rqstp->rq_pages[0];
+ rqstp->rq_next_page = rqstp->rq_respages + 1;
}
/* This accommodates the largest possible Write chunk,
@@ -294,7 +503,6 @@ static int svc_rdma_xdr_decode_req(struct xdr_buf *rq_arg)
{
__be32 *p, *end, *rdma_argp;
unsigned int hdr_len;
- char *proc;
/* Verify that there's enough bytes for header + something */
if (rq_arg->len <= RPCRDMA_HDRLEN_ERR)
@@ -306,10 +514,8 @@ static int svc_rdma_xdr_decode_req(struct xdr_buf *rq_arg)
switch (*(rdma_argp + 3)) {
case rdma_msg:
- proc = "RDMA_MSG";
break;
case rdma_nomsg:
- proc = "RDMA_NOMSG";
break;
case rdma_done:
@@ -339,103 +545,94 @@ static int svc_rdma_xdr_decode_req(struct xdr_buf *rq_arg)
hdr_len = (unsigned long)p - (unsigned long)rdma_argp;
rq_arg->head[0].iov_len -= hdr_len;
rq_arg->len -= hdr_len;
- dprintk("svcrdma: received %s request for XID 0x%08x, hdr_len=%u\n",
- proc, be32_to_cpup(rdma_argp), hdr_len);
+ trace_svcrdma_decode_rqst(rdma_argp, hdr_len);
return hdr_len;
out_short:
- dprintk("svcrdma: header too short = %d\n", rq_arg->len);
+ trace_svcrdma_decode_short(rq_arg->len);
return -EINVAL;
out_version:
- dprintk("svcrdma: bad xprt version: %u\n",
- be32_to_cpup(rdma_argp + 1));
+ trace_svcrdma_decode_badvers(rdma_argp);
return -EPROTONOSUPPORT;
out_drop:
- dprintk("svcrdma: dropping RDMA_DONE/ERROR message\n");
+ trace_svcrdma_decode_drop(rdma_argp);
return 0;
out_proc:
- dprintk("svcrdma: bad rdma procedure (%u)\n",
- be32_to_cpup(rdma_argp + 3));
+ trace_svcrdma_decode_badproc(rdma_argp);
return -EINVAL;
out_inval:
- dprintk("svcrdma: failed to parse transport header\n");
+ trace_svcrdma_decode_parse(rdma_argp);
return -EINVAL;
}
static void rdma_read_complete(struct svc_rqst *rqstp,
- struct svc_rdma_op_ctxt *head)
+ struct svc_rdma_recv_ctxt *head)
{
int page_no;
- /* Copy RPC pages */
- for (page_no = 0; page_no < head->count; page_no++) {
+ /* Move Read chunk pages to rqstp so that they will be released
+ * when svc_process is done with them.
+ */
+ for (page_no = 0; page_no < head->rc_page_count; page_no++) {
put_page(rqstp->rq_pages[page_no]);
- rqstp->rq_pages[page_no] = head->pages[page_no];
+ rqstp->rq_pages[page_no] = head->rc_pages[page_no];
}
+ head->rc_page_count = 0;
/* Point rq_arg.pages past header */
- rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count];
- rqstp->rq_arg.page_len = head->arg.page_len;
+ rqstp->rq_arg.pages = &rqstp->rq_pages[head->rc_hdr_count];
+ rqstp->rq_arg.page_len = head->rc_arg.page_len;
/* rq_respages starts after the last arg page */
rqstp->rq_respages = &rqstp->rq_pages[page_no];
rqstp->rq_next_page = rqstp->rq_respages + 1;
/* Rebuild rq_arg head and tail. */
- rqstp->rq_arg.head[0] = head->arg.head[0];
- rqstp->rq_arg.tail[0] = head->arg.tail[0];
- rqstp->rq_arg.len = head->arg.len;
- rqstp->rq_arg.buflen = head->arg.buflen;
+ rqstp->rq_arg.head[0] = head->rc_arg.head[0];
+ rqstp->rq_arg.tail[0] = head->rc_arg.tail[0];
+ rqstp->rq_arg.len = head->rc_arg.len;
+ rqstp->rq_arg.buflen = head->rc_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;
+ struct svc_rdma_send_ctxt *ctxt;
unsigned int length;
- struct page *page;
+ __be32 *p;
int ret;
- page = alloc_page(GFP_KERNEL);
- if (!page)
+ ctxt = svc_rdma_send_ctxt_get(xprt);
+ if (!ctxt)
return;
- err_msgp = page_address(page);
- p = err_msgp;
+ p = ctxt->sc_xprt_buf;
*p++ = *rdma_argp;
*p++ = *(rdma_argp + 1);
*p++ = xprt->sc_fc_credits;
*p++ = rdma_error;
- if (status == -EPROTONOSUPPORT) {
+ switch (status) {
+ case -EPROTONOSUPPORT:
*p++ = err_vers;
*p++ = rpcrdma_version;
*p++ = rpcrdma_version;
- } else {
+ trace_svcrdma_err_vers(*rdma_argp);
+ break;
+ default:
*p++ = err_chunk;
+ trace_svcrdma_err_chunk(*rdma_argp);
}
- 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;
- }
+ length = (unsigned long)p - (unsigned long)ctxt->sc_xprt_buf;
+ svc_rdma_sync_reply_hdr(xprt, ctxt, length);
- 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);
- }
+ ctxt->sc_send_wr.opcode = IB_WR_SEND;
+ ret = svc_rdma_send(xprt, &ctxt->sc_send_wr);
+ if (ret)
+ svc_rdma_send_ctxt_put(xprt, ctxt);
}
/* By convention, backchannel calls arrive via rdma_msg type
@@ -507,32 +704,28 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
struct svc_xprt *xprt = rqstp->rq_xprt;
struct svcxprt_rdma *rdma_xprt =
container_of(xprt, struct svcxprt_rdma, sc_xprt);
- struct svc_rdma_op_ctxt *ctxt;
+ struct svc_rdma_recv_ctxt *ctxt;
__be32 *p;
int ret;
spin_lock(&rdma_xprt->sc_rq_dto_lock);
- if (!list_empty(&rdma_xprt->sc_read_complete_q)) {
- ctxt = list_first_entry(&rdma_xprt->sc_read_complete_q,
- struct svc_rdma_op_ctxt, list);
- list_del(&ctxt->list);
+ ctxt = svc_rdma_next_recv_ctxt(&rdma_xprt->sc_read_complete_q);
+ if (ctxt) {
+ list_del(&ctxt->rc_list);
spin_unlock(&rdma_xprt->sc_rq_dto_lock);
rdma_read_complete(rqstp, ctxt);
goto complete;
- } else if (!list_empty(&rdma_xprt->sc_rq_dto_q)) {
- ctxt = list_first_entry(&rdma_xprt->sc_rq_dto_q,
- struct svc_rdma_op_ctxt, list);
- list_del(&ctxt->list);
- } else {
+ }
+ ctxt = svc_rdma_next_recv_ctxt(&rdma_xprt->sc_rq_dto_q);
+ if (!ctxt) {
/* No new incoming requests, terminate the loop */
clear_bit(XPT_DATA, &xprt->xpt_flags);
spin_unlock(&rdma_xprt->sc_rq_dto_lock);
return 0;
}
+ list_del(&ctxt->rc_list);
spin_unlock(&rdma_xprt->sc_rq_dto_lock);
- dprintk("svcrdma: recvfrom: ctxt=%p on xprt=%p, rqstp=%p\n",
- ctxt, rdma_xprt, rqstp);
atomic_inc(&rdma_stat_recv);
svc_rdma_build_arg_xdr(rqstp, ctxt);
@@ -548,7 +741,7 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
if (svc_rdma_is_backchannel_reply(xprt, p)) {
ret = svc_rdma_handle_bc_reply(xprt->xpt_bc_xprt, p,
&rqstp->rq_arg);
- svc_rdma_put_context(ctxt, 0);
+ svc_rdma_recv_ctxt_put(rdma_xprt, ctxt);
return ret;
}
@@ -557,9 +750,7 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
goto out_readchunk;
complete:
- svc_rdma_put_context(ctxt, 0);
- dprintk("svcrdma: recvfrom: xprt=%p, rqstp=%p, rq_arg.len=%u\n",
- rdma_xprt, rqstp, rqstp->rq_arg.len);
+ rqstp->rq_xprt_ctxt = ctxt;
rqstp->rq_prot = IPPROTO_MAX;
svc_xprt_copy_addrs(rqstp, xprt);
return rqstp->rq_arg.len;
@@ -572,16 +763,16 @@ out_readchunk:
out_err:
svc_rdma_send_error(rdma_xprt, p, ret);
- svc_rdma_put_context(ctxt, 0);
+ svc_rdma_recv_ctxt_put(rdma_xprt, ctxt);
return 0;
out_postfail:
if (ret == -EINVAL)
svc_rdma_send_error(rdma_xprt, p, ret);
- svc_rdma_put_context(ctxt, 1);
+ svc_rdma_recv_ctxt_put(rdma_xprt, ctxt);
return ret;
out_drop:
- svc_rdma_put_context(ctxt, 1);
+ svc_rdma_recv_ctxt_put(rdma_xprt, ctxt);
return 0;
}
diff --git a/net/sunrpc/xprtrdma/svc_rdma_rw.c b/net/sunrpc/xprtrdma/svc_rdma_rw.c
index 12b9a7e..ce3ea84 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_rw.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_rw.c
@@ -1,15 +1,18 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (c) 2016 Oracle. All rights reserved.
+ * Copyright (c) 2016-2018 Oracle. All rights reserved.
*
* Use the core R/W API to move RPC-over-RDMA Read and Write chunks.
*/
+#include <rdma/rw.h>
+
#include <linux/sunrpc/rpc_rdma.h>
#include <linux/sunrpc/svc_rdma.h>
#include <linux/sunrpc/debug.h>
-#include <rdma/rw.h>
+#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
@@ -205,6 +208,8 @@ static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
struct svc_rdma_write_info *info =
container_of(cc, struct svc_rdma_write_info, wi_cc);
+ trace_svcrdma_wc_write(wc);
+
atomic_add(cc->cc_sqecount, &rdma->sc_sq_avail);
wake_up(&rdma->sc_send_wait);
@@ -222,7 +227,7 @@ static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
/* State for pulling a Read chunk.
*/
struct svc_rdma_read_info {
- struct svc_rdma_op_ctxt *ri_readctxt;
+ struct svc_rdma_recv_ctxt *ri_readctxt;
unsigned int ri_position;
unsigned int ri_pageno;
unsigned int ri_pageoff;
@@ -266,6 +271,8 @@ static void svc_rdma_wc_read_done(struct ib_cq *cq, struct ib_wc *wc)
struct svc_rdma_read_info *info =
container_of(cc, struct svc_rdma_read_info, ri_cc);
+ trace_svcrdma_wc_read(wc);
+
atomic_add(cc->cc_sqecount, &rdma->sc_sq_avail);
wake_up(&rdma->sc_send_wait);
@@ -275,10 +282,10 @@ static void svc_rdma_wc_read_done(struct ib_cq *cq, struct ib_wc *wc)
pr_err("svcrdma: read ctx: %s (%u/0x%x)\n",
ib_wc_status_msg(wc->status),
wc->status, wc->vendor_err);
- svc_rdma_put_context(info->ri_readctxt, 1);
+ svc_rdma_recv_ctxt_put(rdma, info->ri_readctxt);
} else {
spin_lock(&rdma->sc_rq_dto_lock);
- list_add_tail(&info->ri_readctxt->list,
+ list_add_tail(&info->ri_readctxt->rc_list,
&rdma->sc_read_complete_q);
spin_unlock(&rdma->sc_rq_dto_lock);
@@ -323,18 +330,20 @@ static int svc_rdma_post_chunk_ctxt(struct svc_rdma_chunk_ctxt *cc)
if (atomic_sub_return(cc->cc_sqecount,
&rdma->sc_sq_avail) > 0) {
ret = ib_post_send(rdma->sc_qp, first_wr, &bad_wr);
+ trace_svcrdma_post_rw(&cc->cc_cqe,
+ cc->cc_sqecount, ret);
if (ret)
break;
return 0;
}
- atomic_inc(&rdma_stat_sq_starve);
+ trace_svcrdma_sq_full(rdma);
atomic_add(cc->cc_sqecount, &rdma->sc_sq_avail);
wait_event(rdma->sc_send_wait,
atomic_read(&rdma->sc_sq_avail) > cc->cc_sqecount);
+ trace_svcrdma_sq_retry(rdma);
} 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. */
@@ -437,6 +446,7 @@ svc_rdma_build_writes(struct svc_rdma_write_info *info,
if (ret < 0)
goto out_initerr;
+ trace_svcrdma_encode_wseg(seg_handle, write_len, seg_offset);
list_add(&ctxt->rw_list, &cc->cc_rwctxts);
cc->cc_sqecount += ret;
if (write_len == seg_length - info->wi_seg_off) {
@@ -462,7 +472,7 @@ out_noctx:
out_initerr:
svc_rdma_put_rw_ctxt(rdma, ctxt);
- pr_err("svcrdma: failed to map pagelist (%d)\n", ret);
+ trace_svcrdma_dma_map_rwctx(rdma, ret);
return -EIO;
}
@@ -526,6 +536,8 @@ int svc_rdma_send_write_chunk(struct svcxprt_rdma *rdma, __be32 *wr_ch,
ret = svc_rdma_post_chunk_ctxt(&info->wi_cc);
if (ret < 0)
goto out_err;
+
+ trace_svcrdma_encode_write(xdr->page_len);
return xdr->page_len;
out_err:
@@ -582,6 +594,8 @@ int svc_rdma_send_reply_chunk(struct svcxprt_rdma *rdma, __be32 *rp_ch,
ret = svc_rdma_post_chunk_ctxt(&info->wi_cc);
if (ret < 0)
goto out_err;
+
+ trace_svcrdma_encode_reply(consumed);
return consumed;
out_err:
@@ -593,7 +607,7 @@ static int svc_rdma_build_read_segment(struct svc_rdma_read_info *info,
struct svc_rqst *rqstp,
u32 rkey, u32 len, u64 offset)
{
- struct svc_rdma_op_ctxt *head = info->ri_readctxt;
+ struct svc_rdma_recv_ctxt *head = info->ri_readctxt;
struct svc_rdma_chunk_ctxt *cc = &info->ri_cc;
struct svc_rdma_rw_ctxt *ctxt;
unsigned int sge_no, seg_len;
@@ -606,18 +620,15 @@ static int svc_rdma_build_read_segment(struct svc_rdma_read_info *info,
goto out_noctx;
ctxt->rw_nents = sge_no;
- dprintk("svcrdma: reading segment %u@0x%016llx:0x%08x (%u sges)\n",
- len, offset, rkey, sge_no);
-
sg = ctxt->rw_sg_table.sgl;
for (sge_no = 0; sge_no < ctxt->rw_nents; sge_no++) {
seg_len = min_t(unsigned int, len,
PAGE_SIZE - info->ri_pageoff);
- head->arg.pages[info->ri_pageno] =
+ head->rc_arg.pages[info->ri_pageno] =
rqstp->rq_pages[info->ri_pageno];
if (!info->ri_pageoff)
- head->count++;
+ head->rc_page_count++;
sg_set_page(sg, rqstp->rq_pages[info->ri_pageno],
seg_len, info->ri_pageoff);
@@ -656,8 +667,8 @@ out_overrun:
return -EINVAL;
out_initerr:
+ trace_svcrdma_dma_map_rwctx(cc->cc_rdma, ret);
svc_rdma_put_rw_ctxt(cc->cc_rdma, ctxt);
- pr_err("svcrdma: failed to map pagelist (%d)\n", ret);
return -EIO;
}
@@ -686,6 +697,7 @@ static int svc_rdma_build_read_chunk(struct svc_rqst *rqstp,
if (ret < 0)
break;
+ trace_svcrdma_encode_rseg(rs_handle, rs_length, rs_offset);
info->ri_chunklen += rs_length;
}
@@ -693,9 +705,9 @@ static int svc_rdma_build_read_chunk(struct svc_rqst *rqstp,
}
/* Construct RDMA Reads to pull over a normal Read chunk. The chunk
- * data lands in the page list of head->arg.pages.
+ * data lands in the page list of head->rc_arg.pages.
*
- * Currently NFSD does not look at the head->arg.tail[0] iovec.
+ * Currently NFSD does not look at the head->rc_arg.tail[0] iovec.
* Therefore, XDR round-up of the Read chunk and trailing
* inline content must both be added at the end of the pagelist.
*/
@@ -703,29 +715,27 @@ static int svc_rdma_build_normal_read_chunk(struct svc_rqst *rqstp,
struct svc_rdma_read_info *info,
__be32 *p)
{
- struct svc_rdma_op_ctxt *head = info->ri_readctxt;
+ struct svc_rdma_recv_ctxt *head = info->ri_readctxt;
int ret;
- dprintk("svcrdma: Reading Read chunk at position %u\n",
- info->ri_position);
-
- info->ri_pageno = head->hdr_count;
- info->ri_pageoff = 0;
-
ret = svc_rdma_build_read_chunk(rqstp, info, p);
if (ret < 0)
goto out;
+ trace_svcrdma_encode_read(info->ri_chunklen, info->ri_position);
+
+ head->rc_hdr_count = 0;
+
/* Split the Receive buffer between the head and tail
* buffers at Read chunk's position. XDR roundup of the
* chunk is not included in either the pagelist or in
* the tail.
*/
- head->arg.tail[0].iov_base =
- head->arg.head[0].iov_base + info->ri_position;
- head->arg.tail[0].iov_len =
- head->arg.head[0].iov_len - info->ri_position;
- head->arg.head[0].iov_len = info->ri_position;
+ head->rc_arg.tail[0].iov_base =
+ head->rc_arg.head[0].iov_base + info->ri_position;
+ head->rc_arg.tail[0].iov_len =
+ head->rc_arg.head[0].iov_len - info->ri_position;
+ head->rc_arg.head[0].iov_len = info->ri_position;
/* Read chunk may need XDR roundup (see RFC 8166, s. 3.4.5.2).
*
@@ -738,9 +748,9 @@ static int svc_rdma_build_normal_read_chunk(struct svc_rqst *rqstp,
*/
info->ri_chunklen = XDR_QUADLEN(info->ri_chunklen) << 2;
- head->arg.page_len = info->ri_chunklen;
- head->arg.len += info->ri_chunklen;
- head->arg.buflen += info->ri_chunklen;
+ head->rc_arg.page_len = info->ri_chunklen;
+ head->rc_arg.len += info->ri_chunklen;
+ head->rc_arg.buflen += info->ri_chunklen;
out:
return ret;
@@ -749,7 +759,7 @@ out:
/* Construct RDMA Reads to pull over a Position Zero Read chunk.
* The start of the data lands in the first page just after
* the Transport header, and the rest lands in the page list of
- * head->arg.pages.
+ * head->rc_arg.pages.
*
* Assumptions:
* - A PZRC has an XDR-aligned length (no implicit round-up).
@@ -761,35 +771,25 @@ static int svc_rdma_build_pz_read_chunk(struct svc_rqst *rqstp,
struct svc_rdma_read_info *info,
__be32 *p)
{
- struct svc_rdma_op_ctxt *head = info->ri_readctxt;
+ struct svc_rdma_recv_ctxt *head = info->ri_readctxt;
int ret;
- dprintk("svcrdma: Reading Position Zero Read chunk\n");
-
- info->ri_pageno = head->hdr_count - 1;
- info->ri_pageoff = offset_in_page(head->byte_len);
-
ret = svc_rdma_build_read_chunk(rqstp, info, p);
if (ret < 0)
goto out;
- head->arg.len += info->ri_chunklen;
- head->arg.buflen += info->ri_chunklen;
+ trace_svcrdma_encode_pzr(info->ri_chunklen);
- if (head->arg.buflen <= head->sge[0].length) {
- /* Transport header and RPC message fit entirely
- * in page where head iovec resides.
- */
- head->arg.head[0].iov_len = info->ri_chunklen;
- } else {
- /* Transport header and part of RPC message reside
- * in the head iovec's page.
- */
- head->arg.head[0].iov_len =
- head->sge[0].length - head->byte_len;
- head->arg.page_len =
- info->ri_chunklen - head->arg.head[0].iov_len;
- }
+ head->rc_arg.len += info->ri_chunklen;
+ head->rc_arg.buflen += info->ri_chunklen;
+
+ head->rc_hdr_count = 1;
+ head->rc_arg.head[0].iov_base = page_address(head->rc_pages[0]);
+ head->rc_arg.head[0].iov_len = min_t(size_t, PAGE_SIZE,
+ info->ri_chunklen);
+
+ head->rc_arg.page_len = info->ri_chunklen -
+ head->rc_arg.head[0].iov_len;
out:
return ret;
@@ -813,29 +813,30 @@ out:
* - All Read segments in @p have the same Position value.
*/
int svc_rdma_recv_read_chunk(struct svcxprt_rdma *rdma, struct svc_rqst *rqstp,
- struct svc_rdma_op_ctxt *head, __be32 *p)
+ struct svc_rdma_recv_ctxt *head, __be32 *p)
{
struct svc_rdma_read_info *info;
struct page **page;
int ret;
/* The request (with page list) is constructed in
- * head->arg. Pages involved with RDMA Read I/O are
+ * head->rc_arg. Pages involved with RDMA Read I/O are
* transferred there.
*/
- head->hdr_count = head->count;
- head->arg.head[0] = rqstp->rq_arg.head[0];
- head->arg.tail[0] = rqstp->rq_arg.tail[0];
- head->arg.pages = head->pages;
- head->arg.page_base = 0;
- head->arg.page_len = 0;
- head->arg.len = rqstp->rq_arg.len;
- head->arg.buflen = rqstp->rq_arg.buflen;
+ head->rc_arg.head[0] = rqstp->rq_arg.head[0];
+ head->rc_arg.tail[0] = rqstp->rq_arg.tail[0];
+ head->rc_arg.pages = head->rc_pages;
+ head->rc_arg.page_base = 0;
+ head->rc_arg.page_len = 0;
+ head->rc_arg.len = rqstp->rq_arg.len;
+ head->rc_arg.buflen = rqstp->rq_arg.buflen;
info = svc_rdma_read_info_alloc(rdma);
if (!info)
return -ENOMEM;
info->ri_readctxt = head;
+ info->ri_pageno = 0;
+ info->ri_pageoff = 0;
info->ri_position = be32_to_cpup(p + 1);
if (info->ri_position)
@@ -856,7 +857,7 @@ int svc_rdma_recv_read_chunk(struct svcxprt_rdma *rdma, struct svc_rqst *rqstp,
out:
/* Read sink pages have been moved from rqstp->rq_pages to
- * head->arg.pages. Force svc_recv to refill those slots
+ * head->rc_arg.pages. Force svc_recv to refill those slots
* in rq_pages.
*/
for (page = rqstp->rq_pages; page < rqstp->rq_respages; page++)
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index 649441d..4a3efae 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -1,5 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (c) 2016 Oracle. All rights reserved.
+ * Copyright (c) 2016-2018 Oracle. All rights reserved.
* Copyright (c) 2014 Open Grid Computing, Inc. All rights reserved.
* Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved.
*
@@ -74,11 +75,11 @@
* 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.
+ * When the Send WR is constructed, it also gets its own svc_rdma_send_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
+ * The svc_rdma_send_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
@@ -98,16 +99,230 @@
* 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>
#include <asm/unaligned.h>
+
#include <rdma/ib_verbs.h>
#include <rdma/rdma_cm.h>
+
+#include <linux/sunrpc/debug.h>
+#include <linux/sunrpc/rpc_rdma.h>
#include <linux/sunrpc/svc_rdma.h>
+#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
+
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
+static void svc_rdma_wc_send(struct ib_cq *cq, struct ib_wc *wc);
+
+static inline struct svc_rdma_send_ctxt *
+svc_rdma_next_send_ctxt(struct list_head *list)
+{
+ return list_first_entry_or_null(list, struct svc_rdma_send_ctxt,
+ sc_list);
+}
+
+static struct svc_rdma_send_ctxt *
+svc_rdma_send_ctxt_alloc(struct svcxprt_rdma *rdma)
+{
+ struct svc_rdma_send_ctxt *ctxt;
+ dma_addr_t addr;
+ void *buffer;
+ size_t size;
+ int i;
+
+ size = sizeof(*ctxt);
+ size += rdma->sc_max_send_sges * sizeof(struct ib_sge);
+ ctxt = kmalloc(size, GFP_KERNEL);
+ if (!ctxt)
+ goto fail0;
+ buffer = kmalloc(rdma->sc_max_req_size, GFP_KERNEL);
+ if (!buffer)
+ goto fail1;
+ addr = ib_dma_map_single(rdma->sc_pd->device, buffer,
+ rdma->sc_max_req_size, DMA_TO_DEVICE);
+ if (ib_dma_mapping_error(rdma->sc_pd->device, addr))
+ goto fail2;
+
+ ctxt->sc_send_wr.next = NULL;
+ ctxt->sc_send_wr.wr_cqe = &ctxt->sc_cqe;
+ ctxt->sc_send_wr.sg_list = ctxt->sc_sges;
+ ctxt->sc_send_wr.send_flags = IB_SEND_SIGNALED;
+ ctxt->sc_cqe.done = svc_rdma_wc_send;
+ ctxt->sc_xprt_buf = buffer;
+ ctxt->sc_sges[0].addr = addr;
+
+ for (i = 0; i < rdma->sc_max_send_sges; i++)
+ ctxt->sc_sges[i].lkey = rdma->sc_pd->local_dma_lkey;
+ return ctxt;
+
+fail2:
+ kfree(buffer);
+fail1:
+ kfree(ctxt);
+fail0:
+ return NULL;
+}
+
+/**
+ * svc_rdma_send_ctxts_destroy - Release all send_ctxt's for an xprt
+ * @rdma: svcxprt_rdma being torn down
+ *
+ */
+void svc_rdma_send_ctxts_destroy(struct svcxprt_rdma *rdma)
+{
+ struct svc_rdma_send_ctxt *ctxt;
+
+ while ((ctxt = svc_rdma_next_send_ctxt(&rdma->sc_send_ctxts))) {
+ list_del(&ctxt->sc_list);
+ ib_dma_unmap_single(rdma->sc_pd->device,
+ ctxt->sc_sges[0].addr,
+ rdma->sc_max_req_size,
+ DMA_TO_DEVICE);
+ kfree(ctxt->sc_xprt_buf);
+ kfree(ctxt);
+ }
+}
+
+/**
+ * svc_rdma_send_ctxt_get - Get a free send_ctxt
+ * @rdma: controlling svcxprt_rdma
+ *
+ * Returns a ready-to-use send_ctxt, or NULL if none are
+ * available and a fresh one cannot be allocated.
+ */
+struct svc_rdma_send_ctxt *svc_rdma_send_ctxt_get(struct svcxprt_rdma *rdma)
+{
+ struct svc_rdma_send_ctxt *ctxt;
+
+ spin_lock(&rdma->sc_send_lock);
+ ctxt = svc_rdma_next_send_ctxt(&rdma->sc_send_ctxts);
+ if (!ctxt)
+ goto out_empty;
+ list_del(&ctxt->sc_list);
+ spin_unlock(&rdma->sc_send_lock);
+
+out:
+ ctxt->sc_send_wr.num_sge = 0;
+ ctxt->sc_cur_sge_no = 0;
+ ctxt->sc_page_count = 0;
+ return ctxt;
+
+out_empty:
+ spin_unlock(&rdma->sc_send_lock);
+ ctxt = svc_rdma_send_ctxt_alloc(rdma);
+ if (!ctxt)
+ return NULL;
+ goto out;
+}
+
+/**
+ * svc_rdma_send_ctxt_put - Return send_ctxt to free list
+ * @rdma: controlling svcxprt_rdma
+ * @ctxt: object to return to the free list
+ *
+ * Pages left in sc_pages are DMA unmapped and released.
+ */
+void svc_rdma_send_ctxt_put(struct svcxprt_rdma *rdma,
+ struct svc_rdma_send_ctxt *ctxt)
+{
+ struct ib_device *device = rdma->sc_cm_id->device;
+ unsigned int i;
+
+ /* The first SGE contains the transport header, which
+ * remains mapped until @ctxt is destroyed.
+ */
+ for (i = 1; i < ctxt->sc_send_wr.num_sge; i++)
+ ib_dma_unmap_page(device,
+ ctxt->sc_sges[i].addr,
+ ctxt->sc_sges[i].length,
+ DMA_TO_DEVICE);
+
+ for (i = 0; i < ctxt->sc_page_count; ++i)
+ put_page(ctxt->sc_pages[i]);
+
+ spin_lock(&rdma->sc_send_lock);
+ list_add(&ctxt->sc_list, &rdma->sc_send_ctxts);
+ spin_unlock(&rdma->sc_send_lock);
+}
+
+/**
+ * svc_rdma_wc_send - Invoked by RDMA provider for each polled Send WC
+ * @cq: Completion Queue context
+ * @wc: Work Completion object
+ *
+ * NB: The svc_xprt/svcxprt_rdma is pinned whenever it's possible that
+ * the Send completion handler could be running.
+ */
+static void svc_rdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
+{
+ struct svcxprt_rdma *rdma = cq->cq_context;
+ struct ib_cqe *cqe = wc->wr_cqe;
+ struct svc_rdma_send_ctxt *ctxt;
+
+ trace_svcrdma_wc_send(wc);
+
+ atomic_inc(&rdma->sc_sq_avail);
+ wake_up(&rdma->sc_send_wait);
+
+ ctxt = container_of(cqe, struct svc_rdma_send_ctxt, sc_cqe);
+ svc_rdma_send_ctxt_put(rdma, ctxt);
+
+ if (unlikely(wc->status != IB_WC_SUCCESS)) {
+ set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
+ svc_xprt_enqueue(&rdma->sc_xprt);
+ if (wc->status != IB_WC_WR_FLUSH_ERR)
+ pr_err("svcrdma: Send: %s (%u/0x%x)\n",
+ ib_wc_status_msg(wc->status),
+ wc->status, wc->vendor_err);
+ }
+
+ svc_xprt_put(&rdma->sc_xprt);
+}
+
+/**
+ * svc_rdma_send - Post a single Send WR
+ * @rdma: transport on which to post the WR
+ * @wr: prepared Send WR to post
+ *
+ * Returns zero the Send WR was posted successfully. Otherwise, a
+ * negative errno is returned.
+ */
+int svc_rdma_send(struct svcxprt_rdma *rdma, struct ib_send_wr *wr)
+{
+ struct ib_send_wr *bad_wr;
+ int ret;
+
+ might_sleep();
+
+ /* If the SQ is full, wait until an SQ entry is available */
+ while (1) {
+ if ((atomic_dec_return(&rdma->sc_sq_avail) < 0)) {
+ atomic_inc(&rdma_stat_sq_starve);
+ trace_svcrdma_sq_full(rdma);
+ atomic_inc(&rdma->sc_sq_avail);
+ wait_event(rdma->sc_send_wait,
+ atomic_read(&rdma->sc_sq_avail) > 1);
+ if (test_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags))
+ return -ENOTCONN;
+ trace_svcrdma_sq_retry(rdma);
+ continue;
+ }
+
+ svc_xprt_get(&rdma->sc_xprt);
+ ret = ib_post_send(rdma->sc_qp, wr, &bad_wr);
+ trace_svcrdma_post_send(wr, ret);
+ if (ret) {
+ set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
+ svc_xprt_put(&rdma->sc_xprt);
+ wake_up(&rdma->sc_send_wait);
+ }
+ break;
+ }
+ return ret;
+}
+
static u32 xdr_padsize(u32 len)
{
return (len & 3) ? (4 - (len & 3)) : 0;
@@ -296,41 +511,10 @@ static u32 svc_rdma_get_inv_rkey(__be32 *rdma_argp,
return be32_to_cpup(p);
}
-/* 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;
-
- dma_addr = ib_dma_map_page(dev, virt_to_page(base),
- offset, len, DMA_TO_DEVICE);
- if (ib_dma_mapping_error(dev, dma_addr))
- goto out_maperr;
-
- 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;
-
-out_maperr:
- pr_err("svcrdma: failed to map buffer\n");
- return -EIO;
-}
-
static int svc_rdma_dma_map_page(struct svcxprt_rdma *rdma,
- struct svc_rdma_op_ctxt *ctxt,
- unsigned int sge_no,
+ struct svc_rdma_send_ctxt *ctxt,
struct page *page,
- unsigned int offset,
+ unsigned long offset,
unsigned int len)
{
struct ib_device *dev = rdma->sc_cm_id->device;
@@ -340,58 +524,71 @@ static int svc_rdma_dma_map_page(struct svcxprt_rdma *rdma,
if (ib_dma_mapping_error(dev, dma_addr))
goto out_maperr;
- 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);
+ ctxt->sc_sges[ctxt->sc_cur_sge_no].addr = dma_addr;
+ ctxt->sc_sges[ctxt->sc_cur_sge_no].length = len;
+ ctxt->sc_send_wr.num_sge++;
return 0;
out_maperr:
- pr_err("svcrdma: failed to map page\n");
+ trace_svcrdma_dma_map_page(rdma, page);
return -EIO;
}
+/* ib_dma_map_page() is used here because svc_rdma_dma_unmap()
+ * handles DMA-unmap and it uses ib_dma_unmap_page() exclusively.
+ */
+static int svc_rdma_dma_map_buf(struct svcxprt_rdma *rdma,
+ struct svc_rdma_send_ctxt *ctxt,
+ unsigned char *base,
+ unsigned int len)
+{
+ return svc_rdma_dma_map_page(rdma, ctxt, virt_to_page(base),
+ offset_in_page(base), len);
+}
+
/**
- * svc_rdma_map_reply_hdr - DMA map the transport header buffer
+ * svc_rdma_sync_reply_hdr - DMA sync the transport header buffer
* @rdma: controlling transport
- * @ctxt: op_ctxt for the Send WR
- * @rdma_resp: buffer containing transport header
+ * @ctxt: send_ctxt for the Send WR
* @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)
+void svc_rdma_sync_reply_hdr(struct svcxprt_rdma *rdma,
+ struct svc_rdma_send_ctxt *ctxt,
+ unsigned int len)
{
- ctxt->direction = DMA_TO_DEVICE;
- 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);
+ ctxt->sc_sges[0].length = len;
+ ctxt->sc_send_wr.num_sge++;
+ ib_dma_sync_single_for_device(rdma->sc_pd->device,
+ ctxt->sc_sges[0].addr, len,
+ DMA_TO_DEVICE);
}
-/* Load the xdr_buf into the ctxt's sge array, and DMA map each
+/* svc_rdma_map_reply_msg - Map the buffer holding RPC message
+ * @rdma: controlling transport
+ * @ctxt: send_ctxt for the Send WR
+ * @xdr: prepared xdr_buf containing RPC message
+ * @wr_lst: pointer to Call header's Write list, or NULL
+ *
+ * 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.
+ * Returns zero 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)
+int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
+ struct svc_rdma_send_ctxt *ctxt,
+ struct xdr_buf *xdr, __be32 *wr_lst)
{
- unsigned int len, sge_no, remaining, page_off;
+ unsigned int len, remaining;
+ unsigned long page_off;
struct page **ppages;
unsigned char *base;
u32 xdr_pad;
int ret;
- sge_no = 1;
-
- ret = svc_rdma_dma_map_buf(rdma, ctxt, sge_no++,
+ if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
+ return -EIO;
+ ret = svc_rdma_dma_map_buf(rdma, ctxt,
xdr->head[0].iov_base,
xdr->head[0].iov_len);
if (ret < 0)
@@ -421,8 +618,10 @@ static int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
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 (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
+ return -EIO;
+ ret = svc_rdma_dma_map_page(rdma, ctxt, *ppages++,
+ page_off, len);
if (ret < 0)
return ret;
@@ -434,12 +633,14 @@ static int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
len = xdr->tail[0].iov_len;
tail:
if (len) {
- ret = svc_rdma_dma_map_buf(rdma, ctxt, sge_no++, base, len);
+ if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
+ return -EIO;
+ ret = svc_rdma_dma_map_buf(rdma, ctxt, base, len);
if (ret < 0)
return ret;
}
- return sge_no - 1;
+ return 0;
}
/* The svc_rqst and all resources it owns are released as soon as
@@ -447,62 +648,25 @@ tail:
* 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)
+ struct svc_rdma_send_ctxt *ctxt)
{
int i, pages = rqstp->rq_next_page - rqstp->rq_respages;
- ctxt->count += pages;
+ ctxt->sc_page_count += pages;
for (i = 0; i < pages; i++) {
- ctxt->pages[i + 1] = rqstp->rq_respages[i];
+ ctxt->sc_pages[i] = rqstp->rq_respages[i];
rqstp->rq_respages[i] = NULL;
}
rqstp->rq_next_page = rqstp->rq_respages + 1;
}
-/**
- * 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;
-
- 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);
-}
-
/* 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.
+ * in sc_sges[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
+ * In the latter case, only the transport header (sc_sges[0]) is
* transmitted.
*
* RDMA Send is the last step of transmitting an RPC reply. Pages
@@ -515,49 +679,32 @@ int svc_rdma_post_send_wr(struct svcxprt_rdma *rdma,
* - The Reply's transport header will never be larger than a page.
*/
static int svc_rdma_send_reply_msg(struct svcxprt_rdma *rdma,
- __be32 *rdma_argp, __be32 *rdma_resp,
+ struct svc_rdma_send_ctxt *ctxt,
+ __be32 *rdma_argp,
struct svc_rqst *rqstp,
__be32 *wr_lst, __be32 *rp_ch)
{
- struct svc_rdma_op_ctxt *ctxt;
- 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);
-
- ret = svc_rdma_map_reply_hdr(rdma, ctxt, rdma_resp,
- svc_rdma_reply_hdr_len(rdma_resp));
- if (ret < 0)
- goto err;
-
if (!rp_ch) {
ret = svc_rdma_map_reply_msg(rdma, ctxt,
&rqstp->rq_res, wr_lst);
if (ret < 0)
- goto err;
+ return ret;
}
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;
-
- return 0;
-
-err:
- svc_rdma_unmap_dma(ctxt);
- svc_rdma_put_context(ctxt, 1);
- return ret;
+ ctxt->sc_send_wr.opcode = IB_WR_SEND;
+ if (rdma->sc_snd_w_inv) {
+ ctxt->sc_send_wr.ex.invalidate_rkey =
+ svc_rdma_get_inv_rkey(rdma_argp, wr_lst, rp_ch);
+ if (ctxt->sc_send_wr.ex.invalidate_rkey)
+ ctxt->sc_send_wr.opcode = IB_WR_SEND_WITH_INV;
+ }
+ dprintk("svcrdma: posting Send WR with %u sge(s)\n",
+ ctxt->sc_send_wr.num_sge);
+ return svc_rdma_send(rdma, &ctxt->sc_send_wr);
}
/* Given the client-provided Write and Reply chunks, the server was not
@@ -568,38 +715,29 @@ err:
* 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_send_ctxt *ctxt,
+ 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.
- */
- p = rdma_resp + 3;
+ p = ctxt->sc_xprt_buf;
+ trace_svcrdma_err_chunk(*p);
+ p += 3;
*p++ = rdma_error;
*p = err_chunk;
-
- ret = svc_rdma_map_reply_hdr(rdma, ctxt, rdma_resp, 20);
- if (ret < 0)
- goto err;
+ svc_rdma_sync_reply_hdr(rdma, ctxt, RPCRDMA_HDRLEN_ERR);
svc_rdma_save_io_pages(rqstp, ctxt);
- ret = svc_rdma_post_send_wr(rdma, ctxt, 1 + ret, 0);
- if (ret)
- goto err;
+ ctxt->sc_send_wr.opcode = IB_WR_SEND;
+ ret = svc_rdma_send(rdma, &ctxt->sc_send_wr);
+ if (ret) {
+ svc_rdma_send_ctxt_put(rdma, ctxt);
+ return ret;
+ }
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;
}
void svc_rdma_prep_reply_hdr(struct svc_rqst *rqstp)
@@ -623,20 +761,15 @@ 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 svc_rdma_recv_ctxt *rctxt = rqstp->rq_xprt_ctxt;
__be32 *p, *rdma_argp, *rdma_resp, *wr_lst, *rp_ch;
struct xdr_buf *xdr = &rqstp->rq_res;
- struct page *res_page;
+ struct svc_rdma_send_ctxt *sctxt;
int ret;
- /* 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]);
+ rdma_argp = rctxt->rc_recv_buf;
svc_rdma_get_write_arrays(rdma_argp, &wr_lst, &rp_ch);
- 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
* code path below that inserts the credit grant value
@@ -644,10 +777,10 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
* critical section.
*/
ret = -ENOMEM;
- res_page = alloc_page(GFP_KERNEL);
- if (!res_page)
+ sctxt = svc_rdma_send_ctxt_get(rdma);
+ if (!sctxt)
goto err0;
- rdma_resp = page_address(res_page);
+ rdma_resp = sctxt->sc_xprt_buf;
p = rdma_resp;
*p++ = *rdma_argp;
@@ -674,26 +807,33 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
svc_rdma_xdr_encode_reply_chunk(rdma_resp, rp_ch, ret);
}
- ret = svc_rdma_send_reply_msg(rdma, rdma_argp, rdma_resp, rqstp,
+ svc_rdma_sync_reply_hdr(rdma, sctxt, svc_rdma_reply_hdr_len(rdma_resp));
+ ret = svc_rdma_send_reply_msg(rdma, sctxt, rdma_argp, rqstp,
wr_lst, rp_ch);
if (ret < 0)
- goto err0;
- return 0;
+ goto err1;
+ ret = 0;
+
+out:
+ rqstp->rq_xprt_ctxt = NULL;
+ svc_rdma_recv_ctxt_put(rdma, rctxt);
+ return ret;
err2:
if (ret != -E2BIG && ret != -EINVAL)
goto err1;
- ret = svc_rdma_send_error_msg(rdma, rdma_resp, rqstp);
+ ret = svc_rdma_send_error_msg(rdma, sctxt, rqstp);
if (ret < 0)
- goto err0;
- return 0;
+ goto err1;
+ ret = 0;
+ goto out;
err1:
- put_page(res_page);
+ svc_rdma_send_ctxt_put(rdma, sctxt);
err0:
- pr_err("svcrdma: Could not send reply, err=%d. Closing transport.\n",
- ret);
+ trace_svcrdma_send_failed(rqstp, ret);
set_bit(XPT_CLOSE, &xprt->xpt_flags);
- return -ENOTCONN;
+ ret = -ENOTCONN;
+ goto out;
}
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index 96cc8f6..e9535a6 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -1,4 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
+ * Copyright (c) 2015-2018 Oracle. All rights reserved.
* Copyright (c) 2014 Open Grid Computing, Inc. All rights reserved.
* Copyright (c) 2005-2007 Network Appliance, Inc. All rights reserved.
*
@@ -40,26 +42,30 @@
* Author: Tom Tucker <tom@opengridcomputing.com>
*/
-#include <linux/sunrpc/svc_xprt.h>
-#include <linux/sunrpc/addr.h>
-#include <linux/sunrpc/debug.h>
-#include <linux/sunrpc/rpc_rdma.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
+#include <linux/export.h>
+
#include <rdma/ib_verbs.h>
#include <rdma/rdma_cm.h>
#include <rdma/rw.h>
+
+#include <linux/sunrpc/addr.h>
+#include <linux/sunrpc/debug.h>
+#include <linux/sunrpc/rpc_rdma.h>
+#include <linux/sunrpc/svc_xprt.h>
#include <linux/sunrpc/svc_rdma.h>
-#include <linux/export.h>
+
#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
#define RPCDBG_FACILITY RPCDBG_SVCXPRT
-static int svc_rdma_post_recv(struct svcxprt_rdma *xprt);
-static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *, int);
+static struct svcxprt_rdma *svc_rdma_create_xprt(struct svc_serv *serv,
+ struct net *net);
static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
struct net *net,
struct sockaddr *sa, int salen,
@@ -123,7 +129,7 @@ static struct svc_xprt *svc_rdma_bc_create(struct svc_serv *serv,
struct svcxprt_rdma *cma_xprt;
struct svc_xprt *xprt;
- cma_xprt = rdma_create_xprt(serv, 0);
+ cma_xprt = svc_rdma_create_xprt(serv, net);
if (!cma_xprt)
return ERR_PTR(-ENOMEM);
xprt = &cma_xprt->sc_xprt;
@@ -152,133 +158,20 @@ static void svc_rdma_bc_free(struct svc_xprt *xprt)
}
#endif /* CONFIG_SUNRPC_BACKCHANNEL */
-static struct svc_rdma_op_ctxt *alloc_ctxt(struct svcxprt_rdma *xprt,
- gfp_t flags)
-{
- struct svc_rdma_op_ctxt *ctxt;
-
- ctxt = kmalloc(sizeof(*ctxt), flags);
- if (ctxt) {
- ctxt->xprt = xprt;
- INIT_LIST_HEAD(&ctxt->list);
- }
- return ctxt;
-}
-
-static bool svc_rdma_prealloc_ctxts(struct svcxprt_rdma *xprt)
-{
- unsigned int i;
-
- /* Each RPC/RDMA credit can consume one Receive and
- * one Send WQE at the same time.
- */
- i = xprt->sc_sq_depth + xprt->sc_rq_depth;
-
- while (i--) {
- struct svc_rdma_op_ctxt *ctxt;
-
- ctxt = alloc_ctxt(xprt, GFP_KERNEL);
- if (!ctxt) {
- dprintk("svcrdma: No memory for RDMA ctxt\n");
- return false;
- }
- list_add(&ctxt->list, &xprt->sc_ctxts);
- }
- return true;
-}
-
-struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt)
-{
- struct svc_rdma_op_ctxt *ctxt = NULL;
-
- spin_lock(&xprt->sc_ctxt_lock);
- xprt->sc_ctxt_used++;
- if (list_empty(&xprt->sc_ctxts))
- goto out_empty;
-
- ctxt = list_first_entry(&xprt->sc_ctxts,
- struct svc_rdma_op_ctxt, list);
- list_del(&ctxt->list);
- spin_unlock(&xprt->sc_ctxt_lock);
-
-out:
- ctxt->count = 0;
- ctxt->mapped_sges = 0;
- return ctxt;
-
-out_empty:
- /* Either pre-allocation missed the mark, or send
- * queue accounting is broken.
- */
- spin_unlock(&xprt->sc_ctxt_lock);
-
- ctxt = alloc_ctxt(xprt, GFP_NOIO);
- if (ctxt)
- goto out;
-
- spin_lock(&xprt->sc_ctxt_lock);
- xprt->sc_ctxt_used--;
- spin_unlock(&xprt->sc_ctxt_lock);
- WARN_ONCE(1, "svcrdma: empty RDMA ctxt list?\n");
- return NULL;
-}
-
-void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt)
-{
- struct svcxprt_rdma *xprt = ctxt->xprt;
- struct ib_device *device = xprt->sc_cm_id->device;
- unsigned int i;
-
- for (i = 0; i < ctxt->mapped_sges; i++)
- ib_dma_unmap_page(device,
- ctxt->sge[i].addr,
- ctxt->sge[i].length,
- ctxt->direction);
- ctxt->mapped_sges = 0;
-}
-
-void svc_rdma_put_context(struct svc_rdma_op_ctxt *ctxt, int free_pages)
-{
- struct svcxprt_rdma *xprt = ctxt->xprt;
- int i;
-
- if (free_pages)
- for (i = 0; i < ctxt->count; i++)
- put_page(ctxt->pages[i]);
-
- spin_lock(&xprt->sc_ctxt_lock);
- xprt->sc_ctxt_used--;
- list_add(&ctxt->list, &xprt->sc_ctxts);
- spin_unlock(&xprt->sc_ctxt_lock);
-}
-
-static void svc_rdma_destroy_ctxts(struct svcxprt_rdma *xprt)
-{
- while (!list_empty(&xprt->sc_ctxts)) {
- struct svc_rdma_op_ctxt *ctxt;
-
- ctxt = list_first_entry(&xprt->sc_ctxts,
- struct svc_rdma_op_ctxt, list);
- list_del(&ctxt->list);
- kfree(ctxt);
- }
-}
-
/* QP event handler */
static void qp_event_handler(struct ib_event *event, void *context)
{
struct svc_xprt *xprt = context;
+ trace_svcrdma_qp_error(event, (struct sockaddr *)&xprt->xpt_remote);
switch (event->event) {
/* These are considered benign events */
case IB_EVENT_PATH_MIG:
case IB_EVENT_COMM_EST:
case IB_EVENT_SQ_DRAINED:
case IB_EVENT_QP_LAST_WQE_REACHED:
- dprintk("svcrdma: QP event %s (%d) received for QP=%p\n",
- ib_event_msg(event->event), event->event,
- event->element.qp);
break;
+
/* These are considered fatal events */
case IB_EVENT_PATH_MIG_ERR:
case IB_EVENT_QP_FATAL:
@@ -286,111 +179,34 @@ static void qp_event_handler(struct ib_event *event, void *context)
case IB_EVENT_QP_ACCESS_ERR:
case IB_EVENT_DEVICE_FATAL:
default:
- dprintk("svcrdma: QP ERROR event %s (%d) received for QP=%p, "
- "closing transport\n",
- ib_event_msg(event->event), event->event,
- event->element.qp);
set_bit(XPT_CLOSE, &xprt->xpt_flags);
svc_xprt_enqueue(xprt);
break;
}
}
-/**
- * svc_rdma_wc_receive - Invoked by RDMA provider for each polled Receive WC
- * @cq: completion queue
- * @wc: completed WR
- *
- */
-static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct svcxprt_rdma *xprt = cq->cq_context;
- struct ib_cqe *cqe = wc->wr_cqe;
- struct svc_rdma_op_ctxt *ctxt;
-
- /* WARNING: Only wc->wr_cqe and wc->status are reliable */
- ctxt = container_of(cqe, struct svc_rdma_op_ctxt, cqe);
- svc_rdma_unmap_dma(ctxt);
-
- if (wc->status != IB_WC_SUCCESS)
- goto flushed;
-
- /* All wc fields are now known to be valid */
- ctxt->byte_len = wc->byte_len;
- spin_lock(&xprt->sc_rq_dto_lock);
- list_add_tail(&ctxt->list, &xprt->sc_rq_dto_q);
- spin_unlock(&xprt->sc_rq_dto_lock);
-
- svc_rdma_post_recv(xprt);
-
- set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags);
- if (test_bit(RDMAXPRT_CONN_PENDING, &xprt->sc_flags))
- goto out;
- goto out_enqueue;
-
-flushed:
- if (wc->status != IB_WC_WR_FLUSH_ERR)
- pr_err("svcrdma: Recv: %s (%u/0x%x)\n",
- ib_wc_status_msg(wc->status),
- wc->status, wc->vendor_err);
- set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
- svc_rdma_put_context(ctxt, 1);
-
-out_enqueue:
- svc_xprt_enqueue(&xprt->sc_xprt);
-out:
- svc_xprt_put(&xprt->sc_xprt);
-}
-
-/**
- * svc_rdma_wc_send - Invoked by RDMA provider for each polled Send WC
- * @cq: completion queue
- * @wc: completed WR
- *
- */
-void svc_rdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
-{
- struct svcxprt_rdma *xprt = cq->cq_context;
- struct ib_cqe *cqe = wc->wr_cqe;
- struct svc_rdma_op_ctxt *ctxt;
-
- atomic_inc(&xprt->sc_sq_avail);
- wake_up(&xprt->sc_send_wait);
-
- ctxt = container_of(cqe, struct svc_rdma_op_ctxt, cqe);
- svc_rdma_unmap_dma(ctxt);
- svc_rdma_put_context(ctxt, 1);
-
- if (unlikely(wc->status != IB_WC_SUCCESS)) {
- set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
- svc_xprt_enqueue(&xprt->sc_xprt);
- if (wc->status != IB_WC_WR_FLUSH_ERR)
- pr_err("svcrdma: Send: %s (%u/0x%x)\n",
- ib_wc_status_msg(wc->status),
- wc->status, wc->vendor_err);
- }
-
- svc_xprt_put(&xprt->sc_xprt);
-}
-
-static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv,
- int listener)
+static struct svcxprt_rdma *svc_rdma_create_xprt(struct svc_serv *serv,
+ struct net *net)
{
struct svcxprt_rdma *cma_xprt = kzalloc(sizeof *cma_xprt, GFP_KERNEL);
- if (!cma_xprt)
+ if (!cma_xprt) {
+ dprintk("svcrdma: failed to create new transport\n");
return NULL;
- svc_xprt_init(&init_net, &svc_rdma_class, &cma_xprt->sc_xprt, serv);
+ }
+ svc_xprt_init(net, &svc_rdma_class, &cma_xprt->sc_xprt, serv);
INIT_LIST_HEAD(&cma_xprt->sc_accept_q);
INIT_LIST_HEAD(&cma_xprt->sc_rq_dto_q);
INIT_LIST_HEAD(&cma_xprt->sc_read_complete_q);
- INIT_LIST_HEAD(&cma_xprt->sc_ctxts);
+ INIT_LIST_HEAD(&cma_xprt->sc_send_ctxts);
+ INIT_LIST_HEAD(&cma_xprt->sc_recv_ctxts);
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_ctxt_lock);
+ spin_lock_init(&cma_xprt->sc_send_lock);
+ spin_lock_init(&cma_xprt->sc_recv_lock);
spin_lock_init(&cma_xprt->sc_rw_ctxt_lock);
/*
@@ -401,70 +217,9 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv,
*/
set_bit(XPT_CONG_CTRL, &cma_xprt->sc_xprt.xpt_flags);
- if (listener) {
- strcpy(cma_xprt->sc_xprt.xpt_remotebuf, "listener");
- set_bit(XPT_LISTENER, &cma_xprt->sc_xprt.xpt_flags);
- }
-
return cma_xprt;
}
-static int
-svc_rdma_post_recv(struct svcxprt_rdma *xprt)
-{
- struct ib_recv_wr recv_wr, *bad_recv_wr;
- struct svc_rdma_op_ctxt *ctxt;
- struct page *page;
- dma_addr_t pa;
- int sge_no;
- int buflen;
- int ret;
-
- ctxt = svc_rdma_get_context(xprt);
- buflen = 0;
- ctxt->direction = DMA_FROM_DEVICE;
- ctxt->cqe.done = svc_rdma_wc_receive;
- for (sge_no = 0; buflen < xprt->sc_max_req_size; sge_no++) {
- if (sge_no >= xprt->sc_max_sge) {
- pr_err("svcrdma: Too many sges (%d)\n", sge_no);
- goto err_put_ctxt;
- }
- page = alloc_page(GFP_KERNEL);
- if (!page)
- goto err_put_ctxt;
- ctxt->pages[sge_no] = page;
- pa = ib_dma_map_page(xprt->sc_cm_id->device,
- page, 0, PAGE_SIZE,
- DMA_FROM_DEVICE);
- if (ib_dma_mapping_error(xprt->sc_cm_id->device, pa))
- goto err_put_ctxt;
- svc_rdma_count_mappings(xprt, ctxt);
- ctxt->sge[sge_no].addr = pa;
- ctxt->sge[sge_no].length = PAGE_SIZE;
- ctxt->sge[sge_no].lkey = xprt->sc_pd->local_dma_lkey;
- ctxt->count = sge_no + 1;
- buflen += PAGE_SIZE;
- }
- recv_wr.next = NULL;
- recv_wr.sg_list = &ctxt->sge[0];
- recv_wr.num_sge = ctxt->count;
- recv_wr.wr_cqe = &ctxt->cqe;
-
- svc_xprt_get(&xprt->sc_xprt);
- ret = ib_post_recv(xprt->sc_qp, &recv_wr, &bad_recv_wr);
- if (ret) {
- svc_rdma_unmap_dma(ctxt);
- svc_rdma_put_context(ctxt, 1);
- svc_xprt_put(&xprt->sc_xprt);
- }
- return ret;
-
- err_put_ctxt:
- svc_rdma_unmap_dma(ctxt);
- svc_rdma_put_context(ctxt, 1);
- return -ENOMEM;
-}
-
static void
svc_rdma_parse_connect_private(struct svcxprt_rdma *newxprt,
struct rdma_conn_param *param)
@@ -504,15 +259,12 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id,
struct sockaddr *sa;
/* Create a new transport */
- newxprt = rdma_create_xprt(listen_xprt->sc_xprt.xpt_server, 0);
- if (!newxprt) {
- dprintk("svcrdma: failed to create new transport\n");
+ newxprt = svc_rdma_create_xprt(listen_xprt->sc_xprt.xpt_server,
+ listen_xprt->sc_xprt.xpt_net);
+ if (!newxprt)
return;
- }
newxprt->sc_cm_id = new_cma_id;
new_cma_id->context = newxprt;
- dprintk("svcrdma: Creating newxprt=%p, cm_id=%p, listenxprt=%p\n",
- newxprt, newxprt->sc_cm_id, listen_xprt);
svc_rdma_parse_connect_private(newxprt, param);
/* Save client advertised inbound read limit for use later in accept. */
@@ -543,9 +295,11 @@ static void handle_connect_req(struct rdma_cm_id *new_cma_id,
static int rdma_listen_handler(struct rdma_cm_id *cma_id,
struct rdma_cm_event *event)
{
- struct svcxprt_rdma *xprt = cma_id->context;
+ struct sockaddr *sap = (struct sockaddr *)&cma_id->route.addr.src_addr;
int ret = 0;
+ trace_svcrdma_cm_event(event, sap);
+
switch (event->event) {
case RDMA_CM_EVENT_CONNECT_REQUEST:
dprintk("svcrdma: Connect request on cma_id=%p, xprt = %p, "
@@ -553,23 +307,8 @@ static int rdma_listen_handler(struct rdma_cm_id *cma_id,
rdma_event_msg(event->event), event->event);
handle_connect_req(cma_id, &event->param.conn);
break;
-
- case RDMA_CM_EVENT_ESTABLISHED:
- /* Accept complete */
- dprintk("svcrdma: Connection completed on LISTEN xprt=%p, "
- "cm_id=%p\n", xprt, cma_id);
- break;
-
- case RDMA_CM_EVENT_DEVICE_REMOVAL:
- dprintk("svcrdma: Device removal xprt=%p, cm_id=%p\n",
- xprt, cma_id);
- if (xprt) {
- set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
- svc_xprt_enqueue(&xprt->sc_xprt);
- }
- break;
-
default:
+ /* NB: No device removal upcall for INADDR_ANY listeners */
dprintk("svcrdma: Unexpected event on listening endpoint %p, "
"event = %s (%d)\n", cma_id,
rdma_event_msg(event->event), event->event);
@@ -582,9 +321,12 @@ static int rdma_listen_handler(struct rdma_cm_id *cma_id,
static int rdma_cma_handler(struct rdma_cm_id *cma_id,
struct rdma_cm_event *event)
{
- struct svc_xprt *xprt = cma_id->context;
- struct svcxprt_rdma *rdma =
- container_of(xprt, struct svcxprt_rdma, sc_xprt);
+ struct sockaddr *sap = (struct sockaddr *)&cma_id->route.addr.dst_addr;
+ struct svcxprt_rdma *rdma = cma_id->context;
+ struct svc_xprt *xprt = &rdma->sc_xprt;
+
+ trace_svcrdma_cm_event(event, sap);
+
switch (event->event) {
case RDMA_CM_EVENT_ESTABLISHED:
/* Accept complete */
@@ -597,21 +339,17 @@ static int rdma_cma_handler(struct rdma_cm_id *cma_id,
case RDMA_CM_EVENT_DISCONNECTED:
dprintk("svcrdma: Disconnect on DTO xprt=%p, cm_id=%p\n",
xprt, cma_id);
- if (xprt) {
- set_bit(XPT_CLOSE, &xprt->xpt_flags);
- svc_xprt_enqueue(xprt);
- svc_xprt_put(xprt);
- }
+ set_bit(XPT_CLOSE, &xprt->xpt_flags);
+ svc_xprt_enqueue(xprt);
+ svc_xprt_put(xprt);
break;
case RDMA_CM_EVENT_DEVICE_REMOVAL:
dprintk("svcrdma: Device removal cma_id=%p, xprt = %p, "
"event = %s (%d)\n", cma_id, xprt,
rdma_event_msg(event->event), event->event);
- if (xprt) {
- set_bit(XPT_CLOSE, &xprt->xpt_flags);
- svc_xprt_enqueue(xprt);
- svc_xprt_put(xprt);
- }
+ set_bit(XPT_CLOSE, &xprt->xpt_flags);
+ svc_xprt_enqueue(xprt);
+ svc_xprt_put(xprt);
break;
default:
dprintk("svcrdma: Unexpected event on DTO endpoint %p, "
@@ -634,16 +372,18 @@ static struct svc_xprt *svc_rdma_create(struct svc_serv *serv,
struct svcxprt_rdma *cma_xprt;
int ret;
- dprintk("svcrdma: Creating RDMA socket\n");
+ dprintk("svcrdma: Creating RDMA listener\n");
if ((sa->sa_family != AF_INET) && (sa->sa_family != AF_INET6)) {
dprintk("svcrdma: Address family %d is not supported.\n", sa->sa_family);
return ERR_PTR(-EAFNOSUPPORT);
}
- cma_xprt = rdma_create_xprt(serv, 1);
+ cma_xprt = svc_rdma_create_xprt(serv, net);
if (!cma_xprt)
return ERR_PTR(-ENOMEM);
+ set_bit(XPT_LISTENER, &cma_xprt->sc_xprt.xpt_flags);
+ strcpy(cma_xprt->sc_xprt.xpt_remotebuf, "listener");
- listen_id = rdma_create_id(&init_net, rdma_listen_handler, cma_xprt,
+ listen_id = rdma_create_id(net, rdma_listen_handler, cma_xprt,
RDMA_PS_TCP, IB_QPT_RC);
if (IS_ERR(listen_id)) {
ret = PTR_ERR(listen_id);
@@ -708,9 +448,9 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
struct rdma_conn_param conn_param;
struct rpcrdma_connect_private pmsg;
struct ib_qp_init_attr qp_attr;
+ unsigned int ctxts, rq_depth;
struct ib_device *dev;
struct sockaddr *sap;
- unsigned int i, ctxts;
int ret = 0;
listen_rdma = container_of(xprt, struct svcxprt_rdma, sc_xprt);
@@ -736,24 +476,28 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
/* Qualify the transport resource defaults with the
* capabilities of this particular device */
- newxprt->sc_max_sge = min((size_t)dev->attrs.max_sge,
- (size_t)RPCSVC_MAXPAGES);
+ newxprt->sc_max_send_sges = dev->attrs.max_sge;
+ /* transport hdr, head iovec, one page list entry, tail iovec */
+ if (newxprt->sc_max_send_sges < 4) {
+ pr_err("svcrdma: too few Send SGEs available (%d)\n",
+ newxprt->sc_max_send_sges);
+ goto errout;
+ }
newxprt->sc_max_req_size = svcrdma_max_req_size;
newxprt->sc_max_requests = svcrdma_max_requests;
newxprt->sc_max_bc_requests = svcrdma_max_bc_requests;
- newxprt->sc_rq_depth = newxprt->sc_max_requests +
- newxprt->sc_max_bc_requests;
- if (newxprt->sc_rq_depth > dev->attrs.max_qp_wr) {
+ rq_depth = newxprt->sc_max_requests + newxprt->sc_max_bc_requests;
+ if (rq_depth > dev->attrs.max_qp_wr) {
pr_warn("svcrdma: reducing receive depth to %d\n",
dev->attrs.max_qp_wr);
- newxprt->sc_rq_depth = dev->attrs.max_qp_wr;
- newxprt->sc_max_requests = newxprt->sc_rq_depth - 2;
+ rq_depth = dev->attrs.max_qp_wr;
+ newxprt->sc_max_requests = rq_depth - 2;
newxprt->sc_max_bc_requests = 2;
}
newxprt->sc_fc_credits = cpu_to_be32(newxprt->sc_max_requests);
ctxts = rdma_rw_mr_factor(dev, newxprt->sc_port_num, RPCSVC_MAXPAGES);
ctxts *= newxprt->sc_max_requests;
- newxprt->sc_sq_depth = newxprt->sc_rq_depth + ctxts;
+ newxprt->sc_sq_depth = rq_depth + ctxts;
if (newxprt->sc_sq_depth > dev->attrs.max_qp_wr) {
pr_warn("svcrdma: reducing send depth to %d\n",
dev->attrs.max_qp_wr);
@@ -761,9 +505,6 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
}
atomic_set(&newxprt->sc_sq_avail, newxprt->sc_sq_depth);
- if (!svc_rdma_prealloc_ctxts(newxprt))
- goto errout;
-
newxprt->sc_pd = ib_alloc_pd(dev, 0);
if (IS_ERR(newxprt->sc_pd)) {
dprintk("svcrdma: error creating PD for connect request\n");
@@ -775,7 +516,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
dprintk("svcrdma: error creating SQ CQ for connect request\n");
goto errout;
}
- newxprt->sc_rq_cq = ib_alloc_cq(dev, newxprt, newxprt->sc_rq_depth,
+ newxprt->sc_rq_cq = ib_alloc_cq(dev, newxprt, rq_depth,
0, IB_POLL_WORKQUEUE);
if (IS_ERR(newxprt->sc_rq_cq)) {
dprintk("svcrdma: error creating RQ CQ for connect request\n");
@@ -788,9 +529,9 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
qp_attr.port_num = newxprt->sc_port_num;
qp_attr.cap.max_rdma_ctxs = ctxts;
qp_attr.cap.max_send_wr = newxprt->sc_sq_depth - ctxts;
- qp_attr.cap.max_recv_wr = newxprt->sc_rq_depth;
- qp_attr.cap.max_send_sge = newxprt->sc_max_sge;
- qp_attr.cap.max_recv_sge = newxprt->sc_max_sge;
+ qp_attr.cap.max_recv_wr = rq_depth;
+ qp_attr.cap.max_send_sge = newxprt->sc_max_send_sges;
+ qp_attr.cap.max_recv_sge = 1;
qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR;
qp_attr.qp_type = IB_QPT_RC;
qp_attr.send_cq = newxprt->sc_sq_cq;
@@ -815,14 +556,8 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
!rdma_ib_or_roce(dev, newxprt->sc_port_num))
goto errout;
- /* Post receive buffers */
- for (i = 0; i < newxprt->sc_max_requests; i++) {
- ret = svc_rdma_post_recv(newxprt);
- if (ret) {
- dprintk("svcrdma: failure posting receive buffers\n");
- goto errout;
- }
- }
+ if (!svc_rdma_post_recvs(newxprt))
+ goto errout;
/* Swap out the handler */
newxprt->sc_cm_id->event_handler = rdma_cma_handler;
@@ -856,16 +591,18 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
dprintk(" local address : %pIS:%u\n", sap, rpc_get_port(sap));
sap = (struct sockaddr *)&newxprt->sc_cm_id->route.addr.dst_addr;
dprintk(" remote address : %pIS:%u\n", sap, rpc_get_port(sap));
- dprintk(" max_sge : %d\n", newxprt->sc_max_sge);
+ dprintk(" max_sge : %d\n", newxprt->sc_max_send_sges);
dprintk(" sq_depth : %d\n", newxprt->sc_sq_depth);
dprintk(" rdma_rw_ctxs : %d\n", ctxts);
dprintk(" max_requests : %d\n", newxprt->sc_max_requests);
dprintk(" ord : %d\n", conn_param.initiator_depth);
+ trace_svcrdma_xprt_accept(&newxprt->sc_xprt);
return &newxprt->sc_xprt;
errout:
dprintk("svcrdma: failure accepting new connection rc=%d.\n", ret);
+ trace_svcrdma_xprt_fail(&newxprt->sc_xprt);
/* Take a reference in case the DTO handler runs */
svc_xprt_get(&newxprt->sc_xprt);
if (newxprt->sc_qp && !IS_ERR(newxprt->sc_qp))
@@ -896,7 +633,6 @@ static void svc_rdma_detach(struct svc_xprt *xprt)
{
struct svcxprt_rdma *rdma =
container_of(xprt, struct svcxprt_rdma, sc_xprt);
- dprintk("svc: svc_rdma_detach(%p)\n", xprt);
/* Disconnect and flush posted WQE */
rdma_disconnect(rdma->sc_cm_id);
@@ -908,7 +644,7 @@ static void __svc_rdma_free(struct work_struct *work)
container_of(work, struct svcxprt_rdma, sc_work);
struct svc_xprt *xprt = &rdma->sc_xprt;
- dprintk("svcrdma: %s(%p)\n", __func__, rdma);
+ trace_svcrdma_xprt_free(xprt);
if (rdma->sc_qp && !IS_ERR(rdma->sc_qp))
ib_drain_qp(rdma->sc_qp);
@@ -918,25 +654,7 @@ static void __svc_rdma_free(struct work_struct *work)
pr_err("svcrdma: sc_xprt still in use? (%d)\n",
kref_read(&xprt->xpt_ref));
- while (!list_empty(&rdma->sc_read_complete_q)) {
- struct svc_rdma_op_ctxt *ctxt;
- ctxt = list_first_entry(&rdma->sc_read_complete_q,
- struct svc_rdma_op_ctxt, list);
- list_del(&ctxt->list);
- svc_rdma_put_context(ctxt, 1);
- }
- while (!list_empty(&rdma->sc_rq_dto_q)) {
- struct svc_rdma_op_ctxt *ctxt;
- ctxt = list_first_entry(&rdma->sc_rq_dto_q,
- struct svc_rdma_op_ctxt, list);
- list_del(&ctxt->list);
- svc_rdma_put_context(ctxt, 1);
- }
-
- /* Warn if we leaked a resource or under-referenced */
- if (rdma->sc_ctxt_used != 0)
- pr_err("svcrdma: ctxt still in use? (%d)\n",
- rdma->sc_ctxt_used);
+ svc_rdma_flush_recv_queues(rdma);
/* Final put of backchannel client transport */
if (xprt->xpt_bc_xprt) {
@@ -945,7 +663,8 @@ static void __svc_rdma_free(struct work_struct *work)
}
svc_rdma_destroy_rw_ctxts(rdma);
- svc_rdma_destroy_ctxts(rdma);
+ svc_rdma_send_ctxts_destroy(rdma);
+ svc_rdma_recv_ctxts_destroy(rdma);
/* Destroy the QP if present (not a listener) */
if (rdma->sc_qp && !IS_ERR(rdma->sc_qp))
@@ -998,51 +717,3 @@ static void svc_rdma_secure_port(struct svc_rqst *rqstp)
static void svc_rdma_kill_temp_xprt(struct svc_xprt *xprt)
{
}
-
-int svc_rdma_send(struct svcxprt_rdma *xprt, struct ib_send_wr *wr)
-{
- struct ib_send_wr *bad_wr, *n_wr;
- int wr_count;
- int i;
- int ret;
-
- if (test_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags))
- return -ENOTCONN;
-
- wr_count = 1;
- for (n_wr = wr->next; n_wr; n_wr = n_wr->next)
- wr_count++;
-
- /* If the SQ is full, wait until an SQ entry is available */
- while (1) {
- if ((atomic_sub_return(wr_count, &xprt->sc_sq_avail) < 0)) {
- atomic_inc(&rdma_stat_sq_starve);
-
- /* Wait until SQ WR available if SQ still full */
- atomic_add(wr_count, &xprt->sc_sq_avail);
- wait_event(xprt->sc_send_wait,
- atomic_read(&xprt->sc_sq_avail) > wr_count);
- if (test_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags))
- return -ENOTCONN;
- continue;
- }
- /* Take a transport ref for each WR posted */
- for (i = 0; i < wr_count; i++)
- svc_xprt_get(&xprt->sc_xprt);
-
- /* Bump used SQ WR count and post */
- ret = ib_post_send(xprt->sc_qp, wr, &bad_wr);
- if (ret) {
- set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags);
- for (i = 0; i < wr_count; i ++)
- svc_xprt_put(&xprt->sc_xprt);
- dprintk("svcrdma: failed to post SQ WR rc=%d\n", ret);
- dprintk(" sc_sq_avail=%d, sc_sq_depth=%d\n",
- atomic_read(&xprt->sc_sq_avail),
- xprt->sc_sq_depth);
- wake_up(&xprt->sc_send_wait);
- }
- break;
- }
- return ret;
-}
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index cc1aad3..143ce25 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (c) 2014-2017 Oracle. All rights reserved.
* Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@ -51,9 +52,13 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/seq_file.h>
+#include <linux/smp.h>
+
#include <linux/sunrpc/addr.h>
+#include <linux/sunrpc/svc_rdma.h>
#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
# define RPCDBG_FACILITY RPCDBG_TRANS
@@ -330,9 +335,7 @@ xprt_setup_rdma(struct xprt_create *args)
return ERR_PTR(-EBADF);
}
- xprt = xprt_alloc(args->net, sizeof(struct rpcrdma_xprt),
- xprt_rdma_slot_table_entries,
- xprt_rdma_slot_table_entries);
+ xprt = xprt_alloc(args->net, sizeof(struct rpcrdma_xprt), 0, 0);
if (xprt == NULL) {
dprintk("RPC: %s: couldn't allocate rpcrdma_xprt\n",
__func__);
@@ -364,7 +367,7 @@ xprt_setup_rdma(struct xprt_create *args)
xprt_set_bound(xprt);
xprt_rdma_format_addresses(xprt, sap);
- cdata.max_requests = xprt->max_reqs;
+ cdata.max_requests = xprt_rdma_slot_table_entries;
cdata.rsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA write max */
cdata.wsize = RPCRDMA_MAX_SEGS * PAGE_SIZE; /* RDMA read max */
@@ -537,6 +540,47 @@ xprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task)
}
}
+/**
+ * xprt_rdma_alloc_slot - allocate an rpc_rqst
+ * @xprt: controlling RPC transport
+ * @task: RPC task requesting a fresh rpc_rqst
+ *
+ * tk_status values:
+ * %0 if task->tk_rqstp points to a fresh rpc_rqst
+ * %-EAGAIN if no rpc_rqst is available; queued on backlog
+ */
+static void
+xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+ struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
+ struct rpcrdma_req *req;
+
+ req = rpcrdma_buffer_get(&r_xprt->rx_buf);
+ if (!req)
+ goto out_sleep;
+ task->tk_rqstp = &req->rl_slot;
+ task->tk_status = 0;
+ return;
+
+out_sleep:
+ rpc_sleep_on(&xprt->backlog, task, NULL);
+ task->tk_status = -EAGAIN;
+}
+
+/**
+ * xprt_rdma_free_slot - release an rpc_rqst
+ * @xprt: controlling RPC transport
+ * @rqst: rpc_rqst to release
+ *
+ */
+static void
+xprt_rdma_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *rqst)
+{
+ memset(rqst, 0, sizeof(*rqst));
+ rpcrdma_buffer_put(rpcr_to_rdmar(rqst));
+ rpc_wake_up_next(&xprt->backlog);
+}
+
static bool
rpcrdma_get_sendbuf(struct rpcrdma_xprt *r_xprt, struct rpcrdma_req *req,
size_t size, gfp_t flags)
@@ -607,13 +651,9 @@ xprt_rdma_allocate(struct rpc_task *task)
{
struct rpc_rqst *rqst = task->tk_rqstp;
struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(rqst->rq_xprt);
- struct rpcrdma_req *req;
+ struct rpcrdma_req *req = rpcr_to_rdmar(rqst);
gfp_t flags;
- req = rpcrdma_buffer_get(&r_xprt->rx_buf);
- if (req == NULL)
- goto out_get;
-
flags = RPCRDMA_DEF_GFP;
if (RPC_IS_SWAPPER(task))
flags = __GFP_MEMALLOC | GFP_NOWAIT | __GFP_NOWARN;
@@ -623,15 +663,12 @@ xprt_rdma_allocate(struct rpc_task *task)
if (!rpcrdma_get_recvbuf(r_xprt, req, rqst->rq_rcvsize, flags))
goto out_fail;
- rpcrdma_set_xprtdata(rqst, req);
rqst->rq_buffer = req->rl_sendbuf->rg_base;
rqst->rq_rbuffer = req->rl_recvbuf->rg_base;
trace_xprtrdma_allocate(task, req);
return 0;
out_fail:
- rpcrdma_buffer_put(req);
-out_get:
trace_xprtrdma_allocate(task, NULL);
return -ENOMEM;
}
@@ -652,7 +689,6 @@ xprt_rdma_free(struct rpc_task *task)
if (test_bit(RPCRDMA_REQ_F_PENDING, &req->rl_flags))
rpcrdma_release_rqst(r_xprt, req);
trace_xprtrdma_rpc_done(task, req);
- rpcrdma_buffer_put(req);
}
/**
@@ -690,9 +726,6 @@ xprt_rdma_send_request(struct rpc_task *task)
if (rc < 0)
goto failed_marshal;
- if (req->rl_reply == NULL) /* e.g. reconnection */
- rpcrdma_recv_buffer_get(req);
-
/* Must suppress retransmit to maintain credits */
if (rqst->rq_connect_cookie == xprt->connect_cookie)
goto drop_connection;
@@ -779,7 +812,8 @@ xprt_rdma_disable_swap(struct rpc_xprt *xprt)
static const struct rpc_xprt_ops xprt_rdma_procs = {
.reserve_xprt = xprt_reserve_xprt_cong,
.release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */
- .alloc_slot = xprt_alloc_slot,
+ .alloc_slot = xprt_rdma_alloc_slot,
+ .free_slot = xprt_rdma_free_slot,
.release_request = xprt_release_rqst_cong, /* ditto */
.set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */
.timer = xprt_rdma_timer,
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c
index c345d36..16161a3 100644
--- a/net/sunrpc/xprtrdma/verbs.c
+++ b/net/sunrpc/xprtrdma/verbs.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
* Copyright (c) 2014-2017 Oracle. All rights reserved.
* Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@ -59,6 +60,7 @@
#include <rdma/ib_cm.h>
#include "xprt_rdma.h"
+#include <trace/events/rpcrdma.h>
/*
* Globals/Macros
@@ -71,8 +73,10 @@
/*
* internal functions
*/
+static void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc);
static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);
static void rpcrdma_mrs_destroy(struct rpcrdma_buffer *buf);
+static int rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt, bool temp);
static void rpcrdma_dma_unmap_regbuf(struct rpcrdma_regbuf *rb);
struct workqueue_struct *rpcrdma_receive_wq __read_mostly;
@@ -159,7 +163,7 @@ rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
rr_cqe);
/* WARNING: Only wr_id and status are reliable at this point */
- trace_xprtrdma_wc_receive(rep, wc);
+ trace_xprtrdma_wc_receive(wc);
if (wc->status != IB_WC_SUCCESS)
goto out_fail;
@@ -231,7 +235,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)
complete(&ia->ri_done);
break;
case RDMA_CM_EVENT_ADDR_ERROR:
- ia->ri_async_rc = -EHOSTUNREACH;
+ ia->ri_async_rc = -EPROTO;
complete(&ia->ri_done);
break;
case RDMA_CM_EVENT_ROUTE_ERROR:
@@ -262,7 +266,7 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)
connstate = -ENOTCONN;
goto connected;
case RDMA_CM_EVENT_UNREACHABLE:
- connstate = -ENETDOWN;
+ connstate = -ENETUNREACH;
goto connected;
case RDMA_CM_EVENT_REJECTED:
dprintk("rpcrdma: connection to %s:%s rejected: %s\n",
@@ -305,8 +309,8 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt, struct rpcrdma_ia *ia)
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);
+ id = rdma_create_id(xprt->rx_xprt.xprt_net, rpcrdma_conn_upcall,
+ xprt, RDMA_PS_TCP, IB_QPT_RC);
if (IS_ERR(id)) {
rc = PTR_ERR(id);
dprintk("RPC: %s: rdma_create_id() failed %i\n",
@@ -500,8 +504,8 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
struct rpcrdma_create_data_internal *cdata)
{
struct rpcrdma_connect_private *pmsg = &ep->rep_cm_private;
- unsigned int max_qp_wr, max_sge;
struct ib_cq *sendcq, *recvcq;
+ unsigned int max_sge;
int rc;
max_sge = min_t(unsigned int, ia->ri_device->attrs.max_sge,
@@ -512,29 +516,13 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
}
ia->ri_max_send_sges = max_sge;
- if (ia->ri_device->attrs.max_qp_wr <= RPCRDMA_BACKWARD_WRS) {
- dprintk("RPC: %s: insufficient wqe's available\n",
- __func__);
- return -ENOMEM;
- }
- max_qp_wr = ia->ri_device->attrs.max_qp_wr - RPCRDMA_BACKWARD_WRS - 1;
-
- /* check provider's send/recv wr limits */
- if (cdata->max_requests > max_qp_wr)
- cdata->max_requests = max_qp_wr;
+ rc = ia->ri_ops->ro_open(ia, ep, cdata);
+ if (rc)
+ return rc;
ep->rep_attr.event_handler = rpcrdma_qp_async_error_upcall;
ep->rep_attr.qp_context = ep;
ep->rep_attr.srq = NULL;
- ep->rep_attr.cap.max_send_wr = cdata->max_requests;
- ep->rep_attr.cap.max_send_wr += RPCRDMA_BACKWARD_WRS;
- ep->rep_attr.cap.max_send_wr += 1; /* drain cqe */
- rc = ia->ri_ops->ro_open(ia, ep, cdata);
- if (rc)
- return rc;
- ep->rep_attr.cap.max_recv_wr = cdata->max_requests;
- ep->rep_attr.cap.max_recv_wr += RPCRDMA_BACKWARD_WRS;
- ep->rep_attr.cap.max_recv_wr += 1; /* drain cqe */
ep->rep_attr.cap.max_send_sge = max_sge;
ep->rep_attr.cap.max_recv_sge = 1;
ep->rep_attr.cap.max_inline_data = 0;
@@ -741,7 +729,6 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
{
struct rpcrdma_xprt *r_xprt = container_of(ia, struct rpcrdma_xprt,
rx_ia);
- unsigned int extras;
int rc;
retry:
@@ -785,9 +772,8 @@ retry:
}
dprintk("RPC: %s: connected\n", __func__);
- extras = r_xprt->rx_buf.rb_bc_srv_max_requests;
- if (extras)
- rpcrdma_ep_post_extra_recv(r_xprt, extras);
+
+ rpcrdma_post_recvs(r_xprt, true);
out:
if (rc)
@@ -893,6 +879,7 @@ static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt)
sc->sc_xprt = r_xprt;
buf->rb_sc_ctxs[i] = sc;
}
+ buf->rb_flags = 0;
return 0;
@@ -950,7 +937,7 @@ out_emptyq:
* completions recently. This is a sign the Send Queue is
* backing up. Cause the caller to pause and try again.
*/
- dprintk("RPC: %s: empty sendctx queue\n", __func__);
+ set_bit(RPCRDMA_BUF_F_EMPTY_SCQ, &buf->rb_flags);
r_xprt = container_of(buf, struct rpcrdma_xprt, rx_buf);
r_xprt->rx_stats.empty_sendctx_q++;
return NULL;
@@ -965,7 +952,8 @@ out_emptyq:
*
* The caller serializes calls to this function (per rpcrdma_buffer).
*/
-void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc)
+static void
+rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc)
{
struct rpcrdma_buffer *buf = &sc->sc_xprt->rx_buf;
unsigned long next_tail;
@@ -984,6 +972,11 @@ void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc)
/* Paired with READ_ONCE */
smp_store_release(&buf->rb_sc_tail, next_tail);
+
+ if (test_and_clear_bit(RPCRDMA_BUF_F_EMPTY_SCQ, &buf->rb_flags)) {
+ smp_mb__after_atomic();
+ xprt_write_space(&sc->sc_xprt->rx_xprt);
+ }
}
static void
@@ -1097,14 +1090,8 @@ rpcrdma_create_req(struct rpcrdma_xprt *r_xprt)
return req;
}
-/**
- * rpcrdma_create_rep - Allocate an rpcrdma_rep object
- * @r_xprt: controlling transport
- *
- * Returns 0 on success or a negative errno on failure.
- */
-int
-rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt)
+static int
+rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt, bool temp)
{
struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data;
struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
@@ -1132,6 +1119,7 @@ rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt)
rep->rr_recv_wr.wr_cqe = &rep->rr_cqe;
rep->rr_recv_wr.sg_list = &rep->rr_rdmabuf->rg_iov;
rep->rr_recv_wr.num_sge = 1;
+ rep->rr_temp = temp;
spin_lock(&buf->rb_lock);
list_add(&rep->rr_list, &buf->rb_recv_bufs);
@@ -1183,12 +1171,8 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
list_add(&req->rl_list, &buf->rb_send_bufs);
}
+ buf->rb_posted_receives = 0;
INIT_LIST_HEAD(&buf->rb_recv_bufs);
- for (i = 0; i <= buf->rb_max_requests; i++) {
- rc = rpcrdma_create_rep(r_xprt);
- if (rc)
- goto out;
- }
rc = rpcrdma_sendctxs_create(r_xprt);
if (rc)
@@ -1200,28 +1184,6 @@ out:
return rc;
}
-static struct rpcrdma_req *
-rpcrdma_buffer_get_req_locked(struct rpcrdma_buffer *buf)
-{
- struct rpcrdma_req *req;
-
- req = list_first_entry(&buf->rb_send_bufs,
- struct rpcrdma_req, rl_list);
- list_del_init(&req->rl_list);
- return req;
-}
-
-static struct rpcrdma_rep *
-rpcrdma_buffer_get_rep_locked(struct rpcrdma_buffer *buf)
-{
- struct rpcrdma_rep *rep;
-
- rep = list_first_entry(&buf->rb_recv_bufs,
- struct rpcrdma_rep, rr_list);
- list_del(&rep->rr_list);
- return rep;
-}
-
static void
rpcrdma_destroy_rep(struct rpcrdma_rep *rep)
{
@@ -1280,10 +1242,11 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
while (!list_empty(&buf->rb_recv_bufs)) {
struct rpcrdma_rep *rep;
- rep = rpcrdma_buffer_get_rep_locked(buf);
+ rep = list_first_entry(&buf->rb_recv_bufs,
+ struct rpcrdma_rep, rr_list);
+ list_del(&rep->rr_list);
rpcrdma_destroy_rep(rep);
}
- buf->rb_send_count = 0;
spin_lock(&buf->rb_reqslock);
while (!list_empty(&buf->rb_allreqs)) {
@@ -1298,7 +1261,6 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
spin_lock(&buf->rb_reqslock);
}
spin_unlock(&buf->rb_reqslock);
- buf->rb_recv_count = 0;
rpcrdma_mrs_destroy(buf);
}
@@ -1371,27 +1333,11 @@ rpcrdma_mr_unmap_and_put(struct rpcrdma_mr *mr)
__rpcrdma_mr_put(&r_xprt->rx_buf, mr);
}
-static struct rpcrdma_rep *
-rpcrdma_buffer_get_rep(struct rpcrdma_buffer *buffers)
-{
- /* If an RPC previously completed without a reply (say, a
- * credential problem or a soft timeout occurs) then hold off
- * on supplying more Receive buffers until the number of new
- * pending RPCs catches up to the number of posted Receives.
- */
- if (unlikely(buffers->rb_send_count < buffers->rb_recv_count))
- return NULL;
-
- if (unlikely(list_empty(&buffers->rb_recv_bufs)))
- return NULL;
- buffers->rb_recv_count++;
- return rpcrdma_buffer_get_rep_locked(buffers);
-}
-
-/*
- * Get a set of request/reply buffers.
+/**
+ * rpcrdma_buffer_get - Get a request buffer
+ * @buffers: Buffer pool from which to obtain a buffer
*
- * Reply buffer (if available) is attached to send buffer upon return.
+ * Returns a fresh rpcrdma_req, or NULL if none are available.
*/
struct rpcrdma_req *
rpcrdma_buffer_get(struct rpcrdma_buffer *buffers)
@@ -1399,23 +1345,18 @@ rpcrdma_buffer_get(struct rpcrdma_buffer *buffers)
struct rpcrdma_req *req;
spin_lock(&buffers->rb_lock);
- if (list_empty(&buffers->rb_send_bufs))
- goto out_reqbuf;
- buffers->rb_send_count++;
- req = rpcrdma_buffer_get_req_locked(buffers);
- req->rl_reply = rpcrdma_buffer_get_rep(buffers);
+ req = list_first_entry_or_null(&buffers->rb_send_bufs,
+ struct rpcrdma_req, rl_list);
+ if (req)
+ list_del_init(&req->rl_list);
spin_unlock(&buffers->rb_lock);
-
return req;
-
-out_reqbuf:
- spin_unlock(&buffers->rb_lock);
- return NULL;
}
-/*
- * Put request/reply buffers back into pool.
- * Pre-decrement counter/array index.
+/**
+ * rpcrdma_buffer_put - Put request/reply buffers back into pool
+ * @req: object to return
+ *
*/
void
rpcrdma_buffer_put(struct rpcrdma_req *req)
@@ -1426,27 +1367,16 @@ rpcrdma_buffer_put(struct rpcrdma_req *req)
req->rl_reply = NULL;
spin_lock(&buffers->rb_lock);
- buffers->rb_send_count--;
- list_add_tail(&req->rl_list, &buffers->rb_send_bufs);
+ list_add(&req->rl_list, &buffers->rb_send_bufs);
if (rep) {
- buffers->rb_recv_count--;
- list_add_tail(&rep->rr_list, &buffers->rb_recv_bufs);
+ if (!rep->rr_temp) {
+ list_add(&rep->rr_list, &buffers->rb_recv_bufs);
+ rep = NULL;
+ }
}
spin_unlock(&buffers->rb_lock);
-}
-
-/*
- * Recover reply buffers from pool.
- * This happens when recovering from disconnect.
- */
-void
-rpcrdma_recv_buffer_get(struct rpcrdma_req *req)
-{
- struct rpcrdma_buffer *buffers = req->rl_buffer;
-
- spin_lock(&buffers->rb_lock);
- req->rl_reply = rpcrdma_buffer_get_rep(buffers);
- spin_unlock(&buffers->rb_lock);
+ if (rep)
+ rpcrdma_destroy_rep(rep);
}
/*
@@ -1458,10 +1388,13 @@ rpcrdma_recv_buffer_put(struct rpcrdma_rep *rep)
{
struct rpcrdma_buffer *buffers = &rep->rr_rxprt->rx_buf;
- spin_lock(&buffers->rb_lock);
- buffers->rb_recv_count--;
- list_add_tail(&rep->rr_list, &buffers->rb_recv_bufs);
- spin_unlock(&buffers->rb_lock);
+ if (!rep->rr_temp) {
+ spin_lock(&buffers->rb_lock);
+ list_add(&rep->rr_list, &buffers->rb_recv_bufs);
+ spin_unlock(&buffers->rb_lock);
+ } else {
+ rpcrdma_destroy_rep(rep);
+ }
}
/**
@@ -1557,13 +1490,6 @@ rpcrdma_ep_post(struct rpcrdma_ia *ia,
struct ib_send_wr *send_wr = &req->rl_sendctx->sc_wr;
int rc;
- if (req->rl_reply) {
- rc = rpcrdma_ep_post_recv(ia, req->rl_reply);
- if (rc)
- return rc;
- req->rl_reply = NULL;
- }
-
if (!ep->rep_send_count ||
test_bit(RPCRDMA_REQ_F_TX_RESOURCES, &req->rl_flags)) {
send_wr->send_flags |= IB_SEND_SIGNALED;
@@ -1580,61 +1506,69 @@ rpcrdma_ep_post(struct rpcrdma_ia *ia,
return 0;
}
-int
-rpcrdma_ep_post_recv(struct rpcrdma_ia *ia,
- struct rpcrdma_rep *rep)
-{
- struct ib_recv_wr *recv_wr_fail;
- int rc;
-
- if (!rpcrdma_dma_map_regbuf(ia, rep->rr_rdmabuf))
- goto out_map;
- rc = ib_post_recv(ia->ri_id->qp, &rep->rr_recv_wr, &recv_wr_fail);
- trace_xprtrdma_post_recv(rep, rc);
- if (rc)
- return -ENOTCONN;
- return 0;
-
-out_map:
- pr_err("rpcrdma: failed to DMA map the Receive buffer\n");
- return -EIO;
-}
-
/**
- * rpcrdma_ep_post_extra_recv - Post buffers for incoming backchannel requests
- * @r_xprt: transport associated with these backchannel resources
- * @count: minimum number of incoming requests expected
+ * rpcrdma_post_recvs - Maybe post some Receive buffers
+ * @r_xprt: controlling transport
+ * @temp: when true, allocate temp rpcrdma_rep objects
*
- * Returns zero if all requested buffers were posted, or a negative errno.
*/
-int
-rpcrdma_ep_post_extra_recv(struct rpcrdma_xprt *r_xprt, unsigned int count)
+void
+rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp)
{
- struct rpcrdma_buffer *buffers = &r_xprt->rx_buf;
- struct rpcrdma_ia *ia = &r_xprt->rx_ia;
- struct rpcrdma_rep *rep;
- int rc;
+ struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
+ struct ib_recv_wr *wr, *bad_wr;
+ int needed, count, rc;
- while (count--) {
- spin_lock(&buffers->rb_lock);
- if (list_empty(&buffers->rb_recv_bufs))
- goto out_reqbuf;
- rep = rpcrdma_buffer_get_rep_locked(buffers);
- spin_unlock(&buffers->rb_lock);
+ needed = buf->rb_credits + (buf->rb_bc_srv_max_requests << 1);
+ if (buf->rb_posted_receives > needed)
+ return;
+ needed -= buf->rb_posted_receives;
- rc = rpcrdma_ep_post_recv(ia, rep);
- if (rc)
- goto out_rc;
- }
+ count = 0;
+ wr = NULL;
+ while (needed) {
+ struct rpcrdma_regbuf *rb;
+ struct rpcrdma_rep *rep;
- return 0;
+ spin_lock(&buf->rb_lock);
+ rep = list_first_entry_or_null(&buf->rb_recv_bufs,
+ struct rpcrdma_rep, rr_list);
+ if (likely(rep))
+ list_del(&rep->rr_list);
+ spin_unlock(&buf->rb_lock);
+ if (!rep) {
+ if (rpcrdma_create_rep(r_xprt, temp))
+ break;
+ continue;
+ }
-out_reqbuf:
- spin_unlock(&buffers->rb_lock);
- trace_xprtrdma_noreps(r_xprt);
- return -ENOMEM;
+ rb = rep->rr_rdmabuf;
+ if (!rpcrdma_regbuf_is_mapped(rb)) {
+ if (!__rpcrdma_dma_map_regbuf(&r_xprt->rx_ia, rb)) {
+ rpcrdma_recv_buffer_put(rep);
+ break;
+ }
+ }
-out_rc:
- rpcrdma_recv_buffer_put(rep);
- return rc;
+ trace_xprtrdma_post_recv(rep->rr_recv_wr.wr_cqe);
+ rep->rr_recv_wr.next = wr;
+ wr = &rep->rr_recv_wr;
+ ++count;
+ --needed;
+ }
+ if (!count)
+ return;
+
+ rc = ib_post_recv(r_xprt->rx_ia.ri_id->qp, wr, &bad_wr);
+ if (rc) {
+ for (wr = bad_wr; wr; wr = wr->next) {
+ struct rpcrdma_rep *rep;
+
+ rep = container_of(wr, struct rpcrdma_rep, rr_recv_wr);
+ rpcrdma_recv_buffer_put(rep);
+ --count;
+ }
+ }
+ buf->rb_posted_receives += count;
+ trace_xprtrdma_post_recvs(r_xprt, count, rc);
}
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h
index cb41b12..2ca14f7 100644
--- a/net/sunrpc/xprtrdma/xprt_rdma.h
+++ b/net/sunrpc/xprtrdma/xprt_rdma.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (c) 2014-2017 Oracle. All rights reserved.
* Copyright (c) 2003-2007 Network Appliance, Inc. All rights reserved.
@@ -196,6 +197,7 @@ struct rpcrdma_rep {
__be32 rr_proc;
int rr_wc_flags;
u32 rr_inv_rkey;
+ bool rr_temp;
struct rpcrdma_regbuf *rr_rdmabuf;
struct rpcrdma_xprt *rr_rxprt;
struct work_struct rr_work;
@@ -334,6 +336,7 @@ enum {
struct rpcrdma_buffer;
struct rpcrdma_req {
struct list_head rl_list;
+ struct rpc_rqst rl_slot;
struct rpcrdma_buffer *rl_buffer;
struct rpcrdma_rep *rl_reply;
struct xdr_stream rl_stream;
@@ -356,16 +359,10 @@ enum {
RPCRDMA_REQ_F_TX_RESOURCES,
};
-static inline void
-rpcrdma_set_xprtdata(struct rpc_rqst *rqst, struct rpcrdma_req *req)
-{
- rqst->rq_xprtdata = req;
-}
-
static inline struct rpcrdma_req *
rpcr_to_rdmar(const struct rpc_rqst *rqst)
{
- return rqst->rq_xprtdata;
+ return container_of(rqst, struct rpcrdma_req, rl_slot);
}
static inline void
@@ -401,11 +398,12 @@ struct rpcrdma_buffer {
struct rpcrdma_sendctx **rb_sc_ctxs;
spinlock_t rb_lock; /* protect buf lists */
- int rb_send_count, rb_recv_count;
struct list_head rb_send_bufs;
struct list_head rb_recv_bufs;
+ unsigned long rb_flags;
u32 rb_max_requests;
u32 rb_credits; /* most recent credit grant */
+ int rb_posted_receives;
u32 rb_bc_srv_max_requests;
spinlock_t rb_reqslock; /* protect rb_allreqs */
@@ -420,6 +418,11 @@ struct rpcrdma_buffer {
};
#define rdmab_to_ia(b) (&container_of((b), struct rpcrdma_xprt, rx_buf)->rx_ia)
+/* rb_flags */
+enum {
+ RPCRDMA_BUF_F_EMPTY_SCQ = 0,
+};
+
/*
* Internal structure for transport instance creation. This
* exists primarily for modularity.
@@ -561,18 +564,16 @@ void rpcrdma_ep_disconnect(struct rpcrdma_ep *, struct rpcrdma_ia *);
int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *,
struct rpcrdma_req *);
-int rpcrdma_ep_post_recv(struct rpcrdma_ia *, struct rpcrdma_rep *);
+void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp);
/*
* Buffer calls - xprtrdma/verbs.c
*/
struct rpcrdma_req *rpcrdma_create_req(struct rpcrdma_xprt *);
void rpcrdma_destroy_req(struct rpcrdma_req *);
-int rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt);
int rpcrdma_buffer_create(struct rpcrdma_xprt *);
void rpcrdma_buffer_destroy(struct rpcrdma_buffer *);
struct rpcrdma_sendctx *rpcrdma_sendctx_get_locked(struct rpcrdma_buffer *buf);
-void rpcrdma_sendctx_put_locked(struct rpcrdma_sendctx *sc);
struct rpcrdma_mr *rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt);
void rpcrdma_mr_put(struct rpcrdma_mr *mr);
@@ -581,7 +582,6 @@ void rpcrdma_mr_defer_recovery(struct rpcrdma_mr *mr);
struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *);
void rpcrdma_buffer_put(struct rpcrdma_req *);
-void rpcrdma_recv_buffer_get(struct rpcrdma_req *);
void rpcrdma_recv_buffer_put(struct rpcrdma_rep *);
struct rpcrdma_regbuf *rpcrdma_alloc_regbuf(size_t, enum dma_data_direction,
@@ -603,8 +603,6 @@ rpcrdma_dma_map_regbuf(struct rpcrdma_ia *ia, struct rpcrdma_regbuf *rb)
return __rpcrdma_dma_map_regbuf(ia, rb);
}
-int rpcrdma_ep_post_extra_recv(struct rpcrdma_xprt *, unsigned int);
-
int rpcrdma_alloc_wq(void);
void rpcrdma_destroy_wq(void);
@@ -675,5 +673,3 @@ void xprt_rdma_bc_destroy(struct rpc_xprt *, unsigned int);
extern struct xprt_class xprt_rdma_bc;
#endif /* _LINUX_SUNRPC_XPRT_RDMA_H */
-
-#include <trace/events/rpcrdma.h>
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index c8902f1..9e1c502 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -2763,6 +2763,7 @@ static const struct rpc_xprt_ops xs_local_ops = {
.reserve_xprt = xprt_reserve_xprt,
.release_xprt = xs_tcp_release_xprt,
.alloc_slot = xprt_alloc_slot,
+ .free_slot = xprt_free_slot,
.rpcbind = xs_local_rpcbind,
.set_port = xs_local_set_port,
.connect = xs_local_connect,
@@ -2782,6 +2783,7 @@ static const struct rpc_xprt_ops xs_udp_ops = {
.reserve_xprt = xprt_reserve_xprt_cong,
.release_xprt = xprt_release_xprt_cong,
.alloc_slot = xprt_alloc_slot,
+ .free_slot = xprt_free_slot,
.rpcbind = rpcb_getport_async,
.set_port = xs_set_port,
.connect = xs_connect,
@@ -2803,6 +2805,7 @@ static const struct rpc_xprt_ops xs_tcp_ops = {
.reserve_xprt = xprt_reserve_xprt,
.release_xprt = xs_tcp_release_xprt,
.alloc_slot = xprt_lock_and_alloc_slot,
+ .free_slot = xprt_free_slot,
.rpcbind = rpcb_getport_async,
.set_port = xs_set_port,
.connect = xs_connect,
@@ -2834,6 +2837,7 @@ static const struct rpc_xprt_ops bc_tcp_ops = {
.reserve_xprt = xprt_reserve_xprt,
.release_xprt = xprt_release_xprt,
.alloc_slot = xprt_alloc_slot,
+ .free_slot = xprt_free_slot,
.buf_alloc = bc_malloc,
.buf_free = bc_free,
.send_request = bc_send_request,
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index 4492cda..a2f7674 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -285,8 +285,9 @@ static int __tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd,
if (!trans_buf)
return -ENOMEM;
- attrbuf = kmalloc((tipc_genl_family.maxattr + 1) *
- sizeof(struct nlattr *), GFP_KERNEL);
+ attrbuf = kmalloc_array(tipc_genl_family.maxattr + 1,
+ sizeof(struct nlattr *),
+ GFP_KERNEL);
if (!attrbuf) {
err = -ENOMEM;
goto trans_out;
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 301f224..a127d61 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -712,7 +712,7 @@ static int __init tls_register(void)
build_protos(tls_prots[TLSV4], &tcp_prot);
tls_sw_proto_ops = inet_stream_ops;
- tls_sw_proto_ops.poll = tls_sw_poll;
+ tls_sw_proto_ops.poll_mask = tls_sw_poll_mask;
tls_sw_proto_ops.splice_read = tls_sw_splice_read;
#ifdef CONFIG_TLS_DEVICE
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 8ca57d0..f127fac 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -191,18 +191,12 @@ static void tls_free_both_sg(struct sock *sk)
}
static int tls_do_encryption(struct tls_context *tls_ctx,
- struct tls_sw_context_tx *ctx, size_t data_len,
- gfp_t flags)
+ struct tls_sw_context_tx *ctx,
+ struct aead_request *aead_req,
+ size_t data_len)
{
- unsigned int req_size = sizeof(struct aead_request) +
- crypto_aead_reqsize(ctx->aead_send);
- struct aead_request *aead_req;
int rc;
- aead_req = kzalloc(req_size, flags);
- if (!aead_req)
- return -ENOMEM;
-
ctx->sg_encrypted_data[0].offset += tls_ctx->tx.prepend_size;
ctx->sg_encrypted_data[0].length -= tls_ctx->tx.prepend_size;
@@ -219,7 +213,6 @@ static int tls_do_encryption(struct tls_context *tls_ctx,
ctx->sg_encrypted_data[0].offset -= tls_ctx->tx.prepend_size;
ctx->sg_encrypted_data[0].length += tls_ctx->tx.prepend_size;
- kfree(aead_req);
return rc;
}
@@ -228,8 +221,14 @@ static int tls_push_record(struct sock *sk, int flags,
{
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx);
+ struct aead_request *req;
int rc;
+ req = kzalloc(sizeof(struct aead_request) +
+ crypto_aead_reqsize(ctx->aead_send), sk->sk_allocation);
+ if (!req)
+ return -ENOMEM;
+
sg_mark_end(ctx->sg_plaintext_data + ctx->sg_plaintext_num_elem - 1);
sg_mark_end(ctx->sg_encrypted_data + ctx->sg_encrypted_num_elem - 1);
@@ -245,15 +244,14 @@ static int tls_push_record(struct sock *sk, int flags,
tls_ctx->pending_open_record_frags = 0;
set_bit(TLS_PENDING_CLOSED_RECORD, &tls_ctx->flags);
- rc = tls_do_encryption(tls_ctx, ctx, ctx->sg_plaintext_size,
- sk->sk_allocation);
+ rc = tls_do_encryption(tls_ctx, ctx, req, ctx->sg_plaintext_size);
if (rc < 0) {
/* If we are called from write_space and
* we fail, we need to set this SOCK_NOSPACE
* to trigger another write_space in the future.
*/
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
- return rc;
+ goto out_req;
}
free_sg(sk, ctx->sg_plaintext_data, &ctx->sg_plaintext_num_elem,
@@ -268,6 +266,8 @@ static int tls_push_record(struct sock *sk, int flags,
tls_err_abort(sk, EBADMSG);
tls_advance_record_sn(sk, &tls_ctx->tx);
+out_req:
+ kfree(req);
return rc;
}
@@ -754,7 +754,7 @@ int tls_sw_recvmsg(struct sock *sk,
struct sk_buff *skb;
ssize_t copied = 0;
bool cmsg = false;
- int err = 0;
+ int target, err = 0;
long timeo;
flags |= nonblock;
@@ -764,6 +764,7 @@ int tls_sw_recvmsg(struct sock *sk,
lock_sock(sk);
+ target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
do {
bool zc = false;
@@ -856,6 +857,9 @@ fallback_to_reg_recv:
goto recv_end;
}
}
+ /* If we have a new message from strparser, continue now. */
+ if (copied >= target && !ctx->recv_pkt)
+ break;
} while (len);
recv_end:
@@ -915,23 +919,22 @@ splice_read_end:
return copied ? : err;
}
-unsigned int tls_sw_poll(struct file *file, struct socket *sock,
- struct poll_table_struct *wait)
+__poll_t tls_sw_poll_mask(struct socket *sock, __poll_t events)
{
- unsigned int ret;
struct sock *sk = sock->sk;
struct tls_context *tls_ctx = tls_get_ctx(sk);
struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
+ __poll_t mask;
- /* Grab POLLOUT and POLLHUP from the underlying socket */
- ret = ctx->sk_poll(file, sock, wait);
+ /* Grab EPOLLOUT and EPOLLHUP from the underlying socket */
+ mask = ctx->sk_poll_mask(sock, events);
- /* Clear POLLIN bits, and set based on recv_pkt */
- ret &= ~(POLLIN | POLLRDNORM);
+ /* Clear EPOLLIN bits, and set based on recv_pkt */
+ mask &= ~(EPOLLIN | EPOLLRDNORM);
if (ctx->recv_pkt)
- ret |= POLLIN | POLLRDNORM;
+ mask |= EPOLLIN | EPOLLRDNORM;
- return ret;
+ return mask;
}
static int tls_read_size(struct strparser *strp, struct sk_buff *skb)
@@ -1188,7 +1191,7 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx)
sk->sk_data_ready = tls_data_ready;
write_unlock_bh(&sk->sk_callback_lock);
- sw_ctx_rx->sk_poll = sk->sk_socket->ops->poll;
+ sw_ctx_rx->sk_poll_mask = sk->sk_socket->ops->poll_mask;
strp_check_rcv(&sw_ctx_rx->strp);
}
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 5fe35aa..48e80973 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1012,6 +1012,7 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
list_del_rcu(&wdev->list);
+ synchronize_rcu();
rdev->devlist_generation++;
switch (wdev->iftype) {
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 07514ca..c7bbe5f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10833,7 +10833,7 @@ static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
struct nlattr **tb;
int err;
- tb = kzalloc(NUM_NL80211_ATTR * sizeof(*tb), GFP_KERNEL);
+ tb = kcalloc(NUM_NL80211_ATTR, sizeof(*tb), GFP_KERNEL);
if (!tb)
return -ENOMEM;
@@ -11793,7 +11793,7 @@ static int nl80211_nan_add_func(struct sk_buff *skb,
func->srf_num_macs = n_entries;
func->srf_macs =
- kzalloc(sizeof(*func->srf_macs) * n_entries,
+ kcalloc(n_entries, sizeof(*func->srf_macs),
GFP_KERNEL);
if (!func->srf_macs) {
err = -ENOMEM;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index b5bb1c3..3c654cd 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1746,6 +1746,8 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
if (!rdev->ops->get_station)
return -EOPNOTSUPP;
+ memset(sinfo, 0, sizeof(*sinfo));
+
return rdev_get_station(rdev, dev, mac_addr, sinfo);
}
EXPORT_SYMBOL(cfg80211_get_station);
diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c
index 7eb4948..f47abb4 100644
--- a/net/xdp/xdp_umem.c
+++ b/net/xdp/xdp_umem.c
@@ -132,8 +132,10 @@ static void xdp_umem_unpin_pages(struct xdp_umem *umem)
static void xdp_umem_unaccount_pages(struct xdp_umem *umem)
{
- atomic_long_sub(umem->npgs, &umem->user->locked_vm);
- free_uid(umem->user);
+ if (umem->user) {
+ atomic_long_sub(umem->npgs, &umem->user->locked_vm);
+ free_uid(umem->user);
+ }
}
static void xdp_umem_release(struct xdp_umem *umem)
@@ -202,7 +204,8 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem)
long npgs;
int err;
- umem->pgs = kcalloc(umem->npgs, sizeof(*umem->pgs), GFP_KERNEL);
+ umem->pgs = kcalloc(umem->npgs, sizeof(*umem->pgs),
+ GFP_KERNEL | __GFP_NOWARN);
if (!umem->pgs)
return -ENOMEM;
diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
index c6ed245..3b3410a 100644
--- a/net/xdp/xsk.c
+++ b/net/xdp/xsk.c
@@ -118,6 +118,9 @@ int xsk_generic_rcv(struct xdp_sock *xs, struct xdp_buff *xdp)
u64 addr;
int err;
+ if (xs->dev != xdp->rxq->dev || xs->queue_id != xdp->rxq->queue_index)
+ return -EINVAL;
+
if (!xskq_peek_addr(xs->umem->fq, &addr) ||
len > xs->umem->chunk_size_nohr) {
xs->rx_dropped++;
@@ -643,7 +646,7 @@ static int xsk_getsockopt(struct socket *sock, int level, int optname,
static int xsk_mmap(struct file *file, struct socket *sock,
struct vm_area_struct *vma)
{
- unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ loff_t offset = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
unsigned long size = vma->vm_end - vma->vm_start;
struct xdp_sock *xs = xdp_sk(sock->sk);
struct xsk_queue *q = NULL;
diff --git a/samples/Kconfig b/samples/Kconfig
index 3db002b..bd133ef 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -115,6 +115,37 @@ config SAMPLE_VFIO_MDEV_MTTY
Build a virtual tty sample driver for use as a VFIO
mediated device
+config SAMPLE_VFIO_MDEV_MDPY
+ tristate "Build VFIO mdpy example mediated device sample code -- loadable modules only"
+ depends on VFIO_MDEV_DEVICE && m
+ help
+ Build a virtual display sample driver for use as a VFIO
+ mediated device. It is a simple framebuffer and supports
+ the region display interface (VFIO_GFX_PLANE_TYPE_REGION).
+
+config SAMPLE_VFIO_MDEV_MDPY_FB
+ tristate "Build VFIO mdpy example guest fbdev driver -- loadable module only"
+ depends on FB && m
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Guest fbdev driver for the virtual display sample driver.
+
+config SAMPLE_VFIO_MDEV_MBOCHS
+ tristate "Build VFIO mdpy example mediated device sample code -- loadable modules only"
+ depends on VFIO_MDEV_DEVICE && m
+ select DMA_SHARED_BUFFER
+ help
+ Build a virtual display sample driver for use as a VFIO
+ mediated device. It supports the region display interface
+ (VFIO_GFX_PLANE_TYPE_DMABUF).
+ Emulate enough of qemu stdvga to make bochs-drm.ko happy.
+ That is basically the vram memory bar and the bochs dispi
+ interface vbe registers in the mmio register bar.
+ Specifically it does *not* include any legacy vga stuff.
+ Device looks a lot like "qemu -device secondary-vga".
+
config SAMPLE_STATX
bool "Build example extended-stat using code"
depends on BROKEN
diff --git a/samples/vfio-mdev/Makefile b/samples/vfio-mdev/Makefile
index cbbd868..7db889ca13 100644
--- a/samples/vfio-mdev/Makefile
+++ b/samples/vfio-mdev/Makefile
@@ -1 +1,4 @@
obj-$(CONFIG_SAMPLE_VFIO_MDEV_MTTY) += mtty.o
+obj-$(CONFIG_SAMPLE_VFIO_MDEV_MDPY) += mdpy.o
+obj-$(CONFIG_SAMPLE_VFIO_MDEV_MDPY_FB) += mdpy-fb.o
+obj-$(CONFIG_SAMPLE_VFIO_MDEV_MBOCHS) += mbochs.o
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
new file mode 100644
index 0000000..2960e26
--- /dev/null
+++ b/samples/vfio-mdev/mbochs.c
@@ -0,0 +1,1406 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediated virtual PCI display host device driver
+ *
+ * Emulate enough of qemu stdvga to make bochs-drm.ko happy. That is
+ * basically the vram memory bar and the bochs dispi interface vbe
+ * registers in the mmio register bar. Specifically it does *not*
+ * include any legacy vga stuff. Device looks a lot like "qemu -device
+ * secondary-vga".
+ *
+ * (c) Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * based on mtty driver which is:
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Author: Neo Jia <cjia@nvidia.com>
+ * Kirti Wankhede <kwankhede@nvidia.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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/cdev.h>
+#include <linux/vfio.h>
+#include <linux/iommu.h>
+#include <linux/sysfs.h>
+#include <linux/mdev.h>
+#include <linux/pci.h>
+#include <linux/dma-buf.h>
+#include <linux/highmem.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_rect.h>
+#include <drm/drm_modeset_lock.h>
+#include <drm/drm_property.h>
+#include <drm/drm_plane.h>
+
+
+#define VBE_DISPI_INDEX_ID 0x0
+#define VBE_DISPI_INDEX_XRES 0x1
+#define VBE_DISPI_INDEX_YRES 0x2
+#define VBE_DISPI_INDEX_BPP 0x3
+#define VBE_DISPI_INDEX_ENABLE 0x4
+#define VBE_DISPI_INDEX_BANK 0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
+#define VBE_DISPI_INDEX_X_OFFSET 0x8
+#define VBE_DISPI_INDEX_Y_OFFSET 0x9
+#define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa
+#define VBE_DISPI_INDEX_COUNT 0xb
+
+#define VBE_DISPI_ID0 0xB0C0
+#define VBE_DISPI_ID1 0xB0C1
+#define VBE_DISPI_ID2 0xB0C2
+#define VBE_DISPI_ID3 0xB0C3
+#define VBE_DISPI_ID4 0xB0C4
+#define VBE_DISPI_ID5 0xB0C5
+
+#define VBE_DISPI_DISABLED 0x00
+#define VBE_DISPI_ENABLED 0x01
+#define VBE_DISPI_GETCAPS 0x02
+#define VBE_DISPI_8BIT_DAC 0x20
+#define VBE_DISPI_LFB_ENABLED 0x40
+#define VBE_DISPI_NOCLEARMEM 0x80
+
+
+#define MBOCHS_NAME "mbochs"
+#define MBOCHS_CLASS_NAME "mbochs"
+
+#define MBOCHS_CONFIG_SPACE_SIZE 0xff
+#define MBOCHS_MMIO_BAR_OFFSET PAGE_SIZE
+#define MBOCHS_MMIO_BAR_SIZE PAGE_SIZE
+#define MBOCHS_MEMORY_BAR_OFFSET (MBOCHS_MMIO_BAR_OFFSET + \
+ MBOCHS_MMIO_BAR_SIZE)
+
+#define STORE_LE16(addr, val) (*(u16 *)addr = val)
+#define STORE_LE32(addr, val) (*(u32 *)addr = val)
+
+
+MODULE_LICENSE("GPL v2");
+
+static int max_mbytes = 256;
+module_param_named(count, max_mbytes, int, 0444);
+MODULE_PARM_DESC(mem, "megabytes available to " MBOCHS_NAME " devices");
+
+
+#define MBOCHS_TYPE_1 "small"
+#define MBOCHS_TYPE_2 "medium"
+#define MBOCHS_TYPE_3 "large"
+
+static const struct mbochs_type {
+ const char *name;
+ u32 mbytes;
+} mbochs_types[] = {
+ {
+ .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
+ .mbytes = 4,
+ }, {
+ .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
+ .mbytes = 16,
+ }, {
+ .name = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
+ .mbytes = 64,
+ },
+};
+
+
+static dev_t mbochs_devt;
+static struct class *mbochs_class;
+static struct cdev mbochs_cdev;
+static struct device mbochs_dev;
+static int mbochs_used_mbytes;
+
+struct mbochs_mode {
+ u32 drm_format;
+ u32 bytepp;
+ u32 width;
+ u32 height;
+ u32 stride;
+ u32 __pad;
+ u64 offset;
+ u64 size;
+};
+
+struct mbochs_dmabuf {
+ struct mbochs_mode mode;
+ u32 id;
+ struct page **pages;
+ pgoff_t pagecount;
+ struct dma_buf *buf;
+ struct mdev_state *mdev_state;
+ struct list_head next;
+ bool unlinked;
+};
+
+/* State of each mdev device */
+struct mdev_state {
+ u8 *vconfig;
+ u64 bar_mask[3];
+ u32 memory_bar_mask;
+ struct mutex ops_lock;
+ struct mdev_device *mdev;
+ struct vfio_device_info dev_info;
+
+ const struct mbochs_type *type;
+ u16 vbe[VBE_DISPI_INDEX_COUNT];
+ u64 memsize;
+ struct page **pages;
+ pgoff_t pagecount;
+
+ struct list_head dmabufs;
+ u32 active_id;
+ u32 next_id;
+};
+
+static const char *vbe_name_list[VBE_DISPI_INDEX_COUNT] = {
+ [VBE_DISPI_INDEX_ID] = "id",
+ [VBE_DISPI_INDEX_XRES] = "xres",
+ [VBE_DISPI_INDEX_YRES] = "yres",
+ [VBE_DISPI_INDEX_BPP] = "bpp",
+ [VBE_DISPI_INDEX_ENABLE] = "enable",
+ [VBE_DISPI_INDEX_BANK] = "bank",
+ [VBE_DISPI_INDEX_VIRT_WIDTH] = "virt-width",
+ [VBE_DISPI_INDEX_VIRT_HEIGHT] = "virt-height",
+ [VBE_DISPI_INDEX_X_OFFSET] = "x-offset",
+ [VBE_DISPI_INDEX_Y_OFFSET] = "y-offset",
+ [VBE_DISPI_INDEX_VIDEO_MEMORY_64K] = "video-mem",
+};
+
+static const char *vbe_name(u32 index)
+{
+ if (index < ARRAY_SIZE(vbe_name_list))
+ return vbe_name_list[index];
+ return "(invalid)";
+}
+
+static struct page *mbochs_get_page(struct mdev_state *mdev_state,
+ pgoff_t pgoff);
+
+static const struct mbochs_type *mbochs_find_type(struct kobject *kobj)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mbochs_types); i++)
+ if (strcmp(mbochs_types[i].name, kobj->name) == 0)
+ return mbochs_types + i;
+ return NULL;
+}
+
+static void mbochs_create_config_space(struct mdev_state *mdev_state)
+{
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_VENDOR_ID],
+ 0x1234);
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_DEVICE_ID],
+ 0x1111);
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_SUBSYSTEM_VENDOR_ID],
+ PCI_SUBVENDOR_ID_REDHAT_QUMRANET);
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_SUBSYSTEM_ID],
+ PCI_SUBDEVICE_ID_QEMU);
+
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_COMMAND],
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_CLASS_DEVICE],
+ PCI_CLASS_DISPLAY_OTHER);
+ mdev_state->vconfig[PCI_CLASS_REVISION] = 0x01;
+
+ STORE_LE32((u32 *) &mdev_state->vconfig[PCI_BASE_ADDRESS_0],
+ PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_32 |
+ PCI_BASE_ADDRESS_MEM_PREFETCH);
+ mdev_state->bar_mask[0] = ~(mdev_state->memsize) + 1;
+
+ STORE_LE32((u32 *) &mdev_state->vconfig[PCI_BASE_ADDRESS_2],
+ PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_32);
+ mdev_state->bar_mask[2] = ~(MBOCHS_MMIO_BAR_SIZE) + 1;
+}
+
+static int mbochs_check_framebuffer(struct mdev_state *mdev_state,
+ struct mbochs_mode *mode)
+{
+ struct device *dev = mdev_dev(mdev_state->mdev);
+ u16 *vbe = mdev_state->vbe;
+ u32 virt_width;
+
+ WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
+
+ if (!(vbe[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED))
+ goto nofb;
+
+ memset(mode, 0, sizeof(*mode));
+ switch (vbe[VBE_DISPI_INDEX_BPP]) {
+ case 32:
+ mode->drm_format = DRM_FORMAT_XRGB8888;
+ mode->bytepp = 4;
+ break;
+ default:
+ dev_info_ratelimited(dev, "%s: bpp %d not supported\n",
+ __func__, vbe[VBE_DISPI_INDEX_BPP]);
+ goto nofb;
+ }
+
+ mode->width = vbe[VBE_DISPI_INDEX_XRES];
+ mode->height = vbe[VBE_DISPI_INDEX_YRES];
+ virt_width = vbe[VBE_DISPI_INDEX_VIRT_WIDTH];
+ if (virt_width < mode->width)
+ virt_width = mode->width;
+ mode->stride = virt_width * mode->bytepp;
+ mode->size = (u64)mode->stride * mode->height;
+ mode->offset = ((u64)vbe[VBE_DISPI_INDEX_X_OFFSET] * mode->bytepp +
+ (u64)vbe[VBE_DISPI_INDEX_Y_OFFSET] * mode->stride);
+
+ if (mode->width < 64 || mode->height < 64) {
+ dev_info_ratelimited(dev, "%s: invalid resolution %dx%d\n",
+ __func__, mode->width, mode->height);
+ goto nofb;
+ }
+ if (mode->offset + mode->size > mdev_state->memsize) {
+ dev_info_ratelimited(dev, "%s: framebuffer memory overflow\n",
+ __func__);
+ goto nofb;
+ }
+
+ return 0;
+
+nofb:
+ memset(mode, 0, sizeof(*mode));
+ return -EINVAL;
+}
+
+static bool mbochs_modes_equal(struct mbochs_mode *mode1,
+ struct mbochs_mode *mode2)
+{
+ return memcmp(mode1, mode2, sizeof(struct mbochs_mode)) == 0;
+}
+
+static void handle_pci_cfg_write(struct mdev_state *mdev_state, u16 offset,
+ char *buf, u32 count)
+{
+ struct device *dev = mdev_dev(mdev_state->mdev);
+ int index = (offset - PCI_BASE_ADDRESS_0) / 0x04;
+ u32 cfg_addr;
+
+ switch (offset) {
+ case PCI_BASE_ADDRESS_0:
+ case PCI_BASE_ADDRESS_2:
+ cfg_addr = *(u32 *)buf;
+
+ if (cfg_addr == 0xffffffff) {
+ cfg_addr = (cfg_addr & mdev_state->bar_mask[index]);
+ } else {
+ cfg_addr &= PCI_BASE_ADDRESS_MEM_MASK;
+ if (cfg_addr)
+ dev_info(dev, "BAR #%d @ 0x%x\n",
+ index, cfg_addr);
+ }
+
+ cfg_addr |= (mdev_state->vconfig[offset] &
+ ~PCI_BASE_ADDRESS_MEM_MASK);
+ STORE_LE32(&mdev_state->vconfig[offset], cfg_addr);
+ break;
+ }
+}
+
+static void handle_mmio_write(struct mdev_state *mdev_state, u16 offset,
+ char *buf, u32 count)
+{
+ struct device *dev = mdev_dev(mdev_state->mdev);
+ int index;
+ u16 reg16;
+
+ switch (offset) {
+ case 0x400 ... 0x41f: /* vga ioports remapped */
+ goto unhandled;
+ case 0x500 ... 0x515: /* bochs dispi interface */
+ if (count != 2)
+ goto unhandled;
+ index = (offset - 0x500) / 2;
+ reg16 = *(u16 *)buf;
+ if (index < ARRAY_SIZE(mdev_state->vbe))
+ mdev_state->vbe[index] = reg16;
+ dev_dbg(dev, "%s: vbe write %d = %d (%s)\n",
+ __func__, index, reg16, vbe_name(index));
+ break;
+ case 0x600 ... 0x607: /* qemu extended regs */
+ goto unhandled;
+ default:
+unhandled:
+ dev_dbg(dev, "%s: @0x%03x, count %d (unhandled)\n",
+ __func__, offset, count);
+ break;
+ }
+}
+
+static void handle_mmio_read(struct mdev_state *mdev_state, u16 offset,
+ char *buf, u32 count)
+{
+ struct device *dev = mdev_dev(mdev_state->mdev);
+ u16 reg16 = 0;
+ int index;
+
+ switch (offset) {
+ case 0x500 ... 0x515: /* bochs dispi interface */
+ if (count != 2)
+ goto unhandled;
+ index = (offset - 0x500) / 2;
+ if (index < ARRAY_SIZE(mdev_state->vbe))
+ reg16 = mdev_state->vbe[index];
+ dev_dbg(dev, "%s: vbe read %d = %d (%s)\n",
+ __func__, index, reg16, vbe_name(index));
+ *(u16 *)buf = reg16;
+ break;
+ default:
+unhandled:
+ dev_dbg(dev, "%s: @0x%03x, count %d (unhandled)\n",
+ __func__, offset, count);
+ memset(buf, 0, count);
+ break;
+ }
+}
+
+static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
+ loff_t pos, bool is_write)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+ struct device *dev = mdev_dev(mdev);
+ struct page *pg;
+ loff_t poff;
+ char *map;
+ int ret = 0;
+
+ mutex_lock(&mdev_state->ops_lock);
+
+ if (pos < MBOCHS_CONFIG_SPACE_SIZE) {
+ if (is_write)
+ handle_pci_cfg_write(mdev_state, pos, buf, count);
+ else
+ memcpy(buf, (mdev_state->vconfig + pos), count);
+
+ } else if (pos >= MBOCHS_MMIO_BAR_OFFSET &&
+ pos + count <= MBOCHS_MEMORY_BAR_OFFSET) {
+ pos -= MBOCHS_MMIO_BAR_OFFSET;
+ if (is_write)
+ handle_mmio_write(mdev_state, pos, buf, count);
+ else
+ handle_mmio_read(mdev_state, pos, buf, count);
+
+ } else if (pos >= MBOCHS_MEMORY_BAR_OFFSET &&
+ pos + count <=
+ MBOCHS_MEMORY_BAR_OFFSET + mdev_state->memsize) {
+ pos -= MBOCHS_MMIO_BAR_OFFSET;
+ poff = pos & ~PAGE_MASK;
+ pg = mbochs_get_page(mdev_state, pos >> PAGE_SHIFT);
+ map = kmap(pg);
+ if (is_write)
+ memcpy(map + poff, buf, count);
+ else
+ memcpy(buf, map + poff, count);
+ kunmap(pg);
+ put_page(pg);
+
+ } else {
+ dev_dbg(dev, "%s: %s @0x%llx (unhandled)\n",
+ __func__, is_write ? "WR" : "RD", pos);
+ ret = -1;
+ goto accessfailed;
+ }
+
+ ret = count;
+
+
+accessfailed:
+ mutex_unlock(&mdev_state->ops_lock);
+
+ return ret;
+}
+
+static int mbochs_reset(struct mdev_device *mdev)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+ u32 size64k = mdev_state->memsize / (64 * 1024);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mdev_state->vbe); i++)
+ mdev_state->vbe[i] = 0;
+ mdev_state->vbe[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID5;
+ mdev_state->vbe[VBE_DISPI_INDEX_VIDEO_MEMORY_64K] = size64k;
+ return 0;
+}
+
+static int mbochs_create(struct kobject *kobj, struct mdev_device *mdev)
+{
+ const struct mbochs_type *type = mbochs_find_type(kobj);
+ struct device *dev = mdev_dev(mdev);
+ struct mdev_state *mdev_state;
+
+ if (!type)
+ type = &mbochs_types[0];
+ if (type->mbytes + mbochs_used_mbytes > max_mbytes)
+ return -ENOMEM;
+
+ mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
+ if (mdev_state == NULL)
+ return -ENOMEM;
+
+ mdev_state->vconfig = kzalloc(MBOCHS_CONFIG_SPACE_SIZE, GFP_KERNEL);
+ if (mdev_state->vconfig == NULL)
+ goto err_mem;
+
+ mdev_state->memsize = type->mbytes * 1024 * 1024;
+ mdev_state->pagecount = mdev_state->memsize >> PAGE_SHIFT;
+ mdev_state->pages = kcalloc(mdev_state->pagecount,
+ sizeof(struct page *),
+ GFP_KERNEL);
+ if (!mdev_state->pages)
+ goto err_mem;
+
+ dev_info(dev, "%s: %s, %d MB, %ld pages\n", __func__,
+ kobj->name, type->mbytes, mdev_state->pagecount);
+
+ mutex_init(&mdev_state->ops_lock);
+ mdev_state->mdev = mdev;
+ mdev_set_drvdata(mdev, mdev_state);
+ INIT_LIST_HEAD(&mdev_state->dmabufs);
+ mdev_state->next_id = 1;
+
+ mdev_state->type = type;
+ mbochs_create_config_space(mdev_state);
+ mbochs_reset(mdev);
+
+ mbochs_used_mbytes += type->mbytes;
+ return 0;
+
+err_mem:
+ kfree(mdev_state->vconfig);
+ kfree(mdev_state);
+ return -ENOMEM;
+}
+
+static int mbochs_remove(struct mdev_device *mdev)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+
+ mbochs_used_mbytes -= mdev_state->type->mbytes;
+ mdev_set_drvdata(mdev, NULL);
+ kfree(mdev_state->pages);
+ kfree(mdev_state->vconfig);
+ kfree(mdev_state);
+ return 0;
+}
+
+static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int done = 0;
+ int ret;
+
+ while (count) {
+ size_t filled;
+
+ if (count >= 4 && !(*ppos % 4)) {
+ u32 val;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, false);
+ if (ret <= 0)
+ goto read_err;
+
+ if (copy_to_user(buf, &val, sizeof(val)))
+ goto read_err;
+
+ filled = 4;
+ } else if (count >= 2 && !(*ppos % 2)) {
+ u16 val;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, false);
+ if (ret <= 0)
+ goto read_err;
+
+ if (copy_to_user(buf, &val, sizeof(val)))
+ goto read_err;
+
+ filled = 2;
+ } else {
+ u8 val;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, false);
+ if (ret <= 0)
+ goto read_err;
+
+ if (copy_to_user(buf, &val, sizeof(val)))
+ goto read_err;
+
+ filled = 1;
+ }
+
+ count -= filled;
+ done += filled;
+ *ppos += filled;
+ buf += filled;
+ }
+
+ return done;
+
+read_err:
+ return -EFAULT;
+}
+
+static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int done = 0;
+ int ret;
+
+ while (count) {
+ size_t filled;
+
+ if (count >= 4 && !(*ppos % 4)) {
+ u32 val;
+
+ if (copy_from_user(&val, buf, sizeof(val)))
+ goto write_err;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, true);
+ if (ret <= 0)
+ goto write_err;
+
+ filled = 4;
+ } else if (count >= 2 && !(*ppos % 2)) {
+ u16 val;
+
+ if (copy_from_user(&val, buf, sizeof(val)))
+ goto write_err;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, true);
+ if (ret <= 0)
+ goto write_err;
+
+ filled = 2;
+ } else {
+ u8 val;
+
+ if (copy_from_user(&val, buf, sizeof(val)))
+ goto write_err;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, true);
+ if (ret <= 0)
+ goto write_err;
+
+ filled = 1;
+ }
+ count -= filled;
+ done += filled;
+ *ppos += filled;
+ buf += filled;
+ }
+
+ return done;
+write_err:
+ return -EFAULT;
+}
+
+static struct page *__mbochs_get_page(struct mdev_state *mdev_state,
+ pgoff_t pgoff)
+{
+ WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
+
+ if (!mdev_state->pages[pgoff]) {
+ mdev_state->pages[pgoff] =
+ alloc_pages(GFP_HIGHUSER | __GFP_ZERO, 0);
+ if (!mdev_state->pages[pgoff])
+ return NULL;
+ }
+
+ get_page(mdev_state->pages[pgoff]);
+ return mdev_state->pages[pgoff];
+}
+
+static struct page *mbochs_get_page(struct mdev_state *mdev_state,
+ pgoff_t pgoff)
+{
+ struct page *page;
+
+ if (WARN_ON(pgoff >= mdev_state->pagecount))
+ return NULL;
+
+ mutex_lock(&mdev_state->ops_lock);
+ page = __mbochs_get_page(mdev_state, pgoff);
+ mutex_unlock(&mdev_state->ops_lock);
+
+ return page;
+}
+
+static void mbochs_put_pages(struct mdev_state *mdev_state)
+{
+ struct device *dev = mdev_dev(mdev_state->mdev);
+ int i, count = 0;
+
+ WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
+
+ for (i = 0; i < mdev_state->pagecount; i++) {
+ if (!mdev_state->pages[i])
+ continue;
+ put_page(mdev_state->pages[i]);
+ mdev_state->pages[i] = NULL;
+ count++;
+ }
+ dev_dbg(dev, "%s: %d pages released\n", __func__, count);
+}
+
+static int mbochs_region_vm_fault(struct vm_fault *vmf)
+{
+ struct vm_area_struct *vma = vmf->vma;
+ struct mdev_state *mdev_state = vma->vm_private_data;
+ pgoff_t page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
+
+ if (page_offset >= mdev_state->pagecount)
+ return VM_FAULT_SIGBUS;
+
+ vmf->page = mbochs_get_page(mdev_state, page_offset);
+ if (!vmf->page)
+ return VM_FAULT_SIGBUS;
+
+ return 0;
+}
+
+static const struct vm_operations_struct mbochs_region_vm_ops = {
+ .fault = mbochs_region_vm_fault,
+};
+
+static int mbochs_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+
+ if (vma->vm_pgoff != MBOCHS_MEMORY_BAR_OFFSET >> PAGE_SHIFT)
+ return -EINVAL;
+ if (vma->vm_end < vma->vm_start)
+ return -EINVAL;
+ if (vma->vm_end - vma->vm_start > mdev_state->memsize)
+ return -EINVAL;
+ if ((vma->vm_flags & VM_SHARED) == 0)
+ return -EINVAL;
+
+ vma->vm_ops = &mbochs_region_vm_ops;
+ vma->vm_private_data = mdev_state;
+ return 0;
+}
+
+static int mbochs_dmabuf_vm_fault(struct vm_fault *vmf)
+{
+ struct vm_area_struct *vma = vmf->vma;
+ struct mbochs_dmabuf *dmabuf = vma->vm_private_data;
+
+ if (WARN_ON(vmf->pgoff >= dmabuf->pagecount))
+ return VM_FAULT_SIGBUS;
+
+ vmf->page = dmabuf->pages[vmf->pgoff];
+ get_page(vmf->page);
+ return 0;
+}
+
+static const struct vm_operations_struct mbochs_dmabuf_vm_ops = {
+ .fault = mbochs_dmabuf_vm_fault,
+};
+
+static int mbochs_mmap_dmabuf(struct dma_buf *buf, struct vm_area_struct *vma)
+{
+ struct mbochs_dmabuf *dmabuf = buf->priv;
+ struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
+
+ dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
+
+ if ((vma->vm_flags & VM_SHARED) == 0)
+ return -EINVAL;
+
+ vma->vm_ops = &mbochs_dmabuf_vm_ops;
+ vma->vm_private_data = dmabuf;
+ return 0;
+}
+
+static void mbochs_print_dmabuf(struct mbochs_dmabuf *dmabuf,
+ const char *prefix)
+{
+ struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
+ u32 fourcc = dmabuf->mode.drm_format;
+
+ dev_dbg(dev, "%s/%d: %c%c%c%c, %dx%d, stride %d, off 0x%llx, size 0x%llx, pages %ld\n",
+ prefix, dmabuf->id,
+ fourcc ? ((fourcc >> 0) & 0xff) : '-',
+ fourcc ? ((fourcc >> 8) & 0xff) : '-',
+ fourcc ? ((fourcc >> 16) & 0xff) : '-',
+ fourcc ? ((fourcc >> 24) & 0xff) : '-',
+ dmabuf->mode.width, dmabuf->mode.height, dmabuf->mode.stride,
+ dmabuf->mode.offset, dmabuf->mode.size, dmabuf->pagecount);
+}
+
+static struct sg_table *mbochs_map_dmabuf(struct dma_buf_attachment *at,
+ enum dma_data_direction direction)
+{
+ struct mbochs_dmabuf *dmabuf = at->dmabuf->priv;
+ struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
+ struct sg_table *sg;
+
+ dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
+
+ sg = kzalloc(sizeof(*sg), GFP_KERNEL);
+ if (!sg)
+ goto err1;
+ if (sg_alloc_table_from_pages(sg, dmabuf->pages, dmabuf->pagecount,
+ 0, dmabuf->mode.size, GFP_KERNEL) < 0)
+ goto err2;
+ if (!dma_map_sg(at->dev, sg->sgl, sg->nents, direction))
+ goto err3;
+
+ return sg;
+
+err3:
+ sg_free_table(sg);
+err2:
+ kfree(sg);
+err1:
+ return ERR_PTR(-ENOMEM);
+}
+
+static void mbochs_unmap_dmabuf(struct dma_buf_attachment *at,
+ struct sg_table *sg,
+ enum dma_data_direction direction)
+{
+ struct mbochs_dmabuf *dmabuf = at->dmabuf->priv;
+ struct device *dev = mdev_dev(dmabuf->mdev_state->mdev);
+
+ dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
+
+ sg_free_table(sg);
+ kfree(sg);
+}
+
+static void mbochs_release_dmabuf(struct dma_buf *buf)
+{
+ struct mbochs_dmabuf *dmabuf = buf->priv;
+ struct mdev_state *mdev_state = dmabuf->mdev_state;
+ struct device *dev = mdev_dev(mdev_state->mdev);
+ pgoff_t pg;
+
+ dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
+
+ for (pg = 0; pg < dmabuf->pagecount; pg++)
+ put_page(dmabuf->pages[pg]);
+
+ mutex_lock(&mdev_state->ops_lock);
+ dmabuf->buf = NULL;
+ if (dmabuf->unlinked)
+ kfree(dmabuf);
+ mutex_unlock(&mdev_state->ops_lock);
+}
+
+static void *mbochs_kmap_atomic_dmabuf(struct dma_buf *buf,
+ unsigned long page_num)
+{
+ struct mbochs_dmabuf *dmabuf = buf->priv;
+ struct page *page = dmabuf->pages[page_num];
+
+ return kmap_atomic(page);
+}
+
+static void *mbochs_kmap_dmabuf(struct dma_buf *buf, unsigned long page_num)
+{
+ struct mbochs_dmabuf *dmabuf = buf->priv;
+ struct page *page = dmabuf->pages[page_num];
+
+ return kmap(page);
+}
+
+static struct dma_buf_ops mbochs_dmabuf_ops = {
+ .map_dma_buf = mbochs_map_dmabuf,
+ .unmap_dma_buf = mbochs_unmap_dmabuf,
+ .release = mbochs_release_dmabuf,
+ .map_atomic = mbochs_kmap_atomic_dmabuf,
+ .map = mbochs_kmap_dmabuf,
+ .mmap = mbochs_mmap_dmabuf,
+};
+
+static struct mbochs_dmabuf *mbochs_dmabuf_alloc(struct mdev_state *mdev_state,
+ struct mbochs_mode *mode)
+{
+ struct mbochs_dmabuf *dmabuf;
+ pgoff_t page_offset, pg;
+
+ WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
+
+ dmabuf = kzalloc(sizeof(struct mbochs_dmabuf), GFP_KERNEL);
+ if (!dmabuf)
+ return NULL;
+
+ dmabuf->mode = *mode;
+ dmabuf->id = mdev_state->next_id++;
+ dmabuf->pagecount = DIV_ROUND_UP(mode->size, PAGE_SIZE);
+ dmabuf->pages = kcalloc(dmabuf->pagecount, sizeof(struct page *),
+ GFP_KERNEL);
+ if (!dmabuf->pages)
+ goto err_free_dmabuf;
+
+ page_offset = dmabuf->mode.offset >> PAGE_SHIFT;
+ for (pg = 0; pg < dmabuf->pagecount; pg++) {
+ dmabuf->pages[pg] = __mbochs_get_page(mdev_state,
+ page_offset + pg);
+ if (!dmabuf->pages[pg])
+ goto err_free_pages;
+ }
+
+ dmabuf->mdev_state = mdev_state;
+ list_add(&dmabuf->next, &mdev_state->dmabufs);
+
+ mbochs_print_dmabuf(dmabuf, __func__);
+ return dmabuf;
+
+err_free_pages:
+ while (pg > 0)
+ put_page(dmabuf->pages[--pg]);
+ kfree(dmabuf->pages);
+err_free_dmabuf:
+ kfree(dmabuf);
+ return NULL;
+}
+
+static struct mbochs_dmabuf *
+mbochs_dmabuf_find_by_mode(struct mdev_state *mdev_state,
+ struct mbochs_mode *mode)
+{
+ struct mbochs_dmabuf *dmabuf;
+
+ WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
+
+ list_for_each_entry(dmabuf, &mdev_state->dmabufs, next)
+ if (mbochs_modes_equal(&dmabuf->mode, mode))
+ return dmabuf;
+
+ return NULL;
+}
+
+static struct mbochs_dmabuf *
+mbochs_dmabuf_find_by_id(struct mdev_state *mdev_state, u32 id)
+{
+ struct mbochs_dmabuf *dmabuf;
+
+ WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
+
+ list_for_each_entry(dmabuf, &mdev_state->dmabufs, next)
+ if (dmabuf->id == id)
+ return dmabuf;
+
+ return NULL;
+}
+
+static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
+{
+ struct mdev_state *mdev_state = dmabuf->mdev_state;
+ struct device *dev = mdev_dev(mdev_state->mdev);
+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+ struct dma_buf *buf;
+
+ WARN_ON(!mutex_is_locked(&mdev_state->ops_lock));
+
+ if (!IS_ALIGNED(dmabuf->mode.offset, PAGE_SIZE)) {
+ dev_info_ratelimited(dev, "%s: framebuffer not page-aligned\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ exp_info.ops = &mbochs_dmabuf_ops;
+ exp_info.size = dmabuf->mode.size;
+ exp_info.priv = dmabuf;
+
+ buf = dma_buf_export(&exp_info);
+ if (IS_ERR(buf)) {
+ dev_info_ratelimited(dev, "%s: dma_buf_export failed: %ld\n",
+ __func__, PTR_ERR(buf));
+ return PTR_ERR(buf);
+ }
+
+ dmabuf->buf = buf;
+ dev_dbg(dev, "%s: %d\n", __func__, dmabuf->id);
+ return 0;
+}
+
+static int mbochs_get_region_info(struct mdev_device *mdev,
+ struct vfio_region_info *region_info,
+ u16 *cap_type_id, void **cap_type)
+{
+ struct mdev_state *mdev_state;
+
+ mdev_state = mdev_get_drvdata(mdev);
+ if (!mdev_state)
+ return -EINVAL;
+
+ if (region_info->index >= VFIO_PCI_NUM_REGIONS)
+ return -EINVAL;
+
+ switch (region_info->index) {
+ case VFIO_PCI_CONFIG_REGION_INDEX:
+ region_info->offset = 0;
+ region_info->size = MBOCHS_CONFIG_SPACE_SIZE;
+ region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
+ VFIO_REGION_INFO_FLAG_WRITE);
+ break;
+ case VFIO_PCI_BAR0_REGION_INDEX:
+ region_info->offset = MBOCHS_MEMORY_BAR_OFFSET;
+ region_info->size = mdev_state->memsize;
+ region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
+ VFIO_REGION_INFO_FLAG_WRITE |
+ VFIO_REGION_INFO_FLAG_MMAP);
+ break;
+ case VFIO_PCI_BAR2_REGION_INDEX:
+ region_info->offset = MBOCHS_MMIO_BAR_OFFSET;
+ region_info->size = MBOCHS_MMIO_BAR_SIZE;
+ region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
+ VFIO_REGION_INFO_FLAG_WRITE);
+ break;
+ default:
+ region_info->size = 0;
+ region_info->offset = 0;
+ region_info->flags = 0;
+ }
+
+ return 0;
+}
+
+static int mbochs_get_irq_info(struct mdev_device *mdev,
+ struct vfio_irq_info *irq_info)
+{
+ irq_info->count = 0;
+ return 0;
+}
+
+static int mbochs_get_device_info(struct mdev_device *mdev,
+ struct vfio_device_info *dev_info)
+{
+ dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
+ dev_info->num_regions = VFIO_PCI_NUM_REGIONS;
+ dev_info->num_irqs = VFIO_PCI_NUM_IRQS;
+ return 0;
+}
+
+static int mbochs_query_gfx_plane(struct mdev_device *mdev,
+ struct vfio_device_gfx_plane_info *plane)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+ struct device *dev = mdev_dev(mdev);
+ struct mbochs_dmabuf *dmabuf;
+ struct mbochs_mode mode;
+ int ret;
+
+ if (plane->flags & VFIO_GFX_PLANE_TYPE_PROBE) {
+ if (plane->flags == (VFIO_GFX_PLANE_TYPE_PROBE |
+ VFIO_GFX_PLANE_TYPE_DMABUF))
+ return 0;
+ return -EINVAL;
+ }
+
+ if (plane->flags != VFIO_GFX_PLANE_TYPE_DMABUF)
+ return -EINVAL;
+
+ plane->drm_format_mod = 0;
+ plane->x_pos = 0;
+ plane->y_pos = 0;
+ plane->x_hot = 0;
+ plane->y_hot = 0;
+
+ mutex_lock(&mdev_state->ops_lock);
+
+ ret = -EINVAL;
+ if (plane->drm_plane_type == DRM_PLANE_TYPE_PRIMARY)
+ ret = mbochs_check_framebuffer(mdev_state, &mode);
+ if (ret < 0) {
+ plane->drm_format = 0;
+ plane->width = 0;
+ plane->height = 0;
+ plane->stride = 0;
+ plane->size = 0;
+ plane->dmabuf_id = 0;
+ goto done;
+ }
+
+ dmabuf = mbochs_dmabuf_find_by_mode(mdev_state, &mode);
+ if (!dmabuf)
+ mbochs_dmabuf_alloc(mdev_state, &mode);
+ if (!dmabuf) {
+ mutex_unlock(&mdev_state->ops_lock);
+ return -ENOMEM;
+ }
+
+ plane->drm_format = dmabuf->mode.drm_format;
+ plane->width = dmabuf->mode.width;
+ plane->height = dmabuf->mode.height;
+ plane->stride = dmabuf->mode.stride;
+ plane->size = dmabuf->mode.size;
+ plane->dmabuf_id = dmabuf->id;
+
+done:
+ if (plane->drm_plane_type == DRM_PLANE_TYPE_PRIMARY &&
+ mdev_state->active_id != plane->dmabuf_id) {
+ dev_dbg(dev, "%s: primary: %d => %d\n", __func__,
+ mdev_state->active_id, plane->dmabuf_id);
+ mdev_state->active_id = plane->dmabuf_id;
+ }
+ mutex_unlock(&mdev_state->ops_lock);
+ return 0;
+}
+
+static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
+ u32 id)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+ struct mbochs_dmabuf *dmabuf;
+
+ mutex_lock(&mdev_state->ops_lock);
+
+ dmabuf = mbochs_dmabuf_find_by_id(mdev_state, id);
+ if (!dmabuf) {
+ mutex_unlock(&mdev_state->ops_lock);
+ return -ENOENT;
+ }
+
+ if (!dmabuf->buf)
+ mbochs_dmabuf_export(dmabuf);
+
+ mutex_unlock(&mdev_state->ops_lock);
+
+ if (!dmabuf->buf)
+ return -EINVAL;
+
+ return dma_buf_fd(dmabuf->buf, 0);
+}
+
+static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = 0;
+ unsigned long minsz;
+ struct mdev_state *mdev_state;
+
+ mdev_state = mdev_get_drvdata(mdev);
+
+ switch (cmd) {
+ case VFIO_DEVICE_GET_INFO:
+ {
+ struct vfio_device_info info;
+
+ minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ ret = mbochs_get_device_info(mdev, &info);
+ if (ret)
+ return ret;
+
+ memcpy(&mdev_state->dev_info, &info, sizeof(info));
+
+ if (copy_to_user((void __user *)arg, &info, minsz))
+ return -EFAULT;
+
+ return 0;
+ }
+ case VFIO_DEVICE_GET_REGION_INFO:
+ {
+ struct vfio_region_info info;
+ u16 cap_type_id = 0;
+ void *cap_type = NULL;
+
+ minsz = offsetofend(struct vfio_region_info, offset);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ ret = mbochs_get_region_info(mdev, &info, &cap_type_id,
+ &cap_type);
+ if (ret)
+ return ret;
+
+ if (copy_to_user((void __user *)arg, &info, minsz))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ case VFIO_DEVICE_GET_IRQ_INFO:
+ {
+ struct vfio_irq_info info;
+
+ minsz = offsetofend(struct vfio_irq_info, count);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if ((info.argsz < minsz) ||
+ (info.index >= mdev_state->dev_info.num_irqs))
+ return -EINVAL;
+
+ ret = mbochs_get_irq_info(mdev, &info);
+ if (ret)
+ return ret;
+
+ if (copy_to_user((void __user *)arg, &info, minsz))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ case VFIO_DEVICE_QUERY_GFX_PLANE:
+ {
+ struct vfio_device_gfx_plane_info plane;
+
+ minsz = offsetofend(struct vfio_device_gfx_plane_info,
+ region_index);
+
+ if (copy_from_user(&plane, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (plane.argsz < minsz)
+ return -EINVAL;
+
+ ret = mbochs_query_gfx_plane(mdev, &plane);
+ if (ret)
+ return ret;
+
+ if (copy_to_user((void __user *)arg, &plane, minsz))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ case VFIO_DEVICE_GET_GFX_DMABUF:
+ {
+ u32 dmabuf_id;
+
+ if (get_user(dmabuf_id, (__u32 __user *)arg))
+ return -EFAULT;
+
+ return mbochs_get_gfx_dmabuf(mdev, dmabuf_id);
+ }
+
+ case VFIO_DEVICE_SET_IRQS:
+ return -EINVAL;
+
+ case VFIO_DEVICE_RESET:
+ return mbochs_reset(mdev);
+ }
+ return -ENOTTY;
+}
+
+static int mbochs_open(struct mdev_device *mdev)
+{
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
+ return 0;
+}
+
+static void mbochs_close(struct mdev_device *mdev)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+ struct mbochs_dmabuf *dmabuf, *tmp;
+
+ mutex_lock(&mdev_state->ops_lock);
+
+ list_for_each_entry_safe(dmabuf, tmp, &mdev_state->dmabufs, next) {
+ list_del(&dmabuf->next);
+ if (dmabuf->buf) {
+ /* free in mbochs_release_dmabuf() */
+ dmabuf->unlinked = true;
+ } else {
+ kfree(dmabuf);
+ }
+ }
+ mbochs_put_pages(mdev_state);
+
+ mutex_unlock(&mdev_state->ops_lock);
+ module_put(THIS_MODULE);
+}
+
+static ssize_t
+memory_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mdev_device *mdev = mdev_from_dev(dev);
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+
+ return sprintf(buf, "%d MB\n", mdev_state->type->mbytes);
+}
+static DEVICE_ATTR_RO(memory);
+
+static struct attribute *mdev_dev_attrs[] = {
+ &dev_attr_memory.attr,
+ NULL,
+};
+
+static const struct attribute_group mdev_dev_group = {
+ .name = "vendor",
+ .attrs = mdev_dev_attrs,
+};
+
+const struct attribute_group *mdev_dev_groups[] = {
+ &mdev_dev_group,
+ NULL,
+};
+
+static ssize_t
+name_show(struct kobject *kobj, struct device *dev, char *buf)
+{
+ return sprintf(buf, "%s\n", kobj->name);
+}
+MDEV_TYPE_ATTR_RO(name);
+
+static ssize_t
+description_show(struct kobject *kobj, struct device *dev, char *buf)
+{
+ const struct mbochs_type *type = mbochs_find_type(kobj);
+
+ return sprintf(buf, "virtual display, %d MB video memory\n",
+ type ? type->mbytes : 0);
+}
+MDEV_TYPE_ATTR_RO(description);
+
+static ssize_t
+available_instances_show(struct kobject *kobj, struct device *dev, char *buf)
+{
+ const struct mbochs_type *type = mbochs_find_type(kobj);
+ int count = (max_mbytes - mbochs_used_mbytes) / type->mbytes;
+
+ return sprintf(buf, "%d\n", count);
+}
+MDEV_TYPE_ATTR_RO(available_instances);
+
+static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
+}
+MDEV_TYPE_ATTR_RO(device_api);
+
+static struct attribute *mdev_types_attrs[] = {
+ &mdev_type_attr_name.attr,
+ &mdev_type_attr_description.attr,
+ &mdev_type_attr_device_api.attr,
+ &mdev_type_attr_available_instances.attr,
+ NULL,
+};
+
+static struct attribute_group mdev_type_group1 = {
+ .name = MBOCHS_TYPE_1,
+ .attrs = mdev_types_attrs,
+};
+
+static struct attribute_group mdev_type_group2 = {
+ .name = MBOCHS_TYPE_2,
+ .attrs = mdev_types_attrs,
+};
+
+static struct attribute_group mdev_type_group3 = {
+ .name = MBOCHS_TYPE_3,
+ .attrs = mdev_types_attrs,
+};
+
+static struct attribute_group *mdev_type_groups[] = {
+ &mdev_type_group1,
+ &mdev_type_group2,
+ &mdev_type_group3,
+ NULL,
+};
+
+static const struct mdev_parent_ops mdev_fops = {
+ .owner = THIS_MODULE,
+ .mdev_attr_groups = mdev_dev_groups,
+ .supported_type_groups = mdev_type_groups,
+ .create = mbochs_create,
+ .remove = mbochs_remove,
+ .open = mbochs_open,
+ .release = mbochs_close,
+ .read = mbochs_read,
+ .write = mbochs_write,
+ .ioctl = mbochs_ioctl,
+ .mmap = mbochs_mmap,
+};
+
+static const struct file_operations vd_fops = {
+ .owner = THIS_MODULE,
+};
+
+static void mbochs_device_release(struct device *dev)
+{
+ /* nothing */
+}
+
+static int __init mbochs_dev_init(void)
+{
+ int ret = 0;
+
+ ret = alloc_chrdev_region(&mbochs_devt, 0, MINORMASK, MBOCHS_NAME);
+ if (ret < 0) {
+ pr_err("Error: failed to register mbochs_dev, err: %d\n", ret);
+ return ret;
+ }
+ cdev_init(&mbochs_cdev, &vd_fops);
+ cdev_add(&mbochs_cdev, mbochs_devt, MINORMASK);
+ pr_info("%s: major %d\n", __func__, MAJOR(mbochs_devt));
+
+ mbochs_class = class_create(THIS_MODULE, MBOCHS_CLASS_NAME);
+ if (IS_ERR(mbochs_class)) {
+ pr_err("Error: failed to register mbochs_dev class\n");
+ ret = PTR_ERR(mbochs_class);
+ goto failed1;
+ }
+ mbochs_dev.class = mbochs_class;
+ mbochs_dev.release = mbochs_device_release;
+ dev_set_name(&mbochs_dev, "%s", MBOCHS_NAME);
+
+ ret = device_register(&mbochs_dev);
+ if (ret)
+ goto failed2;
+
+ ret = mdev_register_device(&mbochs_dev, &mdev_fops);
+ if (ret)
+ goto failed3;
+
+ return 0;
+
+failed3:
+ device_unregister(&mbochs_dev);
+failed2:
+ class_destroy(mbochs_class);
+failed1:
+ cdev_del(&mbochs_cdev);
+ unregister_chrdev_region(mbochs_devt, MINORMASK);
+ return ret;
+}
+
+static void __exit mbochs_dev_exit(void)
+{
+ mbochs_dev.bus = NULL;
+ mdev_unregister_device(&mbochs_dev);
+
+ device_unregister(&mbochs_dev);
+ cdev_del(&mbochs_cdev);
+ unregister_chrdev_region(mbochs_devt, MINORMASK);
+ class_destroy(mbochs_class);
+ mbochs_class = NULL;
+}
+
+module_init(mbochs_dev_init)
+module_exit(mbochs_dev_exit)
diff --git a/samples/vfio-mdev/mdpy-defs.h b/samples/vfio-mdev/mdpy-defs.h
new file mode 100644
index 0000000..96b3b1b
--- /dev/null
+++ b/samples/vfio-mdev/mdpy-defs.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Simple pci display device.
+ *
+ * Framebuffer memory is pci bar 0.
+ * Configuration (read-only) is in pci config space.
+ * Format field uses drm fourcc codes.
+ * ATM only DRM_FORMAT_XRGB8888 is supported.
+ */
+
+/* pci ids */
+#define MDPY_PCI_VENDOR_ID 0x1b36 /* redhat */
+#define MDPY_PCI_DEVICE_ID 0x000f
+#define MDPY_PCI_SUBVENDOR_ID PCI_SUBVENDOR_ID_REDHAT_QUMRANET
+#define MDPY_PCI_SUBDEVICE_ID PCI_SUBDEVICE_ID_QEMU
+
+/* pci cfg space offsets for fb config (dword) */
+#define MDPY_VENDORCAP_OFFSET 0x40
+#define MDPY_VENDORCAP_SIZE 0x10
+#define MDPY_FORMAT_OFFSET (MDPY_VENDORCAP_OFFSET + 0x04)
+#define MDPY_WIDTH_OFFSET (MDPY_VENDORCAP_OFFSET + 0x08)
+#define MDPY_HEIGHT_OFFSET (MDPY_VENDORCAP_OFFSET + 0x0c)
diff --git a/samples/vfio-mdev/mdpy-fb.c b/samples/vfio-mdev/mdpy-fb.c
new file mode 100644
index 0000000..2719bb2
--- /dev/null
+++ b/samples/vfio-mdev/mdpy-fb.c
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Framebuffer driver for mdpy (mediated virtual pci display device).
+ *
+ * See mdpy-defs.h for device specs
+ *
+ * (c) Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * Using some code snippets from simplefb and cirrusfb.
+ *
+ * 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/errno.h>
+#include <linux/fb.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <drm/drm_fourcc.h>
+#include "mdpy-defs.h"
+
+static const struct fb_fix_screeninfo mdpy_fb_fix = {
+ .id = "mdpy-fb",
+ .type = FB_TYPE_PACKED_PIXELS,
+ .visual = FB_VISUAL_TRUECOLOR,
+ .accel = FB_ACCEL_NONE,
+};
+
+static const struct fb_var_screeninfo mdpy_fb_var = {
+ .height = -1,
+ .width = -1,
+ .activate = FB_ACTIVATE_NOW,
+ .vmode = FB_VMODE_NONINTERLACED,
+
+ .bits_per_pixel = 32,
+ .transp.offset = 24,
+ .red.offset = 16,
+ .green.offset = 8,
+ .blue.offset = 0,
+ .transp.length = 8,
+ .red.length = 8,
+ .green.length = 8,
+ .blue.length = 8,
+};
+
+#define PSEUDO_PALETTE_SIZE 16
+
+struct mdpy_fb_par {
+ u32 palette[PSEUDO_PALETTE_SIZE];
+};
+
+static int mdpy_fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info)
+{
+ u32 *pal = info->pseudo_palette;
+ u32 cr = red >> (16 - info->var.red.length);
+ u32 cg = green >> (16 - info->var.green.length);
+ u32 cb = blue >> (16 - info->var.blue.length);
+ u32 value, mask;
+
+ if (regno >= PSEUDO_PALETTE_SIZE)
+ return -EINVAL;
+
+ value = (cr << info->var.red.offset) |
+ (cg << info->var.green.offset) |
+ (cb << info->var.blue.offset);
+ if (info->var.transp.length > 0) {
+ mask = (1 << info->var.transp.length) - 1;
+ mask <<= info->var.transp.offset;
+ value |= mask;
+ }
+ pal[regno] = value;
+
+ return 0;
+}
+
+static void mdpy_fb_destroy(struct fb_info *info)
+{
+ if (info->screen_base)
+ iounmap(info->screen_base);
+}
+
+static struct fb_ops mdpy_fb_ops = {
+ .owner = THIS_MODULE,
+ .fb_destroy = mdpy_fb_destroy,
+ .fb_setcolreg = mdpy_fb_setcolreg,
+ .fb_fillrect = cfb_fillrect,
+ .fb_copyarea = cfb_copyarea,
+ .fb_imageblit = cfb_imageblit,
+};
+
+static int mdpy_fb_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct fb_info *info;
+ struct mdpy_fb_par *par;
+ u32 format, width, height;
+ int ret;
+
+ ret = pci_enable_device(pdev);
+ if (ret < 0)
+ return ret;
+
+ ret = pci_request_regions(pdev, "mdpy-fb");
+ if (ret < 0)
+ return ret;
+
+ pci_read_config_dword(pdev, MDPY_FORMAT_OFFSET, &format);
+ pci_read_config_dword(pdev, MDPY_WIDTH_OFFSET, &width);
+ pci_read_config_dword(pdev, MDPY_HEIGHT_OFFSET, &height);
+ if (format != DRM_FORMAT_XRGB8888) {
+ pci_err(pdev, "format mismatch (0x%x != 0x%x)\n",
+ format, DRM_FORMAT_XRGB8888);
+ return -EINVAL;
+ }
+ if (width < 100 || width > 10000) {
+ pci_err(pdev, "width (%d) out of range\n", width);
+ return -EINVAL;
+ }
+ if (height < 100 || height > 10000) {
+ pci_err(pdev, "height (%d) out of range\n", height);
+ return -EINVAL;
+ }
+ pci_info(pdev, "mdpy found: %dx%d framebuffer\n",
+ width, height);
+
+ info = framebuffer_alloc(sizeof(struct mdpy_fb_par), &pdev->dev);
+ if (!info)
+ goto err_release_regions;
+ pci_set_drvdata(pdev, info);
+ par = info->par;
+
+ info->fix = mdpy_fb_fix;
+ info->fix.smem_start = pci_resource_start(pdev, 0);
+ info->fix.smem_len = pci_resource_len(pdev, 0);
+ info->fix.line_length = width * 4;
+
+ info->var = mdpy_fb_var;
+ info->var.xres = width;
+ info->var.yres = height;
+ info->var.xres_virtual = width;
+ info->var.yres_virtual = height;
+
+ info->screen_size = info->fix.smem_len;
+ info->screen_base = ioremap(info->fix.smem_start,
+ info->screen_size);
+ if (!info->screen_base) {
+ pci_err(pdev, "ioremap(pcibar) failed\n");
+ ret = -EIO;
+ goto err_release_fb;
+ }
+
+ info->apertures = alloc_apertures(1);
+ if (!info->apertures) {
+ ret = -ENOMEM;
+ goto err_unmap;
+ }
+ info->apertures->ranges[0].base = info->fix.smem_start;
+ info->apertures->ranges[0].size = info->fix.smem_len;
+
+ info->fbops = &mdpy_fb_ops;
+ info->flags = FBINFO_DEFAULT;
+ info->pseudo_palette = par->palette;
+
+ ret = register_framebuffer(info);
+ if (ret < 0) {
+ pci_err(pdev, "mdpy-fb device register failed: %d\n", ret);
+ goto err_unmap;
+ }
+
+ pci_info(pdev, "fb%d registered\n", info->node);
+ return 0;
+
+err_unmap:
+ iounmap(info->screen_base);
+
+err_release_fb:
+ framebuffer_release(info);
+
+err_release_regions:
+ pci_release_regions(pdev);
+
+ return ret;
+}
+
+static void mdpy_fb_remove(struct pci_dev *pdev)
+{
+ struct fb_info *info = pci_get_drvdata(pdev);
+
+ unregister_framebuffer(info);
+ framebuffer_release(info);
+}
+
+static struct pci_device_id mdpy_fb_pci_table[] = {
+ {
+ .vendor = MDPY_PCI_VENDOR_ID,
+ .device = MDPY_PCI_DEVICE_ID,
+ .subvendor = MDPY_PCI_SUBVENDOR_ID,
+ .subdevice = MDPY_PCI_SUBDEVICE_ID,
+ }, {
+ /* end of list */
+ }
+};
+
+static struct pci_driver mdpy_fb_pci_driver = {
+ .name = "mdpy-fb",
+ .id_table = mdpy_fb_pci_table,
+ .probe = mdpy_fb_probe,
+ .remove = mdpy_fb_remove,
+};
+
+static int __init mdpy_fb_init(void)
+{
+ int ret;
+
+ ret = pci_register_driver(&mdpy_fb_pci_driver);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+module_init(mdpy_fb_init);
+
+MODULE_DEVICE_TABLE(pci, mdpy_fb_pci_table);
+MODULE_LICENSE("GPL v2");
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
new file mode 100644
index 0000000..96e7969
--- /dev/null
+++ b/samples/vfio-mdev/mdpy.c
@@ -0,0 +1,807 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediated virtual PCI display host device driver
+ *
+ * See mdpy-defs.h for device specs
+ *
+ * (c) Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * based on mtty driver which is:
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ * Author: Neo Jia <cjia@nvidia.com>
+ * Kirti Wankhede <kwankhede@nvidia.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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/cdev.h>
+#include <linux/vfio.h>
+#include <linux/iommu.h>
+#include <linux/sysfs.h>
+#include <linux/mdev.h>
+#include <linux/pci.h>
+#include <drm/drm_fourcc.h>
+#include "mdpy-defs.h"
+
+#define MDPY_NAME "mdpy"
+#define MDPY_CLASS_NAME "mdpy"
+
+#define MDPY_CONFIG_SPACE_SIZE 0xff
+#define MDPY_MEMORY_BAR_OFFSET PAGE_SIZE
+#define MDPY_DISPLAY_REGION 16
+
+#define STORE_LE16(addr, val) (*(u16 *)addr = val)
+#define STORE_LE32(addr, val) (*(u32 *)addr = val)
+
+
+MODULE_LICENSE("GPL v2");
+
+static int max_devices = 4;
+module_param_named(count, max_devices, int, 0444);
+MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices");
+
+
+#define MDPY_TYPE_1 "vga"
+#define MDPY_TYPE_2 "xga"
+#define MDPY_TYPE_3 "hd"
+
+static const struct mdpy_type {
+ const char *name;
+ u32 format;
+ u32 bytepp;
+ u32 width;
+ u32 height;
+} mdpy_types[] = {
+ {
+ .name = MDPY_CLASS_NAME "-" MDPY_TYPE_1,
+ .format = DRM_FORMAT_XRGB8888,
+ .bytepp = 4,
+ .width = 640,
+ .height = 480,
+ }, {
+ .name = MDPY_CLASS_NAME "-" MDPY_TYPE_2,
+ .format = DRM_FORMAT_XRGB8888,
+ .bytepp = 4,
+ .width = 1024,
+ .height = 768,
+ }, {
+ .name = MDPY_CLASS_NAME "-" MDPY_TYPE_3,
+ .format = DRM_FORMAT_XRGB8888,
+ .bytepp = 4,
+ .width = 1920,
+ .height = 1080,
+ },
+};
+
+static dev_t mdpy_devt;
+static struct class *mdpy_class;
+static struct cdev mdpy_cdev;
+static struct device mdpy_dev;
+static u32 mdpy_count;
+
+/* State of each mdev device */
+struct mdev_state {
+ u8 *vconfig;
+ u32 bar_mask;
+ struct mutex ops_lock;
+ struct mdev_device *mdev;
+ struct vfio_device_info dev_info;
+
+ const struct mdpy_type *type;
+ u32 memsize;
+ void *memblk;
+};
+
+static const struct mdpy_type *mdpy_find_type(struct kobject *kobj)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mdpy_types); i++)
+ if (strcmp(mdpy_types[i].name, kobj->name) == 0)
+ return mdpy_types + i;
+ return NULL;
+}
+
+static void mdpy_create_config_space(struct mdev_state *mdev_state)
+{
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_VENDOR_ID],
+ MDPY_PCI_VENDOR_ID);
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_DEVICE_ID],
+ MDPY_PCI_DEVICE_ID);
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_SUBSYSTEM_VENDOR_ID],
+ MDPY_PCI_SUBVENDOR_ID);
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_SUBSYSTEM_ID],
+ MDPY_PCI_SUBDEVICE_ID);
+
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_COMMAND],
+ PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_STATUS],
+ PCI_STATUS_CAP_LIST);
+ STORE_LE16((u16 *) &mdev_state->vconfig[PCI_CLASS_DEVICE],
+ PCI_CLASS_DISPLAY_OTHER);
+ mdev_state->vconfig[PCI_CLASS_REVISION] = 0x01;
+
+ STORE_LE32((u32 *) &mdev_state->vconfig[PCI_BASE_ADDRESS_0],
+ PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_32 |
+ PCI_BASE_ADDRESS_MEM_PREFETCH);
+ mdev_state->bar_mask = ~(mdev_state->memsize) + 1;
+
+ /* vendor specific capability for the config registers */
+ mdev_state->vconfig[PCI_CAPABILITY_LIST] = MDPY_VENDORCAP_OFFSET;
+ mdev_state->vconfig[MDPY_VENDORCAP_OFFSET + 0] = 0x09; /* vendor cap */
+ mdev_state->vconfig[MDPY_VENDORCAP_OFFSET + 1] = 0x00; /* next ptr */
+ mdev_state->vconfig[MDPY_VENDORCAP_OFFSET + 2] = MDPY_VENDORCAP_SIZE;
+ STORE_LE32((u32 *) &mdev_state->vconfig[MDPY_FORMAT_OFFSET],
+ mdev_state->type->format);
+ STORE_LE32((u32 *) &mdev_state->vconfig[MDPY_WIDTH_OFFSET],
+ mdev_state->type->width);
+ STORE_LE32((u32 *) &mdev_state->vconfig[MDPY_HEIGHT_OFFSET],
+ mdev_state->type->height);
+}
+
+static void handle_pci_cfg_write(struct mdev_state *mdev_state, u16 offset,
+ char *buf, u32 count)
+{
+ struct device *dev = mdev_dev(mdev_state->mdev);
+ u32 cfg_addr;
+
+ switch (offset) {
+ case PCI_BASE_ADDRESS_0:
+ cfg_addr = *(u32 *)buf;
+
+ if (cfg_addr == 0xffffffff) {
+ cfg_addr = (cfg_addr & mdev_state->bar_mask);
+ } else {
+ cfg_addr &= PCI_BASE_ADDRESS_MEM_MASK;
+ if (cfg_addr)
+ dev_info(dev, "BAR0 @ 0x%x\n", cfg_addr);
+ }
+
+ cfg_addr |= (mdev_state->vconfig[offset] &
+ ~PCI_BASE_ADDRESS_MEM_MASK);
+ STORE_LE32(&mdev_state->vconfig[offset], cfg_addr);
+ break;
+ }
+}
+
+static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
+ loff_t pos, bool is_write)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+ struct device *dev = mdev_dev(mdev);
+ int ret = 0;
+
+ mutex_lock(&mdev_state->ops_lock);
+
+ if (pos < MDPY_CONFIG_SPACE_SIZE) {
+ if (is_write)
+ handle_pci_cfg_write(mdev_state, pos, buf, count);
+ else
+ memcpy(buf, (mdev_state->vconfig + pos), count);
+
+ } else if ((pos >= MDPY_MEMORY_BAR_OFFSET) &&
+ (pos + count <=
+ MDPY_MEMORY_BAR_OFFSET + mdev_state->memsize)) {
+ pos -= MDPY_MEMORY_BAR_OFFSET;
+ if (is_write)
+ memcpy(mdev_state->memblk, buf, count);
+ else
+ memcpy(buf, mdev_state->memblk, count);
+
+ } else {
+ dev_info(dev, "%s: %s @0x%llx (unhandled)\n",
+ __func__, is_write ? "WR" : "RD", pos);
+ ret = -1;
+ goto accessfailed;
+ }
+
+ ret = count;
+
+
+accessfailed:
+ mutex_unlock(&mdev_state->ops_lock);
+
+ return ret;
+}
+
+static int mdpy_reset(struct mdev_device *mdev)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+ u32 stride, i;
+
+ /* initialize with gray gradient */
+ stride = mdev_state->type->width * mdev_state->type->bytepp;
+ for (i = 0; i < mdev_state->type->height; i++)
+ memset(mdev_state->memblk + i * stride,
+ i * 255 / mdev_state->type->height,
+ stride);
+ return 0;
+}
+
+static int mdpy_create(struct kobject *kobj, struct mdev_device *mdev)
+{
+ const struct mdpy_type *type = mdpy_find_type(kobj);
+ struct device *dev = mdev_dev(mdev);
+ struct mdev_state *mdev_state;
+ u32 fbsize;
+
+ if (mdpy_count >= max_devices)
+ return -ENOMEM;
+
+ mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
+ if (mdev_state == NULL)
+ return -ENOMEM;
+
+ mdev_state->vconfig = kzalloc(MDPY_CONFIG_SPACE_SIZE, GFP_KERNEL);
+ if (mdev_state->vconfig == NULL) {
+ kfree(mdev_state);
+ return -ENOMEM;
+ }
+
+ if (!type)
+ type = &mdpy_types[0];
+ fbsize = roundup_pow_of_two(type->width * type->height * type->bytepp);
+
+ mdev_state->memblk = vmalloc_user(fbsize);
+ if (!mdev_state->memblk) {
+ kfree(mdev_state->vconfig);
+ kfree(mdev_state);
+ return -ENOMEM;
+ }
+ dev_info(dev, "%s: %s (%dx%d)\n",
+ __func__, kobj->name, type->width, type->height);
+
+ mutex_init(&mdev_state->ops_lock);
+ mdev_state->mdev = mdev;
+ mdev_set_drvdata(mdev, mdev_state);
+
+ mdev_state->type = type;
+ mdev_state->memsize = fbsize;
+ mdpy_create_config_space(mdev_state);
+ mdpy_reset(mdev);
+
+ mdpy_count++;
+ return 0;
+}
+
+static int mdpy_remove(struct mdev_device *mdev)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+ struct device *dev = mdev_dev(mdev);
+
+ dev_info(dev, "%s\n", __func__);
+
+ mdev_set_drvdata(mdev, NULL);
+ vfree(mdev_state->memblk);
+ kfree(mdev_state->vconfig);
+ kfree(mdev_state);
+
+ mdpy_count--;
+ return 0;
+}
+
+static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int done = 0;
+ int ret;
+
+ while (count) {
+ size_t filled;
+
+ if (count >= 4 && !(*ppos % 4)) {
+ u32 val;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, false);
+ if (ret <= 0)
+ goto read_err;
+
+ if (copy_to_user(buf, &val, sizeof(val)))
+ goto read_err;
+
+ filled = 4;
+ } else if (count >= 2 && !(*ppos % 2)) {
+ u16 val;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, false);
+ if (ret <= 0)
+ goto read_err;
+
+ if (copy_to_user(buf, &val, sizeof(val)))
+ goto read_err;
+
+ filled = 2;
+ } else {
+ u8 val;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, false);
+ if (ret <= 0)
+ goto read_err;
+
+ if (copy_to_user(buf, &val, sizeof(val)))
+ goto read_err;
+
+ filled = 1;
+ }
+
+ count -= filled;
+ done += filled;
+ *ppos += filled;
+ buf += filled;
+ }
+
+ return done;
+
+read_err:
+ return -EFAULT;
+}
+
+static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ unsigned int done = 0;
+ int ret;
+
+ while (count) {
+ size_t filled;
+
+ if (count >= 4 && !(*ppos % 4)) {
+ u32 val;
+
+ if (copy_from_user(&val, buf, sizeof(val)))
+ goto write_err;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, true);
+ if (ret <= 0)
+ goto write_err;
+
+ filled = 4;
+ } else if (count >= 2 && !(*ppos % 2)) {
+ u16 val;
+
+ if (copy_from_user(&val, buf, sizeof(val)))
+ goto write_err;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, true);
+ if (ret <= 0)
+ goto write_err;
+
+ filled = 2;
+ } else {
+ u8 val;
+
+ if (copy_from_user(&val, buf, sizeof(val)))
+ goto write_err;
+
+ ret = mdev_access(mdev, (char *)&val, sizeof(val),
+ *ppos, true);
+ if (ret <= 0)
+ goto write_err;
+
+ filled = 1;
+ }
+ count -= filled;
+ done += filled;
+ *ppos += filled;
+ buf += filled;
+ }
+
+ return done;
+write_err:
+ return -EFAULT;
+}
+
+static int mdpy_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+
+ if (vma->vm_pgoff != MDPY_MEMORY_BAR_OFFSET >> PAGE_SHIFT)
+ return -EINVAL;
+ if (vma->vm_end < vma->vm_start)
+ return -EINVAL;
+ if (vma->vm_end - vma->vm_start > mdev_state->memsize)
+ return -EINVAL;
+ if ((vma->vm_flags & VM_SHARED) == 0)
+ return -EINVAL;
+
+ return remap_vmalloc_range_partial(vma, vma->vm_start,
+ mdev_state->memblk,
+ vma->vm_end - vma->vm_start);
+}
+
+static int mdpy_get_region_info(struct mdev_device *mdev,
+ struct vfio_region_info *region_info,
+ u16 *cap_type_id, void **cap_type)
+{
+ struct mdev_state *mdev_state;
+
+ mdev_state = mdev_get_drvdata(mdev);
+ if (!mdev_state)
+ return -EINVAL;
+
+ if (region_info->index >= VFIO_PCI_NUM_REGIONS &&
+ region_info->index != MDPY_DISPLAY_REGION)
+ return -EINVAL;
+
+ switch (region_info->index) {
+ case VFIO_PCI_CONFIG_REGION_INDEX:
+ region_info->offset = 0;
+ region_info->size = MDPY_CONFIG_SPACE_SIZE;
+ region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
+ VFIO_REGION_INFO_FLAG_WRITE);
+ break;
+ case VFIO_PCI_BAR0_REGION_INDEX:
+ case MDPY_DISPLAY_REGION:
+ region_info->offset = MDPY_MEMORY_BAR_OFFSET;
+ region_info->size = mdev_state->memsize;
+ region_info->flags = (VFIO_REGION_INFO_FLAG_READ |
+ VFIO_REGION_INFO_FLAG_WRITE |
+ VFIO_REGION_INFO_FLAG_MMAP);
+ break;
+ default:
+ region_info->size = 0;
+ region_info->offset = 0;
+ region_info->flags = 0;
+ }
+
+ return 0;
+}
+
+static int mdpy_get_irq_info(struct mdev_device *mdev,
+ struct vfio_irq_info *irq_info)
+{
+ irq_info->count = 0;
+ return 0;
+}
+
+static int mdpy_get_device_info(struct mdev_device *mdev,
+ struct vfio_device_info *dev_info)
+{
+ dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
+ dev_info->num_regions = VFIO_PCI_NUM_REGIONS;
+ dev_info->num_irqs = VFIO_PCI_NUM_IRQS;
+ return 0;
+}
+
+static int mdpy_query_gfx_plane(struct mdev_device *mdev,
+ struct vfio_device_gfx_plane_info *plane)
+{
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+
+ if (plane->flags & VFIO_GFX_PLANE_TYPE_PROBE) {
+ if (plane->flags == (VFIO_GFX_PLANE_TYPE_PROBE |
+ VFIO_GFX_PLANE_TYPE_REGION))
+ return 0;
+ return -EINVAL;
+ }
+
+ if (plane->flags != VFIO_GFX_PLANE_TYPE_REGION)
+ return -EINVAL;
+
+ plane->drm_format = mdev_state->type->format;
+ plane->width = mdev_state->type->width;
+ plane->height = mdev_state->type->height;
+ plane->stride = (mdev_state->type->width *
+ mdev_state->type->bytepp);
+ plane->size = mdev_state->memsize;
+ plane->region_index = MDPY_DISPLAY_REGION;
+
+ /* unused */
+ plane->drm_format_mod = 0;
+ plane->x_pos = 0;
+ plane->y_pos = 0;
+ plane->x_hot = 0;
+ plane->y_hot = 0;
+
+ return 0;
+}
+
+static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret = 0;
+ unsigned long minsz;
+ struct mdev_state *mdev_state;
+
+ mdev_state = mdev_get_drvdata(mdev);
+
+ switch (cmd) {
+ case VFIO_DEVICE_GET_INFO:
+ {
+ struct vfio_device_info info;
+
+ minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ ret = mdpy_get_device_info(mdev, &info);
+ if (ret)
+ return ret;
+
+ memcpy(&mdev_state->dev_info, &info, sizeof(info));
+
+ if (copy_to_user((void __user *)arg, &info, minsz))
+ return -EFAULT;
+
+ return 0;
+ }
+ case VFIO_DEVICE_GET_REGION_INFO:
+ {
+ struct vfio_region_info info;
+ u16 cap_type_id = 0;
+ void *cap_type = NULL;
+
+ minsz = offsetofend(struct vfio_region_info, offset);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info.argsz < minsz)
+ return -EINVAL;
+
+ ret = mdpy_get_region_info(mdev, &info, &cap_type_id,
+ &cap_type);
+ if (ret)
+ return ret;
+
+ if (copy_to_user((void __user *)arg, &info, minsz))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ case VFIO_DEVICE_GET_IRQ_INFO:
+ {
+ struct vfio_irq_info info;
+
+ minsz = offsetofend(struct vfio_irq_info, count);
+
+ if (copy_from_user(&info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if ((info.argsz < minsz) ||
+ (info.index >= mdev_state->dev_info.num_irqs))
+ return -EINVAL;
+
+ ret = mdpy_get_irq_info(mdev, &info);
+ if (ret)
+ return ret;
+
+ if (copy_to_user((void __user *)arg, &info, minsz))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ case VFIO_DEVICE_QUERY_GFX_PLANE:
+ {
+ struct vfio_device_gfx_plane_info plane;
+
+ minsz = offsetofend(struct vfio_device_gfx_plane_info,
+ region_index);
+
+ if (copy_from_user(&plane, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (plane.argsz < minsz)
+ return -EINVAL;
+
+ ret = mdpy_query_gfx_plane(mdev, &plane);
+ if (ret)
+ return ret;
+
+ if (copy_to_user((void __user *)arg, &plane, minsz))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ case VFIO_DEVICE_SET_IRQS:
+ return -EINVAL;
+
+ case VFIO_DEVICE_RESET:
+ return mdpy_reset(mdev);
+ }
+ return -ENOTTY;
+}
+
+static int mdpy_open(struct mdev_device *mdev)
+{
+ if (!try_module_get(THIS_MODULE))
+ return -ENODEV;
+
+ return 0;
+}
+
+static void mdpy_close(struct mdev_device *mdev)
+{
+ module_put(THIS_MODULE);
+}
+
+static ssize_t
+resolution_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct mdev_device *mdev = mdev_from_dev(dev);
+ struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+
+ return sprintf(buf, "%dx%d\n",
+ mdev_state->type->width,
+ mdev_state->type->height);
+}
+static DEVICE_ATTR_RO(resolution);
+
+static struct attribute *mdev_dev_attrs[] = {
+ &dev_attr_resolution.attr,
+ NULL,
+};
+
+static const struct attribute_group mdev_dev_group = {
+ .name = "vendor",
+ .attrs = mdev_dev_attrs,
+};
+
+const struct attribute_group *mdev_dev_groups[] = {
+ &mdev_dev_group,
+ NULL,
+};
+
+static ssize_t
+name_show(struct kobject *kobj, struct device *dev, char *buf)
+{
+ return sprintf(buf, "%s\n", kobj->name);
+}
+MDEV_TYPE_ATTR_RO(name);
+
+static ssize_t
+description_show(struct kobject *kobj, struct device *dev, char *buf)
+{
+ const struct mdpy_type *type = mdpy_find_type(kobj);
+
+ return sprintf(buf, "virtual display, %dx%d framebuffer\n",
+ type ? type->width : 0,
+ type ? type->height : 0);
+}
+MDEV_TYPE_ATTR_RO(description);
+
+static ssize_t
+available_instances_show(struct kobject *kobj, struct device *dev, char *buf)
+{
+ return sprintf(buf, "%d\n", max_devices - mdpy_count);
+}
+MDEV_TYPE_ATTR_RO(available_instances);
+
+static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
+ char *buf)
+{
+ return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
+}
+MDEV_TYPE_ATTR_RO(device_api);
+
+static struct attribute *mdev_types_attrs[] = {
+ &mdev_type_attr_name.attr,
+ &mdev_type_attr_description.attr,
+ &mdev_type_attr_device_api.attr,
+ &mdev_type_attr_available_instances.attr,
+ NULL,
+};
+
+static struct attribute_group mdev_type_group1 = {
+ .name = MDPY_TYPE_1,
+ .attrs = mdev_types_attrs,
+};
+
+static struct attribute_group mdev_type_group2 = {
+ .name = MDPY_TYPE_2,
+ .attrs = mdev_types_attrs,
+};
+
+static struct attribute_group mdev_type_group3 = {
+ .name = MDPY_TYPE_3,
+ .attrs = mdev_types_attrs,
+};
+
+static struct attribute_group *mdev_type_groups[] = {
+ &mdev_type_group1,
+ &mdev_type_group2,
+ &mdev_type_group3,
+ NULL,
+};
+
+static const struct mdev_parent_ops mdev_fops = {
+ .owner = THIS_MODULE,
+ .mdev_attr_groups = mdev_dev_groups,
+ .supported_type_groups = mdev_type_groups,
+ .create = mdpy_create,
+ .remove = mdpy_remove,
+ .open = mdpy_open,
+ .release = mdpy_close,
+ .read = mdpy_read,
+ .write = mdpy_write,
+ .ioctl = mdpy_ioctl,
+ .mmap = mdpy_mmap,
+};
+
+static const struct file_operations vd_fops = {
+ .owner = THIS_MODULE,
+};
+
+static void mdpy_device_release(struct device *dev)
+{
+ /* nothing */
+}
+
+static int __init mdpy_dev_init(void)
+{
+ int ret = 0;
+
+ ret = alloc_chrdev_region(&mdpy_devt, 0, MINORMASK, MDPY_NAME);
+ if (ret < 0) {
+ pr_err("Error: failed to register mdpy_dev, err: %d\n", ret);
+ return ret;
+ }
+ cdev_init(&mdpy_cdev, &vd_fops);
+ cdev_add(&mdpy_cdev, mdpy_devt, MINORMASK);
+ pr_info("%s: major %d\n", __func__, MAJOR(mdpy_devt));
+
+ mdpy_class = class_create(THIS_MODULE, MDPY_CLASS_NAME);
+ if (IS_ERR(mdpy_class)) {
+ pr_err("Error: failed to register mdpy_dev class\n");
+ ret = PTR_ERR(mdpy_class);
+ goto failed1;
+ }
+ mdpy_dev.class = mdpy_class;
+ mdpy_dev.release = mdpy_device_release;
+ dev_set_name(&mdpy_dev, "%s", MDPY_NAME);
+
+ ret = device_register(&mdpy_dev);
+ if (ret)
+ goto failed2;
+
+ ret = mdev_register_device(&mdpy_dev, &mdev_fops);
+ if (ret)
+ goto failed3;
+
+ return 0;
+
+failed3:
+ device_unregister(&mdpy_dev);
+failed2:
+ class_destroy(mdpy_class);
+failed1:
+ cdev_del(&mdpy_cdev);
+ unregister_chrdev_region(mdpy_devt, MINORMASK);
+ return ret;
+}
+
+static void __exit mdpy_dev_exit(void)
+{
+ mdpy_dev.bus = NULL;
+ mdev_unregister_device(&mdpy_dev);
+
+ device_unregister(&mdpy_dev);
+ cdev_del(&mdpy_cdev);
+ unregister_chrdev_region(mdpy_devt, MINORMASK);
+ class_destroy(mdpy_class);
+ mdpy_class = NULL;
+}
+
+module_init(mdpy_dev_init)
+module_exit(mdpy_dev_exit)
diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
index bf7c0c9..dad5583 100644
--- a/scripts/Kconfig.include
+++ b/scripts/Kconfig.include
@@ -25,3 +25,6 @@ cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
# $(ld-option,<flag>)
# Return y if the linker supports <flag>, n otherwise
ld-option = $(success,$(LD) -v $(1))
+
+# gcc version including patch level
+gcc-version := $(shell,$(srctree)/scripts/gcc-version.sh -p $(CC) | sed 's/^0*//')
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 34d9e9c..e7889f4 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -239,6 +239,7 @@ cmd_record_mcount = \
"$(CC_FLAGS_FTRACE)" ]; then \
$(sub_cmd_record_mcount) \
fi;
+endif # -record-mcount
endif # CONFIG_FTRACE_MCOUNT_RECORD
ifdef CONFIG_STACK_VALIDATION
@@ -263,7 +264,6 @@ ifneq ($(RETPOLINE_CFLAGS),)
objtool_args += --retpoline
endif
endif
-endif
ifdef CONFIG_MODVERSIONS
diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins
index 7f5c862..c961b9a 100644
--- a/scripts/Makefile.gcc-plugins
+++ b/scripts/Makefile.gcc-plugins
@@ -1,84 +1,37 @@
# SPDX-License-Identifier: GPL-2.0
-ifdef CONFIG_GCC_PLUGINS
- __PLUGINCC := $(call cc-ifversion, -ge, 0408, $(HOSTCXX), $(HOSTCC))
- PLUGINCC := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-plugin.sh "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)")
-
- SANCOV_PLUGIN := -fplugin=$(objtree)/scripts/gcc-plugins/sancov_plugin.so
-
- gcc-plugin-$(CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) += cyc_complexity_plugin.so
+gcc-plugin-$(CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) += cyc_complexity_plugin.so
- gcc-plugin-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += latent_entropy_plugin.so
- gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += -DLATENT_ENTROPY_PLUGIN
- ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
+gcc-plugin-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += latent_entropy_plugin.so
+gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += -DLATENT_ENTROPY_PLUGIN
+ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY
DISABLE_LATENT_ENTROPY_PLUGIN += -fplugin-arg-latent_entropy_plugin-disable
- endif
-
- ifdef CONFIG_GCC_PLUGIN_SANCOV
- ifeq ($(strip $(CFLAGS_KCOV)),)
- # It is needed because of the gcc-plugin.sh and gcc version checks.
- gcc-plugin-$(CONFIG_GCC_PLUGIN_SANCOV) += sancov_plugin.so
-
- ifneq ($(PLUGINCC),)
- CFLAGS_KCOV := $(SANCOV_PLUGIN)
- else
- $(warning warning: cannot use CONFIG_KCOV: -fsanitize-coverage=trace-pc is not supported by compiler)
- endif
- endif
- endif
-
- gcc-plugin-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += structleak_plugin.so
- gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE) += -fplugin-arg-structleak_plugin-verbose
- gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL) += -fplugin-arg-structleak_plugin-byref-all
- gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += -DSTRUCTLEAK_PLUGIN
+endif
- gcc-plugin-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += randomize_layout_plugin.so
- gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += -DRANDSTRUCT_PLUGIN
- gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE) += -fplugin-arg-randomize_layout_plugin-performance-mode
+gcc-plugin-$(CONFIG_GCC_PLUGIN_SANCOV) += sancov_plugin.so
+gcc-plugin-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += structleak_plugin.so
+gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_VERBOSE) += -fplugin-arg-structleak_plugin-verbose
+gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK_BYREF_ALL) += -fplugin-arg-structleak_plugin-byref-all
+gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_STRUCTLEAK) += -DSTRUCTLEAK_PLUGIN
- GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y))
+gcc-plugin-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += randomize_layout_plugin.so
+gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT) += -DRANDSTRUCT_PLUGIN
+gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_RANDSTRUCT_PERFORMANCE) += -fplugin-arg-randomize_layout_plugin-performance-mode
- export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR
- export SANCOV_PLUGIN DISABLE_LATENT_ENTROPY_PLUGIN
+GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y))
- ifneq ($(PLUGINCC),)
- # SANCOV_PLUGIN can be only in CFLAGS_KCOV because avoid duplication.
- GCC_PLUGINS_CFLAGS := $(filter-out $(SANCOV_PLUGIN), $(GCC_PLUGINS_CFLAGS))
- endif
+export GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR
+export DISABLE_LATENT_ENTROPY_PLUGIN
- KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
- GCC_PLUGIN := $(gcc-plugin-y)
- GCC_PLUGIN_SUBDIR := $(gcc-plugin-subdir-y)
-endif
+# sancov_plugin.so can be only in CFLAGS_KCOV because avoid duplication.
+GCC_PLUGINS_CFLAGS := $(filter-out %/sancov_plugin.so, $(GCC_PLUGINS_CFLAGS))
-# If plugins aren't supported, abort the build before hard-to-read compiler
-# errors start getting spewed by the main build.
-PHONY += gcc-plugins-check
-gcc-plugins-check: FORCE
-ifdef CONFIG_GCC_PLUGINS
- ifeq ($(PLUGINCC),)
- ifneq ($(GCC_PLUGINS_CFLAGS),)
- # Various gccs between 4.5 and 5.1 have bugs on powerpc due to missing
- # header files. gcc <= 4.6 doesn't work at all, gccs from 4.8 to 5.1 have
- # issues with 64-bit targets.
- ifeq ($(ARCH),powerpc)
- ifeq ($(call cc-ifversion, -le, 0501, y), y)
- @echo "Cannot use CONFIG_GCC_PLUGINS: plugin support on gcc <= 5.1 is buggy on powerpc, please upgrade to gcc 5.2 or newer" >&2 && exit 1
- endif
- endif
- ifeq ($(call cc-ifversion, -ge, 0405, y), y)
- $(Q)$(srctree)/scripts/gcc-plugin.sh --show-error "$(__PLUGINCC)" "$(HOSTCXX)" "$(CC)" || true
- @echo "Cannot use CONFIG_GCC_PLUGINS: your gcc installation does not support plugins, perhaps the necessary headers are missing?" >&2 && exit 1
- else
- @echo "Cannot use CONFIG_GCC_PLUGINS: your gcc version does not support plugins, you should upgrade it to at least gcc 4.5" >&2 && exit 1
- endif
- endif
- endif
-endif
- @:
+KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS)
+GCC_PLUGIN := $(gcc-plugin-y)
+GCC_PLUGIN_SUBDIR := $(gcc-plugin-subdir-y)
# Actually do the build, if requested.
PHONY += gcc-plugins
-gcc-plugins: scripts_basic gcc-plugins-check
+gcc-plugins: scripts_basic
ifdef CONFIG_GCC_PLUGINS
$(Q)$(MAKE) $(build)=scripts/gcc-plugins
endif
diff --git a/scripts/Makefile.kcov b/scripts/Makefile.kcov
index 5cc7203..3d61c4b 100644
--- a/scripts/Makefile.kcov
+++ b/scripts/Makefile.kcov
@@ -1,7 +1,9 @@
ifdef CONFIG_KCOV
-CFLAGS_KCOV := $(call cc-option,-fsanitize-coverage=trace-pc,)
-ifeq ($(CONFIG_KCOV_ENABLE_COMPARISONS),y)
-CFLAGS_KCOV += $(call cc-option,-fsanitize-coverage=trace-cmp,)
-endif
+
+kcov-flags-$(CONFIG_CC_HAS_SANCOV_TRACE_PC) += -fsanitize-coverage=trace-pc
+kcov-flags-$(CONFIG_KCOV_ENABLE_COMPARISONS) += -fsanitize-coverage=trace-cmp
+kcov-flags-$(CONFIG_GCC_PLUGIN_SANCOV) += -fplugin=$(objtree)/scripts/gcc-plugins/sancov_plugin.so
+
+export CFLAGS_KCOV := $(kcov-flags-y)
endif
diff --git a/scripts/clang-version.sh b/scripts/clang-version.sh
index 9780efa..dbf0a31 100755
--- a/scripts/clang-version.sh
+++ b/scripts/clang-version.sh
@@ -10,24 +10,14 @@
# clang-5.0.1 etc.
#
-if [ "$1" = "-p" ] ; then
- with_patchlevel=1;
- shift;
-fi
-
compiler="$*"
-if [ ${#compiler} -eq 0 ]; then
- echo "Error: No compiler specified."
- printf "Usage:\n\t$0 <clang-command>\n"
+if !( $compiler --version | grep -q clang) ; then
+ echo 0
exit 1
fi
MAJOR=$(echo __clang_major__ | $compiler -E -x c - | tail -n 1)
MINOR=$(echo __clang_minor__ | $compiler -E -x c - | tail -n 1)
-if [ "x$with_patchlevel" != "x" ] ; then
- PATCHLEVEL=$(echo __clang_patchlevel__ | $compiler -E -x c - | tail -n 1)
- printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
-else
- printf "%02d%02d\\n" $MAJOR $MINOR
-fi
+PATCHLEVEL=$(echo __clang_patchlevel__ | $compiler -E -x c - | tail -n 1)
+printf "%d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
diff --git a/scripts/documentation-file-ref-check b/scripts/documentation-file-ref-check
index 2520bc1..078999a 100755
--- a/scripts/documentation-file-ref-check
+++ b/scripts/documentation-file-ref-check
@@ -21,7 +21,7 @@ GetOptions(
);
if ($help != 0) {
- print "$scriptname [--help] [--fix-rst]\n";
+ print "$scriptname [--help] [--fix]\n";
exit -1;
}
@@ -38,16 +38,31 @@ while (<IN>) {
my $f = $1;
my $ln = $2;
- # Makefiles contain nasty expressions to parse docs
- next if ($f =~ m/Makefile/);
+ # Makefiles and scripts contain nasty expressions to parse docs
+ next if ($f =~ m/Makefile/ || $f =~ m/\.sh$/);
+
# Skip this script
next if ($f eq $scriptname);
- if ($ln =~ m,\b(\S*)(Documentation/[A-Za-z0-9\_\.\,\~/\*+-]*),) {
+ if ($ln =~ m,\b(\S*)(Documentation/[A-Za-z0-9\_\.\,\~/\*\[\]\?+-]*)(.*),) {
my $prefix = $1;
my $ref = $2;
my $base = $2;
+ my $extra = $3;
+
+ # some file references are like:
+ # /usr/src/linux/Documentation/DMA-{API,mapping}.txt
+ # For now, ignore them
+ next if ($extra =~ m/^{/);
+
+ # Remove footnotes at the end like:
+ # Documentation/devicetree/dt-object-internal.txt[1]
+ $ref =~ s/(txt|rst)\[\d+]$/$1/;
+
+ # Remove ending ']' without any '['
+ $ref =~ s/\].*// if (!($ref =~ m/\[/));
+ # Remove puntuation marks at the end
$ref =~ s/[\,\.]+$//;
my $fulref = "$prefix$ref";
@@ -63,8 +78,15 @@ while (<IN>) {
# Check if exists, evaluating wildcards
next if (grep -e, glob("$ref $fulref"));
+ # Accept relative Documentation patches for tools/
+ if ($f =~ m/tools/) {
+ my $path = $f;
+ $path =~ s,(.*)/.*,$1,;
+ next if (grep -e, glob("$path/$ref $path/$fulref"));
+ }
+
if ($fix) {
- if (!($ref =~ m/(devicetree|scripts|Kconfig|Kbuild)/)) {
+ if (!($ref =~ m/(scripts|Kconfig|Kbuild)/)) {
$broken_ref{$ref}++;
}
} else {
@@ -84,10 +106,19 @@ foreach my $ref (keys %broken_ref) {
# get just the basename
$new =~ s,.*/,,;
- # Seek for the same name on another place, as it may have been moved
my $f="";
- $f = qx(find . -iname $new) if ($new);
+ # usual reason for breakage: DT file moved around
+ if ($ref =~ /devicetree/) {
+ my $search = $new;
+ $search =~ s,^.*/,,;
+ $f = qx(find Documentation/devicetree/ -iname "*$search*") if ($search);
+ if (!$f) {
+ # Manufacturer name may have changed
+ $search =~ s/^.*,//;
+ $f = qx(find Documentation/devicetree/ -iname "*$search*") if ($search);
+ }
+ }
# usual reason for breakage: file renamed to .rst
if (!$f) {
@@ -95,6 +126,17 @@ foreach my $ref (keys %broken_ref) {
$f=qx(find . -iname $new) if ($new);
}
+ # usual reason for breakage: use dash or underline
+ if (!$f) {
+ $new =~ s/[-_]/[-_]/g;
+ $f=qx(find . -iname $new) if ($new);
+ }
+
+ # Wild guess: seek for the same name on another place
+ if (!$f) {
+ $f = qx(find . -iname $new) if ($new);
+ }
+
my @find = split /\s+/, $f;
if (!$f) {
diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile
index e2ff425..3262546 100644
--- a/scripts/gcc-plugins/Makefile
+++ b/scripts/gcc-plugins/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+PLUGINCC := $(CONFIG_PLUGIN_HOSTCC:"%"=%)
GCC_PLUGINS_DIR := $(shell $(CC) -print-file-name=plugin)
ifeq ($(PLUGINCC),$(HOSTCC))
@@ -13,10 +14,6 @@ else
export HOST_EXTRACXXFLAGS
endif
-ifneq ($(CFLAGS_KCOV), $(SANCOV_PLUGIN))
- GCC_PLUGIN := $(filter-out $(SANCOV_PLUGIN), $(GCC_PLUGIN))
-endif
-
export HOSTLIBS
$(obj)/randomize_layout_plugin.o: $(objtree)/$(obj)/randomize_layout_seed.h
diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh
index 6b2aeef..f5c1194 100755
--- a/scripts/gcc-x86_32-has-stack-protector.sh
+++ b/scripts/gcc-x86_32-has-stack-protector.sh
@@ -1,9 +1,4 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
-echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
-if [ "$?" -eq "0" ] ; then
- echo y
-else
- echo n
-fi
+echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -m32 -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh
index 4a48bdc..3755af0 100755
--- a/scripts/gcc-x86_64-has-stack-protector.sh
+++ b/scripts/gcc-x86_64-has-stack-protector.sh
@@ -2,8 +2,3 @@
# SPDX-License-Identifier: GPL-2.0
echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fno-PIE -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
-if [ "$?" -eq "0" ] ; then
- echo y
-else
- echo n
-fi
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index a2e83ab..4686531 100755
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -165,10 +165,10 @@ sub read_kconfig {
my $last_source = "";
# Check for any environment variables used
- while ($source =~ /\$(\w+)/ && $last_source ne $source) {
+ while ($source =~ /\$\((\w+)\)/ && $last_source ne $source) {
my $env = $1;
$last_source = $source;
- $source =~ s/\$$env/$ENV{$env}/;
+ $source =~ s/\$\($env\)/$ENV{$env}/;
}
open(my $kinfile, '<', $source) || die "Can't open $kconfig";
diff --git a/security/apparmor/audit.c b/security/apparmor/audit.c
index 8f9ecac..eeaddfe 100644
--- a/security/apparmor/audit.c
+++ b/security/apparmor/audit.c
@@ -19,7 +19,7 @@
#include "include/audit.h"
#include "include/policy.h"
#include "include/policy_ns.h"
-
+#include "include/secid.h"
const char *const audit_mode_names[] = {
"normal",
@@ -163,3 +163,91 @@ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
return aad(sa)->error;
}
+
+struct aa_audit_rule {
+ struct aa_label *label;
+};
+
+void aa_audit_rule_free(void *vrule)
+{
+ struct aa_audit_rule *rule = vrule;
+
+ if (rule) {
+ if (!IS_ERR(rule->label))
+ aa_put_label(rule->label);
+ kfree(rule);
+ }
+}
+
+int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
+{
+ struct aa_audit_rule *rule;
+
+ switch (field) {
+ case AUDIT_SUBJ_ROLE:
+ if (op != Audit_equal && op != Audit_not_equal)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ rule = kzalloc(sizeof(struct aa_audit_rule), GFP_KERNEL);
+
+ if (!rule)
+ return -ENOMEM;
+
+ /* Currently rules are treated as coming from the root ns */
+ rule->label = aa_label_parse(&root_ns->unconfined->label, rulestr,
+ GFP_KERNEL, true, false);
+ if (IS_ERR(rule->label)) {
+ aa_audit_rule_free(rule);
+ return PTR_ERR(rule->label);
+ }
+
+ *vrule = rule;
+ return 0;
+}
+
+int aa_audit_rule_known(struct audit_krule *rule)
+{
+ int i;
+
+ for (i = 0; i < rule->field_count; i++) {
+ struct audit_field *f = &rule->fields[i];
+
+ switch (f->type) {
+ case AUDIT_SUBJ_ROLE:
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
+ struct audit_context *actx)
+{
+ struct aa_audit_rule *rule = vrule;
+ struct aa_label *label;
+ int found = 0;
+
+ label = aa_secid_to_label(sid);
+
+ if (!label)
+ return -ENOENT;
+
+ if (aa_label_is_subset(label, rule->label))
+ found = 1;
+
+ switch (field) {
+ case AUDIT_SUBJ_ROLE:
+ switch (op) {
+ case Audit_equal:
+ return found;
+ case Audit_not_equal:
+ return !found;
+ }
+ }
+ return 0;
+}
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 590b7e8..098d546 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -839,7 +839,7 @@ static struct aa_label *handle_onexec(struct aa_label *label,
cond, unsafe));
} else {
- /* TODO: determine how much we want to losen this */
+ /* TODO: determine how much we want to loosen this */
error = fn_for_each_in_ns(label, profile,
profile_onexec(profile, onexec, stack, bprm,
buffer, cond, unsafe));
diff --git a/security/apparmor/include/audit.h b/security/apparmor/include/audit.h
index 9c9be9c..b8c8b10 100644
--- a/security/apparmor/include/audit.h
+++ b/security/apparmor/include/audit.h
@@ -189,4 +189,10 @@ static inline int complain_error(int error)
return error;
}
+void aa_audit_rule_free(void *vrule);
+int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule);
+int aa_audit_rule_known(struct audit_krule *rule);
+int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule,
+ struct audit_context *actx);
+
#endif /* __AA_AUDIT_H */
diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h
index d871e7f..7ce5fe7 100644
--- a/security/apparmor/include/label.h
+++ b/security/apparmor/include/label.h
@@ -281,7 +281,7 @@ void __aa_labelset_update_subtree(struct aa_ns *ns);
void aa_label_free(struct aa_label *label);
void aa_label_kref(struct kref *kref);
-bool aa_label_init(struct aa_label *label, int size);
+bool aa_label_init(struct aa_label *label, int size, gfp_t gfp);
struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp);
bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub);
diff --git a/security/apparmor/include/path.h b/security/apparmor/include/path.h
index e042b99..b6380c5 100644
--- a/security/apparmor/include/path.h
+++ b/security/apparmor/include/path.h
@@ -43,10 +43,11 @@ struct aa_buffers {
DECLARE_PER_CPU(struct aa_buffers, aa_buffers);
-#define ASSIGN(FN, X, N) ((X) = FN(N))
-#define EVAL1(FN, X) ASSIGN(FN, X, 0) /*X = FN(0)*/
-#define EVAL2(FN, X, Y...) do { ASSIGN(FN, X, 1); EVAL1(FN, Y); } while (0)
-#define EVAL(FN, X...) CONCATENATE(EVAL, COUNT_ARGS(X))(FN, X)
+#define ASSIGN(FN, A, X, N) ((X) = FN(A, N))
+#define EVAL1(FN, A, X) ASSIGN(FN, A, X, 0) /*X = FN(0)*/
+#define EVAL2(FN, A, X, Y...) \
+ do { ASSIGN(FN, A, X, 1); EVAL1(FN, A, Y); } while (0)
+#define EVAL(FN, A, X...) CONCATENATE(EVAL, COUNT_ARGS(X))(FN, A, X)
#define for_each_cpu_buffer(I) for ((I) = 0; (I) < MAX_PATH_BUFFERS; (I)++)
@@ -56,26 +57,24 @@ DECLARE_PER_CPU(struct aa_buffers, aa_buffers);
#define AA_BUG_PREEMPT_ENABLED(X) /* nop */
#endif
-#define __get_buffer(N) ({ \
- struct aa_buffers *__cpu_var; \
+#define __get_buffer(C, N) ({ \
AA_BUG_PREEMPT_ENABLED("__get_buffer without preempt disabled"); \
- __cpu_var = this_cpu_ptr(&aa_buffers); \
- __cpu_var->buf[(N)]; })
+ (C)->buf[(N)]; })
-#define __get_buffers(X...) EVAL(__get_buffer, X)
+#define __get_buffers(C, X...) EVAL(__get_buffer, C, X)
#define __put_buffers(X, Y...) ((void)&(X))
-#define get_buffers(X...) \
-do { \
- preempt_disable(); \
- __get_buffers(X); \
+#define get_buffers(X...) \
+do { \
+ struct aa_buffers *__cpu_var = get_cpu_ptr(&aa_buffers); \
+ __get_buffers(__cpu_var, X); \
} while (0)
-#define put_buffers(X, Y...) \
-do { \
- __put_buffers(X, Y); \
- preempt_enable(); \
+#define put_buffers(X, Y...) \
+do { \
+ __put_buffers(X, Y); \
+ put_cpu_ptr(&aa_buffers); \
} while (0)
#endif /* __AA_PATH_H */
diff --git a/security/apparmor/include/secid.h b/security/apparmor/include/secid.h
index 95ed86a..dee6fa3 100644
--- a/security/apparmor/include/secid.h
+++ b/security/apparmor/include/secid.h
@@ -3,7 +3,7 @@
*
* This file contains AppArmor security identifier (secid) definitions
*
- * Copyright 2009-2010 Canonical Ltd.
+ * Copyright 2009-2018 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -14,13 +14,24 @@
#ifndef __AA_SECID_H
#define __AA_SECID_H
+#include <linux/slab.h>
#include <linux/types.h>
+struct aa_label;
+
/* secid value that will not be allocated */
#define AA_SECID_INVALID 0
-#define AA_SECID_ALLOC AA_SECID_INVALID
-u32 aa_alloc_secid(void);
+struct aa_label *aa_secid_to_label(u32 secid);
+int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
+int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
+void apparmor_release_secctx(char *secdata, u32 seclen);
+
+
+int aa_alloc_secid(struct aa_label *label, gfp_t gfp);
void aa_free_secid(u32 secid);
+void aa_secid_update(u32 secid, struct aa_label *label);
+
+void aa_secids_init(void);
#endif /* __AA_SECID_H */
diff --git a/security/apparmor/label.c b/security/apparmor/label.c
index 523250e..ba11bdf 100644
--- a/security/apparmor/label.c
+++ b/security/apparmor/label.c
@@ -128,7 +128,7 @@ static int ns_cmp(struct aa_ns *a, struct aa_ns *b)
}
/**
- * profile_cmp - profile comparision for set ordering
+ * profile_cmp - profile comparison for set ordering
* @a: profile to compare (NOT NULL)
* @b: profile to compare (NOT NULL)
*
@@ -157,7 +157,7 @@ static int profile_cmp(struct aa_profile *a, struct aa_profile *b)
}
/**
- * vec_cmp - label comparision for set ordering
+ * vec_cmp - label comparison for set ordering
* @a: label to compare (NOT NULL)
* @vec: vector of profiles to compare (NOT NULL)
* @n: length of @vec
@@ -402,13 +402,12 @@ static void label_free_or_put_new(struct aa_label *label, struct aa_label *new)
aa_put_label(new);
}
-bool aa_label_init(struct aa_label *label, int size)
+bool aa_label_init(struct aa_label *label, int size, gfp_t gfp)
{
AA_BUG(!label);
AA_BUG(size < 1);
- label->secid = aa_alloc_secid();
- if (label->secid == AA_SECID_INVALID)
+ if (aa_alloc_secid(label, gfp) < 0)
return false;
label->size = size; /* doesn't include null */
@@ -441,7 +440,7 @@ struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp)
if (!new)
goto fail;
- if (!aa_label_init(new, size))
+ if (!aa_label_init(new, size, gfp))
goto fail;
if (!proxy) {
@@ -463,7 +462,7 @@ fail:
/**
- * label_cmp - label comparision for set ordering
+ * label_cmp - label comparison for set ordering
* @a: label to compare (NOT NULL)
* @b: label to compare (NOT NULL)
*
@@ -2011,7 +2010,7 @@ out:
/**
* __label_update - insert updated version of @label into labelset
- * @label - the label to update/repace
+ * @label - the label to update/replace
*
* Returns: new label that is up to date
* else NULL on failure
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 068a9f4..a7b3f68 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -408,7 +408,7 @@ int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
* @request: requested perms
* @deny: Returns: explicit deny set
* @sa: initialized audit structure (MAY BE NULL if not auditing)
- * @cb: callback fn for tpye specific fields (MAY BE NULL)
+ * @cb: callback fn for type specific fields (MAY BE NULL)
*
* Returns: 0 if permission else error code
*
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index ce2b89e..74f1737 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -39,6 +39,7 @@
#include "include/policy_ns.h"
#include "include/procattr.h"
#include "include/mount.h"
+#include "include/secid.h"
/* Flag indicating whether initialization completed */
int apparmor_initialized;
@@ -116,7 +117,8 @@ static int apparmor_ptrace_access_check(struct task_struct *child,
tracer = begin_current_label_crit_section();
tracee = aa_get_task_label(child);
error = aa_may_ptrace(tracer, tracee,
- mode == PTRACE_MODE_READ ? AA_PTRACE_READ : AA_PTRACE_TRACE);
+ (mode & PTRACE_MODE_READ) ? AA_PTRACE_READ
+ : AA_PTRACE_TRACE);
aa_put_label(tracee);
end_current_label_crit_section(tracer);
@@ -710,6 +712,13 @@ static void apparmor_bprm_committed_creds(struct linux_binprm *bprm)
return;
}
+static void apparmor_task_getsecid(struct task_struct *p, u32 *secid)
+{
+ struct aa_label *label = aa_get_task_label(p);
+ *secid = label->secid;
+ aa_put_label(label);
+}
+
static int apparmor_task_setrlimit(struct task_struct *task,
unsigned int resource, struct rlimit *new_rlim)
{
@@ -1186,8 +1195,20 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(task_free, apparmor_task_free),
LSM_HOOK_INIT(task_alloc, apparmor_task_alloc),
+ LSM_HOOK_INIT(task_getsecid, apparmor_task_getsecid),
LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit),
LSM_HOOK_INIT(task_kill, apparmor_task_kill),
+
+#ifdef CONFIG_AUDIT
+ LSM_HOOK_INIT(audit_rule_init, aa_audit_rule_init),
+ LSM_HOOK_INIT(audit_rule_known, aa_audit_rule_known),
+ LSM_HOOK_INIT(audit_rule_match, aa_audit_rule_match),
+ LSM_HOOK_INIT(audit_rule_free, aa_audit_rule_free),
+#endif
+
+ LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx),
+ LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid),
+ LSM_HOOK_INIT(release_secctx, apparmor_release_secctx),
};
/*
@@ -1378,14 +1399,12 @@ static int param_set_audit(const char *val, const struct kernel_param *kp)
if (apparmor_initialized && !policy_admin_capable(NULL))
return -EPERM;
- for (i = 0; i < AUDIT_MAX_INDEX; i++) {
- if (strcmp(val, audit_mode_names[i]) == 0) {
- aa_g_audit = i;
- return 0;
- }
- }
+ i = match_string(audit_mode_names, AUDIT_MAX_INDEX, val);
+ if (i < 0)
+ return -EINVAL;
- return -EINVAL;
+ aa_g_audit = i;
+ return 0;
}
static int param_get_mode(char *buffer, const struct kernel_param *kp)
@@ -1409,14 +1428,13 @@ static int param_set_mode(const char *val, const struct kernel_param *kp)
if (apparmor_initialized && !policy_admin_capable(NULL))
return -EPERM;
- for (i = 0; i < APPARMOR_MODE_NAMES_MAX_INDEX; i++) {
- if (strcmp(val, aa_profile_mode_names[i]) == 0) {
- aa_g_profile_mode = i;
- return 0;
- }
- }
+ i = match_string(aa_profile_mode_names, APPARMOR_MODE_NAMES_MAX_INDEX,
+ val);
+ if (i < 0)
+ return -EINVAL;
- return -EINVAL;
+ aa_g_profile_mode = i;
+ return 0;
}
/*
@@ -1530,6 +1548,8 @@ static int __init apparmor_init(void)
return 0;
}
+ aa_secids_init();
+
error = aa_setup_dfa_engine();
if (error) {
AA_ERROR("Unable to setup dfa engine\n");
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 280eba0..55f2ee5 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -472,7 +472,7 @@ unsigned int aa_dfa_match(struct aa_dfa *dfa, unsigned int start,
/**
* aa_dfa_next - step one character to the next state in the dfa
- * @dfa: the dfa to tranverse (NOT NULL)
+ * @dfa: the dfa to traverse (NOT NULL)
* @state: the state to start in
* @c: the input character to transition on
*
diff --git a/security/apparmor/mount.c b/security/apparmor/mount.c
index 6e8c7ac..c1da224 100644
--- a/security/apparmor/mount.c
+++ b/security/apparmor/mount.c
@@ -121,7 +121,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
* @src_name: src_name of object being mediated (MAYBE_NULL)
* @type: type of filesystem (MAYBE_NULL)
* @trans: name of trans (MAYBE NULL)
- * @flags: filesystem idependent mount flags
+ * @flags: filesystem independent mount flags
* @data: filesystem mount flags
* @request: permissions requested
* @perms: the permissions computed for the request (NOT NULL)
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index c07493c..1590e2d 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -268,7 +268,7 @@ struct aa_profile *aa_alloc_profile(const char *hname, struct aa_proxy *proxy,
if (!aa_policy_init(&profile->base, NULL, hname, gfp))
goto fail;
- if (!aa_label_init(&profile->label, 1))
+ if (!aa_label_init(&profile->label, 1, gfp))
goto fail;
/* update being set needed by fs interface */
@@ -1008,6 +1008,9 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label,
audit_policy(label, op, ns_name, ent->new->base.hname,
"same as current profile, skipping",
error);
+ /* break refcount cycle with proxy. */
+ aa_put_proxy(ent->new->label.proxy);
+ ent->new->label.proxy = NULL;
goto skip;
}
@@ -1085,7 +1088,7 @@ fail:
* Remove a profile or sub namespace from the current namespace, so that
* they can not be found anymore and mark them as replaced by unconfined
*
- * NOTE: removing confinement does not restore rlimits to preconfinemnet values
+ * NOTE: removing confinement does not restore rlimits to preconfinement values
*
* Returns: size of data consume else error code if fails
*/
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index b9e6b2c..0e566a0 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -475,7 +475,7 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_profile *profile)
/* currently 4 exec bits and entries 0-3 are reserved iupcx */
if (size > 16 - 4)
goto fail;
- profile->file.trans.table = kzalloc(sizeof(char *) * size,
+ profile->file.trans.table = kcalloc(size, sizeof(char *),
GFP_KERNEL);
if (!profile->file.trans.table)
goto fail;
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
index d022137..95fd26d 100644
--- a/security/apparmor/resource.c
+++ b/security/apparmor/resource.c
@@ -124,7 +124,7 @@ int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
*/
if (label != peer &&
- !aa_capable(label, CAP_SYS_RESOURCE, SECURITY_CAP_NOAUDIT))
+ aa_capable(label, CAP_SYS_RESOURCE, SECURITY_CAP_NOAUDIT) != 0)
error = fn_for_each(label, profile,
audit_resource(profile, resource,
new_rlim->rlim_max, peer,
diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c
index 3a3edba..f2f22d00 100644
--- a/security/apparmor/secid.c
+++ b/security/apparmor/secid.c
@@ -3,7 +3,7 @@
*
* This file contains AppArmor security identifier (secid) manipulation fns
*
- * Copyright 2009-2010 Canonical Ltd.
+ * Copyright 2009-2017 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -11,38 +11,142 @@
* License.
*
*
- * AppArmor allocates a unique secid for every profile loaded. If a profile
- * is replaced it receives the secid of the profile it is replacing.
- *
- * The secid value of 0 is invalid.
+ * AppArmor allocates a unique secid for every label used. If a label
+ * is replaced it receives the secid of the label it is replacing.
*/
-#include <linux/spinlock.h>
#include <linux/errno.h>
#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/idr.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include "include/cred.h"
+#include "include/lib.h"
#include "include/secid.h"
+#include "include/label.h"
+#include "include/policy_ns.h"
+
+/*
+ * secids - do not pin labels with a refcount. They rely on the label
+ * properly updating/freeing them
+ */
-/* global counter from which secids are allocated */
-static u32 global_secid;
+#define AA_FIRST_SECID 1
+
+static DEFINE_IDR(aa_secids);
static DEFINE_SPINLOCK(secid_lock);
-/* TODO FIXME: add secid to profile mapping, and secid recycling */
+/*
+ * TODO: allow policy to reserve a secid range?
+ * TODO: add secid pinning
+ * TODO: use secid_update in label replace
+ */
+
+/**
+ * aa_secid_update - update a secid mapping to a new label
+ * @secid: secid to update
+ * @label: label the secid will now map to
+ */
+void aa_secid_update(u32 secid, struct aa_label *label)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&secid_lock, flags);
+ idr_replace(&aa_secids, label, secid);
+ spin_unlock_irqrestore(&secid_lock, flags);
+}
+
+/**
+ *
+ * see label for inverse aa_label_to_secid
+ */
+struct aa_label *aa_secid_to_label(u32 secid)
+{
+ struct aa_label *label;
+
+ rcu_read_lock();
+ label = idr_find(&aa_secids, secid);
+ rcu_read_unlock();
+
+ return label;
+}
+
+int apparmor_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+{
+ /* TODO: cache secctx and ref count so we don't have to recreate */
+ struct aa_label *label = aa_secid_to_label(secid);
+ int len;
+
+ AA_BUG(!secdata);
+ AA_BUG(!seclen);
+
+ if (!label)
+ return -EINVAL;
+
+ if (secdata)
+ len = aa_label_asxprint(secdata, root_ns, label,
+ FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
+ FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT,
+ GFP_ATOMIC);
+ else
+ len = aa_label_snxprint(NULL, 0, root_ns, label,
+ FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
+ FLAG_HIDDEN_UNCONFINED | FLAG_ABS_ROOT);
+ if (len < 0)
+ return -ENOMEM;
+
+ *seclen = len;
+
+ return 0;
+}
+
+int apparmor_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid)
+{
+ struct aa_label *label;
+
+ label = aa_label_strn_parse(&root_ns->unconfined->label, secdata,
+ seclen, GFP_KERNEL, false, false);
+ if (IS_ERR(label))
+ return PTR_ERR(label);
+ *secid = label->secid;
+
+ return 0;
+}
+
+void apparmor_release_secctx(char *secdata, u32 seclen)
+{
+ kfree(secdata);
+}
/**
* aa_alloc_secid - allocate a new secid for a profile
+ * @label: the label to allocate a secid for
+ * @gfp: memory allocation flags
+ *
+ * Returns: 0 with @label->secid initialized
+ * <0 returns error with @label->secid set to AA_SECID_INVALID
*/
-u32 aa_alloc_secid(void)
+int aa_alloc_secid(struct aa_label *label, gfp_t gfp)
{
- u32 secid;
+ unsigned long flags;
+ int ret;
+
+ idr_preload(gfp);
+ spin_lock_irqsave(&secid_lock, flags);
+ ret = idr_alloc(&aa_secids, label, AA_FIRST_SECID, 0, GFP_ATOMIC);
+ spin_unlock_irqrestore(&secid_lock, flags);
+ idr_preload_end();
- /*
- * TODO FIXME: secid recycling - part of profile mapping table
- */
- spin_lock(&secid_lock);
- secid = (++global_secid);
- spin_unlock(&secid_lock);
- return secid;
+ if (ret < 0) {
+ label->secid = AA_SECID_INVALID;
+ return ret;
+ }
+
+ AA_BUG(ret == AA_SECID_INVALID);
+ label->secid = ret;
+ return 0;
}
/**
@@ -51,5 +155,14 @@ u32 aa_alloc_secid(void)
*/
void aa_free_secid(u32 secid)
{
- ; /* NOP ATM */
+ unsigned long flags;
+
+ spin_lock_irqsave(&secid_lock, flags);
+ idr_remove(&aa_secids, secid);
+ spin_unlock_irqrestore(&secid_lock, flags);
+}
+
+void aa_secids_init(void)
+{
+ idr_init_base(&aa_secids, AA_FIRST_SECID);
}
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index c65b39b..cd97929 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -509,7 +509,7 @@ static inline int may_allow_all(struct dev_cgroup *parent)
* This is one of the three key functions for hierarchy implementation.
* This function is responsible for re-evaluating all the cgroup's active
* exceptions due to a parent's exception change.
- * Refer to Documentation/cgroups/devices.txt for more details.
+ * Refer to Documentation/cgroup-v1/devices.txt for more details.
*/
static void revalidate_active_exceptions(struct dev_cgroup *devcg)
{
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index 4237766..b69d3b1 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -1148,7 +1148,7 @@ static long trusted_read(const struct key *key, char __user *buffer,
return -EINVAL;
if (buffer && buflen >= 2 * p->blob_len) {
- ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
+ ascii_buf = kmalloc_array(2, p->blob_len, GFP_KERNEL);
if (!ascii_buf)
return -ENOMEM;
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 9a46dc2..2b5ee5f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4728,7 +4728,7 @@ err_af:
}
/* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
- * and sctp_sendmsg(3) as described in Documentation/security/LSM-sctp.txt
+ * and sctp_sendmsg(3) as described in Documentation/security/LSM-sctp.rst
*/
static int selinux_socket_connect_helper(struct socket *sock,
struct sockaddr *address, int addrlen)
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index a2d4482..dd2ceec 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -2118,7 +2118,7 @@ int security_load_policy(struct selinux_state *state, void *data, size_t len)
int rc = 0;
struct policy_file file = { data, len }, *fp = &file;
- oldpolicydb = kzalloc(2 * sizeof(*oldpolicydb), GFP_KERNEL);
+ oldpolicydb = kcalloc(2, sizeof(*oldpolicydb), GFP_KERNEL);
if (!oldpolicydb) {
rc = -ENOMEM;
goto out;
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 6e937a8..63b3ef9 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -48,7 +48,7 @@ config SND_MIXER_OSS
depends on SND_OSSEMUL
help
To enable OSS mixer API emulation (/dev/mixer*), say Y here
- and read <file:Documentation/sound/alsa/OSS-Emulation.txt>.
+ and read <file:Documentation/sound/designs/oss-emulation.rst>.
Many programs still use the OSS API, so say Y.
@@ -61,7 +61,7 @@ config SND_PCM_OSS
select SND_PCM
help
To enable OSS digital audio (PCM) emulation (/dev/dsp*), say Y
- here and read <file:Documentation/sound/alsa/OSS-Emulation.txt>.
+ here and read <file:Documentation/sound/designs/oss-emulation.rst>.
Many programs still use the OSS API, so say Y.
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 39d853b..946ab08 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -426,7 +426,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
get_user(frames, &data32->frames))
return -EFAULT;
bufptr = compat_ptr(buf);
- bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL);
+ bufs = kmalloc_array(ch, sizeof(void __user *), GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < ch; i++) {
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 04c6301..cecc797 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3072,7 +3072,7 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
if (!frame_aligned(runtime, to->iov->iov_len))
return -EINVAL;
frames = bytes_to_samples(runtime, to->iov->iov_len);
- bufs = kmalloc(sizeof(void *) * to->nr_segs, GFP_KERNEL);
+ bufs = kmalloc_array(to->nr_segs, sizeof(void *), GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < to->nr_segs; ++i)
@@ -3107,7 +3107,7 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
!frame_aligned(runtime, from->iov->iov_len))
return -EINVAL;
frames = bytes_to_samples(runtime, from->iov->iov_len);
- bufs = kmalloc(sizeof(void *) * from->nr_segs, GFP_KERNEL);
+ bufs = kmalloc_array(from->nr_segs, sizeof(void *), GFP_KERNEL);
if (bufs == NULL)
return -ENOMEM;
for (i = 0; i < from->nr_segs; ++i)
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index ab1112e9..a4c8543 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -389,7 +389,8 @@ int snd_seq_pool_init(struct snd_seq_pool *pool)
if (snd_BUG_ON(!pool))
return -EINVAL;
- cellptr = vmalloc(sizeof(struct snd_seq_event_cell) * pool->size);
+ cellptr = vmalloc(array_size(sizeof(struct snd_seq_event_cell),
+ pool->size));
if (!cellptr)
return -ENOMEM;
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index 9e2912e..288f839 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -657,7 +657,7 @@ static struct snd_midi_channel *snd_midi_channel_init_set(int n)
struct snd_midi_channel *chan;
int i;
- chan = kmalloc(n * sizeof(struct snd_midi_channel), GFP_KERNEL);
+ chan = kmalloc_array(n, sizeof(struct snd_midi_channel), GFP_KERNEL);
if (chan) {
for (i = 0; i < n; i++)
snd_midi_channel_init(chan+i, i);
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 7144cc3..648a12d 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -153,7 +153,7 @@ config SND_SERIAL_U16550
select SND_RAWMIDI
help
To include support for MIDI serial port interfaces, say Y here
- and read <file:Documentation/sound/alsa/serial-u16550.txt>.
+ and read <file:Documentation/sound/cards/serial-u16550.rst>.
This driver works with serial UARTs 16550 and better.
This driver accesses the serial port hardware directly, so
@@ -223,7 +223,7 @@ config SND_AC97_POWER_SAVE
the device frequently. A value of 10 seconds would be a
good choice for normal operations.
- See Documentation/sound/alsa/powersave.txt for more details.
+ See Documentation/sound/designs/powersave.rst for more details.
config SND_AC97_POWER_SAVE_DEFAULT
int "Default time-out for AC97 power-save mode"
diff --git a/sound/firewire/fireface/ff-protocol-ff400.c b/sound/firewire/fireface/ff-protocol-ff400.c
index 12aa15d..ad7a0a3 100644
--- a/sound/firewire/fireface/ff-protocol-ff400.c
+++ b/sound/firewire/fireface/ff-protocol-ff400.c
@@ -147,7 +147,7 @@ static int ff400_switch_fetching_mode(struct snd_ff *ff, bool enable)
__le32 *reg;
int i;
- reg = kzalloc(sizeof(__le32) * 18, GFP_KERNEL);
+ reg = kcalloc(18, sizeof(__le32), GFP_KERNEL);
if (reg == NULL)
return -ENOMEM;
diff --git a/sound/firewire/packets-buffer.c b/sound/firewire/packets-buffer.c
index ea15066..1ebf00c 100644
--- a/sound/firewire/packets-buffer.c
+++ b/sound/firewire/packets-buffer.c
@@ -27,7 +27,7 @@ int iso_packets_buffer_init(struct iso_packets_buffer *b, struct fw_unit *unit,
void *p;
int err;
- b->packets = kmalloc(count * sizeof(*b->packets), GFP_KERNEL);
+ b->packets = kmalloc_array(count, sizeof(*b->packets), GFP_KERNEL);
if (!b->packets) {
err = -ENOMEM;
goto error;
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index 8c0f8a9..fc9bcd4 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -420,7 +420,7 @@ static int sq_allocate_buffers(struct sound_queue *sq, int num, int size)
return 0;
sq->numBufs = num;
sq->bufSize = size;
- sq->buffers = kmalloc (num * sizeof(char *), GFP_KERNEL);
+ sq->buffers = kmalloc_array (num, sizeof(char *), GFP_KERNEL);
if (!sq->buffers)
return -ENOMEM;
for (i = 0; i < num; i++) {
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index d9f3fdb..4105d9f 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -175,7 +175,7 @@ config SND_BT87X
help
If you want to record audio from TV cards based on
Brooktree Bt878/Bt879 chips, say Y here and read
- <file:Documentation/sound/alsa/Bt87x.txt>.
+ <file:Documentation/sound/cards/bt87x.rst>.
To compile this driver as a module, choose M here: the module
will be called snd-bt87x.
@@ -210,7 +210,7 @@ config SND_CMIPCI
help
If you want to use soundcards based on C-Media CMI8338, CMI8738,
CMI8768 or CMI8770 chips, say Y here and read
- <file:Documentation/sound/alsa/CMIPCI.txt>.
+ <file:Documentation/sound/cards/cmipci.rst>.
To compile this driver as a module, choose M here: the module
will be called snd-cmipci.
@@ -472,8 +472,8 @@ config SND_EMU10K1
Audigy and E-mu APS (partially supported) soundcards.
The confusing multitude of mixer controls is documented in
- <file:Documentation/sound/alsa/SB-Live-mixer.txt> and
- <file:Documentation/sound/alsa/Audigy-mixer.txt>.
+ <file:Documentation/sound/cards/sb-live-mixer.rst> and
+ <file:Documentation/sound/cards/audigy-mixer.rst>.
To compile this driver as a module, choose M here: the module
will be called snd-emu10k1.
@@ -735,7 +735,7 @@ config SND_MIXART
select SND_PCM
help
If you want to use Digigram miXart soundcards, say Y here and
- read <file:Documentation/sound/alsa/MIXART.txt>.
+ read <file:Documentation/sound/cards/mixart.rst>.
To compile this driver as a module, choose M here: the module
will be called snd-mixart.
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index ed1251c..146e1a3 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -460,7 +460,7 @@ static int load_firmware(struct snd_cs46xx *chip,
entry->size = le32_to_cpu(fwdat[fwlen++]);
if (fwlen + entry->size > fwsize)
goto error_inval;
- entry->data = kmalloc(entry->size * 4, GFP_KERNEL);
+ entry->data = kmalloc_array(entry->size, 4, GFP_KERNEL);
if (!entry->data)
goto error;
memcpy_le32(entry->data, &fwdat[fwlen], entry->size * 4);
@@ -4036,8 +4036,9 @@ int snd_cs46xx_create(struct snd_card *card,
snd_cs46xx_proc_init(card, chip);
#ifdef CONFIG_PM_SLEEP
- chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) *
- ARRAY_SIZE(saved_regs), GFP_KERNEL);
+ chip->saved_regs = kmalloc_array(ARRAY_SIZE(saved_regs),
+ sizeof(*chip->saved_regs),
+ GFP_KERNEL);
if (!chip->saved_regs) {
snd_cs46xx_free(chip);
return -ENOMEM;
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c
index c44eade..598d140 100644
--- a/sound/pci/cs46xx/dsp_spos.c
+++ b/sound/pci/cs46xx/dsp_spos.c
@@ -240,10 +240,13 @@ struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip)
return NULL;
/* better to use vmalloc for this big table */
- ins->symbol_table.symbols = vmalloc(sizeof(struct dsp_symbol_entry) *
- DSP_MAX_SYMBOLS);
+ ins->symbol_table.symbols =
+ vmalloc(array_size(DSP_MAX_SYMBOLS,
+ sizeof(struct dsp_symbol_entry)));
ins->code.data = kmalloc(DSP_CODE_BYTE_SIZE, GFP_KERNEL);
- ins->modules = kmalloc(sizeof(struct dsp_module_desc) * DSP_MAX_MODULES, GFP_KERNEL);
+ ins->modules = kmalloc_array(DSP_MAX_MODULES,
+ sizeof(struct dsp_module_desc),
+ GFP_KERNEL);
if (!ins->symbol_table.symbols || !ins->code.data || !ins->modules) {
cs46xx_dsp_spos_destroy(chip);
goto error;
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c
index 908658a..2ada844 100644
--- a/sound/pci/ctxfi/ctatc.c
+++ b/sound/pci/ctxfi/ctatc.c
@@ -275,7 +275,7 @@ static int atc_pcm_playback_prepare(struct ct_atc *atc, struct ct_atc_pcm *apcm)
/* Get AMIXER resource */
n_amixer = (n_amixer < 2) ? 2 : n_amixer;
- apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
+ apcm->amixers = kcalloc(n_amixer, sizeof(void *), GFP_KERNEL);
if (!apcm->amixers) {
err = -ENOMEM;
goto error1;
@@ -543,18 +543,18 @@ atc_pcm_capture_get_resources(struct ct_atc *atc, struct ct_atc_pcm *apcm)
}
if (n_srcc) {
- apcm->srccs = kzalloc(sizeof(void *)*n_srcc, GFP_KERNEL);
+ apcm->srccs = kcalloc(n_srcc, sizeof(void *), GFP_KERNEL);
if (!apcm->srccs)
return -ENOMEM;
}
if (n_amixer) {
- apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
+ apcm->amixers = kcalloc(n_amixer, sizeof(void *), GFP_KERNEL);
if (!apcm->amixers) {
err = -ENOMEM;
goto error1;
}
}
- apcm->srcimps = kzalloc(sizeof(void *)*n_srcimp, GFP_KERNEL);
+ apcm->srcimps = kcalloc(n_srcimp, sizeof(void *), GFP_KERNEL);
if (!apcm->srcimps) {
err = -ENOMEM;
goto error1;
@@ -819,7 +819,7 @@ static int spdif_passthru_playback_get_resources(struct ct_atc *atc,
/* Get AMIXER resource */
n_amixer = (n_amixer < 2) ? 2 : n_amixer;
- apcm->amixers = kzalloc(sizeof(void *)*n_amixer, GFP_KERNEL);
+ apcm->amixers = kcalloc(n_amixer, sizeof(void *), GFP_KERNEL);
if (!apcm->amixers) {
err = -ENOMEM;
goto error1;
@@ -1378,19 +1378,19 @@ static int atc_get_resources(struct ct_atc *atc)
num_daios = ((atc->model == CTSB1270) ? 8 : 7);
num_srcs = ((atc->model == CTSB1270) ? 6 : 4);
- atc->daios = kzalloc(sizeof(void *)*num_daios, GFP_KERNEL);
+ atc->daios = kcalloc(num_daios, sizeof(void *), GFP_KERNEL);
if (!atc->daios)
return -ENOMEM;
- atc->srcs = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL);
+ atc->srcs = kcalloc(num_srcs, sizeof(void *), GFP_KERNEL);
if (!atc->srcs)
return -ENOMEM;
- atc->srcimps = kzalloc(sizeof(void *)*num_srcs, GFP_KERNEL);
+ atc->srcimps = kcalloc(num_srcs, sizeof(void *), GFP_KERNEL);
if (!atc->srcimps)
return -ENOMEM;
- atc->pcm = kzalloc(sizeof(void *)*(2*4), GFP_KERNEL);
+ atc->pcm = kcalloc(2 * 4, sizeof(void *), GFP_KERNEL);
if (!atc->pcm)
return -ENOMEM;
diff --git a/sound/pci/ctxfi/ctdaio.c b/sound/pci/ctxfi/ctdaio.c
index 7f089cb4..f35a734 100644
--- a/sound/pci/ctxfi/ctdaio.c
+++ b/sound/pci/ctxfi/ctdaio.c
@@ -398,7 +398,8 @@ static int dao_rsc_init(struct dao *dao,
if (err)
return err;
- dao->imappers = kzalloc(sizeof(void *)*desc->msr*2, GFP_KERNEL);
+ dao->imappers = kzalloc(array3_size(sizeof(void *), desc->msr, 2),
+ GFP_KERNEL);
if (!dao->imappers) {
err = -ENOMEM;
goto error1;
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c
index 4f4a2a5..db710d0 100644
--- a/sound/pci/ctxfi/ctmixer.c
+++ b/sound/pci/ctxfi/ctmixer.c
@@ -910,13 +910,14 @@ static int ct_mixer_get_mem(struct ct_mixer **rmixer)
if (!mixer)
return -ENOMEM;
- mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM),
+ mixer->amixers = kcalloc(NUM_CT_AMIXERS * CHN_NUM, sizeof(void *),
GFP_KERNEL);
if (!mixer->amixers) {
err = -ENOMEM;
goto error1;
}
- mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL);
+ mixer->sums = kcalloc(NUM_CT_SUMS * CHN_NUM, sizeof(void *),
+ GFP_KERNEL);
if (!mixer->sums) {
err = -ENOMEM;
goto error2;
diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c
index bb4c9c3..a4fc107 100644
--- a/sound/pci/ctxfi/ctsrc.c
+++ b/sound/pci/ctxfi/ctsrc.c
@@ -679,7 +679,7 @@ static int srcimp_rsc_init(struct srcimp *srcimp,
return err;
/* Reserve memory for imapper nodes */
- srcimp->imappers = kzalloc(sizeof(struct imapper)*desc->msr,
+ srcimp->imappers = kcalloc(desc->msr, sizeof(struct imapper),
GFP_KERNEL);
if (!srcimp->imappers) {
err = -ENOMEM;
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 18267de..61f85ff 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1941,9 +1941,10 @@ int snd_emu10k1_create(struct snd_card *card,
(unsigned long)emu->ptb_pages.addr,
(unsigned long)(emu->ptb_pages.addr + emu->ptb_pages.bytes));
- emu->page_ptr_table = vmalloc(emu->max_cache_pages * sizeof(void *));
- emu->page_addr_table = vmalloc(emu->max_cache_pages *
- sizeof(unsigned long));
+ emu->page_ptr_table = vmalloc(array_size(sizeof(void *),
+ emu->max_cache_pages));
+ emu->page_addr_table = vmalloc(array_size(sizeof(unsigned long),
+ emu->max_cache_pages));
if (emu->page_ptr_table == NULL || emu->page_addr_table == NULL) {
err = -ENOMEM;
goto error;
@@ -2099,7 +2100,7 @@ static int alloc_pm_buffer(struct snd_emu10k1 *emu)
size = ARRAY_SIZE(saved_regs);
if (emu->audigy)
size += ARRAY_SIZE(saved_regs_audigy);
- emu->saved_ptr = vmalloc(4 * NUM_G * size);
+ emu->saved_ptr = vmalloc(array3_size(4, NUM_G, size));
if (!emu->saved_ptr)
return -ENOMEM;
if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0)
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index b45a01b..de2ecbe 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -2683,16 +2683,16 @@ int snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu)
int len;
len = emu->audigy ? 0x200 : 0x100;
- emu->saved_gpr = kmalloc(len * 4, GFP_KERNEL);
+ emu->saved_gpr = kmalloc_array(len, 4, GFP_KERNEL);
if (! emu->saved_gpr)
return -ENOMEM;
len = emu->audigy ? 0x100 : 0xa0;
- emu->tram_val_saved = kmalloc(len * 4, GFP_KERNEL);
- emu->tram_addr_saved = kmalloc(len * 4, GFP_KERNEL);
+ emu->tram_val_saved = kmalloc_array(len, 4, GFP_KERNEL);
+ emu->tram_addr_saved = kmalloc_array(len, 4, GFP_KERNEL);
if (! emu->tram_val_saved || ! emu->tram_addr_saved)
return -ENOMEM;
len = emu->audigy ? 2 * 1024 : 2 * 512;
- emu->saved_icode = vmalloc(len * 4);
+ emu->saved_icode = vmalloc(array_size(len, 4));
if (! emu->saved_icode)
return -ENOMEM;
return 0;
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index d39458a..69f9b10 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1858,7 +1858,9 @@ int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device)
if (!kctl)
return -ENOMEM;
kctl->id.device = device;
- snd_ctl_add(emu->card, kctl);
+ err = snd_ctl_add(emu->card, kctl);
+ if (err < 0)
+ return err;
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index a30da78..4948b95 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -874,7 +874,7 @@ int snd_p16v_mixer(struct snd_emu10k1 *emu)
int snd_p16v_alloc_pm_buffer(struct snd_emu10k1 *emu)
{
- emu->p16v_saved = vmalloc(NUM_CHS * 4 * 0x80);
+ emu->p16v_saved = vmalloc(array_size(NUM_CHS * 4, 0x80));
if (! emu->p16v_saved)
return -ENOMEM;
return 0;
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 73a67bc..e3fb9c6 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1068,11 +1068,19 @@ static int snd_fm801_mixer(struct fm801 *chip)
if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_sec)) < 0)
return err;
}
- for (i = 0; i < FM801_CONTROLS; i++)
- snd_ctl_add(chip->card, snd_ctl_new1(&snd_fm801_controls[i], chip));
+ for (i = 0; i < FM801_CONTROLS; i++) {
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&snd_fm801_controls[i], chip));
+ if (err < 0)
+ return err;
+ }
if (chip->multichannel) {
- for (i = 0; i < FM801_CONTROLS_MULTI; i++)
- snd_ctl_add(chip->card, snd_ctl_new1(&snd_fm801_controls_multi[i], chip));
+ for (i = 0; i < FM801_CONTROLS_MULTI; i++) {
+ err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&snd_fm801_controls_multi[i], chip));
+ if (err < 0)
+ return err;
+ }
}
return 0;
}
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 08151f3..d91c87e 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -158,7 +158,7 @@ static int read_and_add_raw_conns(struct hda_codec *codec, hda_nid_t nid)
len = snd_hda_get_raw_connections(codec, nid, list, ARRAY_SIZE(list));
if (len == -ENOSPC) {
len = snd_hda_get_num_raw_conns(codec, nid);
- result = kmalloc(sizeof(hda_nid_t) * len, GFP_KERNEL);
+ result = kmalloc_array(len, sizeof(hda_nid_t), GFP_KERNEL);
if (!result)
return -ENOMEM;
len = snd_hda_get_raw_connections(codec, nid, result, len);
@@ -438,7 +438,7 @@ static int read_widget_caps(struct hda_codec *codec, hda_nid_t fg_node)
int i;
hda_nid_t nid;
- codec->wcaps = kmalloc(codec->core.num_nodes * 4, GFP_KERNEL);
+ codec->wcaps = kmalloc_array(codec->core.num_nodes, 4, GFP_KERNEL);
if (!codec->wcaps)
return -ENOMEM;
nid = codec->core.start_nid;
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 033aa84..c6b778b 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -825,8 +825,9 @@ static void print_codec_info(struct snd_info_entry *entry,
if (wid_caps & AC_WCAP_CONN_LIST) {
conn_len = snd_hda_get_num_raw_conns(codec, nid);
if (conn_len > 0) {
- conn = kmalloc(sizeof(hda_nid_t) * conn_len,
- GFP_KERNEL);
+ conn = kmalloc_array(conn_len,
+ sizeof(hda_nid_t),
+ GFP_KERNEL);
if (!conn)
return;
if (snd_hda_get_raw_connections(codec, nid, conn,
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 292e2c5..04e949a 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -7482,7 +7482,9 @@ static int ca0132_prepare_verbs(struct hda_codec *codec)
spec->chip_init_verbs = ca0132_init_verbs0;
if (spec->quirk == QUIRK_SBZ)
spec->sbz_init_verbs = sbz_init_verbs;
- spec->spec_init_verbs = kzalloc(sizeof(struct hda_verb) * NUM_SPEC_VERBS, GFP_KERNEL);
+ spec->spec_init_verbs = kcalloc(NUM_SPEC_VERBS,
+ sizeof(struct hda_verb),
+ GFP_KERNEL);
if (!spec->spec_init_verbs)
return -ENOMEM;
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index dbf9910..e7fcfc3 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -958,6 +958,8 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x8079, "HP EliteBook 840 G3", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK),
+ SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
+ SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
SND_PCI_QUIRK(0x103c, 0x8115, "HP Z1 Gen3", CXT_FIXUP_HP_GATE_MIC),
SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index d64dcb9..e9bd33e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -793,6 +793,9 @@ static inline void alc_shutup(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ if (!snd_hda_get_bool_hint(codec, "shutup"))
+ return; /* disabled explicitly by hints */
+
if (spec && spec->shutup)
spec->shutup(codec);
else
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index 9655b08..6c85f13 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -1016,6 +1016,10 @@ static int snd_lx6464es_create(struct snd_card *card,
/* dsp port */
chip->port_dsp_bar = pci_ioremap_bar(pci, 2);
+ if (!chip->port_dsp_bar) {
+ dev_err(card->dev, "cannot remap PCI memory region\n");
+ goto remap_pci_failed;
+ }
err = request_threaded_irq(pci->irq, lx_interrupt, lx_threaded_irq,
IRQF_SHARED, KBUILD_MODNAME, chip);
@@ -1055,6 +1059,9 @@ device_new_failed:
free_irq(pci->irq, chip);
request_irq_failed:
+ iounmap(chip->port_dsp_bar);
+
+remap_pci_failed:
pci_release_regions(pci);
request_regions_failed:
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 8f20dec..224e942 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2657,7 +2657,10 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
chip->irq = pci->irq;
#ifdef CONFIG_PM_SLEEP
- chip->suspend_mem = vmalloc(sizeof(u16) * (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH));
+ chip->suspend_mem =
+ vmalloc(array_size(sizeof(u16),
+ REV_B_CODE_MEMORY_LENGTH +
+ REV_B_DATA_MEMORY_LENGTH));
if (chip->suspend_mem == NULL)
dev_warn(card->dev, "can't allocate apm buffer\n");
#endif
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index a8abb15..7fbdb70 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1188,6 +1188,7 @@ SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);
static int snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
{
struct gameport *gp;
+ int err;
sonic->gameport = gp = gameport_allocate_port();
if (!gp) {
@@ -1203,7 +1204,10 @@ static int snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
gameport_register_port(gp);
- snd_ctl_add(sonic->card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));
+ err = snd_ctl_add(sonic->card,
+ snd_ctl_new1(&snd_sonicvibes_game_control, sonic));
+ if (err < 0)
+ return err;
return 0;
}
@@ -1515,7 +1519,11 @@ static int snd_sonic_probe(struct pci_dev *pci,
return err;
}
- snd_sonicvibes_create_gameport(sonic);
+ err = snd_sonicvibes_create_gameport(sonic);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index eabd84d9..49c64fa 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -3362,7 +3362,9 @@ static int snd_trident_tlb_alloc(struct snd_trident *trident)
trident->tlb.entries = (unsigned int*)ALIGN((unsigned long)trident->tlb.buffer.area, SNDRV_TRIDENT_MAX_PAGES * 4);
trident->tlb.entries_dmaaddr = ALIGN(trident->tlb.buffer.addr, SNDRV_TRIDENT_MAX_PAGES * 4);
/* allocate shadow TLB page table (virtual addresses) */
- trident->tlb.shadow_entries = vmalloc(SNDRV_TRIDENT_MAX_PAGES*sizeof(unsigned long));
+ trident->tlb.shadow_entries =
+ vmalloc(array_size(SNDRV_TRIDENT_MAX_PAGES,
+ sizeof(unsigned long)));
if (!trident->tlb.shadow_entries)
return -ENOMEM;
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 3a1c0b8..c488c5a 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -439,7 +439,9 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
return -ENOMEM;
}
if (! dev->idx_table) {
- dev->idx_table = kmalloc(sizeof(*dev->idx_table) * VIA_TABLE_SIZE, GFP_KERNEL);
+ dev->idx_table = kmalloc_array(VIA_TABLE_SIZE,
+ sizeof(*dev->idx_table),
+ GFP_KERNEL);
if (! dev->idx_table)
return -ENOMEM;
}
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 8a69221..b13c868 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -292,7 +292,9 @@ static int build_via_table(struct viadev *dev, struct snd_pcm_substream *substre
return -ENOMEM;
}
if (! dev->idx_table) {
- dev->idx_table = kmalloc(sizeof(*dev->idx_table) * VIA_TABLE_SIZE, GFP_KERNEL);
+ dev->idx_table = kmalloc_array(VIA_TABLE_SIZE,
+ sizeof(*dev->idx_table),
+ GFP_KERNEL);
if (! dev->idx_table)
return -ENOMEM;
}
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 8ca2e41..6f81396 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2435,8 +2435,8 @@ int snd_ymfpci_create(struct snd_card *card,
goto free_chip;
#ifdef CONFIG_PM_SLEEP
- chip->saved_regs = kmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32),
- GFP_KERNEL);
+ chip->saved_regs = kmalloc_array(YDSXGR_NUM_SAVED_REGS, sizeof(u32),
+ GFP_KERNEL);
if (chip->saved_regs == NULL) {
err = -ENOMEM;
goto free_chip;
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index fb65065..a906560 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -339,8 +339,8 @@ static int au1xpsc_pcm_drvprobe(struct platform_device *pdev)
{
struct au1xpsc_audio_dmadata *dmadata;
- dmadata = devm_kzalloc(&pdev->dev,
- 2 * sizeof(struct au1xpsc_audio_dmadata),
+ dmadata = devm_kcalloc(&pdev->dev,
+ 2, sizeof(struct au1xpsc_audio_dmadata),
GFP_KERNEL);
if (!dmadata)
return -ENOMEM;
diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c
index 6fa1188..38e4a85 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -771,7 +771,7 @@ static int hdmi_codec_probe(struct platform_device *pdev)
hcp->hcd = *hcd;
mutex_init(&hcp->current_stream_lock);
- hcp->daidrv = devm_kzalloc(dev, dai_count * sizeof(*hcp->daidrv),
+ hcp->daidrv = devm_kcalloc(dev, dai_count, sizeof(*hcp->daidrv),
GFP_KERNEL);
if (!hcp->daidrv)
return -ENOMEM;
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 7123845..1dc70f4 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -3449,8 +3449,9 @@ static int rt5645_probe(struct snd_soc_component *component)
if (rt5645->pdata.long_name)
component->card->long_name = rt5645->pdata.long_name;
- rt5645->eq_param = devm_kzalloc(component->dev,
- RT5645_HWEQ_NUM * sizeof(struct rt5645_eq_param_s), GFP_KERNEL);
+ rt5645->eq_param = devm_kcalloc(component->dev,
+ RT5645_HWEQ_NUM, sizeof(struct rt5645_eq_param_s),
+ GFP_KERNEL);
return 0;
}
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index f13ef33..9037a35 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -2023,8 +2023,9 @@ static void wm8904_handle_pdata(struct snd_soc_component *component)
wm8904_get_drc_enum, wm8904_put_drc_enum);
/* We need an array of texts for the enum API */
- wm8904->drc_texts = kmalloc(sizeof(char *)
- * pdata->num_drc_cfgs, GFP_KERNEL);
+ wm8904->drc_texts = kmalloc_array(pdata->num_drc_cfgs,
+ sizeof(char *),
+ GFP_KERNEL);
if (!wm8904->drc_texts)
return;
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 8d49522..108e8bf 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -932,8 +932,9 @@ void wm8958_dsp2_init(struct snd_soc_component *component)
};
/* We need an array of texts for the enum API */
- wm8994->mbc_texts = kmalloc(sizeof(char *)
- * pdata->num_mbc_cfgs, GFP_KERNEL);
+ wm8994->mbc_texts = kmalloc_array(pdata->num_mbc_cfgs,
+ sizeof(char *),
+ GFP_KERNEL);
if (!wm8994->mbc_texts)
return;
@@ -957,8 +958,9 @@ void wm8958_dsp2_init(struct snd_soc_component *component)
};
/* We need an array of texts for the enum API */
- wm8994->vss_texts = kmalloc(sizeof(char *)
- * pdata->num_vss_cfgs, GFP_KERNEL);
+ wm8994->vss_texts = kmalloc_array(pdata->num_vss_cfgs,
+ sizeof(char *),
+ GFP_KERNEL);
if (!wm8994->vss_texts)
return;
@@ -983,8 +985,9 @@ void wm8958_dsp2_init(struct snd_soc_component *component)
};
/* We need an array of texts for the enum API */
- wm8994->vss_hpf_texts = kmalloc(sizeof(char *)
- * pdata->num_vss_hpf_cfgs, GFP_KERNEL);
+ wm8994->vss_hpf_texts = kmalloc_array(pdata->num_vss_hpf_cfgs,
+ sizeof(char *),
+ GFP_KERNEL);
if (!wm8994->vss_hpf_texts)
return;
@@ -1010,8 +1013,9 @@ void wm8958_dsp2_init(struct snd_soc_component *component)
};
/* We need an array of texts for the enum API */
- wm8994->enh_eq_texts = kmalloc(sizeof(char *)
- * pdata->num_enh_eq_cfgs, GFP_KERNEL);
+ wm8994->enh_eq_texts = kmalloc_array(pdata->num_enh_eq_cfgs,
+ sizeof(char *),
+ GFP_KERNEL);
if (!wm8994->enh_eq_texts)
return;
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index 6e9e32a..7fdfdf3 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -3298,8 +3298,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
};
/* We need an array of texts for the enum API */
- wm8994->drc_texts = devm_kzalloc(wm8994->hubs.component->dev,
- sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL);
+ wm8994->drc_texts = devm_kcalloc(wm8994->hubs.component->dev,
+ pdata->num_drc_cfgs, sizeof(char *), GFP_KERNEL);
if (!wm8994->drc_texts)
return;
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 2175dcc..2fcdd84 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1899,7 +1899,7 @@ static void *wm_adsp_read_algs(struct wm_adsp *dsp, size_t n_algs,
adsp_warn(dsp, "Algorithm list end %x 0x%x != 0xbedead\n",
pos + len, be32_to_cpu(val));
- alg = kzalloc(len * 2, GFP_KERNEL | GFP_DMA);
+ alg = kcalloc(len, 2, GFP_KERNEL | GFP_DMA);
if (!alg)
return ERR_PTR(-ENOMEM);
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 1f96c9d..47c0c82 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -1868,8 +1868,8 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
mcasp->num_serializer = pdata->num_serializer;
#ifdef CONFIG_PM_SLEEP
- mcasp->context.xrsr_regs = devm_kzalloc(&pdev->dev,
- sizeof(u32) * mcasp->num_serializer,
+ mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev,
+ mcasp->num_serializer, sizeof(u32),
GFP_KERNEL);
if (!mcasp->context.xrsr_regs) {
ret = -ENOMEM;
@@ -2004,13 +2004,15 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
* bytes.
*/
mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list =
- devm_kzalloc(mcasp->dev, sizeof(unsigned int) *
- (32 + mcasp->num_serializer - 1),
+ devm_kcalloc(mcasp->dev,
+ 32 + mcasp->num_serializer - 1,
+ sizeof(unsigned int),
GFP_KERNEL);
mcasp->chconstr[SNDRV_PCM_STREAM_CAPTURE].list =
- devm_kzalloc(mcasp->dev, sizeof(unsigned int) *
- (32 + mcasp->num_serializer - 1),
+ devm_kcalloc(mcasp->dev,
+ 32 + mcasp->num_serializer - 1,
+ sizeof(unsigned int),
GFP_KERNEL);
if (!mcasp->chconstr[SNDRV_PCM_STREAM_PLAYBACK].list ||
diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c
index 1b61642..d93baca 100644
--- a/sound/soc/generic/audio-graph-card.c
+++ b/sound/soc/generic/audio-graph-card.c
@@ -296,8 +296,8 @@ static int asoc_graph_card_probe(struct platform_device *pdev)
if (num == 0)
return -EINVAL;
- dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
- dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
+ dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL);
+ dai_link = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL);
if (!dai_props || !dai_link)
return -ENOMEM;
diff --git a/sound/soc/generic/audio-graph-scu-card.c b/sound/soc/generic/audio-graph-scu-card.c
index a967aa1..095ef64 100644
--- a/sound/soc/generic/audio-graph-scu-card.c
+++ b/sound/soc/generic/audio-graph-scu-card.c
@@ -348,8 +348,8 @@ static int asoc_graph_card_probe(struct platform_device *pdev)
if (num == 0)
return -EINVAL;
- dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
- dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
+ dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL);
+ dai_link = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL);
if (!dai_props || !dai_link)
return -ENOMEM;
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index 4a516c4..8b374af 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -340,8 +340,8 @@ static int asoc_simple_card_parse_aux_devs(struct device_node *node,
if (n <= 0)
return -EINVAL;
- card->aux_dev = devm_kzalloc(dev,
- n * sizeof(*card->aux_dev), GFP_KERNEL);
+ card->aux_dev = devm_kcalloc(dev,
+ n, sizeof(*card->aux_dev), GFP_KERNEL);
if (!card->aux_dev)
return -ENOMEM;
@@ -435,8 +435,8 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
- dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
- dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
+ dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL);
+ dai_link = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL);
if (!dai_props || !dai_link)
return -ENOMEM;
diff --git a/sound/soc/generic/simple-scu-card.c b/sound/soc/generic/simple-scu-card.c
index 48606c6..4877165 100644
--- a/sound/soc/generic/simple-scu-card.c
+++ b/sound/soc/generic/simple-scu-card.c
@@ -246,8 +246,8 @@ static int asoc_simple_card_probe(struct platform_device *pdev)
num = of_get_child_count(np);
- dai_props = devm_kzalloc(dev, sizeof(*dai_props) * num, GFP_KERNEL);
- dai_link = devm_kzalloc(dev, sizeof(*dai_link) * num, GFP_KERNEL);
+ dai_props = devm_kcalloc(dev, num, sizeof(*dai_props), GFP_KERNEL);
+ dai_link = devm_kcalloc(dev, num, sizeof(*dai_link), GFP_KERNEL);
if (!dai_props || !dai_link)
return -ENOMEM;
diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c
index d7fbb0a..388cefd 100644
--- a/sound/soc/img/img-i2s-in.c
+++ b/sound/soc/img/img-i2s-in.c
@@ -509,8 +509,8 @@ static int img_i2s_in_probe(struct platform_device *pdev)
pm_runtime_put(&pdev->dev);
- i2s->suspend_ch_ctl = devm_kzalloc(dev,
- sizeof(*i2s->suspend_ch_ctl) * i2s->max_i2s_chan, GFP_KERNEL);
+ i2s->suspend_ch_ctl = devm_kcalloc(dev,
+ i2s->max_i2s_chan, sizeof(*i2s->suspend_ch_ctl), GFP_KERNEL);
if (!i2s->suspend_ch_ctl) {
ret = -ENOMEM;
goto err_suspend;
diff --git a/sound/soc/img/img-i2s-out.c b/sound/soc/img/img-i2s-out.c
index 30a95bc..fc2d1da 100644
--- a/sound/soc/img/img-i2s-out.c
+++ b/sound/soc/img/img-i2s-out.c
@@ -479,8 +479,8 @@ static int img_i2s_out_probe(struct platform_device *pdev)
return PTR_ERR(i2s->clk_ref);
}
- i2s->suspend_ch_ctl = devm_kzalloc(dev,
- sizeof(*i2s->suspend_ch_ctl) * i2s->max_i2s_chan, GFP_KERNEL);
+ i2s->suspend_ch_ctl = devm_kcalloc(dev,
+ i2s->max_i2s_chan, sizeof(*i2s->suspend_ch_ctl), GFP_KERNEL);
if (!i2s->suspend_ch_ctl)
return -ENOMEM;
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c
index 62f3a8e..dcff138 100644
--- a/sound/soc/intel/common/sst-ipc.c
+++ b/sound/soc/intel/common/sst-ipc.c
@@ -121,8 +121,8 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc)
{
int i;
- ipc->msg = kzalloc(sizeof(struct ipc_message) *
- IPC_EMPTY_LIST_SIZE, GFP_KERNEL);
+ ipc->msg = kcalloc(IPC_EMPTY_LIST_SIZE, sizeof(struct ipc_message),
+ GFP_KERNEL);
if (ipc->msg == NULL)
return -ENOMEM;
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c
index 2c51297..fcdc716 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -2428,8 +2428,10 @@ static int skl_tplg_get_token(struct device *dev,
case SKL_TKN_U8_DYN_IN_PIN:
if (!mconfig->m_in_pin)
- mconfig->m_in_pin = devm_kzalloc(dev, MAX_IN_QUEUE *
- sizeof(*mconfig->m_in_pin), GFP_KERNEL);
+ mconfig->m_in_pin =
+ devm_kcalloc(dev, MAX_IN_QUEUE,
+ sizeof(*mconfig->m_in_pin),
+ GFP_KERNEL);
if (!mconfig->m_in_pin)
return -ENOMEM;
@@ -2439,8 +2441,10 @@ static int skl_tplg_get_token(struct device *dev,
case SKL_TKN_U8_DYN_OUT_PIN:
if (!mconfig->m_out_pin)
- mconfig->m_out_pin = devm_kzalloc(dev, MAX_IN_QUEUE *
- sizeof(*mconfig->m_in_pin), GFP_KERNEL);
+ mconfig->m_out_pin =
+ devm_kcalloc(dev, MAX_IN_QUEUE,
+ sizeof(*mconfig->m_in_pin),
+ GFP_KERNEL);
if (!mconfig->m_out_pin)
return -ENOMEM;
@@ -2852,14 +2856,14 @@ static int skl_tplg_get_pvt_data_v4(struct snd_soc_tplg_dapm_widget *tplg_w,
mconfig->time_slot = dfw->time_slot;
mconfig->formats_config.caps_size = dfw->caps.caps_size;
- mconfig->m_in_pin = devm_kzalloc(dev,
- MAX_IN_QUEUE * sizeof(*mconfig->m_in_pin),
+ mconfig->m_in_pin = devm_kcalloc(dev,
+ MAX_IN_QUEUE, sizeof(*mconfig->m_in_pin),
GFP_KERNEL);
if (!mconfig->m_in_pin)
return -ENOMEM;
- mconfig->m_out_pin = devm_kzalloc(dev,
- MAX_OUT_QUEUE * sizeof(*mconfig->m_out_pin),
+ mconfig->m_out_pin = devm_kcalloc(dev,
+ MAX_OUT_QUEUE, sizeof(*mconfig->m_out_pin),
GFP_KERNEL);
if (!mconfig->m_out_pin)
return -ENOMEM;
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index 828d11c..968fba4 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -1347,7 +1347,8 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
afe->dev = &pdev->dev;
dev = afe->dev;
- afe_priv->i2s_path = devm_kzalloc(dev, afe_priv->soc->i2s_num *
+ afe_priv->i2s_path = devm_kcalloc(dev,
+ afe_priv->soc->i2s_num,
sizeof(struct mt2701_i2s_path),
GFP_KERNEL);
if (!afe_priv->i2s_path)
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 77a30f0..4dce494 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -22,7 +22,7 @@
*
*/
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/spinlock.h>
#include <linux/tty.h>
#include <linux/module.h>
@@ -32,7 +32,6 @@
#include <asm/mach-types.h>
-#include <mach/board-ams-delta.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h"
@@ -213,7 +212,6 @@ static const struct snd_kcontrol_new ams_delta_audio_controls[] = {
static struct snd_soc_jack ams_delta_hook_switch;
static struct snd_soc_jack_gpio ams_delta_hook_switch_gpios[] = {
{
- .gpio = 4,
.name = "hook_switch",
.report = SND_JACK_HEADSET,
.invert = 1,
@@ -259,6 +257,7 @@ static struct timer_list cx81801_timer;
static bool cx81801_cmd_pending;
static bool ams_delta_muted;
static DEFINE_SPINLOCK(ams_delta_lock);
+static struct gpio_desc *gpiod_modem_codec;
static void cx81801_timeout(struct timer_list *unused)
{
@@ -272,7 +271,7 @@ static void cx81801_timeout(struct timer_list *unused)
/* Reconnect the codec DAI back from the modem to the CPU DAI
* only if digital mute still off */
if (!muted)
- ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC, 0);
+ gpiod_set_value(gpiod_modem_codec, 0);
}
/* Line discipline .open() */
@@ -381,8 +380,7 @@ static void cx81801_receive(struct tty_struct *tty,
/* Apply config pulse by connecting the codec to the modem
* if not already done */
if (apply)
- ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
- AMS_DELTA_LATCH2_MODEM_CODEC);
+ gpiod_set_value(gpiod_modem_codec, 1);
break;
}
}
@@ -432,8 +430,7 @@ static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute)
spin_unlock_bh(&ams_delta_lock);
if (apply)
- ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_CODEC,
- mute ? AMS_DELTA_LATCH2_MODEM_CODEC : 0);
+ gpiod_set_value(gpiod_modem_codec, !!mute);
return 0;
}
@@ -469,14 +466,6 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
/* Store a pointer to the codec structure for tty ldisc use */
cx20442_codec = rtd->codec_dai->component;
- /* Set up digital mute if not provided by the codec */
- if (!codec_dai->driver->ops) {
- codec_dai->driver->ops = &ams_delta_dai_ops;
- } else {
- ams_delta_ops.startup = ams_delta_startup;
- ams_delta_ops.shutdown = ams_delta_shutdown;
- }
-
/* Add hook switch - can be used to control the codec from userspace
* even if line discipline fails */
ret = snd_soc_card_jack_new(card, "hook_switch", SND_JACK_HEADSET,
@@ -486,7 +475,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
"Failed to allocate resources for hook switch, "
"will continue without one.\n");
else {
- ret = snd_soc_jack_add_gpios(&ams_delta_hook_switch,
+ ret = snd_soc_jack_add_gpiods(card->dev, &ams_delta_hook_switch,
ARRAY_SIZE(ams_delta_hook_switch_gpios),
ams_delta_hook_switch_gpios);
if (ret)
@@ -495,6 +484,21 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
"will continue with hook switch inactive.\n");
}
+ gpiod_modem_codec = devm_gpiod_get(card->dev, "modem_codec",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(gpiod_modem_codec)) {
+ dev_warn(card->dev, "Failed to obtain modem_codec GPIO\n");
+ return 0;
+ }
+
+ /* Set up digital mute if not provided by the codec */
+ if (!codec_dai->driver->ops) {
+ codec_dai->driver->ops = &ams_delta_dai_ops;
+ } else {
+ ams_delta_ops.startup = ams_delta_startup;
+ ams_delta_ops.shutdown = ams_delta_shutdown;
+ }
+
/* Register optional line discipline for over the modem control */
ret = tty_register_ldisc(N_V253, &cx81801_ops);
if (ret) {
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 7c998ea..12d4513 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -425,8 +425,8 @@ static int asoc_mmp_sspa_probe(struct platform_device *pdev)
if (priv->sspa == NULL)
return -ENOMEM;
- priv->dma_params = devm_kzalloc(&pdev->dev,
- 2 * sizeof(struct snd_dmaengine_dai_dma_data),
+ priv->dma_params = devm_kcalloc(&pdev->dev,
+ 2, sizeof(struct snd_dmaengine_dai_dma_data),
GFP_KERNEL);
if (priv->dma_params == NULL)
return -ENOMEM;
diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c
index f184168..f2a51ae 100644
--- a/sound/soc/rockchip/rk3399_gru_sound.c
+++ b/sound/soc/rockchip/rk3399_gru_sound.c
@@ -462,7 +462,7 @@ static int rockchip_sound_of_parse_dais(struct device *dev,
num_routes = 0;
for (i = 0; i < ARRAY_SIZE(rockchip_routes); i++)
num_routes += rockchip_routes[i].num_routes;
- routes = devm_kzalloc(dev, num_routes * sizeof(*routes),
+ routes = devm_kcalloc(dev, num_routes, sizeof(*routes),
GFP_KERNEL);
if (!routes)
return -ENOMEM;
diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c
index 4221937..5900fb5 100644
--- a/sound/soc/sh/rcar/cmd.c
+++ b/sound/soc/sh/rcar/cmd.c
@@ -155,7 +155,7 @@ int rsnd_cmd_probe(struct rsnd_priv *priv)
if (!nr)
return 0;
- cmd = devm_kzalloc(dev, sizeof(*cmd) * nr, GFP_KERNEL);
+ cmd = devm_kcalloc(dev, nr, sizeof(*cmd), GFP_KERNEL);
if (!cmd)
return -ENOMEM;
diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c
index af04d41..f237002 100644
--- a/sound/soc/sh/rcar/core.c
+++ b/sound/soc/sh/rcar/core.c
@@ -1110,8 +1110,8 @@ static int rsnd_dai_probe(struct rsnd_priv *priv)
if (!nr)
return -EINVAL;
- rdrv = devm_kzalloc(dev, sizeof(*rdrv) * nr, GFP_KERNEL);
- rdai = devm_kzalloc(dev, sizeof(*rdai) * nr, GFP_KERNEL);
+ rdrv = devm_kcalloc(dev, nr, sizeof(*rdrv), GFP_KERNEL);
+ rdai = devm_kcalloc(dev, nr, sizeof(*rdai), GFP_KERNEL);
if (!rdrv || !rdai)
return -ENOMEM;
diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c
index d201d55..83be7d3 100644
--- a/sound/soc/sh/rcar/ctu.c
+++ b/sound/soc/sh/rcar/ctu.c
@@ -378,7 +378,7 @@ int rsnd_ctu_probe(struct rsnd_priv *priv)
goto rsnd_ctu_probe_done;
}
- ctu = devm_kzalloc(dev, sizeof(*ctu) * nr, GFP_KERNEL);
+ ctu = devm_kcalloc(dev, nr, sizeof(*ctu), GFP_KERNEL);
if (!ctu) {
ret = -ENOMEM;
goto rsnd_ctu_probe_done;
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index dbe54f0..ca1780e 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -344,7 +344,7 @@ int rsnd_dvc_probe(struct rsnd_priv *priv)
goto rsnd_dvc_probe_done;
}
- dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL);
+ dvc = devm_kcalloc(dev, nr, sizeof(*dvc), GFP_KERNEL);
if (!dvc) {
ret = -ENOMEM;
goto rsnd_dvc_probe_done;
diff --git a/sound/soc/sh/rcar/mix.c b/sound/soc/sh/rcar/mix.c
index 7998380..1881b2d 100644
--- a/sound/soc/sh/rcar/mix.c
+++ b/sound/soc/sh/rcar/mix.c
@@ -294,7 +294,7 @@ int rsnd_mix_probe(struct rsnd_priv *priv)
goto rsnd_mix_probe_done;
}
- mix = devm_kzalloc(dev, sizeof(*mix) * nr, GFP_KERNEL);
+ mix = devm_kcalloc(dev, nr, sizeof(*mix), GFP_KERNEL);
if (!mix) {
ret = -ENOMEM;
goto rsnd_mix_probe_done;
diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c
index a727e71..6c72d1a 100644
--- a/sound/soc/sh/rcar/src.c
+++ b/sound/soc/sh/rcar/src.c
@@ -575,7 +575,7 @@ int rsnd_src_probe(struct rsnd_priv *priv)
goto rsnd_src_probe_done;
}
- src = devm_kzalloc(dev, sizeof(*src) * nr, GFP_KERNEL);
+ src = devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL);
if (!src) {
ret = -ENOMEM;
goto rsnd_src_probe_done;
diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c
index 9538f76..6e1166e 100644
--- a/sound/soc/sh/rcar/ssi.c
+++ b/sound/soc/sh/rcar/ssi.c
@@ -1116,7 +1116,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv)
goto rsnd_ssi_probe_done;
}
- ssi = devm_kzalloc(dev, sizeof(*ssi) * nr, GFP_KERNEL);
+ ssi = devm_kcalloc(dev, nr, sizeof(*ssi), GFP_KERNEL);
if (!ssi) {
ret = -ENOMEM;
goto rsnd_ssi_probe_done;
diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c
index 6ff8a36..47bdba9 100644
--- a/sound/soc/sh/rcar/ssiu.c
+++ b/sound/soc/sh/rcar/ssiu.c
@@ -258,7 +258,7 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
/* same number to SSI */
nr = priv->ssi_nr;
- ssiu = devm_kzalloc(dev, sizeof(*ssiu) * nr, GFP_KERNEL);
+ ssiu = devm_kcalloc(dev, nr, sizeof(*ssiu), GFP_KERNEL);
if (!ssiu)
return -ENOMEM;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 3d56f1f..4663de3 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -373,8 +373,8 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
if (!rtd->dai_link->ops)
rtd->dai_link->ops = &null_snd_soc_ops;
- rtd->codec_dais = kzalloc(sizeof(struct snd_soc_dai *) *
- dai_link->num_codecs,
+ rtd->codec_dais = kcalloc(dai_link->num_codecs,
+ sizeof(struct snd_soc_dai *),
GFP_KERNEL);
if (!rtd->codec_dais) {
kfree(rtd);
@@ -3354,7 +3354,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
return -EINVAL;
}
- routes = devm_kzalloc(card->dev, num_routes * sizeof(*routes),
+ routes = devm_kcalloc(card->dev, num_routes, sizeof(*routes),
GFP_KERNEL);
if (!routes) {
dev_err(card->dev,
@@ -3678,8 +3678,8 @@ int snd_soc_of_get_dai_link_codecs(struct device *dev,
dev_err(dev, "Bad phandle in 'sound-dai'\n");
return num_codecs;
}
- component = devm_kzalloc(dev,
- sizeof *component * num_codecs,
+ component = devm_kcalloc(dev,
+ num_codecs, sizeof(*component),
GFP_KERNEL);
if (!component)
return -ENOMEM;
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 255cad4..229c123 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -3055,7 +3055,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_card *card)
continue;
if (w->num_kcontrols) {
- w->kcontrols = kzalloc(w->num_kcontrols *
+ w->kcontrols = kcalloc(w->num_kcontrols,
sizeof(struct snd_kcontrol *),
GFP_KERNEL);
if (!w->kcontrols) {
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 3fd5d9c..53f121a 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -885,7 +885,7 @@ static int soc_tplg_denum_create_texts(struct soc_enum *se,
int i, ret;
se->dobj.control.dtexts =
- kzalloc(sizeof(char *) * ec->items, GFP_KERNEL);
+ kcalloc(ec->items, sizeof(char *), GFP_KERNEL);
if (se->dobj.control.dtexts == NULL)
return -ENOMEM;
diff --git a/sound/soc/uniphier/aio-cpu.c b/sound/soc/uniphier/aio-cpu.c
index 80daec1..2d9b7dd 100644
--- a/sound/soc/uniphier/aio-cpu.c
+++ b/sound/soc/uniphier/aio-cpu.c
@@ -624,15 +624,17 @@ int uniphier_aio_probe(struct platform_device *pdev)
return PTR_ERR(chip->rst);
chip->num_aios = chip->chip_spec->num_dais;
- chip->aios = devm_kzalloc(dev,
- sizeof(struct uniphier_aio) * chip->num_aios,
+ chip->aios = devm_kcalloc(dev,
+ chip->num_aios, sizeof(struct uniphier_aio),
GFP_KERNEL);
if (!chip->aios)
return -ENOMEM;
chip->num_plls = chip->chip_spec->num_plls;
- chip->plls = devm_kzalloc(dev, sizeof(struct uniphier_aio_pll) *
- chip->num_plls, GFP_KERNEL);
+ chip->plls = devm_kcalloc(dev,
+ chip->num_plls,
+ sizeof(struct uniphier_aio_pll),
+ GFP_KERNEL);
if (!chip->plls)
return -ENOMEM;
memcpy(chip->plls, chip->chip_spec->plls,
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
index 224a6a5..2dd2518 100644
--- a/sound/usb/6fire/pcm.c
+++ b/sound/usb/6fire/pcm.c
@@ -591,12 +591,14 @@ static int usb6fire_pcm_buffers_init(struct pcm_runtime *rt)
int i;
for (i = 0; i < PCM_N_URBS; i++) {
- rt->out_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
- * PCM_MAX_PACKET_SIZE, GFP_KERNEL);
+ rt->out_urbs[i].buffer = kcalloc(PCM_MAX_PACKET_SIZE,
+ PCM_N_PACKETS_PER_URB,
+ GFP_KERNEL);
if (!rt->out_urbs[i].buffer)
return -ENOMEM;
- rt->in_urbs[i].buffer = kzalloc(PCM_N_PACKETS_PER_URB
- * PCM_MAX_PACKET_SIZE, GFP_KERNEL);
+ rt->in_urbs[i].buffer = kcalloc(PCM_MAX_PACKET_SIZE,
+ PCM_N_PACKETS_PER_URB,
+ GFP_KERNEL);
if (!rt->in_urbs[i].buffer)
return -ENOMEM;
}
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index fb1c1ea..f35d29f 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -728,7 +728,7 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret)
usb_sndisocpipe(usb_dev, ENDPOINT_PLAYBACK) :
usb_rcvisocpipe(usb_dev, ENDPOINT_CAPTURE);
- urbs = kmalloc(N_URBS * sizeof(*urbs), GFP_KERNEL);
+ urbs = kmalloc_array(N_URBS, sizeof(*urbs), GFP_KERNEL);
if (!urbs) {
*ret = -ENOMEM;
return NULL;
@@ -742,7 +742,8 @@ static struct urb **alloc_urbs(struct snd_usb_caiaqdev *cdev, int dir, int *ret)
}
urbs[i]->transfer_buffer =
- kmalloc(FRAMES_PER_URB * BYTES_PER_FRAME, GFP_KERNEL);
+ kmalloc_array(BYTES_PER_FRAME, FRAMES_PER_URB,
+ GFP_KERNEL);
if (!urbs[i]->transfer_buffer) {
*ret = -ENOMEM;
return urbs;
@@ -857,7 +858,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
&snd_usb_caiaq_ops);
cdev->data_cb_info =
- kmalloc(sizeof(struct snd_usb_caiaq_cb_info) * N_URBS,
+ kmalloc_array(N_URBS, sizeof(struct snd_usb_caiaq_cb_info),
GFP_KERNEL);
if (!cdev->data_cb_info)
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 1406292..9b41b7d 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -32,6 +32,7 @@ struct audioformat {
struct snd_pcm_chmap_elem *chmap; /* (optional) channel map */
bool dsd_dop; /* add DOP headers in case of DSD samples */
bool dsd_bitrev; /* reverse the bits of each DSD sample */
+ bool dsd_raw; /* altsetting is raw DSD */
};
struct snd_usb_substream;
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 49e7ec6..fd13ac1 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -64,8 +64,11 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
sample_width = fmt->bBitResolution;
sample_bytes = fmt->bSubslotSize;
- if (format & UAC2_FORMAT_TYPE_I_RAW_DATA)
+ if (format & UAC2_FORMAT_TYPE_I_RAW_DATA) {
pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL;
+ /* flag potentially raw DSD capable altsettings */
+ fp->dsd_raw = true;
+ }
format <<= 1;
break;
@@ -188,7 +191,8 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
*/
int r, idx;
- fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
+ fp->rate_table = kmalloc_array(nr_rates, sizeof(int),
+ GFP_KERNEL);
if (fp->rate_table == NULL)
return -ENOMEM;
@@ -362,7 +366,7 @@ static int parse_audio_format_rates_v2v3(struct snd_usb_audio *chip,
goto err_free;
}
- fp->rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
+ fp->rate_table = kmalloc_array(fp->nr_rates, sizeof(int), GFP_KERNEL);
if (!fp->rate_table) {
ret = -ENOMEM;
goto err_free;
diff --git a/sound/usb/line6/capture.c b/sound/usb/line6/capture.c
index 947d616..d8a14d7 100644
--- a/sound/usb/line6/capture.c
+++ b/sound/usb/line6/capture.c
@@ -264,8 +264,8 @@ int line6_create_audio_in_urbs(struct snd_line6_pcm *line6pcm)
struct usb_line6 *line6 = line6pcm->line6;
int i;
- line6pcm->in.urbs = kzalloc(
- sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL);
+ line6pcm->in.urbs = kcalloc(line6->iso_buffers, sizeof(struct urb *),
+ GFP_KERNEL);
if (line6pcm->in.urbs == NULL)
return -ENOMEM;
diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c
index b3854f8..72c6f8e 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -158,8 +158,10 @@ static int line6_buffer_acquire(struct snd_line6_pcm *line6pcm,
/* Invoked multiple times in a row so allocate once only */
if (!test_and_set_bit(type, &pstr->opened) && !pstr->buffer) {
- pstr->buffer = kmalloc(line6pcm->line6->iso_buffers *
- LINE6_ISO_PACKETS * pkt_size, GFP_KERNEL);
+ pstr->buffer =
+ kmalloc(array3_size(line6pcm->line6->iso_buffers,
+ LINE6_ISO_PACKETS, pkt_size),
+ GFP_KERNEL);
if (!pstr->buffer)
return -ENOMEM;
}
diff --git a/sound/usb/line6/playback.c b/sound/usb/line6/playback.c
index 819e9b2..dec89d2 100644
--- a/sound/usb/line6/playback.c
+++ b/sound/usb/line6/playback.c
@@ -409,8 +409,8 @@ int line6_create_audio_out_urbs(struct snd_line6_pcm *line6pcm)
struct usb_line6 *line6 = line6pcm->line6;
int i;
- line6pcm->out.urbs = kzalloc(
- sizeof(struct urb *) * line6->iso_buffers, GFP_KERNEL);
+ line6pcm->out.urbs = kcalloc(line6->iso_buffers, sizeof(struct urb *),
+ GFP_KERNEL);
if (line6pcm->out.urbs == NULL)
return -ENOMEM;
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 898afd3..ca963e9 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1653,11 +1653,11 @@ static void build_feature_ctl_badd(struct usb_mixer_interface *mixer,
NULL, NULL, unitid, 0, 0);
}
-static void get_connector_control_name(struct mixer_build *state,
+static void get_connector_control_name(struct usb_mixer_interface *mixer,
struct usb_audio_term *term,
bool is_input, char *name, int name_size)
{
- int name_len = get_term_name(state->chip, term, name, name_size, 0);
+ int name_len = get_term_name(mixer->chip, term, name, name_size, 0);
if (name_len == 0)
strlcpy(name, "Unknown", name_size);
@@ -1674,7 +1674,7 @@ static void get_connector_control_name(struct mixer_build *state,
}
/* Build a mixer control for a UAC connector control (jack-detect) */
-static void build_connector_control(struct mixer_build *state,
+static void build_connector_control(struct usb_mixer_interface *mixer,
struct usb_audio_term *term, bool is_input)
{
struct snd_kcontrol *kctl;
@@ -1683,7 +1683,7 @@ static void build_connector_control(struct mixer_build *state,
cval = kzalloc(sizeof(*cval), GFP_KERNEL);
if (!cval)
return;
- snd_usb_mixer_elem_init_std(&cval->head, state->mixer, term->id);
+ snd_usb_mixer_elem_init_std(&cval->head, mixer, term->id);
/*
* UAC2: The first byte from reading the UAC2_TE_CONNECTOR control returns the
* number of channels connected.
@@ -1694,7 +1694,7 @@ static void build_connector_control(struct mixer_build *state,
* This boolean ctl will simply report if any channels are connected
* or not.
*/
- if (state->mixer->protocol == UAC_VERSION_2)
+ if (mixer->protocol == UAC_VERSION_2)
cval->control = UAC2_TE_CONNECTOR;
else /* UAC_VERSION_3 */
cval->control = UAC3_TE_INSERTION;
@@ -1705,11 +1705,11 @@ static void build_connector_control(struct mixer_build *state,
cval->max = 1;
kctl = snd_ctl_new1(&usb_connector_ctl_ro, cval);
if (!kctl) {
- usb_audio_err(state->chip, "cannot malloc kcontrol\n");
+ usb_audio_err(mixer->chip, "cannot malloc kcontrol\n");
kfree(cval);
return;
}
- get_connector_control_name(state, term, is_input, kctl->id.name,
+ get_connector_control_name(mixer, term, is_input, kctl->id.name,
sizeof(kctl->id.name));
kctl->private_free = snd_usb_mixer_elem_free;
snd_usb_mixer_add_control(&cval->head, kctl);
@@ -2042,7 +2042,7 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid,
/* Check for jack detection. */
if (uac_v2v3_control_is_readable(bmctls, control))
- build_connector_control(state, &iterm, true);
+ build_connector_control(state->mixer, &iterm, true);
return 0;
}
@@ -2515,7 +2515,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
cval->control = (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) ?
UAC2_CX_CLOCK_SELECTOR : UAC2_SU_SELECTOR;
- namelist = kmalloc(sizeof(char *) * desc->bNrInPins, GFP_KERNEL);
+ namelist = kmalloc_array(desc->bNrInPins, sizeof(char *), GFP_KERNEL);
if (!namelist) {
kfree(cval);
return -ENOMEM;
@@ -2918,6 +2918,23 @@ static int snd_usb_mixer_controls_badd(struct usb_mixer_interface *mixer,
UAC3_BADD_FU_ID7, map->map);
}
+ /* Insertion Control */
+ if (f->subclass == UAC3_FUNCTION_SUBCLASS_HEADSET_ADAPTER) {
+ struct usb_audio_term iterm, oterm;
+
+ /* Input Term - Insertion control */
+ memset(&iterm, 0, sizeof(iterm));
+ iterm.id = UAC3_BADD_IT_ID4;
+ iterm.type = UAC_BIDIR_TERMINAL_HEADSET;
+ build_connector_control(mixer, &iterm, true);
+
+ /* Output Term - Insertion control */
+ memset(&oterm, 0, sizeof(oterm));
+ oterm.id = UAC3_BADD_OT_ID3;
+ oterm.type = UAC_BIDIR_TERMINAL_HEADSET;
+ build_connector_control(mixer, &oterm, false);
+ }
+
return 0;
}
@@ -2990,7 +3007,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
if (uac_v2v3_control_is_readable(le16_to_cpu(desc->bmControls),
UAC2_TE_CONNECTOR)) {
- build_connector_control(&state, &state.oterm,
+ build_connector_control(state.mixer, &state.oterm,
false);
}
} else { /* UAC_VERSION_3 */
@@ -3017,7 +3034,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
if (uac_v2v3_control_is_readable(le32_to_cpu(desc->bmControls),
UAC3_TE_INSERTION)) {
- build_connector_control(&state, &state.oterm,
+ build_connector_control(state.mixer, &state.oterm,
false);
}
}
@@ -3321,10 +3338,12 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
err = snd_usb_mixer_controls(mixer);
if (err < 0)
goto _error;
- err = snd_usb_mixer_status_create(mixer);
- if (err < 0)
- goto _error;
}
+
+ err = snd_usb_mixer_status_create(mixer);
+ if (err < 0)
+ goto _error;
+
err = create_keep_iface_ctl(mixer);
if (err < 0)
goto _error;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 78d1cad..160f52c 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1123,7 +1123,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
return 0;
subs->rate_list.list = rate_list =
- kmalloc(sizeof(int) * count, GFP_KERNEL);
+ kmalloc_array(count, sizeof(int), GFP_KERNEL);
if (!subs->rate_list.list)
return -ENOMEM;
subs->rate_list.count = count;
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 0e37e35..8aac48f 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3277,6 +3277,10 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
}
},
+/* disabled due to regression for other devices;
+ * see https://bugzilla.kernel.org/show_bug.cgi?id=199905
+ */
+#if 0
{
/*
* Nura's first gen headphones use Cambridge Silicon Radio's vendor
@@ -3324,6 +3328,7 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
}
}
},
+#endif /* disabled */
{
/*
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index f4b6917..02b6cc0 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1362,16 +1362,12 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
case USB_ID(0x1511, 0x0037): /* AURALiC VEGA */
case USB_ID(0x20b1, 0x0002): /* Wyred 4 Sound DAC-2 DSD */
case USB_ID(0x20b1, 0x2004): /* Matrix Audio X-SPDIF 2 */
- case USB_ID(0x20b1, 0x3008): /* iFi Audio micro/nano iDSD */
case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */
case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */
case USB_ID(0x22d9, 0x0416): /* OPPO HA-1 */
case USB_ID(0x22d9, 0x0436): /* OPPO Sonica */
case USB_ID(0x22d9, 0x0461): /* OPPO UDP-205 */
case USB_ID(0x2522, 0x0012): /* LH Labs VI DAC Infinity */
- case USB_ID(0x25ce, 0x001f): /* Mytek Brooklyn DAC */
- case USB_ID(0x25ce, 0x0021): /* Mytek Manhattan DAC */
- case USB_ID(0x25ce, 0x8025): /* Mytek Brooklyn DAC+ */
case USB_ID(0x2772, 0x0230): /* Pro-Ject Pre Box S2 Digital */
if (fp->altsetting == 2)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
@@ -1389,7 +1385,6 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
case USB_ID(0x20b1, 0x3021): /* Eastern El. MiniMax Tube DAC Supreme */
case USB_ID(0x20b1, 0x3023): /* Aune X1S 32BIT/384 DSD DAC */
case USB_ID(0x20b1, 0x302d): /* Unison Research Unico CD Due */
- case USB_ID(0x20b1, 0x3036): /* Holo Springs Level 3 R2R DAC */
case USB_ID(0x20b1, 0x307b): /* CH Precision C1 DAC */
case USB_ID(0x20b1, 0x3086): /* Singxer F-1 converter board */
case USB_ID(0x22d9, 0x0426): /* OPPO HA-2 */
@@ -1443,6 +1438,20 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
}
+ /* Mostly generic method to detect many DSD-capable implementations -
+ * from XMOS/Thesycon
+ */
+ switch (USB_ID_VENDOR(chip->usb_id)) {
+ case 0x20b1: /* XMOS based devices */
+ case 0x25ce: /* Mytek devices */
+ if (fp->dsd_raw)
+ return SNDRV_PCM_FMTBIT_DSD_U32_BE;
+ break;
+ default:
+ break;
+
+ }
+
return 0;
}
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index 0ddf292..da4a5a5 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -266,7 +266,9 @@ int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y)
int err = 0,
i;
- if (NULL == (usX2Y->AS04.buffer = kmalloc(URB_DataLen_AsyncSeq*URBS_AsyncSeq, GFP_KERNEL))) {
+ usX2Y->AS04.buffer = kmalloc_array(URBS_AsyncSeq,
+ URB_DataLen_AsyncSeq, GFP_KERNEL);
+ if (NULL == usX2Y->AS04.buffer) {
err = -ENOMEM;
} else
for (i = 0; i < URBS_AsyncSeq; ++i) {
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 345e439..2b83305 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -436,7 +436,9 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs)
}
if (!is_playback && !(*purb)->transfer_buffer) {
/* allocate a capture buffer per urb */
- (*purb)->transfer_buffer = kmalloc(subs->maxpacksize * nr_of_packs(), GFP_KERNEL);
+ (*purb)->transfer_buffer =
+ kmalloc_array(subs->maxpacksize,
+ nr_of_packs(), GFP_KERNEL);
if (NULL == (*purb)->transfer_buffer) {
usX2Y_urbs_release(subs);
return -ENOMEM;
@@ -662,7 +664,8 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate)
err = -ENOMEM;
goto cleanup;
}
- usbdata = kmalloc(sizeof(int) * NOOF_SETRATE_URBS, GFP_KERNEL);
+ usbdata = kmalloc_array(NOOF_SETRATE_URBS, sizeof(int),
+ GFP_KERNEL);
if (NULL == usbdata) {
err = -ENOMEM;
goto cleanup;
diff --git a/tools/bpf/bpftool/perf.c b/tools/bpf/bpftool/perf.c
index ac6b1a1..b76b77d 100644
--- a/tools/bpf/bpftool/perf.c
+++ b/tools/bpf/bpftool/perf.c
@@ -29,9 +29,10 @@ static bool has_perf_query_support(void)
if (perf_query_supported)
goto out;
- fd = open(bin_name, O_RDONLY);
+ fd = open("/", O_RDONLY);
if (fd < 0) {
- p_err("perf_query_support: %s", strerror(errno));
+ p_err("perf_query_support: cannot open directory \"/\" (%s)",
+ strerror(errno));
goto out;
}
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index a4f4352..05f42a4 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -90,7 +90,9 @@ static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
}
wallclock_secs = (real_time_ts.tv_sec - boot_time_ts.tv_sec) +
- nsecs / 1000000000;
+ (real_time_ts.tv_nsec - boot_time_ts.tv_nsec + nsecs) /
+ 1000000000;
+
if (!localtime_r(&wallclock_secs, &load_tm)) {
snprintf(buf, size, "%llu", nsecs / 1000000000);
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index b02c41e..39e364c 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -677,10 +677,10 @@ struct kvm_ioeventfd {
};
#define KVM_X86_DISABLE_EXITS_MWAIT (1 << 0)
-#define KVM_X86_DISABLE_EXITS_HTL (1 << 1)
+#define KVM_X86_DISABLE_EXITS_HLT (1 << 1)
#define KVM_X86_DISABLE_EXITS_PAUSE (1 << 2)
#define KVM_X86_DISABLE_VALID_EXITS (KVM_X86_DISABLE_EXITS_MWAIT | \
- KVM_X86_DISABLE_EXITS_HTL | \
+ KVM_X86_DISABLE_EXITS_HLT | \
KVM_X86_DISABLE_EXITS_PAUSE)
/* for KVM_ENABLE_CAP */
diff --git a/tools/include/uapi/linux/prctl.h b/tools/include/uapi/linux/prctl.h
index db9f15f..c0d7ea0 100644
--- a/tools/include/uapi/linux/prctl.h
+++ b/tools/include/uapi/linux/prctl.h
@@ -170,7 +170,7 @@ struct prctl_mm_map {
* asking selinux for a specific new context (e.g. with runcon) will result
* in execve returning -EPERM.
*
- * See Documentation/prctl/no_new_privs.txt for more details.
+ * See Documentation/userspace-api/no_new_privs.rst for more details.
*/
#define PR_SET_NO_NEW_PRIVS 38
#define PR_GET_NO_NEW_PRIVS 39
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index 6a12bbf..7aba824 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -201,7 +201,7 @@ static void mem_toupper(char *f, size_t len)
/*
* Check for "NAME_PATH" environment variable to override fs location (for
- * testing). This matches the recommendation in Documentation/sysfs-rules.txt
+ * testing). This matches the recommendation in Documentation/admin-guide/sysfs-rules.rst
* for SYSFS_PATH.
*/
static bool fs__env_override(struct fs *fs)
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 38047c6..f4a25bd 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -164,6 +164,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
"lbug_with_loc",
"fortify_panic",
"usercopy_abort",
+ "machine_real_restart",
};
if (func->bind == STB_WEAK)
diff --git a/tools/perf/util/bpf-prologue.c b/tools/perf/util/bpf-prologue.c
index 2934775..77e4891 100644
--- a/tools/perf/util/bpf-prologue.c
+++ b/tools/perf/util/bpf-prologue.c
@@ -61,7 +61,7 @@ check_pos(struct bpf_insn_pos *pos)
/*
* Convert type string (u8/u16/u32/u64/s8/s16/s32/s64 ..., see
- * Documentation/trace/kprobetrace.txt) to size field of BPF_LDX_MEM
+ * Documentation/trace/kprobetrace.rst) to size field of BPF_LDX_MEM
* instruction (BPF_{B,H,W,DW}).
*/
static int
diff --git a/tools/power/cpupower/bench/parse.c b/tools/power/cpupower/bench/parse.c
index 9b65f05..9ba8a44 100644
--- a/tools/power/cpupower/bench/parse.c
+++ b/tools/power/cpupower/bench/parse.c
@@ -104,7 +104,7 @@ FILE *prepare_output(const char *dirname)
dirname, time(NULL));
}
- dprintf("logilename: %s\n", filename);
+ dprintf("logfilename: %s\n", filename);
output = fopen(filename, "w+");
if (output == NULL) {
diff --git a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
index 5b3205f..5b8c495 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpuidle_sysfs.c
@@ -126,6 +126,20 @@ void fix_up_intel_idle_driver_name(char *tmp, int num)
}
}
+#ifdef __powerpc__
+void map_power_idle_state_name(char *tmp)
+{
+ if (!strncmp(tmp, "stop0_lite", CSTATE_NAME_LEN))
+ strcpy(tmp, "stop0L");
+ else if (!strncmp(tmp, "stop1_lite", CSTATE_NAME_LEN))
+ strcpy(tmp, "stop1L");
+ else if (!strncmp(tmp, "stop2_lite", CSTATE_NAME_LEN))
+ strcpy(tmp, "stop2L");
+}
+#else
+void map_power_idle_state_name(char *tmp) { }
+#endif
+
static struct cpuidle_monitor *cpuidle_register(void)
{
int num;
@@ -145,6 +159,7 @@ static struct cpuidle_monitor *cpuidle_register(void)
if (tmp == NULL)
continue;
+ map_power_idle_state_name(tmp);
fix_up_intel_idle_driver_name(tmp, num);
strncpy(cpuidle_cstates[num].name, tmp, CSTATE_NAME_LEN - 1);
free(tmp);
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
index 05f953f..051da0a 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c
@@ -70,36 +70,43 @@ void print_n_spaces(int n)
printf(" ");
}
-/* size of s must be at least n + 1 */
+/*s is filled with left and right spaces
+ *to make its length atleast n+1
+ */
int fill_string_with_spaces(char *s, int n)
{
+ char *temp;
int len = strlen(s);
- if (len > n)
+
+ if (len >= n)
return -1;
+
+ temp = malloc(sizeof(char) * (n+1));
for (; len < n; len++)
s[len] = ' ';
s[len] = '\0';
+ snprintf(temp, n+1, " %s", s);
+ strcpy(s, temp);
+ free(temp);
return 0;
}
+#define MAX_COL_WIDTH 6
void print_header(int topology_depth)
{
int unsigned mon;
int state, need_len;
cstate_t s;
char buf[128] = "";
- int percent_width = 4;
fill_string_with_spaces(buf, topology_depth * 5 - 1);
printf("%s|", buf);
for (mon = 0; mon < avail_monitors; mon++) {
- need_len = monitors[mon]->hw_states_num * (percent_width + 3)
+ need_len = monitors[mon]->hw_states_num * (MAX_COL_WIDTH + 1)
- 1;
- if (mon != 0) {
- printf("|| ");
- need_len--;
- }
+ if (mon != 0)
+ printf("||");
sprintf(buf, "%s", monitors[mon]->name);
fill_string_with_spaces(buf, need_len);
printf("%s", buf);
@@ -107,23 +114,21 @@ void print_header(int topology_depth)
printf("\n");
if (topology_depth > 2)
- printf("PKG |");
+ printf(" PKG|");
if (topology_depth > 1)
printf("CORE|");
if (topology_depth > 0)
- printf("CPU |");
+ printf(" CPU|");
for (mon = 0; mon < avail_monitors; mon++) {
if (mon != 0)
- printf("|| ");
- else
- printf(" ");
+ printf("||");
for (state = 0; state < monitors[mon]->hw_states_num; state++) {
if (state != 0)
- printf(" | ");
+ printf("|");
s = monitors[mon]->hw_states[state];
sprintf(buf, "%s", s.name);
- fill_string_with_spaces(buf, percent_width);
+ fill_string_with_spaces(buf, MAX_COL_WIDTH);
printf("%s", buf);
}
printf(" ");
diff --git a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
index 9e43f33..2ae50b4 100644
--- a/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
+++ b/tools/power/cpupower/utils/idle_monitor/cpupower-monitor.h
@@ -15,7 +15,16 @@
#define MONITORS_MAX 20
#define MONITOR_NAME_LEN 20
+
+/* CSTATE_NAME_LEN is limited by header field width defined
+ * in cpupower-monitor.c. Header field width is defined to be
+ * sum of percent width and two spaces for padding.
+ */
+#ifdef __powerpc__
+#define CSTATE_NAME_LEN 7
+#else
#define CSTATE_NAME_LEN 5
+#endif
#define CSTATE_DESC_LEN 60
int cpu_count;
diff --git a/tools/power/pm-graph/config/custom-timeline-functions.cfg b/tools/power/pm-graph/config/custom-timeline-functions.cfg
index 4f80ad7..f8fcb06 100644
--- a/tools/power/pm-graph/config/custom-timeline-functions.cfg
+++ b/tools/power/pm-graph/config/custom-timeline-functions.cfg
@@ -105,7 +105,7 @@ override-dev-timeline-functions: true
# example: [color=#CC00CC]
#
# arglist: A list of arguments from registers/stack addresses. See URL:
-# https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt
+# https://www.kernel.org/doc/Documentation/trace/kprobetrace.rst
#
# example: cpu=%di:s32
#
@@ -170,7 +170,7 @@ pm_restore_console:
# example: [color=#CC00CC]
#
# arglist: A list of arguments from registers/stack addresses. See URL:
-# https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt
+# https://www.kernel.org/doc/Documentation/trace/kprobetrace.rst
#
# example: port=+36(%di):s32
#
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index ca9ef70..d39e4ff 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -56,7 +56,7 @@ name as necessary to disambiguate it from others is necessary. Note that option
.PP
\fB--hide column\fP do not show the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--hide sysfs" to hide the sysfs statistics columns as a group.
.PP
-\fB--enable column\fP show the specified built-in columns, which are otherwise disabled, by default. Currently the only built-in counters disabled by default are "usec" and "Time_Of_Day_Seconds".
+\fB--enable column\fP show the specified built-in columns, which are otherwise disabled, by default. Currently the only built-in counters disabled by default are "usec", "Time_Of_Day_Seconds", "APIC" and "X2APIC".
The column name "all" can be used to enable all disabled-by-default built-in counters.
.PP
\fB--show column\fP show only the specified built-in columns. May be invoked multiple times, or with a comma-separated list of column names. Use "--show sysfs" to show the sysfs statistics columns as a group.
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index d6cff30..4d14bbb 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -109,6 +109,7 @@ unsigned int has_hwp_activity_window; /* IA32_HWP_REQUEST[bits 41:32] */
unsigned int has_hwp_epp; /* IA32_HWP_REQUEST[bits 31:24] */
unsigned int has_hwp_pkg; /* IA32_HWP_REQUEST_PKG */
unsigned int has_misc_feature_control;
+unsigned int first_counter_read = 1;
#define RAPL_PKG (1 << 0)
/* 0x610 MSR_PKG_POWER_LIMIT */
@@ -170,6 +171,8 @@ struct thread_data {
unsigned long long irq_count;
unsigned int smi_count;
unsigned int cpu_id;
+ unsigned int apic_id;
+ unsigned int x2apic_id;
unsigned int flags;
#define CPU_IS_FIRST_THREAD_IN_CORE 0x2
#define CPU_IS_FIRST_CORE_IN_PACKAGE 0x4
@@ -381,19 +384,23 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
}
/*
- * Each string in this array is compared in --show and --hide cmdline.
- * Thus, strings that are proper sub-sets must follow their more specific peers.
+ * This list matches the column headers, except
+ * 1. built-in only, the sysfs counters are not here -- we learn of those at run-time
+ * 2. Core and CPU are moved to the end, we can't have strings that contain them
+ * matching on them for --show and --hide.
*/
struct msr_counter bic[] = {
{ 0x0, "usec" },
{ 0x0, "Time_Of_Day_Seconds" },
{ 0x0, "Package" },
+ { 0x0, "Node" },
{ 0x0, "Avg_MHz" },
+ { 0x0, "Busy%" },
{ 0x0, "Bzy_MHz" },
{ 0x0, "TSC_MHz" },
{ 0x0, "IRQ" },
{ 0x0, "SMI", "", 32, 0, FORMAT_DELTA, NULL},
- { 0x0, "Busy%" },
+ { 0x0, "sysfs" },
{ 0x0, "CPU%c1" },
{ 0x0, "CPU%c3" },
{ 0x0, "CPU%c6" },
@@ -424,73 +431,73 @@ struct msr_counter bic[] = {
{ 0x0, "Cor_J" },
{ 0x0, "GFX_J" },
{ 0x0, "RAM_J" },
- { 0x0, "Core" },
- { 0x0, "CPU" },
{ 0x0, "Mod%c6" },
- { 0x0, "sysfs" },
{ 0x0, "Totl%C0" },
{ 0x0, "Any%C0" },
{ 0x0, "GFX%C0" },
{ 0x0, "CPUGFX%" },
- { 0x0, "Node%" },
+ { 0x0, "Core" },
+ { 0x0, "CPU" },
+ { 0x0, "APIC" },
+ { 0x0, "X2APIC" },
};
-
-
#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
#define BIC_USEC (1ULL << 0)
#define BIC_TOD (1ULL << 1)
#define BIC_Package (1ULL << 2)
-#define BIC_Avg_MHz (1ULL << 3)
-#define BIC_Bzy_MHz (1ULL << 4)
-#define BIC_TSC_MHz (1ULL << 5)
-#define BIC_IRQ (1ULL << 6)
-#define BIC_SMI (1ULL << 7)
-#define BIC_Busy (1ULL << 8)
-#define BIC_CPU_c1 (1ULL << 9)
-#define BIC_CPU_c3 (1ULL << 10)
-#define BIC_CPU_c6 (1ULL << 11)
-#define BIC_CPU_c7 (1ULL << 12)
-#define BIC_ThreadC (1ULL << 13)
-#define BIC_CoreTmp (1ULL << 14)
-#define BIC_CoreCnt (1ULL << 15)
-#define BIC_PkgTmp (1ULL << 16)
-#define BIC_GFX_rc6 (1ULL << 17)
-#define BIC_GFXMHz (1ULL << 18)
-#define BIC_Pkgpc2 (1ULL << 19)
-#define BIC_Pkgpc3 (1ULL << 20)
-#define BIC_Pkgpc6 (1ULL << 21)
-#define BIC_Pkgpc7 (1ULL << 22)
-#define BIC_Pkgpc8 (1ULL << 23)
-#define BIC_Pkgpc9 (1ULL << 24)
-#define BIC_Pkgpc10 (1ULL << 25)
-#define BIC_CPU_LPI (1ULL << 26)
-#define BIC_SYS_LPI (1ULL << 27)
-#define BIC_PkgWatt (1ULL << 26)
-#define BIC_CorWatt (1ULL << 27)
-#define BIC_GFXWatt (1ULL << 28)
-#define BIC_PkgCnt (1ULL << 29)
-#define BIC_RAMWatt (1ULL << 30)
-#define BIC_PKG__ (1ULL << 31)
-#define BIC_RAM__ (1ULL << 32)
-#define BIC_Pkg_J (1ULL << 33)
-#define BIC_Cor_J (1ULL << 34)
-#define BIC_GFX_J (1ULL << 35)
-#define BIC_RAM_J (1ULL << 36)
-#define BIC_Core (1ULL << 37)
-#define BIC_CPU (1ULL << 38)
-#define BIC_Mod_c6 (1ULL << 39)
-#define BIC_sysfs (1ULL << 40)
-#define BIC_Totl_c0 (1ULL << 41)
-#define BIC_Any_c0 (1ULL << 42)
-#define BIC_GFX_c0 (1ULL << 43)
-#define BIC_CPUGFX (1ULL << 44)
-#define BIC_Node (1ULL << 45)
-
-#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD)
+#define BIC_Node (1ULL << 3)
+#define BIC_Avg_MHz (1ULL << 4)
+#define BIC_Busy (1ULL << 5)
+#define BIC_Bzy_MHz (1ULL << 6)
+#define BIC_TSC_MHz (1ULL << 7)
+#define BIC_IRQ (1ULL << 8)
+#define BIC_SMI (1ULL << 9)
+#define BIC_sysfs (1ULL << 10)
+#define BIC_CPU_c1 (1ULL << 11)
+#define BIC_CPU_c3 (1ULL << 12)
+#define BIC_CPU_c6 (1ULL << 13)
+#define BIC_CPU_c7 (1ULL << 14)
+#define BIC_ThreadC (1ULL << 15)
+#define BIC_CoreTmp (1ULL << 16)
+#define BIC_CoreCnt (1ULL << 17)
+#define BIC_PkgTmp (1ULL << 18)
+#define BIC_GFX_rc6 (1ULL << 19)
+#define BIC_GFXMHz (1ULL << 20)
+#define BIC_Pkgpc2 (1ULL << 21)
+#define BIC_Pkgpc3 (1ULL << 22)
+#define BIC_Pkgpc6 (1ULL << 23)
+#define BIC_Pkgpc7 (1ULL << 24)
+#define BIC_Pkgpc8 (1ULL << 25)
+#define BIC_Pkgpc9 (1ULL << 26)
+#define BIC_Pkgpc10 (1ULL << 27)
+#define BIC_CPU_LPI (1ULL << 28)
+#define BIC_SYS_LPI (1ULL << 29)
+#define BIC_PkgWatt (1ULL << 30)
+#define BIC_CorWatt (1ULL << 31)
+#define BIC_GFXWatt (1ULL << 32)
+#define BIC_PkgCnt (1ULL << 33)
+#define BIC_RAMWatt (1ULL << 34)
+#define BIC_PKG__ (1ULL << 35)
+#define BIC_RAM__ (1ULL << 36)
+#define BIC_Pkg_J (1ULL << 37)
+#define BIC_Cor_J (1ULL << 38)
+#define BIC_GFX_J (1ULL << 39)
+#define BIC_RAM_J (1ULL << 40)
+#define BIC_Mod_c6 (1ULL << 41)
+#define BIC_Totl_c0 (1ULL << 42)
+#define BIC_Any_c0 (1ULL << 43)
+#define BIC_GFX_c0 (1ULL << 44)
+#define BIC_CPUGFX (1ULL << 45)
+#define BIC_Core (1ULL << 46)
+#define BIC_CPU (1ULL << 47)
+#define BIC_APIC (1ULL << 48)
+#define BIC_X2APIC (1ULL << 49)
+
+#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)
unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT);
-unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs;
+unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;
#define DO_BIC(COUNTER_NAME) (bic_enabled & bic_present & COUNTER_NAME)
#define ENABLE_BIC(COUNTER_NAME) (bic_enabled |= COUNTER_NAME)
@@ -517,17 +524,34 @@ void help(void)
"when COMMAND completes.\n"
"If no COMMAND is specified, turbostat wakes every 5-seconds\n"
"to print statistics, until interrupted.\n"
- "--add add a counter\n"
- " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
- "--cpu cpu-set limit output to summary plus cpu-set:\n"
- " {core | package | j,k,l..m,n-p }\n"
- "--quiet skip decoding system configuration header\n"
- "--interval sec.subsec Override default 5-second measurement interval\n"
- "--help print this help message\n"
- "--list list column headers only\n"
- "--num_iterations num number of the measurement iterations\n"
- "--out file create or truncate \"file\" for all output\n"
- "--version print version information\n"
+ " -a, --add add a counter\n"
+ " eg. --add msr0x10,u64,cpu,delta,MY_TSC\n"
+ " -c, --cpu cpu-set limit output to summary plus cpu-set:\n"
+ " {core | package | j,k,l..m,n-p }\n"
+ " -d, --debug displays usec, Time_Of_Day_Seconds and more debugging\n"
+ " -D, --Dump displays the raw counter values\n"
+ " -e, --enable [all | column]\n"
+ " shows all or the specified disabled column\n"
+ " -H, --hide [column|column,column,...]\n"
+ " hide the specified column(s)\n"
+ " -i, --interval sec.subsec\n"
+ " Override default 5-second measurement interval\n"
+ " -J, --Joules displays energy in Joules instead of Watts\n"
+ " -l, --list list column headers only\n"
+ " -n, --num_iterations num\n"
+ " number of the measurement iterations\n"
+ " -o, --out file\n"
+ " create or truncate \"file\" for all output\n"
+ " -q, --quiet skip decoding system configuration header\n"
+ " -s, --show [column|column,column,...]\n"
+ " show only the specified column(s)\n"
+ " -S, --Summary\n"
+ " limits output to 1-line system summary per interval\n"
+ " -T, --TCC temperature\n"
+ " sets the Thermal Control Circuit temperature in\n"
+ " degrees Celsius\n"
+ " -h, --help print this help message\n"
+ " -v, --version print version information\n"
"\n"
"For more help, run \"man turbostat\"\n");
}
@@ -601,6 +625,10 @@ void print_header(char *delim)
outp += sprintf(outp, "%sCore", (printed++ ? delim : ""));
if (DO_BIC(BIC_CPU))
outp += sprintf(outp, "%sCPU", (printed++ ? delim : ""));
+ if (DO_BIC(BIC_APIC))
+ outp += sprintf(outp, "%sAPIC", (printed++ ? delim : ""));
+ if (DO_BIC(BIC_X2APIC))
+ outp += sprintf(outp, "%sX2APIC", (printed++ ? delim : ""));
if (DO_BIC(BIC_Avg_MHz))
outp += sprintf(outp, "%sAvg_MHz", (printed++ ? delim : ""));
if (DO_BIC(BIC_Busy))
@@ -880,6 +908,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
if (DO_BIC(BIC_CPU))
outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
+ if (DO_BIC(BIC_APIC))
+ outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
+ if (DO_BIC(BIC_X2APIC))
+ outp += sprintf(outp, "%s-", (printed++ ? delim : ""));
} else {
if (DO_BIC(BIC_Package)) {
if (p)
@@ -904,6 +936,10 @@ int format_counters(struct thread_data *t, struct core_data *c,
}
if (DO_BIC(BIC_CPU))
outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->cpu_id);
+ if (DO_BIC(BIC_APIC))
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->apic_id);
+ if (DO_BIC(BIC_X2APIC))
+ outp += sprintf(outp, "%s%d", (printed++ ? delim : ""), t->x2apic_id);
}
if (DO_BIC(BIC_Avg_MHz))
@@ -1231,6 +1267,12 @@ delta_thread(struct thread_data *new, struct thread_data *old,
int i;
struct msr_counter *mp;
+ /* we run cpuid just the 1st time, copy the results */
+ if (DO_BIC(BIC_APIC))
+ new->apic_id = old->apic_id;
+ if (DO_BIC(BIC_X2APIC))
+ new->x2apic_id = old->x2apic_id;
+
/*
* the timestamps from start of measurement interval are in "old"
* the timestamp from end of measurement interval are in "new"
@@ -1393,6 +1435,12 @@ int sum_counters(struct thread_data *t, struct core_data *c,
int i;
struct msr_counter *mp;
+ /* copy un-changing apic_id's */
+ if (DO_BIC(BIC_APIC))
+ average.threads.apic_id = t->apic_id;
+ if (DO_BIC(BIC_X2APIC))
+ average.threads.x2apic_id = t->x2apic_id;
+
/* remember first tv_begin */
if (average.threads.tv_begin.tv_sec == 0)
average.threads.tv_begin = t->tv_begin;
@@ -1619,6 +1667,34 @@ int get_mp(int cpu, struct msr_counter *mp, unsigned long long *counterp)
return 0;
}
+void get_apic_id(struct thread_data *t)
+{
+ unsigned int eax, ebx, ecx, edx, max_level;
+
+ eax = ebx = ecx = edx = 0;
+
+ if (!genuine_intel)
+ return;
+
+ __cpuid(0, max_level, ebx, ecx, edx);
+
+ __cpuid(1, eax, ebx, ecx, edx);
+ t->apic_id = (ebx >> 24) & 0xf;
+
+ if (max_level < 0xb)
+ return;
+
+ if (!DO_BIC(BIC_X2APIC))
+ return;
+
+ ecx = 0;
+ __cpuid(0xb, eax, ebx, ecx, edx);
+ t->x2apic_id = edx;
+
+ if (debug && (t->apic_id != t->x2apic_id))
+ fprintf(stderr, "cpu%d: apic 0x%x x2apic 0x%x\n", t->cpu_id, t->apic_id, t->x2apic_id);
+}
+
/*
* get_counters(...)
* migrate to cpu
@@ -1632,7 +1708,6 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
struct msr_counter *mp;
int i;
-
gettimeofday(&t->tv_begin, (struct timezone *)NULL);
if (cpu_migrate(cpu)) {
@@ -1640,6 +1715,8 @@ int get_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
return -1;
}
+ if (first_counter_read)
+ get_apic_id(t);
retry:
t->tsc = rdtsc(); /* we are running on local CPU of interest */
@@ -2432,6 +2509,12 @@ void set_node_data(void)
if (pni[pkg].count > topo.nodes_per_pkg)
topo.nodes_per_pkg = pni[0].count;
+ /* Fake 1 node per pkg for machines that don't
+ * expose nodes and thus avoid -nan results
+ */
+ if (topo.nodes_per_pkg == 0)
+ topo.nodes_per_pkg = 1;
+
for (cpu = 0; cpu < topo.num_cpus; cpu++) {
pkg = cpus[cpu].physical_package_id;
node = cpus[cpu].physical_node_id;
@@ -2879,6 +2962,7 @@ void do_sleep(void)
}
}
+
void turbostat_loop()
{
int retval;
@@ -2892,6 +2976,7 @@ restart:
snapshot_proc_sysfs_files();
retval = for_all_cpus(get_counters, EVEN_COUNTERS);
+ first_counter_read = 0;
if (retval < -1) {
exit(retval);
} else if (retval == -1) {
@@ -4392,7 +4477,7 @@ void process_cpuid()
if (!quiet) {
fprintf(outf, "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
max_level, family, model, stepping, family, model, stepping);
- fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s\n",
+ fprintf(outf, "CPUID(1): %s %s %s %s %s %s %s %s %s %s\n",
ecx & (1 << 0) ? "SSE3" : "-",
ecx & (1 << 3) ? "MONITOR" : "-",
ecx & (1 << 6) ? "SMX" : "-",
@@ -4401,6 +4486,7 @@ void process_cpuid()
edx & (1 << 4) ? "TSC" : "-",
edx & (1 << 5) ? "MSR" : "-",
edx & (1 << 22) ? "ACPI-TM" : "-",
+ edx & (1 << 28) ? "HT" : "-",
edx & (1 << 29) ? "TM" : "-");
}
@@ -4652,7 +4738,6 @@ void process_cpuid()
return;
}
-
/*
* in /dev/cpu/ return success for names that are numbers
* ie. filter out ".", "..", "microcode".
@@ -4842,6 +4927,13 @@ void init_counter(struct thread_data *thread_base, struct core_data *core_base,
struct core_data *c;
struct pkg_data *p;
+
+ /* Workaround for systems where physical_node_id==-1
+ * and logical_node_id==(-1 - topo.num_cpus)
+ */
+ if (node_id < 0)
+ node_id = 0;
+
t = GET_THREAD(thread_base, thread_id, core_id, node_id, pkg_id);
c = GET_CORE(core_base, core_id, node_id, pkg_id);
p = GET_PKG(pkg_base, pkg_id);
@@ -4946,6 +5038,7 @@ int fork_it(char **argv)
snapshot_proc_sysfs_files();
status = for_all_cpus(get_counters, EVEN_COUNTERS);
+ first_counter_read = 0;
if (status)
exit(status);
/* clear affinity side-effect of get_counters() */
@@ -5009,7 +5102,7 @@ int get_and_dump_counters(void)
}
void print_version() {
- fprintf(outf, "turbostat version 18.06.01"
+ fprintf(outf, "turbostat version 18.06.20"
" - Len Brown <lenb@kernel.org>\n");
}
@@ -5381,7 +5474,7 @@ void cmdline(int argc, char **argv)
break;
case 'e':
/* --enable specified counter */
- bic_enabled |= bic_lookup(optarg, SHOW_LIST);
+ bic_enabled = bic_enabled | bic_lookup(optarg, SHOW_LIST);
break;
case 'd':
debug++;
@@ -5465,7 +5558,6 @@ void cmdline(int argc, char **argv)
int main(int argc, char **argv)
{
outf = stderr;
-
cmdline(argc, argv);
if (!quiet)
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 607ed87..7a6214e 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -16,9 +16,7 @@ LDLIBS += -lcap -lelf -lrt -lpthread
TEST_CUSTOM_PROGS = $(OUTPUT)/urandom_read
all: $(TEST_CUSTOM_PROGS)
-$(TEST_CUSTOM_PROGS): urandom_read
-
-urandom_read: urandom_read.c
+$(TEST_CUSTOM_PROGS): $(OUTPUT)/%: %.c
$(CC) -o $(TEST_CUSTOM_PROGS) -static $< -Wl,--build-id
# Order correspond to 'make run_tests' order
diff --git a/tools/testing/selftests/bpf/config b/tools/testing/selftests/bpf/config
index 1eefe21..7eb613f 100644
--- a/tools/testing/selftests/bpf/config
+++ b/tools/testing/selftests/bpf/config
@@ -7,3 +7,13 @@ CONFIG_CGROUP_BPF=y
CONFIG_NETDEVSIM=m
CONFIG_NET_CLS_ACT=y
CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_IPIP=y
+CONFIG_IPV6=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=y
+CONFIG_IPV6_GRE=y
+CONFIG_CRYPTO_USER_API_HASH=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_VXLAN=y
+CONFIG_GENEVE=y
diff --git a/tools/testing/selftests/bpf/get_cgroup_id_kern.c b/tools/testing/selftests/bpf/get_cgroup_id_kern.c
index 2cf8cb2..014dba1 100644
--- a/tools/testing/selftests/bpf/get_cgroup_id_kern.c
+++ b/tools/testing/selftests/bpf/get_cgroup_id_kern.c
@@ -11,12 +11,24 @@ struct bpf_map_def SEC("maps") cg_ids = {
.max_entries = 1,
};
+struct bpf_map_def SEC("maps") pidmap = {
+ .type = BPF_MAP_TYPE_ARRAY,
+ .key_size = sizeof(__u32),
+ .value_size = sizeof(__u32),
+ .max_entries = 1,
+};
+
SEC("tracepoint/syscalls/sys_enter_nanosleep")
int trace(void *ctx)
{
- __u32 key = 0;
+ __u32 pid = bpf_get_current_pid_tgid();
+ __u32 key = 0, *expected_pid;
__u64 *val;
+ expected_pid = bpf_map_lookup_elem(&pidmap, &key);
+ if (!expected_pid || *expected_pid != pid)
+ return 0;
+
val = bpf_map_lookup_elem(&cg_ids, &key);
if (val)
*val = bpf_get_current_cgroup_id();
diff --git a/tools/testing/selftests/bpf/get_cgroup_id_user.c b/tools/testing/selftests/bpf/get_cgroup_id_user.c
index ea19a42..e8da7b3 100644
--- a/tools/testing/selftests/bpf/get_cgroup_id_user.c
+++ b/tools/testing/selftests/bpf/get_cgroup_id_user.c
@@ -50,13 +50,13 @@ int main(int argc, char **argv)
const char *probe_name = "syscalls/sys_enter_nanosleep";
const char *file = "get_cgroup_id_kern.o";
int err, bytes, efd, prog_fd, pmu_fd;
+ int cgroup_fd, cgidmap_fd, pidmap_fd;
struct perf_event_attr attr = {};
- int cgroup_fd, cgidmap_fd;
struct bpf_object *obj;
__u64 kcgid = 0, ucgid;
+ __u32 key = 0, pid;
int exit_code = 1;
char buf[256];
- __u32 key = 0;
err = setup_cgroup_environment();
if (CHECK(err, "setup_cgroup_environment", "err %d errno %d\n", err,
@@ -81,6 +81,14 @@ int main(int argc, char **argv)
cgidmap_fd, errno))
goto close_prog;
+ pidmap_fd = bpf_find_map(__func__, obj, "pidmap");
+ if (CHECK(pidmap_fd < 0, "bpf_find_map", "err %d errno %d\n",
+ pidmap_fd, errno))
+ goto close_prog;
+
+ pid = getpid();
+ bpf_map_update_elem(pidmap_fd, &key, &pid, 0);
+
snprintf(buf, sizeof(buf),
"/sys/kernel/debug/tracing/events/%s/id", probe_name);
efd = open(buf, O_RDONLY, 0);
diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py
index e78aad0..be800d0 100755
--- a/tools/testing/selftests/bpf/test_offload.py
+++ b/tools/testing/selftests/bpf/test_offload.py
@@ -163,6 +163,10 @@ def bpftool(args, JSON=True, ns="", fail=True):
def bpftool_prog_list(expected=None, ns=""):
_, progs = bpftool("prog show", JSON=True, ns=ns, fail=True)
+ # Remove the base progs
+ for p in base_progs:
+ if p in progs:
+ progs.remove(p)
if expected is not None:
if len(progs) != expected:
fail(True, "%d BPF programs loaded, expected %d" %
@@ -171,6 +175,10 @@ def bpftool_prog_list(expected=None, ns=""):
def bpftool_map_list(expected=None, ns=""):
_, maps = bpftool("map show", JSON=True, ns=ns, fail=True)
+ # Remove the base maps
+ for m in base_maps:
+ if m in maps:
+ maps.remove(m)
if expected is not None:
if len(maps) != expected:
fail(True, "%d BPF maps loaded, expected %d" %
@@ -585,8 +593,8 @@ skip(os.getuid() != 0, "test must be run as root")
# Check tools
ret, progs = bpftool("prog", fail=False)
skip(ret != 0, "bpftool not installed")
-# Check no BPF programs are loaded
-skip(len(progs) != 0, "BPF programs already loaded on the system")
+base_progs = progs
+_, base_maps = bpftool("map")
# Check netdevsim
ret, out = cmd("modprobe netdevsim", fail=False)
diff --git a/tools/testing/selftests/bpf/test_tunnel.sh b/tools/testing/selftests/bpf/test_tunnel.sh
index aeb2901..546aee3 100755
--- a/tools/testing/selftests/bpf/test_tunnel.sh
+++ b/tools/testing/selftests/bpf/test_tunnel.sh
@@ -608,28 +608,26 @@ setup_xfrm_tunnel()
test_xfrm_tunnel()
{
config_device
- #tcpdump -nei veth1 ip &
- output=$(mktemp)
- cat /sys/kernel/debug/tracing/trace_pipe | tee $output &
- setup_xfrm_tunnel
+ > /sys/kernel/debug/tracing/trace
+ setup_xfrm_tunnel
tc qdisc add dev veth1 clsact
tc filter add dev veth1 proto ip ingress bpf da obj test_tunnel_kern.o \
sec xfrm_get_state
ip netns exec at_ns0 ping $PING_ARG 10.1.1.200
sleep 1
- grep "reqid 1" $output
+ grep "reqid 1" /sys/kernel/debug/tracing/trace
check_err $?
- grep "spi 0x1" $output
+ grep "spi 0x1" /sys/kernel/debug/tracing/trace
check_err $?
- grep "remote ip 0xac100164" $output
+ grep "remote ip 0xac100164" /sys/kernel/debug/tracing/trace
check_err $?
cleanup
if [ $ret -ne 0 ]; then
- echo -e ${RED}"FAIL: xfrm tunnel"${NC}
- return 1
- fi
- echo -e ${GREEN}"PASS: xfrm tunnel"${NC}
+ echo -e ${RED}"FAIL: xfrm tunnel"${NC}
+ return 1
+ fi
+ echo -e ${GREEN}"PASS: xfrm tunnel"${NC}
}
attach_bpf()
@@ -657,6 +655,10 @@ cleanup()
ip link del ip6geneve11 2> /dev/null
ip link del erspan11 2> /dev/null
ip link del ip6erspan11 2> /dev/null
+ ip xfrm policy delete dir out src 10.1.1.200/32 dst 10.1.1.100/32 2> /dev/null
+ ip xfrm policy delete dir in src 10.1.1.100/32 dst 10.1.1.200/32 2> /dev/null
+ ip xfrm state delete src 172.16.1.100 dst 172.16.1.200 proto esp spi 0x1 2> /dev/null
+ ip xfrm state delete src 172.16.1.200 dst 172.16.1.100 proto esp spi 0x2 2> /dev/null
}
cleanup_exit()
@@ -668,7 +670,7 @@ cleanup_exit()
check()
{
- ip link help $1 2>&1 | grep -q "^Usage:"
+ ip link help 2>&1 | grep -q "\s$1\s"
if [ $? -ne 0 ];then
echo "SKIP $1: iproute2 not support"
cleanup
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 7cb1d74..2ecd27b 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -8647,7 +8647,7 @@ static struct bpf_test tests[] = {
offsetof(struct __sk_buff, mark)),
BPF_EXIT_INSN(),
},
- .errstr = "dereference of modified ctx ptr R1 off=68+8, ctx+const is allowed, ctx+const+const is not",
+ .errstr = "dereference of modified ctx ptr",
.result = REJECT,
.prog_type = BPF_PROG_TYPE_SCHED_CLS,
},
@@ -12258,6 +12258,62 @@ static struct bpf_test tests[] = {
.result = ACCEPT,
.retval = 5,
},
+ {
+ "pass unmodified ctx pointer to helper",
+ .insns = {
+ BPF_MOV64_IMM(BPF_REG_2, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_update),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+ .result = ACCEPT,
+ },
+ {
+ "pass modified ctx pointer to helper, 1",
+ .insns = {
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612),
+ BPF_MOV64_IMM(BPF_REG_2, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_update),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+ .result = REJECT,
+ .errstr = "dereference of modified ctx ptr",
+ },
+ {
+ "pass modified ctx pointer to helper, 2",
+ .insns = {
+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -612),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_get_socket_cookie),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .result_unpriv = REJECT,
+ .result = REJECT,
+ .errstr_unpriv = "dereference of modified ctx ptr",
+ .errstr = "dereference of modified ctx ptr",
+ },
+ {
+ "pass modified ctx pointer to helper, 3",
+ .insns = {
+ BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, 0),
+ BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 4),
+ BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_3),
+ BPF_MOV64_IMM(BPF_REG_2, 0),
+ BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
+ BPF_FUNC_csum_update),
+ BPF_MOV64_IMM(BPF_REG_0, 0),
+ BPF_EXIT_INSN(),
+ },
+ .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+ .result = REJECT,
+ .errstr = "variable ctx access var_off=(0x0; 0x4)",
+ },
};
static int probe_filter_length(const struct bpf_insn *fp)
diff --git a/tools/testing/selftests/cgroup/cgroup_util.c b/tools/testing/selftests/cgroup/cgroup_util.c
index b69bdeb..1e9e3c4 100644
--- a/tools/testing/selftests/cgroup/cgroup_util.c
+++ b/tools/testing/selftests/cgroup/cgroup_util.c
@@ -35,7 +35,7 @@ out:
return len;
}
-static ssize_t write_text(const char *path, char *buf, size_t len)
+static ssize_t write_text(const char *path, char *buf, ssize_t len)
{
int fd;
@@ -140,7 +140,7 @@ long cg_read_key_long(const char *cgroup, const char *control, const char *key)
int cg_write(const char *cgroup, const char *control, char *buf)
{
char path[PATH_MAX];
- size_t len = strlen(buf);
+ ssize_t len = strlen(buf);
snprintf(path, sizeof(path), "%s/%s", cgroup, control);
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc
index 5ba7303..a000256 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_string.tc
@@ -24,6 +24,14 @@ arm*)
ARG2=%r1
OFFS=4
;;
+ppc64*)
+ ARG2=%r4
+ OFFS=8
+;;
+ppc*)
+ ARG2=%r4
+ OFFS=4
+;;
*)
echo "Please implement other architecture here"
exit_untested
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc
index 231bcd2..d026ff4 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_syntax.tc
@@ -34,6 +34,13 @@ arm*)
GOODREG=%r0
BADREG=%ax
;;
+ppc*)
+ GOODREG=%r3
+ BADREG=%msr
+;;
+*)
+ echo "Please implement other architecture here"
+ exit_untested
esac
test_goodarg() # Good-args
diff --git a/tools/testing/selftests/pstore/pstore_post_reboot_tests b/tools/testing/selftests/pstore/pstore_post_reboot_tests
index 6ccb154..22f8df1 100755
--- a/tools/testing/selftests/pstore/pstore_post_reboot_tests
+++ b/tools/testing/selftests/pstore/pstore_post_reboot_tests
@@ -7,13 +7,16 @@
#
# Released under the terms of the GPL v2.
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
. ./common_tests
if [ -e $REBOOT_FLAG ]; then
rm $REBOOT_FLAG
else
prlog "pstore_crash_test has not been executed yet. we skip further tests."
- exit 0
+ exit $ksft_skip
fi
prlog -n "Mounting pstore filesystem ... "
diff --git a/tools/testing/selftests/rseq/param_test.c b/tools/testing/selftests/rseq/param_test.c
index 6a9f602..6152523 100644
--- a/tools/testing/selftests/rseq/param_test.c
+++ b/tools/testing/selftests/rseq/param_test.c
@@ -137,6 +137,30 @@ unsigned int yield_mod_cnt, nr_abort;
"subic. %%" INJECT_ASM_REG ", %%" INJECT_ASM_REG ", 1\n\t" \
"bne 222b\n\t" \
"333:\n\t"
+
+#elif defined(__mips__)
+
+#define RSEQ_INJECT_INPUT \
+ , [loop_cnt_1]"m"(loop_cnt[1]) \
+ , [loop_cnt_2]"m"(loop_cnt[2]) \
+ , [loop_cnt_3]"m"(loop_cnt[3]) \
+ , [loop_cnt_4]"m"(loop_cnt[4]) \
+ , [loop_cnt_5]"m"(loop_cnt[5]) \
+ , [loop_cnt_6]"m"(loop_cnt[6])
+
+#define INJECT_ASM_REG "$5"
+
+#define RSEQ_INJECT_CLOBBER \
+ , INJECT_ASM_REG
+
+#define RSEQ_INJECT_ASM(n) \
+ "lw " INJECT_ASM_REG ", %[loop_cnt_" #n "]\n\t" \
+ "beqz " INJECT_ASM_REG ", 333f\n\t" \
+ "222:\n\t" \
+ "addiu " INJECT_ASM_REG ", -1\n\t" \
+ "bnez " INJECT_ASM_REG ", 222b\n\t" \
+ "333:\n\t"
+
#else
#error unsupported target
#endif
diff --git a/tools/testing/selftests/rseq/rseq-arm.h b/tools/testing/selftests/rseq/rseq-arm.h
index 3b055f9..3cea198 100644
--- a/tools/testing/selftests/rseq/rseq-arm.h
+++ b/tools/testing/selftests/rseq/rseq-arm.h
@@ -57,6 +57,7 @@ do { \
#define __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \
abort_label, version, flags, \
start_ip, post_commit_offset, abort_ip) \
+ ".balign 32\n\t" \
__rseq_str(table_label) ":\n\t" \
".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
".word " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) ", 0x0\n\t" \
diff --git a/tools/testing/selftests/rseq/rseq-mips.h b/tools/testing/selftests/rseq/rseq-mips.h
new file mode 100644
index 0000000..7f48ecf
--- /dev/null
+++ b/tools/testing/selftests/rseq/rseq-mips.h
@@ -0,0 +1,725 @@
+/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
+/*
+ * Author: Paul Burton <paul.burton@mips.com>
+ * (C) Copyright 2018 MIPS Tech LLC
+ *
+ * Based on rseq-arm.h:
+ * (C) Copyright 2016-2018 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#define RSEQ_SIG 0x53053053
+
+#define rseq_smp_mb() __asm__ __volatile__ ("sync" ::: "memory")
+#define rseq_smp_rmb() rseq_smp_mb()
+#define rseq_smp_wmb() rseq_smp_mb()
+
+#define rseq_smp_load_acquire(p) \
+__extension__ ({ \
+ __typeof(*p) ____p1 = RSEQ_READ_ONCE(*p); \
+ rseq_smp_mb(); \
+ ____p1; \
+})
+
+#define rseq_smp_acquire__after_ctrl_dep() rseq_smp_rmb()
+
+#define rseq_smp_store_release(p, v) \
+do { \
+ rseq_smp_mb(); \
+ RSEQ_WRITE_ONCE(*p, v); \
+} while (0)
+
+#ifdef RSEQ_SKIP_FASTPATH
+#include "rseq-skip.h"
+#else /* !RSEQ_SKIP_FASTPATH */
+
+#if _MIPS_SZLONG == 64
+# define LONG ".dword"
+# define LONG_LA "dla"
+# define LONG_L "ld"
+# define LONG_S "sd"
+# define LONG_ADDI "daddiu"
+# define U32_U64_PAD(x) x
+#elif _MIPS_SZLONG == 32
+# define LONG ".word"
+# define LONG_LA "la"
+# define LONG_L "lw"
+# define LONG_S "sw"
+# define LONG_ADDI "addiu"
+# ifdef __BIG_ENDIAN
+# define U32_U64_PAD(x) "0x0, " x
+# else
+# define U32_U64_PAD(x) x ", 0x0"
+# endif
+#else
+# error unsupported _MIPS_SZLONG
+#endif
+
+#define __RSEQ_ASM_DEFINE_TABLE(version, flags, start_ip, \
+ post_commit_offset, abort_ip) \
+ ".pushsection __rseq_table, \"aw\"\n\t" \
+ ".balign 32\n\t" \
+ ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
+ LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \
+ LONG " " U32_U64_PAD(__rseq_str(post_commit_offset)) "\n\t" \
+ LONG " " U32_U64_PAD(__rseq_str(abort_ip)) "\n\t" \
+ ".popsection\n\t"
+
+#define RSEQ_ASM_DEFINE_TABLE(start_ip, post_commit_ip, abort_ip) \
+ __RSEQ_ASM_DEFINE_TABLE(0x0, 0x0, start_ip, \
+ (post_commit_ip - start_ip), abort_ip)
+
+#define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
+ RSEQ_INJECT_ASM(1) \
+ LONG_LA " $4, " __rseq_str(cs_label) "\n\t" \
+ LONG_S " $4, %[" __rseq_str(rseq_cs) "]\n\t" \
+ __rseq_str(label) ":\n\t"
+
+#define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \
+ RSEQ_INJECT_ASM(2) \
+ "lw $4, %[" __rseq_str(current_cpu_id) "]\n\t" \
+ "bne $4, %[" __rseq_str(cpu_id) "], " __rseq_str(label) "\n\t"
+
+#define __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \
+ abort_label, version, flags, \
+ start_ip, post_commit_offset, abort_ip) \
+ ".balign 32\n\t" \
+ __rseq_str(table_label) ":\n\t" \
+ ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
+ LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \
+ LONG " " U32_U64_PAD(__rseq_str(post_commit_offset)) "\n\t" \
+ LONG " " U32_U64_PAD(__rseq_str(abort_ip)) "\n\t" \
+ ".word " __rseq_str(RSEQ_SIG) "\n\t" \
+ __rseq_str(label) ":\n\t" \
+ teardown \
+ "b %l[" __rseq_str(abort_label) "]\n\t"
+
+#define RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, abort_label, \
+ start_ip, post_commit_ip, abort_ip) \
+ __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \
+ abort_label, 0x0, 0x0, start_ip, \
+ (post_commit_ip - start_ip), abort_ip)
+
+#define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label) \
+ __rseq_str(label) ":\n\t" \
+ teardown \
+ "b %l[" __rseq_str(cmpfail_label) "]\n\t"
+
+#define rseq_workaround_gcc_asm_size_guess() __asm__ __volatile__("")
+
+static inline __attribute__((always_inline))
+int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
+{
+ RSEQ_INJECT_C(9)
+
+ rseq_workaround_gcc_asm_size_guess();
+ __asm__ __volatile__ goto (
+ RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+ /* Start rseq by storing table entry pointer into rseq_cs. */
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+ RSEQ_INJECT_ASM(3)
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], %l[cmpfail]\n\t"
+ RSEQ_INJECT_ASM(4)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], %l[error2]\n\t"
+#endif
+ /* final store */
+ LONG_S " %[newv], %[v]\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(5)
+ "b 5f\n\t"
+ RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
+ "5:\n\t"
+ : /* gcc asm goto does not allow outputs */
+ : [cpu_id] "r" (cpu),
+ [current_cpu_id] "m" (__rseq_abi.cpu_id),
+ [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [v] "m" (*v),
+ [expect] "r" (expect),
+ [newv] "r" (newv)
+ RSEQ_INJECT_INPUT
+ : "$4", "memory"
+ RSEQ_INJECT_CLOBBER
+ : abort, cmpfail
+#ifdef RSEQ_COMPARE_TWICE
+ , error1, error2
+#endif
+ );
+ rseq_workaround_gcc_asm_size_guess();
+ return 0;
+abort:
+ rseq_workaround_gcc_asm_size_guess();
+ RSEQ_INJECT_FAILED
+ return -1;
+cmpfail:
+ rseq_workaround_gcc_asm_size_guess();
+ return 1;
+#ifdef RSEQ_COMPARE_TWICE
+error1:
+ rseq_bug("cpu_id comparison failed");
+error2:
+ rseq_bug("expected value comparison failed");
+#endif
+}
+
+static inline __attribute__((always_inline))
+int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
+ off_t voffp, intptr_t *load, int cpu)
+{
+ RSEQ_INJECT_C(9)
+
+ rseq_workaround_gcc_asm_size_guess();
+ __asm__ __volatile__ goto (
+ RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+ /* Start rseq by storing table entry pointer into rseq_cs. */
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+ RSEQ_INJECT_ASM(3)
+ LONG_L " $4, %[v]\n\t"
+ "beq $4, %[expectnot], %l[cmpfail]\n\t"
+ RSEQ_INJECT_ASM(4)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+ LONG_L " $4, %[v]\n\t"
+ "beq $4, %[expectnot], %l[error2]\n\t"
+#endif
+ LONG_S " $4, %[load]\n\t"
+ LONG_ADDI " $4, %[voffp]\n\t"
+ LONG_L " $4, 0($4)\n\t"
+ /* final store */
+ LONG_S " $4, %[v]\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(5)
+ "b 5f\n\t"
+ RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
+ "5:\n\t"
+ : /* gcc asm goto does not allow outputs */
+ : [cpu_id] "r" (cpu),
+ [current_cpu_id] "m" (__rseq_abi.cpu_id),
+ [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ /* final store input */
+ [v] "m" (*v),
+ [expectnot] "r" (expectnot),
+ [voffp] "Ir" (voffp),
+ [load] "m" (*load)
+ RSEQ_INJECT_INPUT
+ : "$4", "memory"
+ RSEQ_INJECT_CLOBBER
+ : abort, cmpfail
+#ifdef RSEQ_COMPARE_TWICE
+ , error1, error2
+#endif
+ );
+ rseq_workaround_gcc_asm_size_guess();
+ return 0;
+abort:
+ rseq_workaround_gcc_asm_size_guess();
+ RSEQ_INJECT_FAILED
+ return -1;
+cmpfail:
+ rseq_workaround_gcc_asm_size_guess();
+ return 1;
+#ifdef RSEQ_COMPARE_TWICE
+error1:
+ rseq_bug("cpu_id comparison failed");
+error2:
+ rseq_bug("expected value comparison failed");
+#endif
+}
+
+static inline __attribute__((always_inline))
+int rseq_addv(intptr_t *v, intptr_t count, int cpu)
+{
+ RSEQ_INJECT_C(9)
+
+ rseq_workaround_gcc_asm_size_guess();
+ __asm__ __volatile__ goto (
+ RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+ /* Start rseq by storing table entry pointer into rseq_cs. */
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+ RSEQ_INJECT_ASM(3)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+#endif
+ LONG_L " $4, %[v]\n\t"
+ LONG_ADDI " $4, %[count]\n\t"
+ /* final store */
+ LONG_S " $4, %[v]\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(4)
+ "b 5f\n\t"
+ RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
+ "5:\n\t"
+ : /* gcc asm goto does not allow outputs */
+ : [cpu_id] "r" (cpu),
+ [current_cpu_id] "m" (__rseq_abi.cpu_id),
+ [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ [v] "m" (*v),
+ [count] "Ir" (count)
+ RSEQ_INJECT_INPUT
+ : "$4", "memory"
+ RSEQ_INJECT_CLOBBER
+ : abort
+#ifdef RSEQ_COMPARE_TWICE
+ , error1
+#endif
+ );
+ rseq_workaround_gcc_asm_size_guess();
+ return 0;
+abort:
+ rseq_workaround_gcc_asm_size_guess();
+ RSEQ_INJECT_FAILED
+ return -1;
+#ifdef RSEQ_COMPARE_TWICE
+error1:
+ rseq_bug("cpu_id comparison failed");
+#endif
+}
+
+static inline __attribute__((always_inline))
+int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
+ intptr_t *v2, intptr_t newv2,
+ intptr_t newv, int cpu)
+{
+ RSEQ_INJECT_C(9)
+
+ rseq_workaround_gcc_asm_size_guess();
+ __asm__ __volatile__ goto (
+ RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+ /* Start rseq by storing table entry pointer into rseq_cs. */
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+ RSEQ_INJECT_ASM(3)
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], %l[cmpfail]\n\t"
+ RSEQ_INJECT_ASM(4)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], %l[error2]\n\t"
+#endif
+ /* try store */
+ LONG_S " %[newv2], %[v2]\n\t"
+ RSEQ_INJECT_ASM(5)
+ /* final store */
+ LONG_S " %[newv], %[v]\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(6)
+ "b 5f\n\t"
+ RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
+ "5:\n\t"
+ : /* gcc asm goto does not allow outputs */
+ : [cpu_id] "r" (cpu),
+ [current_cpu_id] "m" (__rseq_abi.cpu_id),
+ [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ /* try store input */
+ [v2] "m" (*v2),
+ [newv2] "r" (newv2),
+ /* final store input */
+ [v] "m" (*v),
+ [expect] "r" (expect),
+ [newv] "r" (newv)
+ RSEQ_INJECT_INPUT
+ : "$4", "memory"
+ RSEQ_INJECT_CLOBBER
+ : abort, cmpfail
+#ifdef RSEQ_COMPARE_TWICE
+ , error1, error2
+#endif
+ );
+ rseq_workaround_gcc_asm_size_guess();
+ return 0;
+abort:
+ rseq_workaround_gcc_asm_size_guess();
+ RSEQ_INJECT_FAILED
+ return -1;
+cmpfail:
+ rseq_workaround_gcc_asm_size_guess();
+ return 1;
+#ifdef RSEQ_COMPARE_TWICE
+error1:
+ rseq_bug("cpu_id comparison failed");
+error2:
+ rseq_bug("expected value comparison failed");
+#endif
+}
+
+static inline __attribute__((always_inline))
+int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
+ intptr_t *v2, intptr_t newv2,
+ intptr_t newv, int cpu)
+{
+ RSEQ_INJECT_C(9)
+
+ rseq_workaround_gcc_asm_size_guess();
+ __asm__ __volatile__ goto (
+ RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+ /* Start rseq by storing table entry pointer into rseq_cs. */
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+ RSEQ_INJECT_ASM(3)
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], %l[cmpfail]\n\t"
+ RSEQ_INJECT_ASM(4)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], %l[error2]\n\t"
+#endif
+ /* try store */
+ LONG_S " %[newv2], %[v2]\n\t"
+ RSEQ_INJECT_ASM(5)
+ "sync\n\t" /* full sync provides store-release */
+ /* final store */
+ LONG_S " %[newv], %[v]\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(6)
+ "b 5f\n\t"
+ RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
+ "5:\n\t"
+ : /* gcc asm goto does not allow outputs */
+ : [cpu_id] "r" (cpu),
+ [current_cpu_id] "m" (__rseq_abi.cpu_id),
+ [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ /* try store input */
+ [v2] "m" (*v2),
+ [newv2] "r" (newv2),
+ /* final store input */
+ [v] "m" (*v),
+ [expect] "r" (expect),
+ [newv] "r" (newv)
+ RSEQ_INJECT_INPUT
+ : "$4", "memory"
+ RSEQ_INJECT_CLOBBER
+ : abort, cmpfail
+#ifdef RSEQ_COMPARE_TWICE
+ , error1, error2
+#endif
+ );
+ rseq_workaround_gcc_asm_size_guess();
+ return 0;
+abort:
+ rseq_workaround_gcc_asm_size_guess();
+ RSEQ_INJECT_FAILED
+ return -1;
+cmpfail:
+ rseq_workaround_gcc_asm_size_guess();
+ return 1;
+#ifdef RSEQ_COMPARE_TWICE
+error1:
+ rseq_bug("cpu_id comparison failed");
+error2:
+ rseq_bug("expected value comparison failed");
+#endif
+}
+
+static inline __attribute__((always_inline))
+int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
+ intptr_t *v2, intptr_t expect2,
+ intptr_t newv, int cpu)
+{
+ RSEQ_INJECT_C(9)
+
+ rseq_workaround_gcc_asm_size_guess();
+ __asm__ __volatile__ goto (
+ RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+ /* Start rseq by storing table entry pointer into rseq_cs. */
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+ RSEQ_INJECT_ASM(3)
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], %l[cmpfail]\n\t"
+ RSEQ_INJECT_ASM(4)
+ LONG_L " $4, %[v2]\n\t"
+ "bne $4, %[expect2], %l[cmpfail]\n\t"
+ RSEQ_INJECT_ASM(5)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], %l[error2]\n\t"
+ LONG_L " $4, %[v2]\n\t"
+ "bne $4, %[expect2], %l[error3]\n\t"
+#endif
+ /* final store */
+ LONG_S " %[newv], %[v]\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(6)
+ "b 5f\n\t"
+ RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
+ "5:\n\t"
+ : /* gcc asm goto does not allow outputs */
+ : [cpu_id] "r" (cpu),
+ [current_cpu_id] "m" (__rseq_abi.cpu_id),
+ [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ /* cmp2 input */
+ [v2] "m" (*v2),
+ [expect2] "r" (expect2),
+ /* final store input */
+ [v] "m" (*v),
+ [expect] "r" (expect),
+ [newv] "r" (newv)
+ RSEQ_INJECT_INPUT
+ : "$4", "memory"
+ RSEQ_INJECT_CLOBBER
+ : abort, cmpfail
+#ifdef RSEQ_COMPARE_TWICE
+ , error1, error2, error3
+#endif
+ );
+ rseq_workaround_gcc_asm_size_guess();
+ return 0;
+abort:
+ rseq_workaround_gcc_asm_size_guess();
+ RSEQ_INJECT_FAILED
+ return -1;
+cmpfail:
+ rseq_workaround_gcc_asm_size_guess();
+ return 1;
+#ifdef RSEQ_COMPARE_TWICE
+error1:
+ rseq_bug("cpu_id comparison failed");
+error2:
+ rseq_bug("1st expected value comparison failed");
+error3:
+ rseq_bug("2nd expected value comparison failed");
+#endif
+}
+
+static inline __attribute__((always_inline))
+int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
+ void *dst, void *src, size_t len,
+ intptr_t newv, int cpu)
+{
+ uintptr_t rseq_scratch[3];
+
+ RSEQ_INJECT_C(9)
+
+ rseq_workaround_gcc_asm_size_guess();
+ __asm__ __volatile__ goto (
+ RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+ LONG_S " %[src], %[rseq_scratch0]\n\t"
+ LONG_S " %[dst], %[rseq_scratch1]\n\t"
+ LONG_S " %[len], %[rseq_scratch2]\n\t"
+ /* Start rseq by storing table entry pointer into rseq_cs. */
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+ RSEQ_INJECT_ASM(3)
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], 5f\n\t"
+ RSEQ_INJECT_ASM(4)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], 7f\n\t"
+#endif
+ /* try memcpy */
+ "beqz %[len], 333f\n\t" \
+ "222:\n\t" \
+ "lb $4, 0(%[src])\n\t" \
+ "sb $4, 0(%[dst])\n\t" \
+ LONG_ADDI " %[src], 1\n\t" \
+ LONG_ADDI " %[dst], 1\n\t" \
+ LONG_ADDI " %[len], -1\n\t" \
+ "bnez %[len], 222b\n\t" \
+ "333:\n\t" \
+ RSEQ_INJECT_ASM(5)
+ /* final store */
+ LONG_S " %[newv], %[v]\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(6)
+ /* teardown */
+ LONG_L " %[len], %[rseq_scratch2]\n\t"
+ LONG_L " %[dst], %[rseq_scratch1]\n\t"
+ LONG_L " %[src], %[rseq_scratch0]\n\t"
+ "b 8f\n\t"
+ RSEQ_ASM_DEFINE_ABORT(3, 4,
+ /* teardown */
+ LONG_L " %[len], %[rseq_scratch2]\n\t"
+ LONG_L " %[dst], %[rseq_scratch1]\n\t"
+ LONG_L " %[src], %[rseq_scratch0]\n\t",
+ abort, 1b, 2b, 4f)
+ RSEQ_ASM_DEFINE_CMPFAIL(5,
+ /* teardown */
+ LONG_L " %[len], %[rseq_scratch2]\n\t"
+ LONG_L " %[dst], %[rseq_scratch1]\n\t"
+ LONG_L " %[src], %[rseq_scratch0]\n\t",
+ cmpfail)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_DEFINE_CMPFAIL(6,
+ /* teardown */
+ LONG_L " %[len], %[rseq_scratch2]\n\t"
+ LONG_L " %[dst], %[rseq_scratch1]\n\t"
+ LONG_L " %[src], %[rseq_scratch0]\n\t",
+ error1)
+ RSEQ_ASM_DEFINE_CMPFAIL(7,
+ /* teardown */
+ LONG_L " %[len], %[rseq_scratch2]\n\t"
+ LONG_L " %[dst], %[rseq_scratch1]\n\t"
+ LONG_L " %[src], %[rseq_scratch0]\n\t",
+ error2)
+#endif
+ "8:\n\t"
+ : /* gcc asm goto does not allow outputs */
+ : [cpu_id] "r" (cpu),
+ [current_cpu_id] "m" (__rseq_abi.cpu_id),
+ [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ /* final store input */
+ [v] "m" (*v),
+ [expect] "r" (expect),
+ [newv] "r" (newv),
+ /* try memcpy input */
+ [dst] "r" (dst),
+ [src] "r" (src),
+ [len] "r" (len),
+ [rseq_scratch0] "m" (rseq_scratch[0]),
+ [rseq_scratch1] "m" (rseq_scratch[1]),
+ [rseq_scratch2] "m" (rseq_scratch[2])
+ RSEQ_INJECT_INPUT
+ : "$4", "memory"
+ RSEQ_INJECT_CLOBBER
+ : abort, cmpfail
+#ifdef RSEQ_COMPARE_TWICE
+ , error1, error2
+#endif
+ );
+ rseq_workaround_gcc_asm_size_guess();
+ return 0;
+abort:
+ rseq_workaround_gcc_asm_size_guess();
+ RSEQ_INJECT_FAILED
+ return -1;
+cmpfail:
+ rseq_workaround_gcc_asm_size_guess();
+ return 1;
+#ifdef RSEQ_COMPARE_TWICE
+error1:
+ rseq_workaround_gcc_asm_size_guess();
+ rseq_bug("cpu_id comparison failed");
+error2:
+ rseq_workaround_gcc_asm_size_guess();
+ rseq_bug("expected value comparison failed");
+#endif
+}
+
+static inline __attribute__((always_inline))
+int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
+ void *dst, void *src, size_t len,
+ intptr_t newv, int cpu)
+{
+ uintptr_t rseq_scratch[3];
+
+ RSEQ_INJECT_C(9)
+
+ rseq_workaround_gcc_asm_size_guess();
+ __asm__ __volatile__ goto (
+ RSEQ_ASM_DEFINE_TABLE(1f, 2f, 4f) /* start, commit, abort */
+ LONG_S " %[src], %[rseq_scratch0]\n\t"
+ LONG_S " %[dst], %[rseq_scratch1]\n\t"
+ LONG_S " %[len], %[rseq_scratch2]\n\t"
+ /* Start rseq by storing table entry pointer into rseq_cs. */
+ RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
+ RSEQ_INJECT_ASM(3)
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], 5f\n\t"
+ RSEQ_INJECT_ASM(4)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
+ LONG_L " $4, %[v]\n\t"
+ "bne $4, %[expect], 7f\n\t"
+#endif
+ /* try memcpy */
+ "beqz %[len], 333f\n\t" \
+ "222:\n\t" \
+ "lb $4, 0(%[src])\n\t" \
+ "sb $4, 0(%[dst])\n\t" \
+ LONG_ADDI " %[src], 1\n\t" \
+ LONG_ADDI " %[dst], 1\n\t" \
+ LONG_ADDI " %[len], -1\n\t" \
+ "bnez %[len], 222b\n\t" \
+ "333:\n\t" \
+ RSEQ_INJECT_ASM(5)
+ "sync\n\t" /* full sync provides store-release */
+ /* final store */
+ LONG_S " %[newv], %[v]\n\t"
+ "2:\n\t"
+ RSEQ_INJECT_ASM(6)
+ /* teardown */
+ LONG_L " %[len], %[rseq_scratch2]\n\t"
+ LONG_L " %[dst], %[rseq_scratch1]\n\t"
+ LONG_L " %[src], %[rseq_scratch0]\n\t"
+ "b 8f\n\t"
+ RSEQ_ASM_DEFINE_ABORT(3, 4,
+ /* teardown */
+ LONG_L " %[len], %[rseq_scratch2]\n\t"
+ LONG_L " %[dst], %[rseq_scratch1]\n\t"
+ LONG_L " %[src], %[rseq_scratch0]\n\t",
+ abort, 1b, 2b, 4f)
+ RSEQ_ASM_DEFINE_CMPFAIL(5,
+ /* teardown */
+ LONG_L " %[len], %[rseq_scratch2]\n\t"
+ LONG_L " %[dst], %[rseq_scratch1]\n\t"
+ LONG_L " %[src], %[rseq_scratch0]\n\t",
+ cmpfail)
+#ifdef RSEQ_COMPARE_TWICE
+ RSEQ_ASM_DEFINE_CMPFAIL(6,
+ /* teardown */
+ LONG_L " %[len], %[rseq_scratch2]\n\t"
+ LONG_L " %[dst], %[rseq_scratch1]\n\t"
+ LONG_L " %[src], %[rseq_scratch0]\n\t",
+ error1)
+ RSEQ_ASM_DEFINE_CMPFAIL(7,
+ /* teardown */
+ LONG_L " %[len], %[rseq_scratch2]\n\t"
+ LONG_L " %[dst], %[rseq_scratch1]\n\t"
+ LONG_L " %[src], %[rseq_scratch0]\n\t",
+ error2)
+#endif
+ "8:\n\t"
+ : /* gcc asm goto does not allow outputs */
+ : [cpu_id] "r" (cpu),
+ [current_cpu_id] "m" (__rseq_abi.cpu_id),
+ [rseq_cs] "m" (__rseq_abi.rseq_cs),
+ /* final store input */
+ [v] "m" (*v),
+ [expect] "r" (expect),
+ [newv] "r" (newv),
+ /* try memcpy input */
+ [dst] "r" (dst),
+ [src] "r" (src),
+ [len] "r" (len),
+ [rseq_scratch0] "m" (rseq_scratch[0]),
+ [rseq_scratch1] "m" (rseq_scratch[1]),
+ [rseq_scratch2] "m" (rseq_scratch[2])
+ RSEQ_INJECT_INPUT
+ : "$4", "memory"
+ RSEQ_INJECT_CLOBBER
+ : abort, cmpfail
+#ifdef RSEQ_COMPARE_TWICE
+ , error1, error2
+#endif
+ );
+ rseq_workaround_gcc_asm_size_guess();
+ return 0;
+abort:
+ rseq_workaround_gcc_asm_size_guess();
+ RSEQ_INJECT_FAILED
+ return -1;
+cmpfail:
+ rseq_workaround_gcc_asm_size_guess();
+ return 1;
+#ifdef RSEQ_COMPARE_TWICE
+error1:
+ rseq_workaround_gcc_asm_size_guess();
+ rseq_bug("cpu_id comparison failed");
+error2:
+ rseq_workaround_gcc_asm_size_guess();
+ rseq_bug("expected value comparison failed");
+#endif
+}
+
+#endif /* !RSEQ_SKIP_FASTPATH */
diff --git a/tools/testing/selftests/rseq/rseq.h b/tools/testing/selftests/rseq/rseq.h
index 0a80857..a468411 100644
--- a/tools/testing/selftests/rseq/rseq.h
+++ b/tools/testing/selftests/rseq/rseq.h
@@ -73,6 +73,8 @@ extern __thread volatile struct rseq __rseq_abi;
#include <rseq-arm.h>
#elif defined(__PPC__)
#include <rseq-ppc.h>
+#elif defined(__mips__)
+#include <rseq-mips.h>
#else
#error unsupported target
#endif
diff --git a/tools/testing/selftests/rseq/run_param_test.sh b/tools/testing/selftests/rseq/run_param_test.sh
index 3acd6d7..3acd6d7 100644..100755
--- a/tools/testing/selftests/rseq/run_param_test.sh
+++ b/tools/testing/selftests/rseq/run_param_test.sh
diff --git a/tools/testing/selftests/sparc64/Makefile b/tools/testing/selftests/sparc64/Makefile
index 2082eef..a19531d 100644
--- a/tools/testing/selftests/sparc64/Makefile
+++ b/tools/testing/selftests/sparc64/Makefile
@@ -1,7 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0
+uname_M := $(shell uname -m 2>/dev/null || echo not)
+ARCH ?= $(shell echo $(uname_M) | sed -e s/x86_64/x86/)
+
+ifneq ($(ARCH),sparc64)
+nothing:
+.PHONY: all clean run_tests install
+.SILENT:
+else
+
SUBDIRS := drivers
TEST_PROGS := run.sh
+
.PHONY: all clean
include ../lib.mk
@@ -18,10 +29,6 @@ all:
fi \
done
-override define RUN_TESTS
- @cd $(OUTPUT); ./run.sh
-endef
-
override define INSTALL_RULE
mkdir -p $(INSTALL_PATH)
install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)
@@ -33,10 +40,6 @@ override define INSTALL_RULE
done;
endef
-override define EMIT_TESTS
- echo "./run.sh"
-endef
-
override define CLEAN
@for DIR in $(SUBDIRS); do \
BUILD_TARGET=$(OUTPUT)/$$DIR; \
@@ -44,3 +47,4 @@ override define CLEAN
make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
done
endef
+endif
diff --git a/tools/testing/selftests/sparc64/drivers/Makefile b/tools/testing/selftests/sparc64/drivers/Makefile
index 6264f40..deb0df4 100644
--- a/tools/testing/selftests/sparc64/drivers/Makefile
+++ b/tools/testing/selftests/sparc64/drivers/Makefile
@@ -1,4 +1,4 @@
-
+# SPDX-License-Identifier: GPL-2.0
INCLUDEDIR := -I.
CFLAGS := $(CFLAGS) $(INCLUDEDIR) -Wall -O2 -g
diff --git a/tools/testing/selftests/static_keys/test_static_keys.sh b/tools/testing/selftests/static_keys/test_static_keys.sh
index 24cff49..fc9f8cd 100755
--- a/tools/testing/selftests/static_keys/test_static_keys.sh
+++ b/tools/testing/selftests/static_keys/test_static_keys.sh
@@ -2,6 +2,19 @@
# SPDX-License-Identifier: GPL-2.0
# Runs static keys kernel module tests
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
+if ! /sbin/modprobe -q -n test_static_key_base; then
+ echo "static_key: module test_static_key_base is not found [SKIP]"
+ exit $ksft_skip
+fi
+
+if ! /sbin/modprobe -q -n test_static_keys; then
+ echo "static_key: module test_static_keys is not found [SKIP]"
+ exit $ksft_skip
+fi
+
if /sbin/modprobe -q test_static_key_base; then
if /sbin/modprobe -q test_static_keys; then
echo "static_key: ok"
diff --git a/tools/testing/selftests/sync/config b/tools/testing/selftests/sync/config
new file mode 100644
index 0000000..1ab7e81
--- /dev/null
+++ b/tools/testing/selftests/sync/config
@@ -0,0 +1,4 @@
+CONFIG_STAGING=y
+CONFIG_ANDROID=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
diff --git a/tools/testing/selftests/sysctl/sysctl.sh b/tools/testing/selftests/sysctl/sysctl.sh
index ec232c3..584eb8e 100755
--- a/tools/testing/selftests/sysctl/sysctl.sh
+++ b/tools/testing/selftests/sysctl/sysctl.sh
@@ -14,6 +14,9 @@
# This performs a series tests against the proc sysctl interface.
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
TEST_NAME="sysctl"
TEST_DRIVER="test_${TEST_NAME}"
TEST_DIR=$(dirname $0)
@@ -41,7 +44,7 @@ test_modprobe()
echo "$0: $DIR not present" >&2
echo "You must have the following enabled in your kernel:" >&2
cat $TEST_DIR/config >&2
- exit 1
+ exit $ksft_skip
fi
}
@@ -98,28 +101,30 @@ test_reqs()
uid=$(id -u)
if [ $uid -ne 0 ]; then
echo $msg must be run as root >&2
- exit 0
+ exit $ksft_skip
fi
if ! which perl 2> /dev/null > /dev/null; then
echo "$0: You need perl installed"
- exit 1
+ exit $ksft_skip
fi
if ! which getconf 2> /dev/null > /dev/null; then
echo "$0: You need getconf installed"
- exit 1
+ exit $ksft_skip
fi
if ! which diff 2> /dev/null > /dev/null; then
echo "$0: You need diff installed"
- exit 1
+ exit $ksft_skip
fi
}
function load_req_mod()
{
- trap "test_modprobe" EXIT
-
if [ ! -d $DIR ]; then
+ if ! modprobe -q -n $TEST_DRIVER; then
+ echo "$0: module $TEST_DRIVER not found [SKIP]"
+ exit $ksft_skip
+ fi
modprobe $TEST_DRIVER
if [ $? -ne 0 ]; then
exit
@@ -765,6 +770,7 @@ function parse_args()
test_reqs
allow_user_defaults
check_production_sysctl_writes_strict
+test_modprobe
load_req_mod
trap "test_finish" EXIT
diff --git a/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json b/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json
index de97e4f..637ea02 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/actions/ife.json
@@ -568,7 +568,7 @@
"matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*use tcindex 65535.*index 1",
"matchCount": "1",
"teardown": [
- "$TC actions flush action skbedit"
+ "$TC actions flush action ife"
]
},
{
diff --git a/tools/testing/selftests/user/test_user_copy.sh b/tools/testing/selftests/user/test_user_copy.sh
index d60506f..f9b31a5 100755
--- a/tools/testing/selftests/user/test_user_copy.sh
+++ b/tools/testing/selftests/user/test_user_copy.sh
@@ -2,6 +2,13 @@
# SPDX-License-Identifier: GPL-2.0
# Runs copy_to/from_user infrastructure using test_user_copy kernel module
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
+if ! /sbin/modprobe -q -n test_user_copy; then
+ echo "user: module test_user_copy is not found [SKIP]"
+ exit $ksft_skip
+fi
if /sbin/modprobe -q test_user_copy; then
/sbin/modprobe -q -r test_user_copy
echo "user_copy: ok"
diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c
index 1097f04..bcec712 100644
--- a/tools/testing/selftests/vm/compaction_test.c
+++ b/tools/testing/selftests/vm/compaction_test.c
@@ -16,6 +16,8 @@
#include <unistd.h>
#include <string.h>
+#include "../kselftest.h"
+
#define MAP_SIZE 1048576
struct map_list {
@@ -169,7 +171,7 @@ int main(int argc, char **argv)
printf("Either the sysctl compact_unevictable_allowed is not\n"
"set to 1 or couldn't read the proc file.\n"
"Skipping the test\n");
- return 0;
+ return KSFT_SKIP;
}
lim.rlim_cur = RLIM_INFINITY;
diff --git a/tools/testing/selftests/vm/mlock2-tests.c b/tools/testing/selftests/vm/mlock2-tests.c
index 4997b92..637b6d0 100644
--- a/tools/testing/selftests/vm/mlock2-tests.c
+++ b/tools/testing/selftests/vm/mlock2-tests.c
@@ -9,6 +9,8 @@
#include <stdbool.h>
#include "mlock2.h"
+#include "../kselftest.h"
+
struct vm_boundaries {
unsigned long start;
unsigned long end;
@@ -303,7 +305,7 @@ static int test_mlock_lock()
if (mlock2_(map, 2 * page_size, 0)) {
if (errno == ENOSYS) {
printf("Cannot call new mlock family, skipping test\n");
- _exit(0);
+ _exit(KSFT_SKIP);
}
perror("mlock2(0)");
goto unmap;
@@ -412,7 +414,7 @@ static int test_mlock_onfault()
if (mlock2_(map, 2 * page_size, MLOCK_ONFAULT)) {
if (errno == ENOSYS) {
printf("Cannot call new mlock family, skipping test\n");
- _exit(0);
+ _exit(KSFT_SKIP);
}
perror("mlock2(MLOCK_ONFAULT)");
goto unmap;
@@ -425,7 +427,7 @@ static int test_mlock_onfault()
if (munlock(map, 2 * page_size)) {
if (errno == ENOSYS) {
printf("Cannot call new mlock family, skipping test\n");
- _exit(0);
+ _exit(KSFT_SKIP);
}
perror("munlock()");
goto unmap;
@@ -457,7 +459,7 @@ static int test_lock_onfault_of_present()
if (mlock2_(map, 2 * page_size, MLOCK_ONFAULT)) {
if (errno == ENOSYS) {
printf("Cannot call new mlock family, skipping test\n");
- _exit(0);
+ _exit(KSFT_SKIP);
}
perror("mlock2(MLOCK_ONFAULT)");
goto unmap;
@@ -583,7 +585,7 @@ static int test_vma_management(bool call_mlock)
if (call_mlock && mlock2_(map, 3 * page_size, MLOCK_ONFAULT)) {
if (errno == ENOSYS) {
printf("Cannot call new mlock family, skipping test\n");
- _exit(0);
+ _exit(KSFT_SKIP);
}
perror("mlock(ONFAULT)\n");
goto out;
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
index 22d5646..88cbe55 100755
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -2,6 +2,9 @@
# SPDX-License-Identifier: GPL-2.0
#please run as root
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
mnt=./huge
exitcode=0
@@ -36,7 +39,7 @@ if [ -n "$freepgs" ] && [ -n "$hpgsize_KB" ]; then
echo $(( $lackpgs + $nr_hugepgs )) > /proc/sys/vm/nr_hugepages
if [ $? -ne 0 ]; then
echo "Please run this test as root"
- exit 1
+ exit $ksft_skip
fi
while read name size unit; do
if [ "$name" = "HugePages_Free:" ]; then
diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
index de2f9ec..7b8171e 100644
--- a/tools/testing/selftests/vm/userfaultfd.c
+++ b/tools/testing/selftests/vm/userfaultfd.c
@@ -69,6 +69,8 @@
#include <setjmp.h>
#include <stdbool.h>
+#include "../kselftest.h"
+
#ifdef __NR_userfaultfd
static unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size;
@@ -1322,7 +1324,7 @@ int main(int argc, char **argv)
int main(void)
{
printf("skip: Skipping userfaultfd test (missing __NR_userfaultfd)\n");
- return 0;
+ return KSFT_SKIP;
}
#endif /* __NR_userfaultfd */
diff --git a/tools/testing/selftests/zram/zram.sh b/tools/testing/selftests/zram/zram.sh
index 754de7d..232e958 100755
--- a/tools/testing/selftests/zram/zram.sh
+++ b/tools/testing/selftests/zram/zram.sh
@@ -2,6 +2,9 @@
# SPDX-License-Identifier: GPL-2.0
TCID="zram.sh"
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
. ./zram_lib.sh
run_zram () {
@@ -24,5 +27,5 @@ elif [ -b /dev/zram0 ]; then
else
echo "$TCID : No zram.ko module or /dev/zram0 device file not found"
echo "$TCID : CONFIG_ZRAM is not set"
- exit 1
+ exit $ksft_skip
fi
diff --git a/tools/testing/selftests/zram/zram_lib.sh b/tools/testing/selftests/zram/zram_lib.sh
index f6a9c73..9e73a4f 100755
--- a/tools/testing/selftests/zram/zram_lib.sh
+++ b/tools/testing/selftests/zram/zram_lib.sh
@@ -18,6 +18,9 @@ MODULE=0
dev_makeswap=-1
dev_mounted=-1
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
trap INT
check_prereqs()
@@ -27,7 +30,7 @@ check_prereqs()
if [ $uid -ne 0 ]; then
echo $msg must be run as root >&2
- exit 0
+ exit $ksft_skip
fi
}
diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig
index cca7e06..ea434dd 100644
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -47,10 +47,13 @@ config KVM_GENERIC_DIRTYLOG_READ_PROTECT
config KVM_COMPAT
def_bool y
- depends on KVM && COMPAT && !S390
+ depends on KVM && COMPAT && !(S390 || ARM64)
config HAVE_KVM_IRQ_BYPASS
bool
config HAVE_KVM_VCPU_ASYNC_IOCTL
bool
+
+config HAVE_KVM_VCPU_RUN_PID_CHANGE
+ bool
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 2d9b479..04e554c 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -16,6 +16,7 @@
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <linux/bug.h>
#include <linux/cpu_pm.h>
#include <linux/errno.h>
#include <linux/err.h>
@@ -41,6 +42,7 @@
#include <asm/mman.h>
#include <asm/tlbflush.h>
#include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
#include <asm/virt.h>
#include <asm/kvm_arm.h>
#include <asm/kvm_asm.h>
@@ -163,7 +165,7 @@ int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
return 0;
}
-int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
+vm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
{
return VM_FAULT_SIGBUS;
}
@@ -249,6 +251,21 @@ long kvm_arch_dev_ioctl(struct file *filp,
return -EINVAL;
}
+struct kvm *kvm_arch_alloc_vm(void)
+{
+ if (!has_vhe())
+ return kzalloc(sizeof(struct kvm), GFP_KERNEL);
+
+ return vzalloc(sizeof(struct kvm));
+}
+
+void kvm_arch_free_vm(struct kvm *kvm)
+{
+ if (!has_vhe())
+ kfree(kvm);
+ else
+ vfree(kvm);
+}
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
{
@@ -290,7 +307,6 @@ out:
void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
{
- kvm_vgic_vcpu_early_init(vcpu);
}
void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
@@ -363,10 +379,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
kvm_vgic_load(vcpu);
kvm_timer_vcpu_load(vcpu);
kvm_vcpu_load_sysregs(vcpu);
+ kvm_arch_vcpu_load_fp(vcpu);
}
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
{
+ kvm_arch_vcpu_put_fp(vcpu);
kvm_vcpu_put_sysregs(vcpu);
kvm_timer_vcpu_put(vcpu);
kvm_vgic_put(vcpu);
@@ -678,9 +696,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
*/
preempt_disable();
- /* Flush FP/SIMD state that can't survive guest entry/exit */
- kvm_fpsimd_flush_cpu_state();
-
kvm_pmu_flush_hwstate(vcpu);
local_irq_disable();
@@ -778,6 +793,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
if (static_branch_unlikely(&userspace_irqchip_in_use))
kvm_timer_sync_hwstate(vcpu);
+ kvm_arch_vcpu_ctxsync_fp(vcpu);
+
/*
* We may have taken a host interrupt in HYP mode (ie
* while executing the guest). This interrupt is still
@@ -1574,6 +1591,11 @@ int kvm_arch_init(void *opaque)
return -ENODEV;
}
+ if (!kvm_arch_check_sve_has_vhe()) {
+ kvm_pr_unimpl("SVE system without VHE unsupported. Broken cpu?");
+ return -ENODEV;
+ }
+
for_each_online_cpu(cpu) {
smp_call_function_single(cpu, check_kvm_target_cpu, &ret, 1);
if (ret < 0) {
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 8d90de2..1d90d79 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -297,6 +297,8 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
phys_addr_t next;
assert_spin_locked(&kvm->mmu_lock);
+ WARN_ON(size & ~PAGE_MASK);
+
pgd = kvm->arch.pgd + stage2_pgd_index(addr);
do {
/*
diff --git a/virt/kvm/arm/vgic/vgic-debug.c b/virt/kvm/arm/vgic/vgic-debug.c
index 4ffc0b5..c589d4c 100644
--- a/virt/kvm/arm/vgic/vgic-debug.c
+++ b/virt/kvm/arm/vgic/vgic-debug.c
@@ -264,21 +264,12 @@ static const struct file_operations vgic_debug_fops = {
.release = seq_release
};
-int vgic_debug_init(struct kvm *kvm)
+void vgic_debug_init(struct kvm *kvm)
{
- if (!kvm->debugfs_dentry)
- return -ENOENT;
-
- if (!debugfs_create_file("vgic-state", 0444,
- kvm->debugfs_dentry,
- kvm,
- &vgic_debug_fops))
- return -ENOMEM;
-
- return 0;
+ debugfs_create_file("vgic-state", 0444, kvm->debugfs_dentry, kvm,
+ &vgic_debug_fops);
}
-int vgic_debug_destroy(struct kvm *kvm)
+void vgic_debug_destroy(struct kvm *kvm)
{
- return 0;
}
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index e07156c..2673efc 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -44,7 +44,7 @@
*
* CPU Interface:
*
- * - kvm_vgic_vcpu_early_init(): initialization of static data that
+ * - kvm_vgic_vcpu_init(): initialization of static data that
* doesn't depend on any sizing information or emulation type. No
* allocation is allowed there.
*/
@@ -67,46 +67,6 @@ void kvm_vgic_early_init(struct kvm *kvm)
spin_lock_init(&dist->lpi_list_lock);
}
-/**
- * kvm_vgic_vcpu_early_init() - Initialize static VGIC VCPU data structures
- * @vcpu: The VCPU whose VGIC data structures whould be initialized
- *
- * Only do initialization, but do not actually enable the VGIC CPU interface
- * yet.
- */
-void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu)
-{
- struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
- int i;
-
- INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
- spin_lock_init(&vgic_cpu->ap_list_lock);
-
- /*
- * Enable and configure all SGIs to be edge-triggered and
- * configure all PPIs as level-triggered.
- */
- for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
- struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
-
- INIT_LIST_HEAD(&irq->ap_list);
- spin_lock_init(&irq->irq_lock);
- irq->intid = i;
- irq->vcpu = NULL;
- irq->target_vcpu = vcpu;
- irq->targets = 1U << vcpu->vcpu_id;
- kref_init(&irq->refcount);
- if (vgic_irq_is_sgi(i)) {
- /* SGIs */
- irq->enabled = 1;
- irq->config = VGIC_CONFIG_EDGE;
- } else {
- /* PPIs */
- irq->config = VGIC_CONFIG_LEVEL;
- }
- }
-}
-
/* CREATION */
/**
@@ -167,8 +127,11 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
kvm->arch.vgic.vgic_model = type;
kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
- kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
- kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
+
+ if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
+ kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
+ else
+ INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
out_unlock:
for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
@@ -221,13 +184,50 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
}
/**
- * kvm_vgic_vcpu_init() - Register VCPU-specific KVM iodevs
+ * kvm_vgic_vcpu_init() - Initialize static VGIC VCPU data
+ * structures and register VCPU-specific KVM iodevs
+ *
* @vcpu: pointer to the VCPU being created and initialized
+ *
+ * Only do initialization, but do not actually enable the
+ * VGIC CPU interface
*/
int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
{
- int ret = 0;
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+ int ret = 0;
+ int i;
+
+ vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
+ vgic_cpu->sgi_iodev.base_addr = VGIC_ADDR_UNDEF;
+
+ INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
+ spin_lock_init(&vgic_cpu->ap_list_lock);
+
+ /*
+ * Enable and configure all SGIs to be edge-triggered and
+ * configure all PPIs as level-triggered.
+ */
+ for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
+ struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
+
+ INIT_LIST_HEAD(&irq->ap_list);
+ spin_lock_init(&irq->irq_lock);
+ irq->intid = i;
+ irq->vcpu = NULL;
+ irq->target_vcpu = vcpu;
+ irq->targets = 1U << vcpu->vcpu_id;
+ kref_init(&irq->refcount);
+ if (vgic_irq_is_sgi(i)) {
+ /* SGIs */
+ irq->enabled = 1;
+ irq->config = VGIC_CONFIG_EDGE;
+ } else {
+ /* PPIs */
+ irq->config = VGIC_CONFIG_LEVEL;
+ }
+ }
if (!irqchip_in_kernel(vcpu->kvm))
return 0;
@@ -303,13 +303,23 @@ out:
static void kvm_vgic_dist_destroy(struct kvm *kvm)
{
struct vgic_dist *dist = &kvm->arch.vgic;
+ struct vgic_redist_region *rdreg, *next;
dist->ready = false;
dist->initialized = false;
kfree(dist->spis);
+ dist->spis = NULL;
dist->nr_spis = 0;
+ if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
+ list_for_each_entry_safe(rdreg, next, &dist->rd_regions, list) {
+ list_del(&rdreg->list);
+ kfree(rdreg);
+ }
+ INIT_LIST_HEAD(&dist->rd_regions);
+ }
+
if (vgic_supports_direct_msis(kvm))
vgic_v4_teardown(kvm);
}
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index 10ae6f3..6ada243 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -66,6 +66,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
int r = 0;
struct vgic_dist *vgic = &kvm->arch.vgic;
phys_addr_t *addr_ptr, alignment;
+ u64 undef_value = VGIC_ADDR_UNDEF;
mutex_lock(&kvm->lock);
switch (type) {
@@ -84,16 +85,61 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
addr_ptr = &vgic->vgic_dist_base;
alignment = SZ_64K;
break;
- case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+ case KVM_VGIC_V3_ADDR_TYPE_REDIST: {
+ struct vgic_redist_region *rdreg;
+
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
if (r)
break;
if (write) {
- r = vgic_v3_set_redist_base(kvm, *addr);
+ r = vgic_v3_set_redist_base(kvm, 0, *addr, 0);
goto out;
}
- addr_ptr = &vgic->vgic_redist_base;
+ rdreg = list_first_entry(&vgic->rd_regions,
+ struct vgic_redist_region, list);
+ if (!rdreg)
+ addr_ptr = &undef_value;
+ else
+ addr_ptr = &rdreg->base;
break;
+ }
+ case KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION:
+ {
+ struct vgic_redist_region *rdreg;
+ u8 index;
+
+ r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
+ if (r)
+ break;
+
+ index = *addr & KVM_VGIC_V3_RDIST_INDEX_MASK;
+
+ if (write) {
+ gpa_t base = *addr & KVM_VGIC_V3_RDIST_BASE_MASK;
+ u32 count = (*addr & KVM_VGIC_V3_RDIST_COUNT_MASK)
+ >> KVM_VGIC_V3_RDIST_COUNT_SHIFT;
+ u8 flags = (*addr & KVM_VGIC_V3_RDIST_FLAGS_MASK)
+ >> KVM_VGIC_V3_RDIST_FLAGS_SHIFT;
+
+ if (!count || flags)
+ r = -EINVAL;
+ else
+ r = vgic_v3_set_redist_base(kvm, index,
+ base, count);
+ goto out;
+ }
+
+ rdreg = vgic_v3_rdist_region_from_index(kvm, index);
+ if (!rdreg) {
+ r = -ENOENT;
+ goto out;
+ }
+
+ *addr = index;
+ *addr |= rdreg->base;
+ *addr |= (u64)rdreg->count << KVM_VGIC_V3_RDIST_COUNT_SHIFT;
+ goto out;
+ }
default:
r = -ENODEV;
}
@@ -665,6 +711,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
switch (attr->attr) {
case KVM_VGIC_V3_ADDR_TYPE_DIST:
case KVM_VGIC_V3_ADDR_TYPE_REDIST:
+ case KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION:
return 0;
}
break;
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 671fe81..2877840 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -184,12 +184,17 @@ static unsigned long vgic_mmio_read_v3r_typer(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len)
{
unsigned long mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+ struct vgic_redist_region *rdreg = vgic_cpu->rdreg;
int target_vcpu_id = vcpu->vcpu_id;
+ gpa_t last_rdist_typer = rdreg->base + GICR_TYPER +
+ (rdreg->free_index - 1) * KVM_VGIC_V3_REDIST_SIZE;
u64 value;
value = (u64)(mpidr & GENMASK(23, 0)) << 32;
value |= ((target_vcpu_id & 0xffff) << 8);
- if (target_vcpu_id == atomic_read(&vcpu->kvm->online_vcpus) - 1)
+
+ if (addr == last_rdist_typer)
value |= GICR_TYPER_LAST;
if (vgic_has_its(vcpu->kvm))
value |= GICR_TYPER_PLPIS;
@@ -580,24 +585,32 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = vcpu->kvm;
struct vgic_dist *vgic = &kvm->arch.vgic;
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev;
struct vgic_io_device *sgi_dev = &vcpu->arch.vgic_cpu.sgi_iodev;
+ struct vgic_redist_region *rdreg;
gpa_t rd_base, sgi_base;
int ret;
+ if (!IS_VGIC_ADDR_UNDEF(vgic_cpu->rd_iodev.base_addr))
+ return 0;
+
/*
* 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))
+ rdreg = vgic_v3_rdist_free_slot(&vgic->rd_regions);
+ if (!rdreg)
return 0;
if (!vgic_v3_check_base(kvm))
return -EINVAL;
- rd_base = vgic->vgic_redist_base + vgic->vgic_redist_free_offset;
+ vgic_cpu->rdreg = rdreg;
+
+ rd_base = rdreg->base + rdreg->free_index * KVM_VGIC_V3_REDIST_SIZE;
sgi_base = rd_base + SZ_64K;
kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
@@ -631,7 +644,7 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
goto out;
}
- vgic->vgic_redist_free_offset += 2 * SZ_64K;
+ rdreg->free_index++;
out:
mutex_unlock(&kvm->slots_lock);
return ret;
@@ -670,23 +683,96 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm)
return ret;
}
-int vgic_v3_set_redist_base(struct kvm *kvm, u64 addr)
+/**
+ * vgic_v3_insert_redist_region - Insert a new redistributor region
+ *
+ * Performs various checks before inserting the rdist region in the list.
+ * Those tests depend on whether the size of the rdist region is known
+ * (ie. count != 0). The list is sorted by rdist region index.
+ *
+ * @kvm: kvm handle
+ * @index: redist region index
+ * @base: base of the new rdist region
+ * @count: number of redistributors the region is made of (0 in the old style
+ * single region, whose size is induced from the number of vcpus)
+ *
+ * Return 0 on success, < 0 otherwise
+ */
+static int vgic_v3_insert_redist_region(struct kvm *kvm, uint32_t index,
+ gpa_t base, uint32_t count)
{
- struct vgic_dist *vgic = &kvm->arch.vgic;
+ struct vgic_dist *d = &kvm->arch.vgic;
+ struct vgic_redist_region *rdreg;
+ struct list_head *rd_regions = &d->rd_regions;
+ size_t size = count * KVM_VGIC_V3_REDIST_SIZE;
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;
+ /* single rdist region already set ?*/
+ if (!count && !list_empty(rd_regions))
+ return -EINVAL;
- vgic->vgic_redist_base = addr;
- if (!vgic_v3_check_base(kvm)) {
- vgic->vgic_redist_base = VGIC_ADDR_UNDEF;
+ /* cross the end of memory ? */
+ if (base + size < base)
return -EINVAL;
+
+ if (list_empty(rd_regions)) {
+ if (index != 0)
+ return -EINVAL;
+ } else {
+ rdreg = list_last_entry(rd_regions,
+ struct vgic_redist_region, list);
+ if (index != rdreg->index + 1)
+ return -EINVAL;
+
+ /* Cannot add an explicitly sized regions after legacy region */
+ if (!rdreg->count)
+ return -EINVAL;
}
/*
+ * For legacy single-region redistributor regions (!count),
+ * check that the redistributor region does not overlap with the
+ * distributor's address space.
+ */
+ if (!count && !IS_VGIC_ADDR_UNDEF(d->vgic_dist_base) &&
+ vgic_dist_overlap(kvm, base, size))
+ return -EINVAL;
+
+ /* collision with any other rdist region? */
+ if (vgic_v3_rdist_overlap(kvm, base, size))
+ return -EINVAL;
+
+ rdreg = kzalloc(sizeof(*rdreg), GFP_KERNEL);
+ if (!rdreg)
+ return -ENOMEM;
+
+ rdreg->base = VGIC_ADDR_UNDEF;
+
+ ret = vgic_check_ioaddr(kvm, &rdreg->base, base, SZ_64K);
+ if (ret)
+ goto free;
+
+ rdreg->base = base;
+ rdreg->count = count;
+ rdreg->free_index = 0;
+ rdreg->index = index;
+
+ list_add_tail(&rdreg->list, rd_regions);
+ return 0;
+free:
+ kfree(rdreg);
+ return ret;
+}
+
+int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count)
+{
+ int ret;
+
+ ret = vgic_v3_insert_redist_region(kvm, index, addr, count);
+ if (ret)
+ return ret;
+
+ /*
* Register iodevs for each existing VCPU. Adding more VCPUs
* afterwards will register the iodevs when needed.
*/
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index bdcf8e7..cdce653 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -419,6 +419,29 @@ int vgic_v3_save_pending_tables(struct kvm *kvm)
return 0;
}
+/**
+ * vgic_v3_rdist_overlap - check if a region overlaps with any
+ * existing redistributor region
+ *
+ * @kvm: kvm handle
+ * @base: base of the region
+ * @size: size of region
+ *
+ * Return: true if there is an overlap
+ */
+bool vgic_v3_rdist_overlap(struct kvm *kvm, gpa_t base, size_t size)
+{
+ struct vgic_dist *d = &kvm->arch.vgic;
+ struct vgic_redist_region *rdreg;
+
+ list_for_each_entry(rdreg, &d->rd_regions, list) {
+ if ((base + size > rdreg->base) &&
+ (base < rdreg->base + vgic_v3_rd_region_size(kvm, rdreg)))
+ return true;
+ }
+ return false;
+}
+
/*
* Check for overlapping regions and for regions crossing the end of memory
* for base addresses which have already been set.
@@ -426,41 +449,83 @@ int vgic_v3_save_pending_tables(struct kvm *kvm)
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);
+ struct vgic_redist_region *rdreg;
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 (!IS_VGIC_ADDR_UNDEF(d->vgic_redist_base) &&
- d->vgic_redist_base + redist_size < d->vgic_redist_base)
- return false;
+ list_for_each_entry(rdreg, &d->rd_regions, list) {
+ if (rdreg->base + vgic_v3_rd_region_size(kvm, rdreg) <
+ rdreg->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))
+ if (IS_VGIC_ADDR_UNDEF(d->vgic_dist_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)
- return true;
+ return !vgic_v3_rdist_overlap(kvm, d->vgic_dist_base,
+ KVM_VGIC_V3_DIST_SIZE);
+}
- return false;
+/**
+ * vgic_v3_rdist_free_slot - Look up registered rdist regions and identify one
+ * which has free space to put a new rdist region.
+ *
+ * @rd_regions: redistributor region list head
+ *
+ * A redistributor regions maps n redistributors, n = region size / (2 x 64kB).
+ * Stride between redistributors is 0 and regions are filled in the index order.
+ *
+ * Return: the redist region handle, if any, that has space to map a new rdist
+ * region.
+ */
+struct vgic_redist_region *vgic_v3_rdist_free_slot(struct list_head *rd_regions)
+{
+ struct vgic_redist_region *rdreg;
+
+ list_for_each_entry(rdreg, rd_regions, list) {
+ if (!vgic_v3_redist_region_full(rdreg))
+ return rdreg;
+ }
+ return NULL;
+}
+
+struct vgic_redist_region *vgic_v3_rdist_region_from_index(struct kvm *kvm,
+ u32 index)
+{
+ struct list_head *rd_regions = &kvm->arch.vgic.rd_regions;
+ struct vgic_redist_region *rdreg;
+
+ list_for_each_entry(rdreg, rd_regions, list) {
+ if (rdreg->index == index)
+ return rdreg;
+ }
+ return NULL;
}
+
int vgic_v3_map_resources(struct kvm *kvm)
{
- int ret = 0;
struct vgic_dist *dist = &kvm->arch.vgic;
+ struct kvm_vcpu *vcpu;
+ int ret = 0;
+ int c;
if (vgic_ready(kvm))
goto out;
- if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
- IS_VGIC_ADDR_UNDEF(dist->vgic_redist_base)) {
+ kvm_for_each_vcpu(c, vcpu, kvm) {
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+ if (IS_VGIC_ADDR_UNDEF(vgic_cpu->rd_iodev.base_addr)) {
+ kvm_debug("vcpu %d redistributor base not set\n", c);
+ ret = -ENXIO;
+ goto out;
+ }
+ }
+
+ if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base)) {
kvm_err("Need to set vgic distributor addresses first\n");
ret = -ENXIO;
goto out;
@@ -552,11 +617,6 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
pr_warn("GICV physical address 0x%llx not page aligned\n",
(unsigned long long)info->vcpu.start);
kvm_vgic_global_state.vcpu_base = 0;
- } else if (!PAGE_ALIGNED(resource_size(&info->vcpu))) {
- pr_warn("GICV size 0x%llx not a multiple of page size 0x%lx\n",
- (unsigned long long)resource_size(&info->vcpu),
- PAGE_SIZE);
- kvm_vgic_global_state.vcpu_base = 0;
} else {
kvm_vgic_global_state.vcpu_base = info->vcpu.start;
kvm_vgic_global_state.can_emulate_gicv2 = true;
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index bc42651..1ed5f22 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -126,7 +126,7 @@ int vgic_v4_init(struct kvm *kvm)
nr_vcpus = atomic_read(&kvm->online_vcpus);
- dist->its_vm.vpes = kzalloc(sizeof(*dist->its_vm.vpes) * nr_vcpus,
+ dist->its_vm.vpes = kcalloc(nr_vcpus, sizeof(*dist->its_vm.vpes),
GFP_KERNEL);
if (!dist->its_vm.vpes)
return -ENOMEM;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 32c25d4..ead00b2 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -96,6 +96,13 @@
/* we only support 64 kB translation table page size */
#define KVM_ITS_L1E_ADDR_MASK GENMASK_ULL(51, 16)
+#define KVM_VGIC_V3_RDIST_INDEX_MASK GENMASK_ULL(11, 0)
+#define KVM_VGIC_V3_RDIST_FLAGS_MASK GENMASK_ULL(15, 12)
+#define KVM_VGIC_V3_RDIST_FLAGS_SHIFT 12
+#define KVM_VGIC_V3_RDIST_BASE_MASK GENMASK_ULL(51, 16)
+#define KVM_VGIC_V3_RDIST_COUNT_MASK GENMASK_ULL(63, 52)
+#define KVM_VGIC_V3_RDIST_COUNT_SHIFT 52
+
/* Requires the irq_lock to be held by the caller. */
static inline bool irq_is_pending(struct vgic_irq *irq)
{
@@ -215,7 +222,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info);
int vgic_v3_map_resources(struct kvm *kvm);
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_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count);
int vgic_register_redist_iodev(struct kvm_vcpu *vcpu);
bool vgic_v3_check_base(struct kvm *kvm);
@@ -243,8 +250,8 @@ void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
int vgic_lazy_init(struct kvm *kvm);
int vgic_init(struct kvm *kvm);
-int vgic_debug_init(struct kvm *kvm);
-int vgic_debug_destroy(struct kvm *kvm);
+void vgic_debug_init(struct kvm *kvm);
+void vgic_debug_destroy(struct kvm *kvm);
bool lock_all_vcpus(struct kvm *kvm);
void unlock_all_vcpus(struct kvm *kvm);
@@ -265,6 +272,39 @@ static inline int vgic_v3_max_apr_idx(struct kvm_vcpu *vcpu)
}
}
+static inline bool
+vgic_v3_redist_region_full(struct vgic_redist_region *region)
+{
+ if (!region->count)
+ return false;
+
+ return (region->free_index >= region->count);
+}
+
+struct vgic_redist_region *vgic_v3_rdist_free_slot(struct list_head *rdregs);
+
+static inline size_t
+vgic_v3_rd_region_size(struct kvm *kvm, struct vgic_redist_region *rdreg)
+{
+ if (!rdreg->count)
+ return atomic_read(&kvm->online_vcpus) * KVM_VGIC_V3_REDIST_SIZE;
+ else
+ return rdreg->count * KVM_VGIC_V3_REDIST_SIZE;
+}
+
+struct vgic_redist_region *vgic_v3_rdist_region_from_index(struct kvm *kvm,
+ u32 index);
+
+bool vgic_v3_rdist_overlap(struct kvm *kvm, gpa_t base, size_t size);
+
+static inline bool vgic_dist_overlap(struct kvm *kvm, gpa_t base, size_t size)
+{
+ struct vgic_dist *d = &kvm->arch.vgic;
+
+ return (base + size > d->vgic_dist_base) &&
+ (base < d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE);
+}
+
int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
u32 devid, u32 eventid, struct vgic_irq **irq);
struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index c7b2e92..8b47507f 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -116,6 +116,11 @@ static long kvm_vcpu_ioctl(struct file *file, unsigned int ioctl,
#ifdef CONFIG_KVM_COMPAT
static long kvm_vcpu_compat_ioctl(struct file *file, unsigned int ioctl,
unsigned long arg);
+#define KVM_COMPAT(c) .compat_ioctl = (c)
+#else
+static long kvm_no_compat_ioctl(struct file *file, unsigned int ioctl,
+ unsigned long arg) { return -EINVAL; }
+#define KVM_COMPAT(c) .compat_ioctl = kvm_no_compat_ioctl
#endif
static int hardware_enable_all(void);
static void hardware_disable_all(void);
@@ -203,29 +208,47 @@ static inline bool kvm_kick_many_cpus(const struct cpumask *cpus, bool wait)
return true;
}
-bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req)
+bool kvm_make_vcpus_request_mask(struct kvm *kvm, unsigned int req,
+ unsigned long *vcpu_bitmap, cpumask_var_t tmp)
{
int i, cpu, me;
- cpumask_var_t cpus;
- bool called;
struct kvm_vcpu *vcpu;
-
- zalloc_cpumask_var(&cpus, GFP_ATOMIC);
+ bool called;
me = get_cpu();
+
kvm_for_each_vcpu(i, vcpu, kvm) {
+ if (!test_bit(i, vcpu_bitmap))
+ continue;
+
kvm_make_request(req, vcpu);
cpu = vcpu->cpu;
if (!(req & KVM_REQUEST_NO_WAKEUP) && kvm_vcpu_wake_up(vcpu))
continue;
- if (cpus != NULL && cpu != -1 && cpu != me &&
+ if (tmp != NULL && cpu != -1 && cpu != me &&
kvm_request_needs_ipi(vcpu, req))
- __cpumask_set_cpu(cpu, cpus);
+ __cpumask_set_cpu(cpu, tmp);
}
- called = kvm_kick_many_cpus(cpus, !!(req & KVM_REQUEST_WAIT));
+
+ called = kvm_kick_many_cpus(tmp, !!(req & KVM_REQUEST_WAIT));
put_cpu();
+
+ return called;
+}
+
+bool kvm_make_all_cpus_request(struct kvm *kvm, unsigned int req)
+{
+ cpumask_var_t cpus;
+ bool called;
+ static unsigned long vcpu_bitmap[BITS_TO_LONGS(KVM_MAX_VCPUS)]
+ = {[0 ... BITS_TO_LONGS(KVM_MAX_VCPUS)-1] = ULONG_MAX};
+
+ zalloc_cpumask_var(&cpus, GFP_ATOMIC);
+
+ called = kvm_make_vcpus_request_mask(kvm, req, vcpu_bitmap, cpus);
+
free_cpumask_var(cpus);
return called;
}
@@ -572,10 +595,7 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)
return 0;
snprintf(dir_name, sizeof(dir_name), "%d-%d", task_pid_nr(current), fd);
- kvm->debugfs_dentry = debugfs_create_dir(dir_name,
- kvm_debugfs_dir);
- if (!kvm->debugfs_dentry)
- return -ENOMEM;
+ kvm->debugfs_dentry = debugfs_create_dir(dir_name, kvm_debugfs_dir);
kvm->debugfs_stat_data = kcalloc(kvm_debugfs_num_entries,
sizeof(*kvm->debugfs_stat_data),
@@ -591,11 +611,8 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)
stat_data->kvm = kvm;
stat_data->offset = p->offset;
kvm->debugfs_stat_data[p - debugfs_entries] = stat_data;
- if (!debugfs_create_file(p->name, 0644,
- kvm->debugfs_dentry,
- stat_data,
- stat_fops_per_vm[p->kind]))
- return -ENOMEM;
+ debugfs_create_file(p->name, 0644, kvm->debugfs_dentry,
+ stat_data, stat_fops_per_vm[p->kind]);
}
return 0;
}
@@ -2340,7 +2357,7 @@ void kvm_vcpu_on_spin(struct kvm_vcpu *me, bool yield_to_kernel_mode)
}
EXPORT_SYMBOL_GPL(kvm_vcpu_on_spin);
-static int kvm_vcpu_fault(struct vm_fault *vmf)
+static vm_fault_t kvm_vcpu_fault(struct vm_fault *vmf)
{
struct kvm_vcpu *vcpu = vmf->vma->vm_file->private_data;
struct page *page;
@@ -2384,11 +2401,9 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp)
static struct file_operations kvm_vcpu_fops = {
.release = kvm_vcpu_release,
.unlocked_ioctl = kvm_vcpu_ioctl,
-#ifdef CONFIG_KVM_COMPAT
- .compat_ioctl = kvm_vcpu_compat_ioctl,
-#endif
.mmap = kvm_vcpu_mmap,
.llseek = noop_llseek,
+ KVM_COMPAT(kvm_vcpu_compat_ioctl),
};
/*
@@ -2550,8 +2565,13 @@ static long kvm_vcpu_ioctl(struct file *filp,
oldpid = rcu_access_pointer(vcpu->pid);
if (unlikely(oldpid != current->pids[PIDTYPE_PID].pid)) {
/* The thread running this VCPU changed. */
- struct pid *newpid = get_task_pid(current, PIDTYPE_PID);
+ struct pid *newpid;
+ r = kvm_arch_vcpu_run_pid_change(vcpu);
+ if (r)
+ break;
+
+ newpid = get_task_pid(current, PIDTYPE_PID);
rcu_assign_pointer(vcpu->pid, newpid);
if (oldpid)
synchronize_rcu();
@@ -2807,10 +2827,8 @@ static int kvm_device_release(struct inode *inode, struct file *filp)
static const struct file_operations kvm_device_fops = {
.unlocked_ioctl = kvm_device_ioctl,
-#ifdef CONFIG_KVM_COMPAT
- .compat_ioctl = kvm_device_ioctl,
-#endif
.release = kvm_device_release,
+ KVM_COMPAT(kvm_device_ioctl),
};
struct kvm_device *kvm_device_from_filp(struct file *filp)
@@ -3059,7 +3077,8 @@ static long kvm_vm_ioctl(struct file *filp,
goto out;
if (routing.nr) {
r = -ENOMEM;
- entries = vmalloc(routing.nr * sizeof(*entries));
+ entries = vmalloc(array_size(sizeof(*entries),
+ routing.nr));
if (!entries)
goto out;
r = -EFAULT;
@@ -3147,10 +3166,8 @@ static long kvm_vm_compat_ioctl(struct file *filp,
static struct file_operations kvm_vm_fops = {
.release = kvm_vm_release,
.unlocked_ioctl = kvm_vm_ioctl,
-#ifdef CONFIG_KVM_COMPAT
- .compat_ioctl = kvm_vm_compat_ioctl,
-#endif
.llseek = noop_llseek,
+ KVM_COMPAT(kvm_vm_compat_ioctl),
};
static int kvm_dev_ioctl_create_vm(unsigned long type)
@@ -3241,8 +3258,8 @@ out:
static struct file_operations kvm_chardev_ops = {
.unlocked_ioctl = kvm_dev_ioctl,
- .compat_ioctl = kvm_dev_ioctl,
.llseek = noop_llseek,
+ KVM_COMPAT(kvm_dev_ioctl),
};
static struct miscdevice kvm_dev = {
@@ -3896,29 +3913,18 @@ static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm)
kfree(env);
}
-static int kvm_init_debug(void)
+static void kvm_init_debug(void)
{
- int r = -EEXIST;
struct kvm_stats_debugfs_item *p;
kvm_debugfs_dir = debugfs_create_dir("kvm", NULL);
- if (kvm_debugfs_dir == NULL)
- goto out;
kvm_debugfs_num_entries = 0;
for (p = debugfs_entries; p->name; ++p, kvm_debugfs_num_entries++) {
- if (!debugfs_create_file(p->name, 0644, kvm_debugfs_dir,
- (void *)(long)p->offset,
- stat_fops[p->kind]))
- goto out_dir;
+ debugfs_create_file(p->name, 0644, kvm_debugfs_dir,
+ (void *)(long)p->offset,
+ stat_fops[p->kind]);
}
-
- return 0;
-
-out_dir:
- debugfs_remove_recursive(kvm_debugfs_dir);
-out:
- return r;
}
static int kvm_suspend(void)
@@ -4046,20 +4052,13 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
kvm_preempt_ops.sched_in = kvm_sched_in;
kvm_preempt_ops.sched_out = kvm_sched_out;
- r = kvm_init_debug();
- if (r) {
- pr_err("kvm: create debugfs files failed\n");
- goto out_undebugfs;
- }
+ kvm_init_debug();
r = kvm_vfio_ops_init();
WARN_ON(r);
return 0;
-out_undebugfs:
- unregister_syscore_ops(&kvm_syscore_ops);
- misc_deregister(&kvm_dev);
out_unreg:
kvm_async_pf_deinit();
out_free:
OpenPOWER on IntegriCloud